Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,7 @@ Sentry.init({

The content of generative AI inputs (system instructions, prompt messages, tool definitions, and tool call arguments) and outputs (such as completion text and tool call results) might carry personal data. By default, the SDK records both inputs and outputs. Metadata like model ID and token counts is always collected.

The same setting applies to MCP servers instrumented with `wrapMcpServerWithSentry`. By default, the SDK records the inputs and outputs of tool calls, prompt retrievals, and resource reads. Use the wrapper's `recordInputs` and `recordOutputs` options to control recording per server.
The same setting applies to instrumented MCP servers. By default, the SDK records the inputs and outputs of tool calls, prompt retrievals, and resource reads. Use the `recordInputs` and `recordOutputs` options of `wrapMcpServerWithSentry` to control recording per server.

Use the `dataCollection.genAI` option to control this. For example, opt out of recording AI message content while keeping the metadata:

Expand Down
14 changes: 7 additions & 7 deletions docs/platforms/javascript/common/mcp-monitoring/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ Before you begin, <PlatformLink to="/tracing/">set up tracing</PlatformLink>.

## Instrument the MCP Server

Wrap each `McpServer` instance with `wrapMcpServerWithSentry` to automatically record MCP requests, tool calls, prompt retrievals, resource reads, and handler errors.
Starting with Sentry JavaScript SDK version `11.1.0`, the SDK instruments every `McpServer` instance automatically when tracing is enabled. It records MCP requests, tool calls, prompt retrievals, resource reads, and handler errors. Automatic instrumentation supports `@modelcontextprotocol/server` `>=2.0.0 <3` and `@modelcontextprotocol/sdk` `>=1.9.0 <2`.

<PlatformContent includePath="mcp-monitoring/setup" />

Expand All @@ -35,7 +35,7 @@ Sentry.init({
});
```

Use `recordInputs` and `recordOutputs` to control recording for a specific server. These options override the `dataCollection.genAI` settings:
To control recording for a specific server, pass it to `wrapMcpServerWithSentry` with the `recordInputs` and `recordOutputs` options. These options override the `dataCollection.genAI` settings, and they also apply to a server the SDK has already instrumented automatically:

```javascript
const server = Sentry.wrapMcpServerWithSentry(mcpServer, {
Expand All @@ -50,13 +50,13 @@ The `recordInputs` and `recordOutputs` options require Sentry JavaScript SDK ver

## Preserve MCP Spans After the Response

Cloudflare MCP work can finish after the Worker returns an HTTP response, including work kept alive with `waitUntil()`. The SDK streams spans by default, sending each sampled span as it finishes, so this work is captured without extra configuration. You still need to wrap the MCP server as shown above.
Cloudflare MCP work can finish after the Worker returns an HTTP response, including work kept alive with `waitUntil()`. The SDK streams spans by default, sending each sampled span as it finishes, so this work is captured without extra configuration. You still need to instrument the MCP server as shown above.

If you set `traceLifecycle: "static"`, the SDK snapshots the request transaction when the response is returned and MCP spans that finish later are dropped. Remove the option to get them back.

Streaming sends span records instead of assembling one transaction event with embedded spans. `beforeSendTransaction` and `ignoreTransactions` don't apply to streamed spans. Use <PlatformLink to="/configuration/options/#beforeSendSpan">beforeSendSpan</PlatformLink> and <PlatformLink to="/configuration/options/#ignoreSpans">ignoreSpans</PlatformLink> instead.

If you use `McpAgent`, wrap the `McpServer` returned by its `server` getter, and make sure that the Agent class is instrumented to preserve request and RPC context. The <PlatformLink to="/install/vite-plugin/">Vite plugin</PlatformLink> does this automatically. On a plain Wrangler build, wrap the class with `instrumentAgentWithSentry`. Agent instrumentation, MCP server wrapping, and span streaming solve different parts of the setup; none replaces the others. See <PlatformLink to="/agent-tracing/agents-sdk/">Agents SDK</PlatformLink>.
If you use `McpAgent`, make sure the `McpServer` returned by its `server` getter is instrumented, and that the Agent class is instrumented to preserve request and RPC context. The <PlatformLink to="/install/vite-plugin/">Vite plugin</PlatformLink> does both automatically. On a plain Wrangler build, wrap the server with `wrapMcpServerWithSentry` and the class with `instrumentAgentWithSentry`. Agent instrumentation, MCP server instrumentation, and span streaming solve different parts of the setup; none replaces the others. See <PlatformLink to="/agent-tracing/agents-sdk/">Agents SDK</PlatformLink>.

</PlatformSection>

Expand All @@ -77,15 +77,15 @@ app.use(
);
```

You still need `wrapMcpServerWithSentry` to instrument MCP operations. See <PlatformLink to="/tracing/streamed-spans/">Streamed Spans</PlatformLink> for configuration and filtering differences.
On Cloudflare Workers, MCP servers are instrumented automatically only when you build with the Sentry Cloudflare Vite plugin. Otherwise, you still need `wrapMcpServerWithSentry` to instrument MCP operations. See <PlatformLink to="/tracing/streamed-spans/">Streamed Spans</PlatformLink> for configuration and filtering differences.

</PlatformSection>

## Manual Instrumentation

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 setup above instruments MCP servers built with the official [MCP SDK](https://github.com/modelcontextprotocol/typescript-sdk) (`@modelcontextprotocol/server` or `@modelcontextprotocol/sdk`). If your server uses a different library or a custom implementation that the SDK can't instrument, you can record the same spans manually.

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.
You don't need this if your server is already instrumented, automatically or with `wrapMcpServerWithSentry`. The SDK 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

Expand Down
20 changes: 9 additions & 11 deletions docs/product/mcp-servers/getting-started.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -27,36 +27,34 @@ To start sending MCP data to Sentry, make sure you've created a Sentry project f
minVersion="9.46.0"
/>

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.
Starting with Sentry JavaScript SDK version `11.1.0`, the SDK automatically instruments every `McpServer` from [`@modelcontextprotocol/server`](https://www.npmjs.com/package/@modelcontextprotocol/server) 2.x and [`@modelcontextprotocol/sdk`](https://www.npmjs.com/package/@modelcontextprotocol/sdk) 1.x when tracing is enabled. It 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/server/mcp.js";
import { McpServer } from "@modelcontextprotocol/server";

// Sentry init needs to be above everything else
Sentry.init({
dsn: "___PUBLIC_DSN___",
tracesSampleRate: 1.0,
});

// Wrap every MCP server instance
const server = Sentry.wrapMcpServerWithSentry(
new McpServer({
name: "my-mcp-server",
version: "1.0.0",
}),
);
// No wrapping needed, the SDK instruments the server automatically
const server = new McpServer({
name: "my-mcp-server",
version: "1.0.0",
});

...
```

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/).
On Cloudflare Workers, automatic instrumentation requires building with the Sentry Cloudflare Vite plugin. Without the plugin, or on SDK versions earlier than `11.1.0`, wrap each server instance with `Sentry.wrapMcpServerWithSentry(new McpServer(...))`. 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.
Pass these options to `wrapMcpServerWithSentry` to configure a specific server, including one the SDK already instrumented automatically. The `recordInputs` and `recordOutputs` options require Sentry JavaScript SDK version `10.33.0` or newer.

##### `recordInputs`

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,15 @@
Import Sentry from `@sentry/node`, then wrap the MCP server instance before connecting it to a transport:
Create your MCP server as usual. No Sentry-specific code is needed:

```javascript {filename:mcp-server.js}
import { McpServer } from "@modelcontextprotocol/server";

const server = new McpServer({
name: "my-mcp-server",
version: "1.0.0",
});
```

On SDK versions earlier than `11.1.0`, or if automatic instrumentation isn't set up for your app, import Sentry from `@sentry/node` and wrap the MCP server instance before connecting it to a transport:

```javascript {filename:mcp-server.js}
import * as Sentry from "@sentry/node";
Expand All @@ -12,4 +23,4 @@ const server = Sentry.wrapMcpServerWithSentry(
);
```

Register tools, prompts, and resources on `server` as usual. The wrapper returns the same server instance.
The wrapper returns the same server instance. Wrapping a server the SDK already instrumented doesn't instrument it twice.
26 changes: 26 additions & 0 deletions platform-includes/mcp-monitoring/setup/javascript.cloudflare.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
If you build your Worker with the <PlatformLink to="/install/vite-plugin/">Sentry Vite plugin</PlatformLink>, create your MCP server as usual. No Sentry-specific code is needed:

```javascript {filename:mcp-server.js}
import { McpServer } from "@modelcontextprotocol/server";

const server = new McpServer({
name: "my-mcp-server",
version: "1.0.0",
});
```

On a plain Wrangler build, or on SDK versions earlier than `11.1.0`, import Sentry from `@sentry/cloudflare` and wrap the MCP server instance before connecting it to a transport:

```javascript {filename:mcp-server.js}
import * as Sentry from "@sentry/cloudflare";
import { McpServer } from "@modelcontextprotocol/server";

const server = Sentry.wrapMcpServerWithSentry(
new McpServer({
name: "my-mcp-server",
version: "1.0.0",
})
);
```

The wrapper returns the same server instance. Wrapping a server the SDK already instrumented doesn't instrument it twice.
15 changes: 13 additions & 2 deletions platform-includes/mcp-monitoring/setup/javascript.hono.mdx
Original file line number Diff line number Diff line change
@@ -1,4 +1,15 @@
Hono uses a runtime-specific Sentry entrypoint. Import Sentry from the entrypoint that matches your deployment:
The SDK instruments your MCP server automatically. Create it as usual. On Bun, this requires building your app with the [Sentry Bun plugin](/platforms/javascript/guides/bun/#build-with-the-sentry-plugin-recommended). On Cloudflare Workers, it requires building with the [Sentry Cloudflare Vite plugin](/platforms/javascript/guides/cloudflare/install/vite-plugin/):

```javascript {filename:mcp-server.js}
import { McpServer } from "@modelcontextprotocol/server";

const server = new McpServer({
name: "my-mcp-server",
version: "1.0.0",
});
```

On SDK versions earlier than `11.1.0`, or if automatic instrumentation isn't set up for your app, wrap the MCP server instance manually. Import Sentry from the entrypoint that matches your deployment:

```javascript {tabTitle:Cloudflare Workers} {filename:mcp-server.js}
import * as Sentry from "@sentry/hono/cloudflare";
Expand Down Expand Up @@ -29,4 +40,4 @@ const server = Sentry.wrapMcpServerWithSentry(
);
```

Register tools, prompts, and resources on `server` as usual. The wrapper returns the same server instance.
The wrapper returns the same server instance. Wrapping a server the SDK already instrumented doesn't instrument it twice.
27 changes: 25 additions & 2 deletions platform-includes/mcp-monitoring/setup/javascript.mdx
Original file line number Diff line number Diff line change
@@ -1,4 +1,27 @@
Import Sentry from your framework's SDK package, then wrap the MCP server instance before connecting it to a transport:
Create your MCP server as usual. No Sentry-specific code is needed:

```javascript {filename:mcp-server.js}
import { McpServer } from "@modelcontextprotocol/server";

const server = new McpServer({
name: "my-mcp-server",
version: "1.0.0",
});
```

<PlatformSection supported={["javascript.nextjs"]}>

Run your MCP server in the Node.js runtime. Automatic instrumentation isn't available in the Edge runtime.

</PlatformSection>

<PlatformSection supported={["javascript.bun"]}>

On Bun, automatic instrumentation requires building your app with the [Sentry Bun plugin](/platforms/javascript/guides/bun/#build-with-the-sentry-plugin-recommended).

</PlatformSection>

On SDK versions earlier than `11.1.0`, or if automatic instrumentation isn't set up for your app, wrap the MCP server instance before connecting it to a transport:

```javascript {filename:mcp-server.js}
import * as Sentry from "___SDK_PACKAGE___";
Expand All @@ -12,4 +35,4 @@ const server = Sentry.wrapMcpServerWithSentry(
);
```

Register tools, prompts, and resources on `server` as usual. The wrapper returns the same server instance.
The wrapper returns the same server instance. Wrapping a server the SDK already instrumented doesn't instrument it twice.
Loading