Skip to content

Conversation

@kashishhora
Copy link
Member

Summary

Modified

  • Refactored tracing architecture from per-tool callback wrapping to handler-level wrapping in tracingV2.ts
  • Added setupToolsCallHandlerWrapping() to intercept setRequestHandler() calls for tools/call handler
  • Added createToolsCallWrapper() to centralize tracing logic at the protocol handler level
  • Simplified addTracingToToolCallback() to only remove context from args instead of handling full tracing

Test Plan

  • All existing tests pass
  • Type checks pass
  • New tests added for handler-level architecture
  • Tests verify no duplicate events when track() called multiple times
  • Tests verify context parameter is properly removed before callback execution

@kashishhora kashishhora requested a review from naji247 November 20, 2025 18:37
Comment on lines 31 to 36
if (!(error instanceof Error)) {
return {
message: stringifyNonError(error),
type: "NonError",
type: "UnknownErrorType",
platform: "javascript",
};
Copy link
Member

Choose a reason for hiding this comment

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

I think based on their code, we know it is an McpError type I'm pretty sure. You could do a quick includes check or something here.

Comment on lines +287 to +297
return await (
originalCallback as (
extra: CompatibleRequestHandlerExtra,
) => Promise<CallToolResult>
)(extra);
} else {
return await (
originalCallback as (
args: any,
extra: CompatibleRequestHandlerExtra,
) => Promise<CallToolResult>
Copy link
Member

Choose a reason for hiding this comment

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

I feel like the type casting here makes this way less readable... Can we remove?

Comment on lines +329 to +361
function setupToolsCallHandlerWrapping(server: HighLevelMCPServerLike): void {
const lowLevelServer = server.server as MCPServerLike;

// Check if tools/call handler already exists
const existingHandler = lowLevelServer._requestHandlers.get("tools/call");
if (existingHandler) {
const wrappedHandler = createToolsCallWrapper(
existingHandler,
lowLevelServer,
);
lowLevelServer._requestHandlers.set("tools/call", wrappedHandler);
}

// Intercept future calls to setRequestHandler for tools registered after track()
const originalSetRequestHandler =
lowLevelServer.setRequestHandler.bind(lowLevelServer);

lowLevelServer.setRequestHandler = function (
requestSchema: any,
handler: any,
) {
const method = requestSchema?.shape?.method?.value;

// Only wrap tools/call handler
if (method === "tools/call") {
const wrappedHandler = createToolsCallWrapper(handler, lowLevelServer);
return originalSetRequestHandler(requestSchema, wrappedHandler);
}

// Pass through all other handlers unchanged
return originalSetRequestHandler(requestSchema, handler);
} as any;
}
Copy link
Member

Choose a reason for hiding this comment

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

I'm a bit confused as to what this whole function does lol...

Comment on lines +342 to +360
// Intercept future calls to setRequestHandler for tools registered after track()
const originalSetRequestHandler =
lowLevelServer.setRequestHandler.bind(lowLevelServer);

lowLevelServer.setRequestHandler = function (
requestSchema: any,
handler: any,
) {
const method = requestSchema?.shape?.method?.value;

// Only wrap tools/call handler
if (method === "tools/call") {
const wrappedHandler = createToolsCallWrapper(handler, lowLevelServer);
return originalSetRequestHandler(requestSchema, wrappedHandler);
}

// Pass through all other handlers unchanged
return originalSetRequestHandler(requestSchema, handler);
} as any;
Copy link
Member

Choose a reason for hiding this comment

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

I guess I just don't think this handler is ever called more than once so the rest of this function may be redundant

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.

3 participants