Add more test clients

This commit is contained in:
ihrpr 2025-04-21 11:54:10 +01:00
commit 70608b5876
No known key found for this signature in database
2 changed files with 608 additions and 0 deletions

View 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);
});

View 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);
});