@sentry/core
Version:
Base implementation for all Sentry JavaScript SDKs
125 lines (107 loc) • 4.39 kB
JavaScript
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
const debugBuild = require('./debug-build.js');
const semanticAttributes = require('./semanticAttributes.js');
require('./tracing/errors.js');
require('./utils-hoist/debug-build.js');
const logger = require('./utils-hoist/logger.js');
require('./utils-hoist/time.js');
require('./utils-hoist/syncpromise.js');
const trace = require('./tracing/trace.js');
const wrappedMcpServerInstances = new WeakSet();
/**
* Wraps a MCP Server instance from the `@modelcontextprotocol/sdk` package with Sentry instrumentation.
*
* Compatible with versions `^1.9.0` of the `@modelcontextprotocol/sdk` package.
*/
// We are exposing this API for non-node runtimes that cannot rely on auto-instrumentation.
function wrapMcpServerWithSentry(mcpServerInstance) {
if (wrappedMcpServerInstances.has(mcpServerInstance)) {
return mcpServerInstance;
}
if (!isMcpServerInstance(mcpServerInstance)) {
debugBuild.DEBUG_BUILD && logger.logger.warn('Did not patch MCP server. Interface is incompatible.');
return mcpServerInstance;
}
mcpServerInstance.resource = new Proxy(mcpServerInstance.resource, {
apply(target, thisArg, argArray) {
const resourceName = argArray[0];
const resourceHandler = argArray[argArray.length - 1];
if (typeof resourceName !== 'string' || typeof resourceHandler !== 'function') {
return target.apply(thisArg, argArray);
}
return trace.startSpan(
{
name: `mcp-server/resource:${resourceName}`,
forceTransaction: true,
attributes: {
[semanticAttributes.SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'auto.function.mcp-server',
[semanticAttributes.SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.function.mcp-server',
[semanticAttributes.SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'route',
'mcp_server.resource': resourceName,
},
},
() => target.apply(thisArg, argArray),
);
},
});
mcpServerInstance.tool = new Proxy(mcpServerInstance.tool, {
apply(target, thisArg, argArray) {
const toolName = argArray[0];
const toolHandler = argArray[argArray.length - 1];
if (typeof toolName !== 'string' || typeof toolHandler !== 'function') {
return target.apply(thisArg, argArray);
}
return trace.startSpan(
{
name: `mcp-server/tool:${toolName}`,
forceTransaction: true,
attributes: {
[semanticAttributes.SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'auto.function.mcp-server',
[semanticAttributes.SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.function.mcp-server',
[semanticAttributes.SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'route',
'mcp_server.tool': toolName,
},
},
() => target.apply(thisArg, argArray),
);
},
});
mcpServerInstance.prompt = new Proxy(mcpServerInstance.prompt, {
apply(target, thisArg, argArray) {
const promptName = argArray[0];
const promptHandler = argArray[argArray.length - 1];
if (typeof promptName !== 'string' || typeof promptHandler !== 'function') {
return target.apply(thisArg, argArray);
}
return trace.startSpan(
{
name: `mcp-server/resource:${promptName}`,
forceTransaction: true,
attributes: {
[semanticAttributes.SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'auto.function.mcp-server',
[semanticAttributes.SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.function.mcp-server',
[semanticAttributes.SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'route',
'mcp_server.prompt': promptName,
},
},
() => target.apply(thisArg, argArray),
);
},
});
wrappedMcpServerInstances.add(mcpServerInstance);
return mcpServerInstance ;
}
function isMcpServerInstance(mcpServerInstance) {
return (
typeof mcpServerInstance === 'object' &&
mcpServerInstance !== null &&
'resource' in mcpServerInstance &&
typeof mcpServerInstance.resource === 'function' &&
'tool' in mcpServerInstance &&
typeof mcpServerInstance.tool === 'function' &&
'prompt' in mcpServerInstance &&
typeof mcpServerInstance.prompt === 'function'
);
}
exports.wrapMcpServerWithSentry = wrapMcpServerWithSentry;
//# sourceMappingURL=mcp-server.js.map