Skip to content

Add validation for callServerTool params argument#449

Merged
ochafik merged 1 commit intomainfrom
claude/defensive-callservertool-GbZYK
Feb 13, 2026
Merged

Add validation for callServerTool params argument#449
ochafik merged 1 commit intomainfrom
claude/defensive-callservertool-GbZYK

Conversation

@ochafik
Copy link
Contributor

@ochafik ochafik commented Feb 12, 2026

Summary

Added input validation to callServerTool() to catch a common usage error where developers pass a string tool name instead of the required params object ( examples: report 1, report 2). When this mistake occurs, the method now throws a helpful error message with a suggestion for the correct usage pattern.

Changes

  • src/app.ts: Added type check in callServerTool() to detect when a string is passed as the first argument and throw a descriptive error with usage guidance
  • src/app-bridge.test.ts: Added test case verifying the error is thrown with the correct message when callServerTool() is called with a string
  • examples/pdf-server/README.md: Updated code example to use the correct callServerTool() API with params object instead of separate arguments

Implementation Details

The validation checks if the params argument is a string and throws an error that:

  • Clearly states what was received (the string value)
  • Explains what was expected (an object)
  • Provides a concrete example of the correct usage pattern with the tool name and arguments structure

https://claude.ai/code/session_01GqAyN4Ux7svWoU2HqsSLZF

@pkg-pr-new
Copy link

pkg-pr-new bot commented Feb 12, 2026

Open in StackBlitz

@modelcontextprotocol/ext-apps

npm i https://pkg.pr.new/modelcontextprotocol/ext-apps/@modelcontextprotocol/ext-apps@449

@modelcontextprotocol/server-basic-react

npm i https://pkg.pr.new/modelcontextprotocol/ext-apps/@modelcontextprotocol/server-basic-react@449

@modelcontextprotocol/server-basic-vanillajs

npm i https://pkg.pr.new/modelcontextprotocol/ext-apps/@modelcontextprotocol/server-basic-vanillajs@449

@modelcontextprotocol/server-budget-allocator

npm i https://pkg.pr.new/modelcontextprotocol/ext-apps/@modelcontextprotocol/server-budget-allocator@449

@modelcontextprotocol/server-cohort-heatmap

npm i https://pkg.pr.new/modelcontextprotocol/ext-apps/@modelcontextprotocol/server-cohort-heatmap@449

@modelcontextprotocol/server-customer-segmentation

npm i https://pkg.pr.new/modelcontextprotocol/ext-apps/@modelcontextprotocol/server-customer-segmentation@449

@modelcontextprotocol/server-map

npm i https://pkg.pr.new/modelcontextprotocol/ext-apps/@modelcontextprotocol/server-map@449

@modelcontextprotocol/server-pdf

npm i https://pkg.pr.new/modelcontextprotocol/ext-apps/@modelcontextprotocol/server-pdf@449

@modelcontextprotocol/server-scenario-modeler

npm i https://pkg.pr.new/modelcontextprotocol/ext-apps/@modelcontextprotocol/server-scenario-modeler@449

@modelcontextprotocol/server-shadertoy

npm i https://pkg.pr.new/modelcontextprotocol/ext-apps/@modelcontextprotocol/server-shadertoy@449

@modelcontextprotocol/server-sheet-music

npm i https://pkg.pr.new/modelcontextprotocol/ext-apps/@modelcontextprotocol/server-sheet-music@449

@modelcontextprotocol/server-system-monitor

npm i https://pkg.pr.new/modelcontextprotocol/ext-apps/@modelcontextprotocol/server-system-monitor@449

@modelcontextprotocol/server-threejs

npm i https://pkg.pr.new/modelcontextprotocol/ext-apps/@modelcontextprotocol/server-threejs@449

@modelcontextprotocol/server-transcript

npm i https://pkg.pr.new/modelcontextprotocol/ext-apps/@modelcontextprotocol/server-transcript@449

@modelcontextprotocol/server-video-resource

npm i https://pkg.pr.new/modelcontextprotocol/ext-apps/@modelcontextprotocol/server-video-resource@449

@modelcontextprotocol/server-wiki-explorer

npm i https://pkg.pr.new/modelcontextprotocol/ext-apps/@modelcontextprotocol/server-wiki-explorer@449

commit: 30fcb7d

…tring

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
@ochafik ochafik force-pushed the claude/defensive-callservertool-GbZYK branch from 64236a2 to 30fcb7d Compare February 12, 2026 19:54
@ochafik ochafik marked this pull request as ready for review February 12, 2026 20:36
@ochafik ochafik requested a review from antonpk1 February 12, 2026 20:36
Comment on lines 723 to +732
async callServerTool(
params: CallToolRequest["params"],
options?: RequestOptions,
): Promise<CallToolResult> {
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: { ... } })?`,
);
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Checking typeof params === "string" when params: CallToolRequest["params"] feels a bit funny.

Something that puzzles me: in at least one report, the developer is using TypeScript, so why wasn't the error caught by the type checker?

By the way, another alternative would be to add a function overload. (Though the proper fix is still to fix type checking.)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah it's a hack to help w/ errors that shouldn't happen, but that do.
I think given I'd left that bad syntax example in pdf-server/README.md, people end up trying their chances even when their typechecker isn't working well.

A function overload would imply it's a valid syntax.

@ochafik ochafik merged commit 6669529 into main Feb 13, 2026
18 of 19 checks passed
ochafik added a commit that referenced this pull request Feb 22, 2026
Features:
- registerAppResource now returns the registered resource (#370)
- Accept UIResourceMeta in both resources/list and resources/read (#410)
- callServerTool throws helpful error when called with a string (#449)
- Add double-connect guard to prevent protocol message handling errors (#450)

Bug fixes:
- Only ignore messages that lack jsonrpc 2.0 in message-transport (#448)
- Align basic-host dark mode styles (#438)

Spec:
- Change Host <> Sandbox communication protocol to SHOULD (#435)
- Clarify UIResourceMeta in both list and read responses (#410)
ochafik added a commit that referenced this pull request Feb 22, 2026
* chore: bump ext-apps to 1.1.0

Features:
- registerAppResource now returns the registered resource (#370)
- Accept UIResourceMeta in both resources/list and resources/read (#410)
- callServerTool throws helpful error when called with a string (#449)
- Add double-connect guard to prevent protocol message handling errors (#450)

Bug fixes:
- Only ignore messages that lack jsonrpc 2.0 in message-transport (#448)
- Align basic-host dark mode styles (#438)

Spec:
- Change Host <> Sandbox communication protocol to SHOULD (#435)
- Clarify UIResourceMeta in both list and read responses (#410)

* fix(debug-server): add missing npm package config (main, bin, types, exports)

Align debug-server package.json with all other server examples:
- main: dist/server.js (was server.ts)
- types: dist/server.d.ts
- bin: mcp-server-debug -> dist/index.js
- exports with types
- files: only dist (remove source server.ts)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants