Skip to content

fix: sanitize internal error details in tool error responses#1651

Open
Bortlesboat wants to merge 2 commits intomodelcontextprotocol:mainfrom
Bortlesboat:fix/sanitize-tool-error-responses
Open

fix: sanitize internal error details in tool error responses#1651
Bortlesboat wants to merge 2 commits intomodelcontextprotocol:mainfrom
Bortlesboat:fix/sanitize-tool-error-responses

Conversation

@Bortlesboat
Copy link

Summary

Fixes #1429

Unhandled exceptions thrown from tool handlers were previously exposed to MCP clients with their full error message, potentially leaking sensitive internal details (stack traces, hostnames, connection strings, etc.).

This PR:

  • Introduces a new ToolError class that tool authors can throw when they intentionally want an error message returned to the client
  • Sanitizes all other unhandled errors to a generic "Internal error" message
  • Preserves ProtocolError messages (SDK-generated validation errors that are already safe)
  • Continues to re-throw UrlElicitationRequiredError as before

Usage

import { McpServer, ToolError } from '@modelcontextprotocol/server';

server.registerTool('my-tool', {}, async () => {
    // This message WILL be visible to the client
    throw new ToolError('Invalid input: missing required field "name"');
});

server.registerTool('my-other-tool', {}, async () => {
    // This message will NOT be visible — client sees "Internal error"
    throw new Error('Connection to internal DB failed at 10.0.0.5:5432');
});

Test plan

  • Updated existing test for generic Error to expect "Internal error" instead of the raw message
  • Added new test verifying ToolError messages are passed through to the client
  • Updated task cancellation test to expect sanitized error
  • All 384 integration tests pass (1 pre-existing Cloudflare Workers failure on Windows unrelated to this change)

Unhandled exceptions thrown from tool handlers were previously
exposed to MCP clients with their full error message, potentially
leaking sensitive internal details (stack traces, hostnames,
connection strings, etc.).

Now only intentional errors are returned to clients:
- ToolError: new exported class for user-visible error messages
- ProtocolError: SDK validation errors (already safe)
- All other errors: sanitized to generic "Internal error"

Fixes modelcontextprotocol#1429
@Bortlesboat Bortlesboat requested a review from a team as a code owner March 9, 2026 18:19
@pkg-pr-new
Copy link

pkg-pr-new bot commented Mar 9, 2026

Open in StackBlitz

@modelcontextprotocol/client

npm i https://pkg.pr.new/modelcontextprotocol/typescript-sdk/@modelcontextprotocol/client@1651

@modelcontextprotocol/server

npm i https://pkg.pr.new/modelcontextprotocol/typescript-sdk/@modelcontextprotocol/server@1651

@modelcontextprotocol/express

npm i https://pkg.pr.new/modelcontextprotocol/typescript-sdk/@modelcontextprotocol/express@1651

@modelcontextprotocol/hono

npm i https://pkg.pr.new/modelcontextprotocol/typescript-sdk/@modelcontextprotocol/hono@1651

@modelcontextprotocol/node

npm i https://pkg.pr.new/modelcontextprotocol/typescript-sdk/@modelcontextprotocol/node@1651

commit: c2a7dec

@changeset-bot
Copy link

changeset-bot bot commented Mar 9, 2026

🦋 Changeset detected

Latest commit: 25907cc

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 4 packages
Name Type
@modelcontextprotocol/server Patch
@modelcontextprotocol/express Patch
@modelcontextprotocol/hono Patch
@modelcontextprotocol/node Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

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.

Do not return and expose internal errors to the client as this is a security risk

1 participant