-
-
Notifications
You must be signed in to change notification settings - Fork 1.8k
MCP tool spans report span.status=ok even when the tool returns a JSON-RPC error #20083
Description
Is there an existing issue for this?
- I have checked for existing issues https://github.com/getsentry/sentry-javascript/issues
- I have reviewed the documentation https://docs.sentry.io/
- I am using the latest SDK release https://github.com/getsentry/sentry-javascript/releases
How do you use Sentry?
Sentry Saas (sentry.io)
Which SDK are you using?
@sentry/core (affects all SDKs using wrapMcpServerWithSentry)
SDK Version
latest
Framework Version
@modelcontextprotocol/sdk ^1.9.0
Link to Sentry event
No response
Reproduction Example/SDK Setup
import { wrapMcpServerWithSentry } from '@sentry/core';
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
import { z } from 'zod';
const server = wrapMcpServerWithSentry(
new McpServer({ name: 'my-server', version: '1.0.0' })
);
// Tool that always fails
server.tool(
'always-error',
{ message: z.string() },
async () => {
throw new Error('something went wrong');
},
);
const transport = new StreamableHTTPServerTransport({ sessionIdGenerator: undefined });
await server.connect(transport);Steps to Reproduce
- Set up
wrapMcpServerWithSentrywith an MCP server - Register a tool that throws or otherwise causes the MCP SDK to return a JSON-RPC error response (i.e. a response with an
errorfield:{ jsonrpc: "2.0", id: 1, error: { code: -32000, message: "..." } }) - Call the tool via an MCP client
- Inspect the resulting
tools/callspan in Sentry
Expected Result
The span should have span.status = error (specifically internal_error), so that failure_rate() in the MCP insights dashboard correctly reflects that the tool failed.
Actual Result
The span always has span.status = ok, even when the tool returned an error. This causes failure_rate() to read 0% for tools that consistently fail.
Root cause: completeSpanWithResults in correlation.ts ends the span without inspecting whether the outgoing JSON-RPC response contains an error field. The error-capture path relies on getActiveSpan(), which returns null in this context (the span is stored in a correlation map and is not the active span), so the error status is never set.
Additional Context
This affects the MCP insights dashboard — tools that always return errors appear healthy because their spans all have span.status=ok.