parallelToolCallsClient.js 6.5 KB

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