Skip to content

feat(v9/core): add MCP server instrumentation #17196

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 29, 2025
Merged

feat(v9/core): add MCP server instrumentation #17196

merged 1 commit into from
Jul 29, 2025

Conversation

AbhiPrasad
Copy link
Member

backport of #16817

…6817)

Closes #16826, #16654, #16666  #16978

Different approach from #16807 .

Using `Proxy` was causing issues in cloudflare #16182.

Now using `fill` we shouldn't have those problems as `fill` doesn't
create a new wrapper object with a different identity, so now:

1. `fill` just replaces the method on the existing object
2. The transport object keeps its original identity
3. When `transport.start()` runs and accesses private fields, this is
still the original transport object
4. The `WeakMap` recognizes it as the same object that owns the private
fields

- Support for new MCP SDK methods (`mcpServerInstance.tool()`,
`mcpServerInstance.resource()`, etc.)
- Tracing instrumentation
- Error handling

It follows [OTEL semantic conventions for
MCP](https://github.com/open-telemetry/semantic-conventions/blob/3097fb0af5b9492b0e3f55dc5f6c21a3dc2be8df/docs/gen-ai/mcp.md)
and adds more attributes we thought are useful.

It also handles PII based on user setting of `sendDefaultPii`.

1. **Transport receives tools/call request (`id: 2`)**
2. **Create INACTIVE `mcp.server` span**
3. **Store span in**`requestIdToSpanMap[2] = { span, method:
"tools/call", startTime }`
4. **Execute handler with span context** *(handler gets requestId: 2)*
5. **Handler finds span using** `requestId: 2`
6. **Tool execution happens within span context**
7. **Response sent with tool results**
8. `completeSpanWithToolResults(2, result)` **enriches and completes
span**

1.  **error capture** - `errorCapture.ts`
- Non-invasive error reporting that never interferes with MCP service
operation
- Error context with MCP-specific metadata
- PII filtering respects `sendDefaultPii` settings
- Resilient to Sentry failures (wrapped in try-catch)

2. **Tool execution error capturing** - `handlers.ts`
- Captures exceptions thrown during tool execution
- Preserves normal MCP behaviour (errors converted to `isError: true`)
- Includes tool name, arguments, and request context
- Handles both sync and async tool handlers

3. **Transport error instrumentation** - `transport.ts`
- Captures connection errors and network failures
- Intercepts JSON-RPC error responses
- Includes transport type and session information
- Handles error responses being sent back to clients
@AbhiPrasad AbhiPrasad self-assigned this Jul 28, 2025
@AbhiPrasad AbhiPrasad marked this pull request as ready for review July 28, 2025 19:25
@AbhiPrasad AbhiPrasad requested review from betegon, a team, Lms24 and RulaKhaled and removed request for a team July 28, 2025 19:25
@AbhiPrasad AbhiPrasad changed the title feat(v9/core): MCP server instrumentation without breaking Miniflare feat(v9/core): add MCP server instrumentation Jul 28, 2025
Copy link
Member

@betegon betegon left a comment

Choose a reason for hiding this comment

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

Looks good! first time seeing a backport but I don't see anything off

@AbhiPrasad AbhiPrasad merged commit 20cc8ac into v9 Jul 29, 2025
171 checks passed
@AbhiPrasad AbhiPrasad deleted the abhi-mcp-v9 branch July 29, 2025 12:22
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.

2 participants