From dd30b198bf4b629387705f147d2fdee94c8ff7b3 Mon Sep 17 00:00:00 2001 From: betegon Date: Fri, 14 Aug 2026 15:53:27 +0200 Subject: [PATCH 1/3] docs(cloudflare): recommend span streaming for MCP Cloudflare MCP work can outlive the HTTP response. Document stream mode as the supported way to retain those spans, while keeping forceTransaction as the static-lifecycle fallback. Co-Authored-By: OpenAI Codex --- .../tracing/instrumentation/mcp-module.mdx | 31 ++++++++++++++++ .../javascript/guides/cloudflare/index.mdx | 35 +++++++++++-------- docs/product/mcp-servers/getting-started.mdx | 6 ++++ 3 files changed, 57 insertions(+), 15 deletions(-) diff --git a/docs/platforms/javascript/common/tracing/instrumentation/mcp-module.mdx b/docs/platforms/javascript/common/tracing/instrumentation/mcp-module.mdx index 6eaaeeb6441c9..6d5320153e1f8 100644 --- a/docs/platforms/javascript/common/tracing/instrumentation/mcp-module.mdx +++ b/docs/platforms/javascript/common/tracing/instrumentation/mcp-module.mdx @@ -36,6 +36,37 @@ The JavaScript SDK supports automatic instrumentation for MCP servers. We recomm - [MCP (Model Context Protocol)](/product/mcp-servers/getting-started/) + + +### Preserve MCP Spans After the Response + +Cloudflare MCP work can finish after the Worker returns an HTTP response, including work kept alive with `waitUntil()`. With the static trace lifecycle, Sentry snapshots the request transaction when the response is returned, so MCP spans that finish later may be missing. + +Set `traceLifecycle: "stream"` so the SDK can send each sampled span when it finishes. Span streaming on Cloudflare requires `@sentry/cloudflare` version `10.49.0` or newer. + +```javascript {filename:index.js} +import * as Sentry from "@sentry/cloudflare"; + +const worker = { + async fetch(request, env, ctx) { + return handleMcpRequest(request, env, ctx); + }, +}; + +export default Sentry.withSentry( + (env) => ({ + dsn: env.SENTRY_DSN, + tracesSampleRate: 1.0, + traceLifecycle: "stream", + }), + worker +); +``` + +Stream mode sends span records instead of assembling one transaction event with embedded spans. Use `beforeSendSpan` and `ignoreSpans` to filter streamed spans instead of `beforeSendTransaction` and `ignoreTransactions`. See Streamed Spans for details. + + + ## Manual Instrumentation For your MCP data to show up in Sentry, spans must be created with well-defined names and data attributes. See below for the different types of MCP operations you can instrument. diff --git a/docs/platforms/javascript/guides/cloudflare/index.mdx b/docs/platforms/javascript/guides/cloudflare/index.mdx index 274a5dea6a27d..69c7ec62aff84 100644 --- a/docs/platforms/javascript/guides/cloudflare/index.mdx +++ b/docs/platforms/javascript/guides/cloudflare/index.mdx @@ -379,17 +379,19 @@ Server-side spans will display `0ms` for their durations. In the Cloudflare Work This is expected behavior in the Cloudflare Workers environment and affects all frameworks deployed to Cloudflare Workers, including Next.js, Astro, Remix, and others. -### Missing Spans in `waitUntil()` +### Spans in `waitUntil()` -If you're using Cloudflare's [`waitUntil()`](https://developers.cloudflare.com/workers/runtime-apis/handlers/fetch/#contextwaituntil) to run background tasks, spans created inside `waitUntil()` may not appear in Sentry because the request's root span has already finished before the background work starts. +Cloudflare's [`waitUntil()`](https://developers.cloudflare.com/workers/runtime-apis/handlers/fetch/#contextwaituntil) lets work continue after the Worker returns a response. With the static trace lifecycle, Sentry snapshots the request transaction when the response is returned, so spans that finish later may be missing. -To capture spans inside `waitUntil()`, wrap your deferred work with `startSpan` and set `forceTransaction: true`. This creates a separate transaction for the background work. +Set `traceLifecycle: "stream"` so the SDK can send each sampled span when it finishes. Span streaming on Cloudflare requires `@sentry/cloudflare` version `10.49.0` or newer. -The `forceTransaction: true` option is required because it creates a separate transaction for the `waitUntil()` work. Without it, spans created after the request ends might get lost. +Stream mode sends span records instead of assembling one transaction event with embedded spans. See Streamed Spans for filtering and migration details. + +If you need to keep the static lifecycle, use `forceTransaction: true` on the background operation instead. This records the work as a separate transaction. `forceTransaction` isn't available in stream mode. @@ -397,26 +399,29 @@ The `forceTransaction: true` option is required because it creates a separate tr ```javascript {filename:index.js} import * as Sentry from "@sentry/cloudflare"; -export default { +const worker = { async fetch(request, env, ctx) { - // Main request handling - const response = processRequest(request); - - // Background work with proper tracing ctx.waitUntil( - Sentry.startSpan( - { name: "background.task", op: "task", forceTransaction: true }, - () => updateCacheAndDatabase() + Sentry.startSpan({ name: "background.task", op: "task" }, () => + updateCacheAndDatabase() ) ); - return response; + return processRequest(request); }, }; +export default Sentry.withSentry( + (env) => ({ + dsn: env.SENTRY_DSN, + tracesSampleRate: 1.0, + traceLifecycle: "stream", + }), + worker +); + async function updateCacheAndDatabase() { - // Database operations - // Any spans created here will be captured + // Deferred work and any child spans are captured when they finish. } ``` diff --git a/docs/product/mcp-servers/getting-started.mdx b/docs/product/mcp-servers/getting-started.mdx index 80d512a1ddda2..2b93a3032bf70 100644 --- a/docs/product/mcp-servers/getting-started.mdx +++ b/docs/product/mcp-servers/getting-started.mdx @@ -73,6 +73,12 @@ Records outputs from MCP tool and prompt calls (such as tool results and prompt Defaults to `true` if `sendDefaultPii` is `true`. +#### Cloudflare Workers + +MCP work on Cloudflare can finish after the Worker returns an HTTP response. Configure `traceLifecycle: "stream"` so spans are sent when they finish instead of depending on a static request snapshot. This requires `@sentry/cloudflare` version `10.49.0` or newer. + +See [Instrument MCP Servers on Cloudflare](/platforms/javascript/guides/cloudflare/tracing/instrumentation/mcp-module/) for the configuration and filtering differences in stream mode. + ### Python - MCP Server Date: Fri, 14 Aug 2026 16:32:05 +0200 Subject: [PATCH 2/3] docs(js): surface MCP Monitoring as a platform feature Place MCP Monitoring alongside Agent Tracing across supported JavaScript guides and document the explicit server wrapper required for instrumentation. Keep Cloudflare span streaming as a separate delivery setting. Co-Authored-By: OpenAI Codex --- .../javascript/common/agent-tracing/index.mdx | 2 +- .../index.mdx} | 85 ++++++++++++------- docs/product/mcp-servers/getting-started.mdx | 28 +++--- middleware.ts | 4 + .../setup/javascript.azure-functions.mdx | 15 ++++ .../mcp-monitoring/setup/javascript.hono.mdx | 32 +++++++ .../mcp-monitoring/setup/javascript.mdx | 15 ++++ 7 files changed, 135 insertions(+), 46 deletions(-) rename docs/platforms/javascript/common/{tracing/instrumentation/mcp-module.mdx => mcp-monitoring/index.mdx} (62%) create mode 100644 platform-includes/mcp-monitoring/setup/javascript.azure-functions.mdx create mode 100644 platform-includes/mcp-monitoring/setup/javascript.hono.mdx create mode 100644 platform-includes/mcp-monitoring/setup/javascript.mdx diff --git a/docs/platforms/javascript/common/agent-tracing/index.mdx b/docs/platforms/javascript/common/agent-tracing/index.mdx index 332ad5ffabd3c..65a0ddd6e379d 100644 --- a/docs/platforms/javascript/common/agent-tracing/index.mdx +++ b/docs/platforms/javascript/common/agent-tracing/index.mdx @@ -219,4 +219,4 @@ If you're using an AI framework with a Sentry exporter, you can send traces to S ## MCP Server Monitoring -If you're building MCP (Model Context Protocol) servers, Sentry can also track tool executions, prompt retrievals, and resource access. See Instrument MCP Servers for setup instructions. +If you're building MCP (Model Context Protocol) servers, Sentry can also track tool executions, prompt retrievals, and resource access. See MCP Monitoring for setup instructions. diff --git a/docs/platforms/javascript/common/tracing/instrumentation/mcp-module.mdx b/docs/platforms/javascript/common/mcp-monitoring/index.mdx similarity index 62% rename from docs/platforms/javascript/common/tracing/instrumentation/mcp-module.mdx rename to docs/platforms/javascript/common/mcp-monitoring/index.mdx index 6d5320153e1f8..fd16eea073c40 100644 --- a/docs/platforms/javascript/common/tracing/instrumentation/mcp-module.mdx +++ b/docs/platforms/javascript/common/mcp-monitoring/index.mdx @@ -1,7 +1,9 @@ --- -title: Instrument MCP Servers -sidebar_order: 600 -description: "Learn how to manually instrument your code to use Sentry's MCP monitoring." +title: Set Up MCP Monitoring +sidebar_title: MCP Monitoring +sidebar_order: 8 +sidebar_section: features +description: "Monitor MCP server tool executions, prompt retrievals, resource access, and errors." supported: - javascript.node - javascript.aws-lambda @@ -26,23 +28,38 @@ supported: - javascript.tanstackstart-react --- -With Sentry's [MCP monitoring](/product/mcp-servers/), you can track and debug MCP servers with full-stack context. You'll be able to monitor tool executions, prompt retrievals, resource access, and error rates. MCP monitoring data will be fully connected to your other Sentry data like logs, errors, and traces. +With Sentry's [MCP Monitoring](/product/mcp-servers/), you can track and debug MCP servers with full-stack context. You can monitor tool executions, prompt retrievals, resource access, and error rates alongside your other Sentry data, including logs, errors, and traces. -As a prerequisite to setting up MCP monitoring with JavaScript, you'll need to first set up tracing. Once this is done, the JavaScript SDK will automatically instrument MCP servers created with supported libraries. If that doesn't fit your use case, you can use custom instrumentation described below. +Before you begin, set up tracing. -## Automatic Instrumentation +## Instrument the MCP Server -The JavaScript SDK supports automatic instrumentation for MCP servers. We recommend adding the MCP integration to your Sentry configuration to automatically capture spans for MCP operations. +Wrap each `McpServer` instance with `wrapMcpServerWithSentry` to automatically record MCP requests, tool calls, prompt retrievals, resource reads, and handler errors. -- [MCP (Model Context Protocol)](/product/mcp-servers/getting-started/) + + +Support for `@modelcontextprotocol/server` 2.x requires Sentry JavaScript SDK version `10.70.0` or newer. For `@modelcontextprotocol/sdk` 1.x, use Sentry JavaScript SDK version `9.46.0` or newer and import `McpServer` from `@modelcontextprotocol/sdk/server/mcp.js`. The Sentry wrapper is otherwise the same. + +### Configure Input and Output Recording + +MCP inputs and outputs may contain sensitive data. Use `recordInputs` and `recordOutputs` to control collection for a specific server: + +```javascript +const server = Sentry.wrapMcpServerWithSentry(mcpServer, { + recordInputs: false, + recordOutputs: false, +}); +``` + +These options override the corresponding `dataCollection.genAI.inputs` and `dataCollection.genAI.outputs` settings and require Sentry JavaScript SDK version `10.33.0` or newer. -### Preserve MCP Spans After the Response +## Preserve MCP Spans After the Response Cloudflare MCP work can finish after the Worker returns an HTTP response, including work kept alive with `waitUntil()`. With the static trace lifecycle, Sentry snapshots the request transaction when the response is returned, so MCP spans that finish later may be missing. -Set `traceLifecycle: "stream"` so the SDK can send each sampled span when it finishes. Span streaming on Cloudflare requires `@sentry/cloudflare` version `10.49.0` or newer. +Set `traceLifecycle: "stream"` so the SDK can send each sampled span when it finishes. This changes how spans are delivered; you still need to wrap the MCP server as shown above. Span streaming on Cloudflare requires `@sentry/cloudflare` version `10.49.0` or newer. ```javascript {filename:index.js} import * as Sentry from "@sentry/cloudflare"; @@ -63,13 +80,37 @@ export default Sentry.withSentry( ); ``` -Stream mode sends span records instead of assembling one transaction event with embedded spans. Use `beforeSendSpan` and `ignoreSpans` to filter streamed spans instead of `beforeSendTransaction` and `ignoreTransactions`. See Streamed Spans for details. +Stream mode sends span records instead of assembling one transaction event with embedded spans. `beforeSendTransaction` and `ignoreTransactions` don't apply to streamed spans. See Streamed Spans for the `beforeSendSpan` and `ignoreSpans` configuration. + +If you use `McpAgent`, wrap the `McpServer` returned by its `server` getter, and wrap the Agent class separately with `instrumentAgentWithSentry` to preserve request and RPC context. Agent instrumentation, MCP server wrapping, and span streaming solve different parts of the setup; none replaces the others. See Agents SDK. -## Manual Instrumentation + + +## Hono on Cloudflare Workers -For your MCP data to show up in Sentry, spans must be created with well-defined names and data attributes. See below for the different types of MCP operations you can instrument. +If your Hono app runs on Cloudflare Workers, MCP work can finish after the Worker returns its response. Set `traceLifecycle: "stream"` in the Hono Sentry middleware so each sampled span is sent when it finishes: + +```javascript {filename:index.js} +import { sentry } from "@sentry/hono/cloudflare"; + +app.use( + sentry(app, { + dsn: "___PUBLIC_DSN___", + tracesSampleRate: 1.0, + traceLifecycle: "stream", + }) +); +``` + +This changes how spans are delivered; it doesn't replace `wrapMcpServerWithSentry`. Stream mode requires `@sentry/hono` and `@sentry/cloudflare` version `10.49.0` or newer. See Streamed Spans for configuration and filtering differences. + + + +## Custom Instrumentation + +If you're not using a supported MCP SDK, create spans with the names and data attributes described below. The [Sentry.startSpan()](/platforms/javascript/tracing/instrumentation/custom-instrumentation/#starting-a-span) method can be used to create these spans. @@ -82,12 +123,6 @@ The [Sentry.startSpan()](/platforms/javascript/tracing/instrumentation/custom-in #### Example Tool Execution Span: ```javascript -import * as Sentry from "@sentry/node"; - -Sentry.init({ - // ... your Sentry configuration -}); - // Example tool execution const toolName = "get_weather"; const toolArguments = { city: "San Francisco" }; @@ -146,12 +181,6 @@ await Sentry.startSpan( #### Example Prompt Retrieval Span: ```javascript -import * as Sentry from "@sentry/node"; - -Sentry.init({ - // ... your Sentry configuration -}); - // Example prompt retrieval const promptName = "code_review"; const promptArguments = { language: "python" }; @@ -204,12 +233,6 @@ await Sentry.startSpan( #### Example Resource Read Span: ```javascript -import * as Sentry from "@sentry/node"; - -Sentry.init({ - // ... your Sentry configuration -}); - // Example resource access const resourceUri = "file:///path/to/resource.txt"; diff --git a/docs/product/mcp-servers/getting-started.mdx b/docs/product/mcp-servers/getting-started.mdx index 2b93a3032bf70..d4ab1888f977a 100644 --- a/docs/product/mcp-servers/getting-started.mdx +++ b/docs/product/mcp-servers/getting-started.mdx @@ -12,7 +12,7 @@ keywords: - Node.js MCP --- -Sentry MCP Observability helps you track and debug Model Context Protocol (MCP) implementations using our supported SDKs and integrations. Monitor your complete MCP workflows from client connections to server responses, including tool executions, resource access, and protocol communications. +Sentry MCP Monitoring helps you track and debug Model Context Protocol (MCP) implementations using our supported SDKs and integrations. Monitor your complete MCP workflows from client connections to server responses, including tool executions, resource access, and protocol communications. To start sending MCP data to Sentry, make sure you've created a Sentry project for your MCP-enabled repository and follow the guide below: @@ -21,18 +21,18 @@ To start sending MCP data to Sentry, make sure you've created a Sentry project f ### JavaScript - MCP Server -The Sentry JavaScript SDK supports MCP observability by wrapping the MCP Server from the [@modelcontextprotocol/sdk](https://www.npmjs.com/package/@modelcontextprotocol/sdk) package. This wrapper automatically captures spans for your MCP server workflows including tool executions, resource access, and client connections. +The example below uses [`@modelcontextprotocol/sdk`](https://www.npmjs.com/package/@modelcontextprotocol/sdk) 1.x. The Sentry wrapper automatically captures spans for MCP server workflows, including tool executions, resource access, and client connections. #### Quick Start with MCP Server ```javascript import * as Sentry from "@sentry/node"; -import { McpServer } from "@modelcontextprotocol/sdk"; +import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; // Sentry init needs to be above everything else Sentry.init({ @@ -40,30 +40,30 @@ Sentry.init({ tracesSampleRate: 1.0, }); -// Your MCP server with optional input/output recording +// Wrap every MCP server instance const server = Sentry.wrapMcpServerWithSentry( new McpServer({ name: "my-mcp-server", version: "1.0.0", }), - { - recordInputs: true, - recordOutputs: true, - } ); ... ``` +Stable `@modelcontextprotocol/server` 2.x support requires Sentry JavaScript SDK version `10.70.0` or newer. For framework-specific setup, see MCP Monitoring for [Node.js](/platforms/javascript/guides/node/mcp-monitoring/), [Hono](/platforms/javascript/guides/hono/mcp-monitoring/), or [Cloudflare](/platforms/javascript/guides/cloudflare/mcp-monitoring/). + #### Options +The `recordInputs` and `recordOutputs` options require Sentry JavaScript SDK version `10.33.0` or newer. + ##### `recordInputs` _Type: `boolean`_ Records inputs to MCP tool and prompt calls (such as tool arguments and prompt parameters). -Defaults to `true` if `sendDefaultPii` is `true`. +Defaults to `dataCollection.genAI.inputs`. In Sentry JavaScript SDK 10.x, when `dataCollection` isn't configured, this follows `sendDefaultPii`. ##### `recordOutputs` @@ -71,23 +71,23 @@ _Type: `boolean`_ Records outputs from MCP tool and prompt calls (such as tool results and prompt messages). -Defaults to `true` if `sendDefaultPii` is `true`. +Defaults to `dataCollection.genAI.outputs`. In Sentry JavaScript SDK 10.x, when `dataCollection` isn't configured, this follows `sendDefaultPii`. #### Cloudflare Workers MCP work on Cloudflare can finish after the Worker returns an HTTP response. Configure `traceLifecycle: "stream"` so spans are sent when they finish instead of depending on a static request snapshot. This requires `@sentry/cloudflare` version `10.49.0` or newer. -See [Instrument MCP Servers on Cloudflare](/platforms/javascript/guides/cloudflare/tracing/instrumentation/mcp-module/) for the configuration and filtering differences in stream mode. +See [MCP Monitoring on Cloudflare](/platforms/javascript/guides/cloudflare/mcp-monitoring/) for the configuration and filtering differences in stream mode. ### Python - MCP Server -The Sentry Python SDK supports MCP observability for the [MCP Python SDK](https://github.com/modelcontextprotocol/python-sdk) (both low-level and FastMCP APIs) and [standalone FastMCP](https://gofastmcp.com/getting-started/welcome). The integration automatically captures spans for your MCP server workflows including tool executions, resource access, and prompt handling. +The Sentry Python SDK supports MCP Monitoring for the [MCP Python SDK](https://github.com/modelcontextprotocol/python-sdk) (both low-level and FastMCP APIs) and [standalone FastMCP](https://gofastmcp.com/getting-started/welcome). The integration automatically captures spans for your MCP server workflows, including tool executions, resource access, and prompt handling. #### Quick Start diff --git a/middleware.ts b/middleware.ts index 222e1a94ef5ac..59b1b8cec656b 100644 --- a/middleware.ts +++ b/middleware.ts @@ -1996,6 +1996,10 @@ const USER_DOCS_REDIRECTS: Redirect[] = [ from: '/platforms/javascript/guides/:guide/tracing/instrumentation/opentelemetry/', to: '/platforms/javascript/guides/:guide/opentelemetry/', }, + { + from: '/platforms/javascript/guides/:guide/tracing/instrumentation/mcp-module/', + to: '/platforms/javascript/guides/:guide/mcp-monitoring/', + }, { from: '/learn/cli/configuration/', to: '/cli/configuration/', diff --git a/platform-includes/mcp-monitoring/setup/javascript.azure-functions.mdx b/platform-includes/mcp-monitoring/setup/javascript.azure-functions.mdx new file mode 100644 index 0000000000000..f9eb702cf5fb2 --- /dev/null +++ b/platform-includes/mcp-monitoring/setup/javascript.azure-functions.mdx @@ -0,0 +1,15 @@ +Import Sentry from `@sentry/node`, then wrap the MCP server instance before connecting it to a transport: + +```javascript {filename:mcp-server.js} +import * as Sentry from "@sentry/node"; +import { McpServer } from "@modelcontextprotocol/server"; + +const server = Sentry.wrapMcpServerWithSentry( + new McpServer({ + name: "my-mcp-server", + version: "1.0.0", + }) +); +``` + +Register tools, prompts, and resources on `server` as usual. The wrapper returns the same server instance. diff --git a/platform-includes/mcp-monitoring/setup/javascript.hono.mdx b/platform-includes/mcp-monitoring/setup/javascript.hono.mdx new file mode 100644 index 0000000000000..a97dba4575c70 --- /dev/null +++ b/platform-includes/mcp-monitoring/setup/javascript.hono.mdx @@ -0,0 +1,32 @@ +Hono uses a runtime-specific Sentry entrypoint. Import Sentry from the entrypoint that matches your deployment: + +```javascript {tabTitle:Cloudflare Workers} {filename:mcp-server.js} +import * as Sentry from "@sentry/hono/cloudflare"; +``` + +```javascript {tabTitle:Node.js} {filename:mcp-server.js} +import * as Sentry from "@sentry/hono/node"; +``` + +```javascript {tabTitle:Bun} {filename:mcp-server.js} +import * as Sentry from "@sentry/hono/bun"; +``` + +```javascript {tabTitle:Deno} {filename:mcp-server.js} +import * as Sentry from "@sentry/hono/deno"; +``` + +Then wrap the MCP server instance before connecting it to a transport: + +```javascript {filename:mcp-server.js} +import { McpServer } from "@modelcontextprotocol/server"; + +const server = Sentry.wrapMcpServerWithSentry( + new McpServer({ + name: "my-mcp-server", + version: "1.0.0", + }) +); +``` + +Register tools, prompts, and resources on `server` as usual. The wrapper returns the same server instance. diff --git a/platform-includes/mcp-monitoring/setup/javascript.mdx b/platform-includes/mcp-monitoring/setup/javascript.mdx new file mode 100644 index 0000000000000..41b8f6a5b2792 --- /dev/null +++ b/platform-includes/mcp-monitoring/setup/javascript.mdx @@ -0,0 +1,15 @@ +Import Sentry from your framework's SDK package, then wrap the MCP server instance before connecting it to a transport: + +```javascript {filename:mcp-server.js} +import * as Sentry from "___SDK_PACKAGE___"; +import { McpServer } from "@modelcontextprotocol/server"; + +const server = Sentry.wrapMcpServerWithSentry( + new McpServer({ + name: "my-mcp-server", + version: "1.0.0", + }) +); +``` + +Register tools, prompts, and resources on `server` as usual. The wrapper returns the same server instance. From a439901479346c6121efb82280c1d73a62263bf6 Mon Sep 17 00:00:00 2001 From: betegon Date: Wed, 19 Aug 2026 12:57:38 +0200 Subject: [PATCH 3/3] docs(js): clarify MCP manual instrumentation section Rename "Custom Instrumentation" to "Manual Instrumentation" (matching the Python page) and drop the "unsupported MCP SDK" wording that read as confusing on supported platforms. Co-Authored-By: Claude Opus 4.8 --- docs/platforms/javascript/common/mcp-monitoring/index.mdx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/platforms/javascript/common/mcp-monitoring/index.mdx b/docs/platforms/javascript/common/mcp-monitoring/index.mdx index fd16eea073c40..dfbec2cbf925a 100644 --- a/docs/platforms/javascript/common/mcp-monitoring/index.mdx +++ b/docs/platforms/javascript/common/mcp-monitoring/index.mdx @@ -108,11 +108,11 @@ This changes how spans are delivered; it doesn't replace `wrapMcpServerWithSentr -## Custom Instrumentation +## Manual Instrumentation -If you're not using a supported MCP SDK, create spans with the names and data attributes described below. +The setup above automatically instruments MCP servers built with the official [MCP SDK](https://github.com/modelcontextprotocol/typescript-sdk) (`@modelcontextprotocol/sdk`). If your server uses a different library or a custom implementation that `wrapMcpServerWithSentry` can't wrap, you can record the same spans manually. -The [Sentry.startSpan()](/platforms/javascript/tracing/instrumentation/custom-instrumentation/#starting-a-span) method can be used to create these spans. +You don't need this if you're already using `wrapMcpServerWithSentry` — it creates these spans for you. Otherwise, use [Sentry.startSpan()](/platforms/javascript/tracing/instrumentation/custom-instrumentation/#starting-a-span) to create the spans described below. ## Spans