1+ import { Client } from '../../client/index.js' ;
2+ import { StreamableHTTPClientTransport } from '../../client/streamableHttp.js' ;
3+ import {
4+ CallToolRequest ,
5+ CallToolResultSchema ,
6+ LoggingMessageNotificationSchema ,
7+ CallToolResult ,
8+ } from '../../types.js' ;
9+
10+ /**
11+ * Multiple Clients MCP Example
12+ *
13+ * This client demonstrates how to:
14+ * 1. Create multiple MCP clients in parallel
15+ * 2. Each client calls a single tool
16+ * 3. Track notifications from each client independently
17+ */
18+
19+ // Command line args processing
20+ const args = process . argv . slice ( 2 ) ;
21+ const serverUrl = args [ 0 ] || 'http://localhost:3000/mcp' ;
22+
23+ interface ClientConfig {
24+ id : string ;
25+ name : string ;
26+ toolName : string ;
27+ toolArguments : Record < string , string | number | boolean > ;
28+ }
29+
30+ async function createAndRunClient ( config : ClientConfig ) : Promise < { id : string ; result : CallToolResult } > {
31+ console . log ( `[${ config . id } ] Creating client: ${ config . name } ` ) ;
32+
33+ const client = new Client ( {
34+ name : config . name ,
35+ version : '1.0.0'
36+ } ) ;
37+
38+ const transport = new StreamableHTTPClientTransport ( new URL ( serverUrl ) ) ;
39+
40+ // Set up client-specific error handler
41+ client . onerror = ( error ) => {
42+ console . error ( `[${ config . id } ] Client error:` , error ) ;
43+ } ;
44+
45+ // Set up client-specific notification handler
46+ client . setNotificationHandler ( LoggingMessageNotificationSchema , ( notification ) => {
47+ console . log ( `[${ config . id } ] Notification: ${ notification . params . data } ` ) ;
48+ } ) ;
49+
50+ try {
51+ // Connect to the server
52+ await client . connect ( transport ) ;
53+ console . log ( `[${ config . id } ] Connected to MCP server` ) ;
54+
55+ // Call the specified tool
56+ console . log ( `[${ config . id } ] Calling tool: ${ config . toolName } ` ) ;
57+ const toolRequest : CallToolRequest = {
58+ method : 'tools/call' ,
59+ params : {
60+ name : config . toolName ,
61+ arguments : {
62+ ...config . toolArguments ,
63+ // Add client ID to arguments for identification in notifications
64+ caller : config . id
65+ }
66+ }
67+ } ;
68+
69+ const result = await client . request ( toolRequest , CallToolResultSchema ) ;
70+ console . log ( `[${ config . id } ] Tool call completed` ) ;
71+
72+ // Keep the connection open for a bit to receive notifications
73+ await new Promise ( resolve => setTimeout ( resolve , 5000 ) ) ;
74+
75+ // Disconnect
76+ await transport . close ( ) ;
77+ console . log ( `[${ config . id } ] Disconnected from MCP server` ) ;
78+
79+ return { id : config . id , result } ;
80+ } catch ( error ) {
81+ console . error ( `[${ config . id } ] Error:` , error ) ;
82+ throw error ;
83+ }
84+ }
85+
86+ async function main ( ) : Promise < void > {
87+ console . log ( 'MCP Multiple Clients Example' ) ;
88+ console . log ( '============================' ) ;
89+ console . log ( `Server URL: ${ serverUrl } ` ) ;
90+ console . log ( '' ) ;
91+
92+ try {
93+ // Define client configurations
94+ const clientConfigs : ClientConfig [ ] = [
95+ {
96+ id : 'client1' ,
97+ name : 'basic-client-1' ,
98+ toolName : 'start-notification-stream' ,
99+ toolArguments : {
100+ interval : 3 , // 1 second between notifications
101+ count : 5 // Send 5 notifications
102+ }
103+ } ,
104+ {
105+ id : 'client2' ,
106+ name : 'basic-client-2' ,
107+ toolName : 'start-notification-stream' ,
108+ toolArguments : {
109+ interval : 2 , // 2 seconds between notifications
110+ count : 3 // Send 3 notifications
111+ }
112+ } ,
113+ {
114+ id : 'client3' ,
115+ name : 'basic-client-3' ,
116+ toolName : 'start-notification-stream' ,
117+ toolArguments : {
118+ interval : 1 , // 0.5 second between notifications
119+ count : 8 // Send 8 notifications
120+ }
121+ }
122+ ] ;
123+
124+ // Start all clients in parallel
125+ console . log ( `Starting ${ clientConfigs . length } clients in parallel...` ) ;
126+ console . log ( '' ) ;
127+
128+ const clientPromises = clientConfigs . map ( config => createAndRunClient ( config ) ) ;
129+ const results = await Promise . all ( clientPromises ) ;
130+
131+ // Display results from all clients
132+ console . log ( '\n=== Final Results ===' ) ;
133+ results . forEach ( ( { id, result } ) => {
134+ console . log ( `\n[${ id } ] Tool result:` ) ;
135+ if ( Array . isArray ( result . content ) ) {
136+ result . content . forEach ( ( item : { type : string ; text ?: string } ) => {
137+ if ( item . type === 'text' && item . text ) {
138+ console . log ( ` ${ item . text } ` ) ;
139+ } else {
140+ console . log ( ` ${ item . type } content:` , item ) ;
141+ }
142+ } ) ;
143+ } else {
144+ console . log ( ` Unexpected result format:` , result ) ;
145+ }
146+ } ) ;
147+
148+ console . log ( '\n=== All clients completed successfully ===' ) ;
149+
150+ } catch ( error ) {
151+ console . error ( 'Error running multiple clients:' , error ) ;
152+ process . exit ( 1 ) ;
153+ }
154+ }
155+
156+ // Start the example
157+ main ( ) . catch ( ( error : unknown ) => {
158+ console . error ( 'Error running MCP multiple clients example:' , error ) ;
159+ process . exit ( 1 ) ;
160+ } ) ;
0 commit comments