Skip to content

Commit f7d44a9

Browse files
committed
sample: Add a sample using a group of MCP clients.
This is introduced as the first step of adding dedicated functionality for managing client groups. It demonstrate what the UX is like right now, and will evolve and hopefully get simpler as we introduce dedicated client group functionality.
1 parent 68a0ca3 commit f7d44a9

File tree

1 file changed

+129
-0
lines changed

1 file changed

+129
-0
lines changed
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
import { Tool } from "../../types.js";
2+
import { Client } from "../../client/index.js";
3+
import { InMemoryTransport } from "../../inMemory.js";
4+
import { McpServer, ToolCallback } from "../../server/mcp.js";
5+
import { Transport } from "../../shared/transport.js";
6+
7+
async function main(): Promise<void> {
8+
console.log("MCP Client Group Example");
9+
console.log("============================");
10+
11+
const clientTransports = await spinUpServers();
12+
13+
const client1 = new Client({
14+
name: "client-1",
15+
version: "1.0.0",
16+
});
17+
client1.connect(clientTransports[0]);
18+
19+
const client2 = new Client({
20+
name: "client-2",
21+
version: "1.0.0",
22+
});
23+
client2.connect(clientTransports[1]);
24+
25+
const client3 = new Client({
26+
name: "client-3",
27+
version: "1.0.0",
28+
});
29+
client3.connect(clientTransports[2]);
30+
31+
const allClients = [client1, client2, client3];
32+
const toolToClient: { [key: string]: Client } = {};
33+
const allTools = [];
34+
35+
for (const client of allClients) {
36+
for (const tool of (await client.listTools()).tools) {
37+
if (toolToClient[tool.name]) {
38+
console.warn(
39+
`Tool name: ${tool.name} is available on multiple servers, picking an arbitrary one`,
40+
);
41+
}
42+
toolToClient[tool.name] = client;
43+
allTools.push(tool);
44+
}
45+
}
46+
47+
const allResources = [];
48+
allResources.push(...(await client1.listResources()).resources);
49+
allResources.push(...(await client2.listResources()).resources);
50+
allResources.push(...(await client3.listResources()).resources);
51+
52+
const toolName = simulatePromptModel(allTools);
53+
54+
console.log(`Invoking tool: ${toolName}`);
55+
const toolResult = await toolToClient[toolName].callTool({
56+
name: toolName,
57+
});
58+
59+
console.log(toolResult);
60+
61+
for (const client of allClients) {
62+
await client.close();
63+
}
64+
}
65+
66+
// Start the example
67+
main().catch((error: unknown) => {
68+
console.error("Error running MCP Client Group example:", error);
69+
process.exit(1);
70+
});
71+
72+
async function spinUpServer(
73+
name: string,
74+
cb: ToolCallback,
75+
): Promise<Transport> {
76+
const server = new McpServer({
77+
name: name,
78+
version: "1.0.0",
79+
});
80+
81+
server.tool(name, cb);
82+
83+
server.resource("greeting", "greeting://hello", async (uri) => ({
84+
contents: [
85+
{
86+
uri: uri.href,
87+
text: `Hello from ${name}!`,
88+
},
89+
],
90+
}));
91+
92+
const transports = InMemoryTransport.createLinkedPair();
93+
await server.connect(transports[0]);
94+
95+
return transports[1];
96+
}
97+
98+
async function spinUpServers(): Promise<Transport[]> {
99+
const clientTransports = [];
100+
clientTransports.push(
101+
await spinUpServer("ping", async () => ({
102+
content: [{ type: "text", text: "pong" }],
103+
})),
104+
);
105+
106+
clientTransports.push(
107+
await spinUpServer("pong", async () => ({
108+
content: [{ type: "text", text: "ping" }],
109+
})),
110+
);
111+
112+
// We deliberately spin up 2 servers with the same tool name to
113+
// demonstrate dealing with that edge case in the sample.
114+
clientTransports.push(
115+
await spinUpServer("ping", async () => ({
116+
content: [{ type: "text", text: "pong2" }],
117+
})),
118+
);
119+
120+
return clientTransports;
121+
}
122+
123+
function simulatePromptModel(tools: Tool[]): string {
124+
console.log(`Model was prompted with the following tools:`);
125+
for (const tool of tools) {
126+
console.log(` - ${tool.name}`);
127+
}
128+
return "ping";
129+
}

0 commit comments

Comments
 (0)