1
+ import { Client } from '../../client/index.js' ;
2
+ import { StreamableHTTPClientTransport } from '../../client/streamableHttp.js' ;
3
+ import {
4
+ ListToolsRequest ,
5
+ ListToolsResultSchema ,
6
+ CallToolRequest ,
7
+ CallToolResultSchema ,
8
+ LoggingMessageNotificationSchema ,
9
+ } from '../../types.js' ;
10
+
11
+ /**
12
+ * Parallel Tool Calls MCP Client
13
+ *
14
+ * This client demonstrates how to:
15
+ * 1. Start multiple tool calls in parallel
16
+ * 2. Track notifications from each tool call using a caller parameter
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
+ async function main ( ) : Promise < void > {
24
+ console . log ( 'MCP Parallel Tool Calls Client' ) ;
25
+ console . log ( '==============================' ) ;
26
+ console . log ( `Connecting to server at: ${ serverUrl } ` ) ;
27
+
28
+ let client : Client ;
29
+ let transport : StreamableHTTPClientTransport ;
30
+
31
+ try {
32
+ // Create client with streamable HTTP transport
33
+ client = new Client ( {
34
+ name : 'parallel-tool-calls-client' ,
35
+ version : '1.0.0'
36
+ } ) ;
37
+
38
+ client . onerror = ( error ) => {
39
+ console . error ( 'Client error:' , error ) ;
40
+ } ;
41
+
42
+ // Connect to the server
43
+ transport = new StreamableHTTPClientTransport ( new URL ( serverUrl ) ) ;
44
+ await client . connect ( transport ) ;
45
+ console . log ( 'Successfully connected to MCP server' ) ;
46
+
47
+ // Set up notification handler with caller identification
48
+ client . setNotificationHandler ( LoggingMessageNotificationSchema , ( notification ) => {
49
+ console . log ( `Notification: ${ notification . params . data } ` ) ;
50
+ } ) ;
51
+
52
+ console . log ( "List tools" )
53
+ const toolsRequest = await listTools ( client ) ;
54
+ console . log ( "Tools: " , toolsRequest )
55
+
56
+
57
+ // 2. Start multiple notification tools in parallel
58
+ console . log ( '\n=== Starting Multiple Notification Streams in Parallel ===' ) ;
59
+ const toolResults = await startParallelNotificationTools ( client ) ;
60
+
61
+ // Log the results from each tool call
62
+ for ( const [ caller , result ] of Object . entries ( toolResults ) ) {
63
+ console . log ( `\n=== Tool result for ${ caller } ===` ) ;
64
+ result . content . forEach ( ( item : { type : string ; text : any ; } ) => {
65
+ if ( item . type === 'text' ) {
66
+ console . log ( ` ${ item . text } ` ) ;
67
+ } else {
68
+ console . log ( ` ${ item . type } content:` , item ) ;
69
+ }
70
+ } ) ;
71
+ }
72
+
73
+ // 3. Wait for all notifications (10 seconds)
74
+ console . log ( '\n=== Waiting for all notifications ===' ) ;
75
+ await new Promise ( resolve => setTimeout ( resolve , 10000 ) ) ;
76
+
77
+ // 4. Disconnect
78
+ console . log ( '\n=== Disconnecting ===' ) ;
79
+ await transport . close ( ) ;
80
+ console . log ( 'Disconnected from MCP server' ) ;
81
+
82
+ } catch ( error ) {
83
+ console . error ( 'Error running client:' , error ) ;
84
+ process . exit ( 1 ) ;
85
+ }
86
+ }
87
+
88
+ /**
89
+ * List available tools on the server
90
+ */
91
+ async function listTools ( client : Client ) : Promise < void > {
92
+ try {
93
+ const toolsRequest : ListToolsRequest = {
94
+ method : 'tools/list' ,
95
+ params : { }
96
+ } ;
97
+ const toolsResult = await client . request ( toolsRequest , ListToolsResultSchema ) ;
98
+
99
+ console . log ( 'Available tools:' ) ;
100
+ if ( toolsResult . tools . length === 0 ) {
101
+ console . log ( ' No tools available' ) ;
102
+ } else {
103
+ for ( const tool of toolsResult . tools ) {
104
+ console . log ( ` - ${ tool . name } : ${ tool . description } ` ) ;
105
+ }
106
+ }
107
+ } catch ( error ) {
108
+ console . log ( `Tools not supported by this server: ${ error } ` ) ;
109
+ }
110
+ }
111
+
112
+ /**
113
+ * Start multiple notification tools in parallel with different configurations
114
+ * Each tool call includes a caller parameter to identify its notifications
115
+ */
116
+ async function startParallelNotificationTools ( client : Client ) : Promise < Record < string , any > > {
117
+ try {
118
+ // Define multiple tool calls with different configurations
119
+ const toolCalls = [
120
+ {
121
+ caller : 'fast-notifier' ,
122
+ request : {
123
+ method : 'tools/call' ,
124
+ params : {
125
+ name : 'start-notification-stream' ,
126
+ arguments : {
127
+ interval : 2 , // 0.5 second between notifications
128
+ count : 10 , // Send 10 notifications
129
+ caller : 'fast-notifier' // Identify this tool call
130
+ }
131
+ }
132
+ }
133
+ } ,
134
+ {
135
+ caller : 'slow-notifier' ,
136
+ request : {
137
+ method : 'tools/call' ,
138
+ params : {
139
+ name : 'start-notification-stream' ,
140
+ arguments : {
141
+ interval : 5 , // 2 seconds between notifications
142
+ count : 5 , // Send 5 notifications
143
+ caller : 'slow-notifier' // Identify this tool call
144
+ }
145
+ }
146
+ }
147
+ } ,
148
+ {
149
+ caller : 'burst-notifier' ,
150
+ request : {
151
+ method : 'tools/call' ,
152
+ params : {
153
+ name : 'start-notification-stream' ,
154
+ arguments : {
155
+ interval : 1 , // 0.1 second between notifications
156
+ count : 3 , // Send just 3 notifications
157
+ caller : 'burst-notifier' // Identify this tool call
158
+ }
159
+ }
160
+ }
161
+ }
162
+ ] ;
163
+
164
+ console . log ( `Starting ${ toolCalls . length } notification tools in parallel...` ) ;
165
+
166
+ // Start all tool calls in parallel
167
+ const toolPromises = toolCalls . map ( ( { caller, request } ) => {
168
+ console . log ( `Starting tool call for ${ caller } ...` ) ;
169
+ return client . request ( request , CallToolResultSchema )
170
+ . then ( result => ( { caller, result } ) )
171
+ . catch ( error => {
172
+ console . error ( `Error in tool call for ${ caller } :` , error ) ;
173
+ throw error ;
174
+ } ) ;
175
+ } ) ;
176
+
177
+ // Wait for all tool calls to complete
178
+ const results = await Promise . all ( toolPromises ) ;
179
+
180
+ // Organize results by caller
181
+ const resultsByTool : Record < string , any > = { } ;
182
+ results . forEach ( ( { caller, result } ) => {
183
+ resultsByTool [ caller ] = result ;
184
+ } ) ;
185
+
186
+ return resultsByTool ;
187
+ } catch ( error ) {
188
+ console . error ( `Error starting parallel notification tools:` , error ) ;
189
+ throw error ;
190
+ }
191
+ }
192
+
193
+ // Start the client
194
+ main ( ) . catch ( ( error : unknown ) => {
195
+ console . error ( 'Error running MCP client:' , error ) ;
196
+ process . exit ( 1 ) ;
197
+ } ) ;
0 commit comments