Skip to content

Commit 20cc8ac

Browse files
AbhiPrasadbetegon
andauthored
feat(v9/core): add MCP server instrumentation (#17196)
backport of #16817 Co-authored-by: Miguel Betegón <[email protected]>
1 parent 343d18a commit 20cc8ac

26 files changed

+3334
-577
lines changed

dev-packages/e2e-tests/test-applications/node-express/src/app.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ import { mcpRouter } from './mcp';
2525
const app = express();
2626
const port = 3030;
2727

28+
app.use(express.json());
29+
2830
app.use(mcpRouter);
2931

3032
app.get('/crash-in-with-monitor/:id', async (req, res) => {

dev-packages/e2e-tests/test-applications/node-express/src/mcp.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ mcpRouter.post('/messages', async (req, res) => {
5555
const sessionId = req.query.sessionId;
5656
const transport = transports[sessionId as string];
5757
if (transport) {
58-
await transport.handlePostMessage(req, res);
58+
await transport.handlePostMessage(req, res, req.body);
5959
} else {
6060
res.status(400).send('No transport found for sessionId');
6161
}

dev-packages/e2e-tests/test-applications/node-express/tests/errors.test.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ test('Sends correct error event', async ({ baseURL }) => {
1313
expect(errorEvent.exception?.values).toHaveLength(1);
1414
expect(errorEvent.exception?.values?.[0]?.value).toBe('This is an exception with id 123');
1515

16-
expect(errorEvent.request).toEqual({
16+
expect(errorEvent.request).toMatchObject({
1717
method: 'GET',
1818
cookies: {},
1919
headers: expect.any(Object),
@@ -43,11 +43,11 @@ test('Should record caught exceptions with local variable', async ({ baseURL })
4343

4444
test('To not crash app from withMonitor', async ({ baseURL }) => {
4545
const doRequest = async (id: number) => {
46-
const response = await fetch(`${baseURL}/crash-in-with-monitor/${id}`)
46+
const response = await fetch(`${baseURL}/crash-in-with-monitor/${id}`);
4747
return response.json();
48-
}
49-
const [response1, response2] = await Promise.all([doRequest(1), doRequest(2)])
50-
expect(response1.message).toBe('This is an exception withMonitor: 1')
51-
expect(response2.message).toBe('This is an exception withMonitor: 2')
52-
expect(response1.pid).toBe(response2.pid) //Just to double-check, TBS
48+
};
49+
const [response1, response2] = await Promise.all([doRequest(1), doRequest(2)]);
50+
expect(response1.message).toBe('This is an exception withMonitor: 1');
51+
expect(response2.message).toBe('This is an exception withMonitor: 2');
52+
expect(response1.pid).toBe(response2.pid); //Just to double-check, TBS
5353
});

dev-packages/e2e-tests/test-applications/node-express/tests/mcp.test.ts

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ test('Should record transactions for mcp handlers', async ({ baseURL }) => {
1818
return transactionEvent.transaction === 'POST /messages';
1919
});
2020
const toolTransactionPromise = waitForTransaction('node-express', transactionEvent => {
21-
return transactionEvent.transaction === 'mcp-server/tool:echo';
21+
return transactionEvent.transaction === 'tools/call echo';
2222
});
2323

2424
const toolResult = await client.callTool({
@@ -39,10 +39,12 @@ test('Should record transactions for mcp handlers', async ({ baseURL }) => {
3939

4040
const postTransaction = await postTransactionPromise;
4141
expect(postTransaction).toBeDefined();
42+
expect(postTransaction.contexts?.trace?.op).toEqual('http.server');
4243

4344
const toolTransaction = await toolTransactionPromise;
4445
expect(toolTransaction).toBeDefined();
45-
46+
expect(toolTransaction.contexts?.trace?.op).toEqual('mcp.server');
47+
expect(toolTransaction.contexts?.trace?.data?.['mcp.method.name']).toEqual('tools/call');
4648
// TODO: When https://github.com/modelcontextprotocol/typescript-sdk/pull/358 is released check for trace id equality between the post transaction and the handler transaction
4749
});
4850

@@ -51,7 +53,7 @@ test('Should record transactions for mcp handlers', async ({ baseURL }) => {
5153
return transactionEvent.transaction === 'POST /messages';
5254
});
5355
const resourceTransactionPromise = waitForTransaction('node-express', transactionEvent => {
54-
return transactionEvent.transaction === 'mcp-server/resource:echo';
56+
return transactionEvent.transaction === 'resources/read echo://foobar';
5557
});
5658

5759
const resourceResult = await client.readResource({
@@ -64,10 +66,12 @@ test('Should record transactions for mcp handlers', async ({ baseURL }) => {
6466

6567
const postTransaction = await postTransactionPromise;
6668
expect(postTransaction).toBeDefined();
69+
expect(postTransaction.contexts?.trace?.op).toEqual('http.server');
6770

6871
const resourceTransaction = await resourceTransactionPromise;
6972
expect(resourceTransaction).toBeDefined();
70-
73+
expect(resourceTransaction.contexts?.trace?.op).toEqual('mcp.server');
74+
expect(resourceTransaction.contexts?.trace?.data?.['mcp.method.name']).toEqual('resources/read');
7175
// TODO: When https://github.com/modelcontextprotocol/typescript-sdk/pull/358 is released check for trace id equality between the post transaction and the handler transaction
7276
});
7377

@@ -76,7 +80,7 @@ test('Should record transactions for mcp handlers', async ({ baseURL }) => {
7680
return transactionEvent.transaction === 'POST /messages';
7781
});
7882
const promptTransactionPromise = waitForTransaction('node-express', transactionEvent => {
79-
return transactionEvent.transaction === 'mcp-server/prompt:echo';
83+
return transactionEvent.transaction === 'prompts/get echo';
8084
});
8185

8286
const promptResult = await client.getPrompt({
@@ -100,10 +104,12 @@ test('Should record transactions for mcp handlers', async ({ baseURL }) => {
100104

101105
const postTransaction = await postTransactionPromise;
102106
expect(postTransaction).toBeDefined();
107+
expect(postTransaction.contexts?.trace?.op).toEqual('http.server');
103108

104109
const promptTransaction = await promptTransactionPromise;
105110
expect(promptTransaction).toBeDefined();
106-
111+
expect(promptTransaction.contexts?.trace?.op).toEqual('mcp.server');
112+
expect(promptTransaction.contexts?.trace?.data?.['mcp.method.name']).toEqual('prompts/get');
107113
// TODO: When https://github.com/modelcontextprotocol/typescript-sdk/pull/358 is released check for trace id equality between the post transaction and the handler transaction
108114
});
109115
});

packages/core/src/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ export { featureFlagsIntegration, type FeatureFlagsIntegration } from './integra
118118
export { profiler } from './profiling';
119119
export { instrumentFetchRequest } from './fetch';
120120
export { trpcMiddleware } from './trpc';
121-
export { wrapMcpServerWithSentry } from './mcp-server';
121+
export { wrapMcpServerWithSentry } from './integrations/mcp-server';
122122
export { captureFeedback } from './feedback';
123123
export type { ReportDialogOptions } from './report-dialog';
124124
export { _INTERNAL_captureLog, _INTERNAL_flushLogsBuffer, _INTERNAL_captureSerializedLog } from './logs/exports';

0 commit comments

Comments
 (0)