Skip to content

Prevent MCP tool errors from exposing internals#6607

Merged
IMax153 merged 2 commits into
Effect-TS:mainfrom
ebramanti:edward/mcp-tool-error-responses
Jul 25, 2026
Merged

Prevent MCP tool errors from exposing internals#6607
IMax153 merged 2 commits into
Effect-TS:mainfrom
ebramanti:edward/mcp-tool-error-responses

Conversation

@ebramanti

@ebramanti ebramanti commented Jul 25, 2026

Copy link
Copy Markdown
Contributor

Type

  • Refactor
  • Feature
  • Bug Fix
  • Optimization
  • Documentation Update

Description

Summary

McpServer.registerToolkit previously converted every failed tool execution into an MCP CallToolResult whose text was Cause.pretty(cause). That diagnostic renderer includes stack traces, nested Cause details, Effect implementation frames, and absolute source paths, so server internals crossed the MCP protocol boundary.

This change sanitizes registered-tool failure responses while preserving the validation feedback a MCP client needs to correct invalid arguments and retry.

Why

Tool-originated errors belong in CallToolResult so an LLM can observe the failure, correct its arguments, and retry. Server diagnostic representations do not belong in that result. In particular, Cause.pretty is suitable for logs and debugging, not client-visible protocol payloads.

For an optional string field, passing null should continue to produce actionable feedback such as:

Invalid parameters for tool 'example': Expected string | undefined, got null
  at ["signature"]

It should not append an Effect error type, stack trace, nested [cause] rendering, or local source paths.

Behavior

Outcome MCP response
Successful tool call Existing successful CallToolResult
ToolParameterValidationError isError: true with reason.message
Declared handler failure represented by a schema-valid Error isError: true with Error.message
Other AiError isError: true with a generic internal-error message
Undeclared or non-public handler failure isError: true with a generic internal-error message
Defect, interruption, empty Cause, or residual Cause isError: true with a generic internal-error message
Unknown tool or malformed MCP request Existing MCP protocol error

Related

Original Effect-smol PR: Effect-TS/effect-smol#2573

Summary by CodeRabbit

  • Bug Fixes
    • Improved MCP tool error responses by suppressing stack traces, rendered causes, and internal file paths while keeping validation messages actionable.
    • Standardized handling of tool failures, including consistent responses for parameter validation errors and unexpected internal failures.
    • Ensured unknown tool names still return the expected protocol-level “InvalidParams” error.
  • Tests
    • Refreshed MCP server/toolkit tests to cover toolkit invocation, validation messaging, and failure cases more thoroughly.

@github-project-automation github-project-automation Bot moved this to Discussion Ongoing in PR Backlog Jul 25, 2026
@changeset-bot

changeset-bot Bot commented Jul 25, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: b86a941

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

This PR includes changesets to release 28 packages
Name Type
effect Patch
@effect/opentelemetry Patch
@effect/platform-browser Patch
@effect/platform-bun Patch
@effect/platform-node-shared Patch
@effect/platform-node Patch
@effect/vitest Patch
@effect/ai-anthropic Patch
@effect/ai-openai-compat Patch
@effect/ai-openai Patch
@effect/ai-openrouter Patch
@effect/atom-react Patch
@effect/atom-solid Patch
@effect/atom-vue Patch
@effect/sql-clickhouse Patch
@effect/sql-d1 Patch
@effect/sql-libsql Patch
@effect/sql-mssql Patch
@effect/sql-mysql2 Patch
@effect/sql-pg Patch
@effect/sql-pglite Patch
@effect/sql-sqlite-bun Patch
@effect/sql-sqlite-do Patch
@effect/sql-sqlite-node Patch
@effect/sql-sqlite-react-native Patch
@effect/sql-sqlite-wasm Patch
@effect/docgen Patch
@effect/openapi-generator 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

@github-actions github-actions Bot added the 4.0 label Jul 25, 2026
@coderabbitai

coderabbitai Bot commented Jul 25, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 3d3a37ba-11f7-481d-9324-cb09a5be4307

📥 Commits

Reviewing files that changed from the base of the PR and between 690a13a and b86a941.

📒 Files selected for processing (2)
  • packages/effect/src/unstable/ai/McpServer.ts
  • packages/effect/test/unstable/ai/McpServer.test.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/effect/test/unstable/ai/McpServer.test.ts

📝 Walkthrough

Walkthrough

MCP toolkit invocation now converts validation, declared, AI, and defect failures into controlled tool error responses. Tests add reusable client and toolkit fixtures covering these outcomes, optional parameters, unknown tools, and suppression of internal error details. A patch changeset documents the behavior.

Changes

MCP tool error handling

