Skip to content

Commit aac1959

Browse files
committed
Errors invoking tools should be erroneous tool results, not McpErrors
1 parent ff22f25 commit aac1959

File tree

2 files changed

+82
-4
lines changed

2 files changed

+82
-4
lines changed

src/server/index.test.ts

Lines changed: 56 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -860,16 +860,70 @@ describe("Server.tool", () => {
860860
server.connect(serverTransport),
861861
]);
862862

863+
const result = await client.request(
864+
{
865+
method: "tools/call",
866+
params: {
867+
name: "error-test",
868+
},
869+
},
870+
CallToolResultSchema,
871+
);
872+
873+
expect(result.isError).toBe(true);
874+
expect(result.content).toEqual([
875+
{
876+
type: "text",
877+
text: "Tool execution failed",
878+
},
879+
]);
880+
});
881+
882+
test("should throw McpError for invalid tool name", async () => {
883+
const server = new Server({
884+
name: "test server",
885+
version: "1.0",
886+
});
887+
888+
const client = new Client(
889+
{
890+
name: "test client",
891+
version: "1.0",
892+
},
893+
{
894+
capabilities: {
895+
tools: {},
896+
},
897+
},
898+
);
899+
900+
server.tool("test-tool", async () => ({
901+
content: [
902+
{
903+
type: "text",
904+
text: "Test response",
905+
},
906+
],
907+
}));
908+
909+
const [clientTransport, serverTransport] =
910+
InMemoryTransport.createLinkedPair();
911+
912+
await Promise.all([
913+
client.connect(clientTransport),
914+
server.connect(serverTransport),
915+
]);
916+
863917
await expect(
864918
client.request(
865919
{
866920
method: "tools/call",
867921
params: {
868-
name: "error-test",
922+
name: "nonexistent-tool",
869923
},
870924
},
871925
CallToolResultSchema,
872926
),
873-
).rejects.toThrow("Tool execution failed");
927+
).rejects.toThrow(/Tool nonexistent-tool not found/);
874928
});
875929
});

src/server/index.ts

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -405,10 +405,34 @@ export class Server<
405405

406406
const args = parseResult.data;
407407
const cb = tool.callback as ToolCallback<ZodRawShape>;
408-
return await Promise.resolve(cb(args, extra));
408+
try {
409+
return await Promise.resolve(cb(args, extra));
410+
} catch (error) {
411+
return {
412+
content: [
413+
{
414+
type: "text",
415+
text: error instanceof Error ? error.message : String(error),
416+
},
417+
],
418+
isError: true,
419+
};
420+
}
409421
} else {
410422
const cb = tool.callback as ToolCallback<undefined>;
411-
return await Promise.resolve(cb(extra));
423+
try {
424+
return await Promise.resolve(cb(extra));
425+
} catch (error) {
426+
return {
427+
content: [
428+
{
429+
type: "text",
430+
text: error instanceof Error ? error.message : String(error),
431+
},
432+
],
433+
isError: true,
434+
};
435+
}
412436
}
413437
},
414438
);

0 commit comments

Comments
 (0)