Skip to content

fix(pdf-server): resolve host-qualified tool names for the viewer's own tool calls - #809

Open
jcollas wants to merge 1 commit into
modelcontextprotocol:mainfrom
jcollas:fix/pdf-server-prefixed-tool-names
Open

jcollas wants to merge 1 commit into
modelcontextprotocol:mainfrom
jcollas:fix/pdf-server-prefixed-tool-names

Conversation

@jcollas

@jcollas jcollas commented Oct 15, 2026

Copy link
Copy Markdown

What

examples/pdf-server's viewer calls its own tools by bare name (read_pdf_bytes, save_pdf, poll_pdf_commands, submit_viewer_state, submit_page_data, submit_save_data). That works when the host connects to the server directly, but fails under a host that qualifies tool names to avoid collisions across aggregated servers (for example an aggregator that prefixes <server>- in a group of two or more servers). The widget still renders, because the host launched it with the qualified pdf-server-display_pdf, but its own follow-up calls go out as read_pdf_bytes and fail to resolve, so the viewer cannot load the file.

This applies the pattern proposed in #753 (and used in #807 for quickstart) to pdf-server, which has nine such call sites. #807 leaves the other examples for follow-ups, so this is the pdf-server one.

Changes

  • examples/pdf-server/src/tool-names.ts (new): resolveToolName(baseName, invokedName) recovers the prefix the host put on display_pdf and applies it to the other tool names. With no host context, or a host that does not rewrite names, it returns the bare name, so behaviour is unchanged there.
  • examples/pdf-server/src/mcp-app.ts: the nine callServerTool sites use it, via app.getHostContext()?.toolInfo?.tool?.name.
  • examples/pdf-server/src/tool-names.test.ts (new): prefix applied, bare name kept for a host that does not rewrite, no host context, and an invoked tool that is not the entry tool.

Testing

  • bun test: the 4 new tests pass (7 expectations), run in an oven/bun container.
  • prettier -u --check on the three changed files (prettier 3.6.2, the repo's version): passes.
  • npm run build in examples/pdf-server (tsc --noEmit, the vite build, and the server bundles): succeeds on this branch.
  • In use: a build of this change runs behind MCPHub 1.1.3 on /mcp/$smart/claude, a group with more than one server, so the entry tool is pdf-server-display_pdf. The MCPHub log shows the viewer's calls going out as pdf-server-read_pdf_bytes, 11 chunked reads of a 561 KB PDF with no errors, and the viewer renders in claude.ai. I have not run this against another host.
  • I did not run the full npm test (bun test src examples) or the e2e tests for the rest of the repo.

This is also the information requested in the comment on #753: MCPHub 1.1.3, host claude.ai (also tried through Open WebUI's MCP apps bridge), route /mcp/$smart/claude, qualified name pdf-server-display_pdf, and the failing calls were the bare read_pdf_bytes and friends before this change.

Refs #753

🤖 Generated with Claude Code

https://claude.ai/code/session_01Bsgz9fZYV5cHdjRq6PzmmF

… own tool calls

The viewer called its own tools (read_pdf_bytes, save_pdf, poll_pdf_commands and
the submit_* helpers) by bare name. When a host qualifies tool names, for
example an aggregator that prefixes "<server>-" in a group of two or more
servers, those calls fail with "tool not found" and the viewer cannot load the
file.

resolveToolName() recovers the prefix from the name display_pdf was invoked
under (getHostContext().toolInfo.tool.name) and applies it to the other tool
names. With no host context, or a host that does not rewrite names, the bare
name is used, so behaviour is unchanged there.

Refs modelcontextprotocol#753

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Bsgz9fZYV5cHdjRq6PzmmF

This branch has not been deployed

No deployments
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.

1 participant