Add more test clients
This commit is contained in:
parent
3ef902328a
commit
70608b5876
2 changed files with 608 additions and 0 deletions
159
src/examples/client/multipleClientsParallel.ts
Normal file
159
src/examples/client/multipleClientsParallel.ts
Normal file
|
|
@ -0,0 +1,159 @@
|
|||
import { Client } from '../../client/index.js';
|
||||
import { StreamableHTTPClientTransport } from '../../client/streamableHttp.js';
|
||||
import {
|
||||
CallToolRequest,
|
||||
CallToolResultSchema,
|
||||
LoggingMessageNotificationSchema,
|
||||
} from '../../types.js';
|
||||
|
||||
/**
|
||||
* Multiple Clients MCP Example
|
||||
*
|
||||
* This client demonstrates how to:
|
||||
* 1. Create multiple MCP clients in parallel
|
||||
* 2. Each client calls a single tool
|
||||
* 3. Track notifications from each client independently
|
||||
*/
|
||||
|
||||
// Command line args processing
|
||||
const args = process.argv.slice(2);
|
||||
const serverUrl = args[0] || 'http://localhost:3000/mcp';
|
||||
|
||||
interface ClientConfig {
|
||||
id: string;
|
||||
name: string;
|
||||
toolName: string;
|
||||
toolArguments: Record<string, any>;
|
||||
}
|
||||
|
||||
async function createAndRunClient(config: ClientConfig): Promise<{ id: string; result: any }> {
|
||||
console.log(`[${config.id}] Creating client: ${config.name}`);
|
||||
|
||||
const client = new Client({
|
||||
name: config.name,
|
||||
version: '1.0.0'
|
||||
});
|
||||
|
||||
const transport = new StreamableHTTPClientTransport(new URL(serverUrl));
|
||||
|
||||
// Set up client-specific error handler
|
||||
client.onerror = (error) => {
|
||||
console.error(`[${config.id}] Client error:`, error);
|
||||
};
|
||||
|
||||
// Set up client-specific notification handler
|
||||
client.setNotificationHandler(LoggingMessageNotificationSchema, (notification) => {
|
||||
console.log(`[${config.id}] Notification: ${notification.params.data}`);
|
||||
});
|
||||
|
||||
try {
|
||||
// Connect to the server
|
||||
await client.connect(transport);
|
||||
console.log(`[${config.id}] Connected to MCP server`);
|
||||
|
||||
// Call the specified tool
|
||||
console.log(`[${config.id}] Calling tool: ${config.toolName}`);
|
||||
const toolRequest: CallToolRequest = {
|
||||
method: 'tools/call',
|
||||
params: {
|
||||
name: config.toolName,
|
||||
arguments: {
|
||||
...config.toolArguments,
|
||||
// Add client ID to arguments for identification in notifications
|
||||
caller: config.id
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const result = await client.request(toolRequest, CallToolResultSchema);
|
||||
console.log(`[${config.id}] Tool call completed`);
|
||||
|
||||
// Keep the connection open for a bit to receive notifications
|
||||
await new Promise(resolve => setTimeout(resolve, 5000));
|
||||
|
||||
// Disconnect
|
||||
await transport.close();
|
||||
console.log(`[${config.id}] Disconnected from MCP server`);
|
||||
|
||||
return { id: config.id, result };
|
||||
} catch (error) {
|
||||
console.error(`[${config.id}] Error:`, error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
async function main(): Promise<void> {
|
||||
console.log('MCP Multiple Clients Example');
|
||||
console.log('============================');
|
||||
console.log(`Server URL: ${serverUrl}`);
|
||||
console.log('');
|
||||
|
||||
try {
|
||||
// Define client configurations
|
||||
const clientConfigs: ClientConfig[] = [
|
||||
{
|
||||
id: 'client1',
|
||||
name: 'basic-client-1',
|
||||
toolName: 'start-notification-stream',
|
||||
toolArguments: {
|
||||
interval: 3, // 1 second between notifications
|
||||
count: 5 // Send 5 notifications
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 'client2',
|
||||
name: 'basic-client-2',
|
||||
toolName: 'start-notification-stream',
|
||||
toolArguments: {
|
||||
interval: 2, // 2 seconds between notifications
|
||||
count: 3 // Send 3 notifications
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 'client3',
|
||||
name: 'basic-client-3',
|
||||
toolName: 'start-notification-stream',
|
||||
toolArguments: {
|
||||
interval: 1, // 0.5 second between notifications
|
||||
count: 8 // Send 8 notifications
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
// Start all clients in parallel
|
||||
console.log(`Starting ${clientConfigs.length} clients in parallel...`);
|
||||
console.log('');
|
||||
|
||||
const clientPromises = clientConfigs.map(config => createAndRunClient(config));
|
||||
const results = await Promise.all(clientPromises);
|
||||
|
||||
// Display results from all clients
|
||||
console.log('\n=== Final Results ===');
|
||||
results.forEach(({ id, result }) => {
|
||||
console.log(`\n[${id}] Tool result:`);
|
||||
if (Array.isArray(result.content)) {
|
||||
result.content.forEach((item: { type: string; text?: string }) => {
|
||||
if (item.type === 'text' && item.text) {
|
||||
console.log(` ${item.text}`);
|
||||
} else {
|
||||
console.log(` ${item.type} content:`, item);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
console.log(` Unexpected result format:`, result);
|
||||
}
|
||||
});
|
||||
|
||||
console.log('\n=== All clients completed successfully ===');
|
||||
|
||||
} catch (error) {
|
||||
console.error('Error running multiple clients:', error);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// Start the example
|
||||
main().catch((error: unknown) => {
|
||||
console.error('Error running MCP multiple clients example:', error);
|
||||
process.exit(1);
|
||||
});
|
||||
197
src/examples/client/parallelToolCallsClient.ts
Normal file
197
src/examples/client/parallelToolCallsClient.ts
Normal file
|
|
@ -0,0 +1,197 @@
|
|||
import { Client } from '../../client/index.js';
|
||||
import { StreamableHTTPClientTransport } from '../../client/streamableHttp.js';
|
||||
import {
|
||||
ListToolsRequest,
|
||||
ListToolsResultSchema,
|
||||
CallToolRequest,
|
||||
CallToolResultSchema,
|
||||
LoggingMessageNotificationSchema,
|
||||
} from '../../types.js';
|
||||
|
||||
/**
|
||||
* Parallel Tool Calls MCP Client
|
||||
*
|
||||
* This client demonstrates how to:
|
||||
* 1. Start multiple tool calls in parallel
|
||||
* 2. Track notifications from each tool call using a caller parameter
|
||||
*/
|
||||
|
||||
// Command line args processing
|
||||
const args = process.argv.slice(2);
|
||||
const serverUrl = args[0] || 'http://localhost:3000/mcp';
|
||||
|
||||
async function main(): Promise<void> {
|
||||
console.log('MCP Parallel Tool Calls Client');
|
||||
console.log('==============================');
|
||||
console.log(`Connecting to server at: ${serverUrl}`);
|
||||
|
||||
let client: Client;
|
||||
let transport: StreamableHTTPClientTransport;
|
||||
|
||||
try {
|
||||
// Create client with streamable HTTP transport
|
||||
client = new Client({
|
||||
name: 'parallel-tool-calls-client',
|
||||
version: '1.0.0'
|
||||
});
|
||||
|
||||
client.onerror = (error) => {
|
||||
console.error('Client error:', error);
|
||||
};
|
||||
|
||||
// Connect to the server
|
||||
transport = new StreamableHTTPClientTransport(new URL(serverUrl));
|
||||
await client.connect(transport);
|
||||
console.log('Successfully connected to MCP server');
|
||||
|
||||
// Set up notification handler with caller identification
|
||||
client.setNotificationHandler(LoggingMessageNotificationSchema, (notification) => {
|
||||
console.log(`Notification: ${notification.params.data}`);
|
||||
});
|
||||
|
||||
console.log("List tools")
|
||||
const toolsRequest = await listTools(client);
|
||||
console.log("Tools: ", toolsRequest)
|
||||
|
||||
|
||||
// 2. Start multiple notification tools in parallel
|
||||
console.log('\n=== Starting Multiple Notification Streams in Parallel ===');
|
||||
const toolResults = await startParallelNotificationTools(client);
|
||||
|
||||
// Log the results from each tool call
|
||||
for (const [caller, result] of Object.entries(toolResults)) {
|
||||
console.log(`\n=== Tool result for ${caller} ===`);
|
||||
result.content.forEach((item: { type: string; text: any; }) => {
|
||||
if (item.type === 'text') {
|
||||
console.log(` ${item.text}`);
|
||||
} else {
|
||||
console.log(` ${item.type} content:`, item);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 3. Wait for all notifications (10 seconds)
|
||||
console.log('\n=== Waiting for all notifications ===');
|
||||
await new Promise(resolve => setTimeout(resolve, 10000));
|
||||
|
||||
// 4. Disconnect
|
||||
console.log('\n=== Disconnecting ===');
|
||||
await transport.close();
|
||||
console.log('Disconnected from MCP server');
|
||||
|
||||
} catch (error) {
|
||||
console.error('Error running client:', error);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* List available tools on the server
|
||||
*/
|
||||
async function listTools(client: Client): Promise<void> {
|
||||
try {
|
||||
const toolsRequest: ListToolsRequest = {
|
||||
method: 'tools/list',
|
||||
params: {}
|
||||
};
|
||||
const toolsResult = await client.request(toolsRequest, ListToolsResultSchema);
|
||||
|
||||
console.log('Available tools:');
|
||||
if (toolsResult.tools.length === 0) {
|
||||
console.log(' No tools available');
|
||||
} else {
|
||||
for (const tool of toolsResult.tools) {
|
||||
console.log(` - ${tool.name}: ${tool.description}`);
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(`Tools not supported by this server: ${error}`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Start multiple notification tools in parallel with different configurations
|
||||
* Each tool call includes a caller parameter to identify its notifications
|
||||
*/
|
||||
async function startParallelNotificationTools(client: Client): Promise<Record<string, any>> {
|
||||
try {
|
||||
// Define multiple tool calls with different configurations
|
||||
const toolCalls = [
|
||||
{
|
||||
caller: 'fast-notifier',
|
||||
request: {
|
||||
method: 'tools/call',
|
||||
params: {
|
||||
name: 'start-notification-stream',
|
||||
arguments: {
|
||||
interval: 2, // 0.5 second between notifications
|
||||
count: 10, // Send 10 notifications
|
||||
caller: 'fast-notifier' // Identify this tool call
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
caller: 'slow-notifier',
|
||||
request: {
|
||||
method: 'tools/call',
|
||||
params: {
|
||||
name: 'start-notification-stream',
|
||||
arguments: {
|
||||
interval: 5, // 2 seconds between notifications
|
||||
count: 5, // Send 5 notifications
|
||||
caller: 'slow-notifier' // Identify this tool call
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
caller: 'burst-notifier',
|
||||
request: {
|
||||
method: 'tools/call',
|
||||
params: {
|
||||
name: 'start-notification-stream',
|
||||
arguments: {
|
||||
interval: 1, // 0.1 second between notifications
|
||||
count: 3, // Send just 3 notifications
|
||||
caller: 'burst-notifier' // Identify this tool call
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
console.log(`Starting ${toolCalls.length} notification tools in parallel...`);
|
||||
|
||||
// Start all tool calls in parallel
|
||||
const toolPromises = toolCalls.map(({ caller, request }) => {
|
||||
console.log(`Starting tool call for ${caller}...`);
|
||||
return client.request(request, CallToolResultSchema)
|
||||
.then(result => ({ caller, result }))
|
||||
.catch(error => {
|
||||
console.error(`Error in tool call for ${caller}:`, error);
|
||||
throw error;
|
||||
});
|
||||
});
|
||||
|
||||
// Wait for all tool calls to complete
|
||||
const results = await Promise.all(toolPromises);
|
||||
|
||||
// Organize results by caller
|
||||
const resultsByTool: Record<string, any> = {};
|
||||
results.forEach(({ caller, result }) => {
|
||||
resultsByTool[caller] = result;
|
||||
});
|
||||
|
||||
return resultsByTool;
|
||||
} catch (error) {
|
||||
console.error(`Error starting parallel notification tools:`, error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
// Start the client
|
||||
main().catch((error: unknown) => {
|
||||
console.error('Error running MCP client:', error);
|
||||
process.exit(1);
|
||||
});
|
||||
Loading…
Reference in a new issue