Skip to content

Instrument MCP Servers | Sentry for Next.js

Source URL: https://docs.sentry.io/platforms/javascript/guides/nextjs/tracing/instrumentation/mcp-module

Instrument MCP Servers | Sentry for Next.js

Section titled “Instrument MCP Servers | Sentry for Next.js”

With Sentry’s MCP monitoring, 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.

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.

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.

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.

The Sentry.startSpan() method can be used to create these spans.

Describes MCP tool execution.

The @sentry_sdk.trace() decorator can also be used to create this span.

  • The span’s op MUST be "mcp.server".
  • The span name SHOULD be "tools/call {mcp.tool.name}".
  • The mcp.tool.name attribute MUST be set to the tool’s name. (e.g. "get_weather")
  • The mcp.method.name attribute SHOULD be set to "tools/call".
  • All Common Span Attributes SHOULD be set.

Additional attributes on the span:

Data AttributeTypeRequirement LevelDescriptionExample
mcp.tool.namestringrequiredThe name of the MCP tool being called."get_weather"
mcp.method.namestringrecommendedShould be set to “tools/call”."tools/call"
mcp.request.idstringoptionalThe unique identifier for the MCP request."req_123abc"
mcp.request.argument.*anyoptionalTool input arguments (requires send_default_pii=True)."San Francisco" for mcp.request.argument.city
mcp.tool.result.contentstringoptionalThe result/output content from the tool execution."The weather is sunny"
mcp.tool.result.content_countintoptionalThe number of items/keys in the tool result.5
mcp.tool.result.is_errorbooleanoptionalWhether the tool execution resulted in an error.True

import * as Sentry from "@sentry/node";
Sentry.init({
// ... your Sentry configuration
});
// Example tool execution
const toolName = "get_weather";
const toolArguments = { city: "San Francisco" };
await Sentry.startSpan(
{
op: "mcp.server",
name: `tools/call ${toolName}`,
},
async (span) => {
// Set MCP-specific attributes
span.setAttribute("mcp.tool.name", toolName);
span.setAttribute("mcp.method.name", "tools/call");
// Set request metadata
span.setAttribute("mcp.request.id", "req_123abc");
span.setAttribute("mcp.session.id", "session_xyz789");
span.setAttribute("mcp.transport", "stdio"); // or "http", "sse" for HTTP/WebSocket/SSE
span.setAttribute("network.transport", "pipe"); // or "tcp" for HTTP/SSE
// Set tool arguments (optional, requires recordInputs: true)
for (const [key, value] of Object.entries(toolArguments)) {
span.setAttribute(`mcp.request.argument.${key}`, value);
}
// Execute the tool
try {
const result = executeTool(toolName, toolArguments);
// Set result data
span.setAttribute("mcp.tool.result.content", JSON.stringify(result));
span.setAttribute("mcp.tool.result.is_error", false);
// Set result content count if applicable
if (
Array.isArray(result) ||
(typeof result === "object" && result !== null)
) {
span.setAttribute(
"mcp.tool.result.content_count",
Array.isArray(result)
? result.length
: Object.keys(result).length,
);
}
} catch (error) {
span.setAttribute("mcp.tool.result.is_error", true);
throw error;
}
},
);

Describes MCP prompt retrieval.

The @sentry_sdk.trace() decorator can also be used to create this span.

  • The span’s op MUST be "mcp.server".
  • The span name SHOULD be "prompts/get {mcp.prompt.name}".
  • The mcp.prompt.name attribute MUST be set to the prompt’s name. (e.g. "code_review")
  • The mcp.method.name attribute SHOULD be set to "prompts/get".
  • All Common Span Attributes SHOULD be set.

Additional attributes on the span:

