Skip to content

Commit 8c2f38c

Browse files
travisbreaksTadao
andcommitted
fix(examples/client-multi-server): try/finally cleanup, assertive route lookups, exitCode pattern
Address two Claude bot review concerns posted after the prior approval (2026-04-09 17:21:58): 1. Cleanup pattern: main() body had no try/finally, so the cleanup loop never ran when an error propagated to the .catch() handler that called process.exit(1) synchronously. Wrapped main() body in try/finally; moved cleanup loop into finally; replaced process.exit(1) with process.exitCode = 1 so the finally block actually runs on error. 2. Silent routing failures: hardcoded prefixed keys with if-guards meant a missing key (renamed server, renamed tool) printed only the routing demo header then "All servers disconnected." with zero indication that no routing was demonstrated. Replaced silent if-guards with assertive lookups that throw a clear error identifying the missing key. Renamed result/text variables to alertsResult/alertsText/weatherResult/ weatherText since de-indenting the call blocks would put two const result declarations in the same scope. No semantic change to the demo output. Local typecheck:all, lint:all, and build:all all pass. Co-Authored-By: Tadao <tadao@travisfixes.com>
1 parent 5c1dc99 commit 8c2f38c

1 file changed

Lines changed: 52 additions & 48 deletions

File tree

  • examples/client-multi-server/src

examples/client-multi-server/src/index.ts

Lines changed: 52 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -36,77 +36,81 @@ const toolRouter = new Map<
3636
async function main() {
3737
const clients: Client[] = [];
3838

39-
// 1. Connect to each server and discover tools
40-
for (const { name, script } of servers) {
41-
const transport = new StdioClientTransport({
42-
command: process.execPath,
43-
args: ['--import', 'tsx', script],
44-
});
45-
const client = new Client({ name: `router-${name}`, version: '1.0.0' });
46-
await client.connect(transport);
47-
clients.push(client);
48-
49-
const { tools } = await client.listTools();
50-
for (const tool of tools) {
51-
const prefixed = `${name}__${tool.name}`;
52-
toolRouter.set(prefixed, {
53-
client,
54-
originalName: tool.name,
55-
serverName: name,
39+
try {
40+
// 1. Connect to each server and discover tools
41+
for (const { name, script } of servers) {
42+
const transport = new StdioClientTransport({
43+
command: process.execPath,
44+
args: ['--import', 'tsx', script],
5645
});
57-
}
46+
const client = new Client({ name: `router-${name}`, version: '1.0.0' });
47+
await client.connect(transport);
48+
clients.push(client);
5849

59-
console.log(`[${name}] connected, tools: ${tools.map((t) => t.name).join(', ')}`);
60-
}
50+
const { tools } = await client.listTools();
51+
for (const tool of tools) {
52+
const prefixed = `${name}__${tool.name}`;
53+
toolRouter.set(prefixed, {
54+
client,
55+
originalName: tool.name,
56+
serverName: name,
57+
});
58+
}
6159

62-
console.log(`\nRouting table (${toolRouter.size} tools):`);
63-
for (const [prefixed, { serverName, originalName }] of toolRouter) {
64-
console.log(` ${prefixed} -> ${serverName} (${originalName})`);
65-
}
60+
console.log(`[${name}] connected, tools: ${tools.map((t) => t.name).join(', ')}`);
61+
}
62+
63+
console.log(`\nRouting table (${toolRouter.size} tools):`);
64+
for (const [prefixed, { serverName, originalName }] of toolRouter) {
65+
console.log(` ${prefixed} -> ${serverName} (${originalName})`);
66+
}
6667

67-
// 2. Demonstrate routing: call one tool from each server
68-
console.log('\n--- Routing demo ---\n');
68+
// 2. Demonstrate routing: call one tool from each server
69+
console.log('\n--- Routing demo ---\n');
6970

70-
// Call get-alerts from weather-nws (server-quickstart)
71-
const alertsKey = 'weather-nws__get-alerts';
72-
const alertsRoute = toolRouter.get(alertsKey);
73-
if (alertsRoute) {
71+
// Call get-alerts from weather-nws (server-quickstart)
72+
const alertsKey = 'weather-nws__get-alerts';
73+
const alertsRoute = toolRouter.get(alertsKey);
74+
if (!alertsRoute) {
75+
throw new Error(`Routing demo: no route for ${alertsKey}. Did a server name or tool name change?`);
76+
}
7477
console.log(`Calling ${alertsKey} ...`);
75-
const result = await alertsRoute.client.callTool({
78+
const alertsResult = await alertsRoute.client.callTool({
7679
name: alertsRoute.originalName,
7780
arguments: { state: 'CA' },
7881
});
79-
const text = result.content
82+
const alertsText = alertsResult.content
8083
.filter((c) => c.type === 'text')
8184
.map((c) => c.text)
8285
.join('\n');
83-
console.log(`Result: ${text.slice(0, 200)}...\n`);
84-
}
86+
console.log(`Result: ${alertsText.slice(0, 200)}...\n`);
8587

86-
// Call get_weather from weather-structured (mcpServerOutputSchema)
87-
const weatherKey = 'weather-structured__get_weather';
88-
const weatherRoute = toolRouter.get(weatherKey);
89-
if (weatherRoute) {
88+
// Call get_weather from weather-structured (mcpServerOutputSchema)
89+
const weatherKey = 'weather-structured__get_weather';
90+
const weatherRoute = toolRouter.get(weatherKey);
91+
if (!weatherRoute) {
92+
throw new Error(`Routing demo: no route for ${weatherKey}. Did a server name or tool name change?`);
93+
}
9094
console.log(`Calling ${weatherKey} ...`);
91-
const result = await weatherRoute.client.callTool({
95+
const weatherResult = await weatherRoute.client.callTool({
9296
name: weatherRoute.originalName,
9397
arguments: { city: 'Seattle', country: 'US' },
9498
});
95-
const text = result.content
99+
const weatherText = weatherResult.content
96100
.filter((c) => c.type === 'text')
97101
.map((c) => c.text)
98102
.join('\n');
99-
console.log(`Result: ${text.slice(0, 200)}...\n`);
100-
}
101-
102-
// 3. Cleanup
103-
for (const client of clients) {
104-
await client.close();
103+
console.log(`Result: ${weatherText.slice(0, 200)}...\n`);
104+
} finally {
105+
// 3. Cleanup runs on success and error
106+
for (const client of clients) {
107+
await client.close();
108+
}
109+
console.log('All servers disconnected.');
105110
}
106-
console.log('All servers disconnected.');
107111
}
108112

109113
main().catch((err) => {
110114
console.error('Fatal error:', err);
111-
process.exit(1);
115+
process.exitCode = 1;
112116
});

0 commit comments

Comments
 (0)