Layer / File(s) Summary
Controlled toolkit error responses
packages/effect/src/unstable/ai/McpServer.ts, .changeset/quiet-tools-smile.md
registerToolkit maps validation and declared failures to actionable messages and maps other AI errors, defects, and causes to a generic internal-tool error response without rendered causes or stack traces.
Toolkit protocol test coverage
packages/effect/test/unstable/ai/McpServer.test.ts
Reusable clients and typed toolkit fixtures test invalid parameters, omitted optional inputs, declared failures, AI errors, defects, and unknown-tool protocol errors.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant MCPClient
  participant MCPServer
  participant ToolHandler
  MCPClient->>MCPServer: Call toolkit tool
  MCPServer->>ToolHandler: Execute with decoded arguments
  ToolHandler-->>MCPServer: Success or classified failure
  MCPServer-->>MCPClient: CallToolResult with structured or controlled error text
Loading

Suggested labels: bug

Suggested reviewers: gcanti, tim-smart

🚥 Pre-merge checks | ✅ 2
✅ Passed checks (2 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot added the bug Something isn't working label Jul 25, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/effect/src/unstable/ai/McpServer.ts`:
- Around line 748-756: Move Effect.tapCause(Effect.log) ahead of
Effect.catchCause in the tool execution effect chain, while keeping the existing
catch handlers and toolErrorResult behavior unchanged. This ensures all causes,
including defects and interruptions, are logged before catchCause converts
failures into successes.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 432aa03f-f74c-4fa9-b5b4-d66750a46785

📥 Commits

Reviewing files that changed from the base of the PR and between 71b3e9a and 690a13a.

📒 Files selected for processing (3)
  • .changeset/quiet-tools-smile.md
  • packages/effect/src/unstable/ai/McpServer.ts
  • packages/effect/test/unstable/ai/McpServer.test.ts

Comment thread packages/effect/src/unstable/ai/McpServer.ts Outdated
@github-project-automation github-project-automation Bot moved this from Discussion Ongoing to Waiting on Author in PR Backlog Jul 25, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Bundle Size Analysis

File Name Current Size Previous Size Difference
basic.ts 6.64 KB 6.64 KB 0.00 KB (0.00%)
batching.ts 9.42 KB 9.42 KB 0.00 KB (0.00%)
brand.ts 6.20 KB 6.20 KB 0.00 KB (0.00%)
cache.ts 10.13 KB 10.13 KB 0.00 KB (0.00%)
config.ts 19.08 KB 19.08 KB 0.00 KB (0.00%)
differ.ts 18.41 KB 18.41 KB 0.00 KB (0.00%)
http-client.ts 20.73 KB 20.73 KB 0.00 KB (0.00%)
logger.ts 10.30 KB 10.30 KB 0.00 KB (0.00%)
metric.ts 8.56 KB 8.56 KB 0.00 KB (0.00%)
optic.ts 7.41 KB 7.41 KB 0.00 KB (0.00%)
pubsub.ts 14.17 KB 14.17 KB 0.00 KB (0.00%)
queue.ts 11.10 KB 11.10 KB 0.00 KB (0.00%)
schedule.ts 10.28 KB 10.28 KB 0.00 KB (0.00%)
schema-class.ts 18.16 KB 18.16 KB 0.00 KB (0.00%)
schema-fromJsonSchemaDocument.ts 27.31 KB 27.31 KB 0.00 KB (0.00%)
schema-representation-roundtrip.ts 24.16 KB 24.16 KB 0.00 KB (0.00%)
schema-string-transformation.ts 12.68 KB 12.68 KB 0.00 KB (0.00%)
schema-string.ts 10.36 KB 10.36 KB 0.00 KB (0.00%)
schema-template-literal.ts 14.38 KB 14.38 KB 0.00 KB (0.00%)
schema-toArbitraryLazy.ts 20.94 KB 20.94 KB 0.00 KB (0.00%)
schema-toCodeDocument.ts 23.42 KB 23.42 KB 0.00 KB (0.00%)
schema-toCodecJson.ts 18.30 KB 18.30 KB 0.00 KB (0.00%)
schema-toEquivalence.ts 18.01 KB 18.01 KB 0.00 KB (0.00%)
schema-toFormatter.ts 17.86 KB 17.86 KB 0.00 KB (0.00%)
schema-toJsonSchemaDocument.ts 21.49 KB 21.49 KB 0.00 KB (0.00%)
schema-toRepresentation.ts 18.55 KB 18.55 KB 0.00 KB (0.00%)
schema.ts 17.43 KB 17.43 KB 0.00 KB (0.00%)
stm.ts 12.07 KB 12.07 KB 0.00 KB (0.00%)
stream.ts 9.36 KB 9.36 KB 0.00 KB (0.00%)

@IMax153
IMax153 merged commit c323d8b into Effect-TS:main Jul 25, 2026
25 of 29 checks passed
@github-project-automation github-project-automation Bot moved this from Waiting on Author to Done in PR Backlog Jul 25, 2026
@ebramanti
ebramanti deleted the edward/mcp-tool-error-responses branch July 25, 2026 19:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

4.0 bug Something isn't working

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

2 participants