Data AttributeTypeRequirement LevelDescriptionExample
mcp.prompt.namestringrequiredThe name of the MCP prompt being retrieved."code_review"
mcp.method.namestringrecommendedShould be set to “prompts/get”."prompts/get"
mcp.request.idstringoptionalThe unique identifier for the MCP request."req_456def"
mcp.request.argument.*anyoptionalPrompt input arguments (requires send_default_pii=True)."python" for mcp.request.argument.language
mcp.prompt.result.message_contentstringoptionalThe message content from the prompt retrieval (requires send_default_pii=True)."Review the following code..."
mcp.prompt.result.message_rolestringoptionalThe role of the message (only for single-message prompts)."user", "assistant", "system"
mcp.prompt.result.message_countintoptionalThe number of messages in the prompt result.1, 3
import * as Sentry from "@sentry/node";
Sentry.init({
// ... your Sentry configuration
});
// Example prompt retrieval
const promptName = "code_review";
const promptArguments = { language: "python" };
await Sentry.startSpan(
{
op: "mcp.server",
name: `prompts/get ${promptName}`,
},
async (span) => {
// Set MCP-specific attributes
span.setAttribute("mcp.prompt.name", promptName);
span.setAttribute("mcp.method.name", "prompts/get");
// Set request metadata
span.setAttribute("mcp.request.id", "req_456def");
span.setAttribute("mcp.session.id", "session_xyz789");
span.setAttribute("mcp.transport", "http");
span.setAttribute("network.transport", "tcp");
// Set prompt arguments (optional, requires recordInputs: true)
for (const [key, value] of Object.entries(promptArguments)) {
span.setAttribute(`mcp.request.argument.${key}`, value);
}
// Retrieve the prompt
const promptResult = getPrompt(promptName, promptArguments);
// Set result data
const messages = promptResult.messages || [];
span.setAttribute("mcp.prompt.result.message_count", messages.length);
// For single-message prompts, set role and content
if (messages.length === 1) {
span.setAttribute(
"mcp.prompt.result.message_role",
messages[0].role,
);
// Content may contain sensitive data, only set if recordOutputs: true
span.setAttribute(
"mcp.prompt.result.message_content",
JSON.stringify(messages[0].content),
);
}
},
);

Describes MCP resource access.

The @sentry_sdk.trace() decorator can also be used to create this span.

  • The span’s op MUST be "mcp.server".
  • The span name SHOULD be "resources/read {mcp.resource.uri}".
  • The mcp.resource.uri attribute MUST be set to the resource’s URI. (e.g. "file:///path/to/resource")
  • The mcp.method.name attribute SHOULD be set to "resources/read".
  • All Common Span Attributes SHOULD be set.

Additional attributes on the span:

Data AttributeTypeRequirement LevelDescriptionExample
mcp.resource.uristringrequiredThe URI of the MCP resource being accessed."file:///path/to/resource"
mcp.method.namestringrecommendedShould be set to “resources/read”"resources/read"
mcp.request.idstringoptionalThe unique identifier for the MCP request."req_789ghi"
mcp.resource.protocolstringoptionalThe protocol/scheme of the MCP resource URI."file", "http", "https"
import * as Sentry from "@sentry/node";
Sentry.init({
// ... your Sentry configuration
});
// Example resource access
const resourceUri = "file:///path/to/resource.txt";
await Sentry.startSpan(
{
op: "mcp.server",
name: `resources/read ${resourceUri}`,
},
async (span) => {
// Set MCP-specific attributes
span.setAttribute("mcp.resource.uri", resourceUri);
span.setAttribute("mcp.method.name", "resources/read");
// Set request metadata
span.setAttribute("mcp.request.id", "req_789ghi");
span.setAttribute("mcp.session.id", "session_xyz789");
span.setAttribute("mcp.transport", "http");
span.setAttribute("network.transport", "tcp");
// Access the resource
const resourceData = readResource(resourceUri);
},
);

The following attributes are common across all MCP span types and SHOULD be set when available:

Data AttributeTypeRequirement LevelDescriptionExample
mcp.transportstringrecommendedThe transport method used for MCP communication."stdio", "sse", "http"
network.transportstringrecommendedThe network transport used."pipe", "tcp"
mcp.session.idstringrecommendedThe session identifier for the MCP connection."a1b2c3d4e5f6"
mcp.request.idstringoptionalThe unique identifier for the MCP request."req_123abc"