From 30fcb7d229245b49f9efe88f067b78a154971589 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 12 Feb 2026 18:39:38 +0000 Subject: [PATCH] feat(app): throw helpful error when callServerTool is called with a string Users frequently call callServerTool("tool_name", args) instead of the correct callServerTool({ name: "tool_name", arguments: args }), resulting in a silent/confusing failure. Detect this and throw immediately with a message that shows the correct call shape. Also fixes the incorrect example in examples/pdf-server/README.md that demonstrated this same wrong usage pattern. Fixes #386 https://claude.ai/code/session_01GqAyN4Ux7svWoU2HqsSLZF --- examples/pdf-server/README.md | 5 ++++- src/app-bridge.test.ts | 13 +++++++++++++ src/app.ts | 6 ++++++ 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/examples/pdf-server/README.md b/examples/pdf-server/README.md index d1af05ee0..b73622cf3 100644 --- a/examples/pdf-server/README.md +++ b/examples/pdf-server/README.md @@ -63,7 +63,10 @@ On some host platforms, tool calls have size limits, so large PDFs cannot be sen ```typescript // Load in chunks with progress while (hasMore) { - const chunk = await app.callServerTool("read_pdf_bytes", { url, offset }); + const chunk = await app.callServerTool({ + name: "read_pdf_bytes", + arguments: { url, offset }, + }); chunks.push(base64ToBytes(chunk.bytes)); offset += chunk.byteCount; hasMore = chunk.hasMore; diff --git a/src/app-bridge.test.ts b/src/app-bridge.test.ts index 875c10e49..ca38e2aa3 100644 --- a/src/app-bridge.test.ts +++ b/src/app-bridge.test.ts @@ -678,6 +678,19 @@ describe("App <-> AppBridge integration", () => { expect(result.content).toEqual(resultContent); }); + it("callServerTool throws a helpful error when called with a string instead of params object", async () => { + await bridge.connect(bridgeTransport); + await app.connect(appTransport); + + await expect( + // @ts-expect-error intentionally testing wrong usage + app.callServerTool("my_tool"), + ).rejects.toThrow( + 'callServerTool() expects an object as its first argument, but received a string ("my_tool"). ' + + 'Did you mean: callServerTool({ name: "my_tool", arguments: { ... } })?', + ); + }); + it("onlistresources setter registers handler for resources/list requests", async () => { const requestParams = {}; const resources = [{ uri: "test://resource", name: "Test" }]; diff --git a/src/app.ts b/src/app.ts index f813f44c8..d8d49edc7 100644 --- a/src/app.ts +++ b/src/app.ts @@ -724,6 +724,12 @@ export class App extends Protocol { params: CallToolRequest["params"], options?: RequestOptions, ): Promise { + if (typeof params === "string") { + throw new Error( + `callServerTool() expects an object as its first argument, but received a string ("${params}"). ` + + `Did you mean: callServerTool({ name: "${params}", arguments: { ... } })?`, + ); + } return await this.request( { method: "tools/call", params }, CallToolResultSchema,