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