Skip to content
Draft
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 @@ -82,12 +82,12 @@ test('sends spans for MCP tool calls via MCPAgent (DurableObject)', async ({ bas
trace_id: expect.any(String),
parent_span_id: expect.any(String),
span_id: expect.any(String),
op: 'mcp.server',
op: 'rpc',
origin: 'auto.function.mcp_server',
status: 'ok',
data: expect.objectContaining({
'sentry.origin': 'auto.function.mcp_server',
'sentry.op': 'mcp.server',
'sentry.op': 'rpc',
'mcp.method.name': 'tools/call',
'mcp.tool.name': 'my-tool',
'mcp.tool.extra': 'from-mcpagent',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,13 +87,17 @@ test('sends spans for MCP tool calls', async ({ baseURL }) => {
trace_id: expect.any(String),
parent_span_id: requestEvent.contexts?.trace?.span_id,
span_id: expect.any(String),
op: 'mcp.server',
op: 'rpc',
origin: 'auto.function.mcp_server',
status: 'ok',
data: {
'sentry.origin': 'auto.function.mcp_server',
'sentry.op': 'mcp.server',
'sentry.op': 'rpc',
'sentry.source': 'route',
'rpc.system.name': 'mcp',
'rpc.method': 'tools/call',
'jsonrpc.protocol.version': '2.0',
'jsonrpc.request.id': '1',
'mcp.transport': 'WorkerTransport',
'network.transport': 'unknown',
'network.protocol.version': '2.0',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ test('Should record transactions for MCP handlers using @modelcontextprotocol/sd
await test.step('initialize handshake', async () => {
const initializeTransaction = await initializeTransactionPromise;
expect(initializeTransaction).toBeDefined();
expect(initializeTransaction.contexts?.trace?.op).toEqual('mcp.server');
expect(initializeTransaction.contexts?.trace?.op).toEqual('rpc');
expect(initializeTransaction.contexts?.trace?.data?.['mcp.method.name']).toEqual('initialize');
expect(initializeTransaction.contexts?.trace?.data?.['mcp.client.name']).toEqual('test-client-v2');
expect(initializeTransaction.contexts?.trace?.data?.['mcp.server.name']).toEqual('Echo-V2');
Expand Down Expand Up @@ -52,7 +52,7 @@ test('Should record transactions for MCP handlers using @modelcontextprotocol/sd

const toolTransaction = await toolTransactionPromise;
expect(toolTransaction).toBeDefined();
expect(toolTransaction.contexts?.trace?.op).toEqual('mcp.server');
expect(toolTransaction.contexts?.trace?.op).toEqual('rpc');
expect(toolTransaction.contexts?.trace?.data?.['mcp.method.name']).toEqual('tools/call');
expect(toolTransaction.contexts?.trace?.data?.['mcp.tool.name']).toEqual('echo');
// Proves span was completed with results (span correlation worked end-to-end)
Expand All @@ -74,7 +74,7 @@ test('Should record transactions for MCP handlers using @modelcontextprotocol/sd

const resourceTransaction = await resourceTransactionPromise;
expect(resourceTransaction).toBeDefined();
expect(resourceTransaction.contexts?.trace?.op).toEqual('mcp.server');
expect(resourceTransaction.contexts?.trace?.op).toEqual('rpc');
expect(resourceTransaction.contexts?.trace?.data?.['mcp.method.name']).toEqual('resources/read');
});

Expand Down Expand Up @@ -104,7 +104,7 @@ test('Should record transactions for MCP handlers using @modelcontextprotocol/sd

const promptTransaction = await promptTransactionPromise;
expect(promptTransaction).toBeDefined();
expect(promptTransaction.contexts?.trace?.op).toEqual('mcp.server');
expect(promptTransaction.contexts?.trace?.op).toEqual('rpc');
expect(promptTransaction.contexts?.trace?.data?.['mcp.method.name']).toEqual('prompts/get');
});

Expand All @@ -121,7 +121,7 @@ test('Should record transactions for MCP handlers using @modelcontextprotocol/sd

const toolTransaction = await toolTransactionPromise;
expect(toolTransaction).toBeDefined();
expect(toolTransaction.contexts?.trace?.op).toEqual('mcp.server');
expect(toolTransaction.contexts?.trace?.op).toEqual('rpc');
expect(toolTransaction.contexts?.trace?.status).toEqual('internal_error');
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,15 @@ test.skip('Should record streamed spans for mcp handlers', async ({ baseURL }) =
});

const initializeSpanPromise = waitForStreamedSpan('node-express-streaming', span => {
return span.name === 'initialize' && getSpanOp(span) === 'mcp.server' && span.is_segment;
return span.name === 'initialize' && getSpanOp(span) === 'rpc' && span.is_segment;
});

await client.connect(transport);

await test.step('initialize handshake', async () => {
const initializeSpan = await initializeSpanPromise;
expect(initializeSpan).toBeDefined();
expect(getSpanOp(initializeSpan)).toBe('mcp.server');
expect(getSpanOp(initializeSpan)).toBe('rpc');
expect(initializeSpan.attributes['mcp.method.name']?.value).toBe('initialize');
expect(initializeSpan.attributes['mcp.client.name']?.value).toBe('test-client');
expect(initializeSpan.attributes['mcp.server.name']?.value).toBe('Echo');
Expand All @@ -35,7 +35,7 @@ test.skip('Should record streamed spans for mcp handlers', async ({ baseURL }) =
return span.name === 'POST /messages' && getSpanOp(span) === 'http.server' && span.is_segment;
});
const toolSpanPromise = waitForStreamedSpan('node-express-streaming', span => {
return span.name === 'tools/call echo' && getSpanOp(span) === 'mcp.server' && span.is_segment;
return span.name === 'tools/call echo' && getSpanOp(span) === 'rpc' && span.is_segment;
});

const toolResult = await client.callTool({
Expand All @@ -60,7 +60,7 @@ test.skip('Should record streamed spans for mcp handlers', async ({ baseURL }) =

const toolSpan = await toolSpanPromise;
expect(toolSpan).toBeDefined();
expect(getSpanOp(toolSpan)).toBe('mcp.server');
expect(getSpanOp(toolSpan)).toBe('rpc');
expect(toolSpan.attributes['mcp.method.name']?.value).toBe('tools/call');
});

Expand All @@ -69,7 +69,7 @@ test.skip('Should record streamed spans for mcp handlers', async ({ baseURL }) =
return span.name === 'POST /messages' && getSpanOp(span) === 'http.server' && span.is_segment;
});
const toolSpanPromise = waitForStreamedSpan('node-express-streaming', span => {
return span.name === 'tools/call echo-register' && getSpanOp(span) === 'mcp.server' && span.is_segment;
return span.name === 'tools/call echo-register' && getSpanOp(span) === 'rpc' && span.is_segment;
});

const toolResult = await client.callTool({
Expand All @@ -94,7 +94,7 @@ test.skip('Should record streamed spans for mcp handlers', async ({ baseURL }) =

const toolSpan = await toolSpanPromise;
expect(toolSpan).toBeDefined();
expect(getSpanOp(toolSpan)).toBe('mcp.server');
expect(getSpanOp(toolSpan)).toBe('rpc');
expect(toolSpan.attributes['mcp.method.name']?.value).toBe('tools/call');
expect(toolSpan.attributes['mcp.tool.name']?.value).toBe('echo-register');
});
Expand All @@ -104,7 +104,7 @@ test.skip('Should record streamed spans for mcp handlers', async ({ baseURL }) =
return span.name === 'POST /messages' && getSpanOp(span) === 'http.server' && span.is_segment;
});
const resourceSpanPromise = waitForStreamedSpan('node-express-streaming', span => {
return span.name === 'resources/read echo://foobar' && getSpanOp(span) === 'mcp.server' && span.is_segment;
return span.name === 'resources/read echo://foobar' && getSpanOp(span) === 'rpc' && span.is_segment;
});

const resourceResult = await client.readResource({
Expand All @@ -121,7 +121,7 @@ test.skip('Should record streamed spans for mcp handlers', async ({ baseURL }) =

const resourceSpan = await resourceSpanPromise;
expect(resourceSpan).toBeDefined();
expect(getSpanOp(resourceSpan)).toBe('mcp.server');
expect(getSpanOp(resourceSpan)).toBe('rpc');
expect(resourceSpan.attributes['mcp.method.name']?.value).toBe('resources/read');
});

Expand All @@ -130,7 +130,7 @@ test.skip('Should record streamed spans for mcp handlers', async ({ baseURL }) =
return span.name === 'POST /messages' && getSpanOp(span) === 'http.server' && span.is_segment;
});
const promptSpanPromise = waitForStreamedSpan('node-express-streaming', span => {
return span.name === 'prompts/get echo' && getSpanOp(span) === 'mcp.server' && span.is_segment;
return span.name === 'prompts/get echo' && getSpanOp(span) === 'rpc' && span.is_segment;
});

const promptResult = await client.getPrompt({
Expand Down Expand Up @@ -158,13 +158,13 @@ test.skip('Should record streamed spans for mcp handlers', async ({ baseURL }) =

const promptSpan = await promptSpanPromise;
expect(promptSpan).toBeDefined();
expect(getSpanOp(promptSpan)).toBe('mcp.server');
expect(getSpanOp(promptSpan)).toBe('rpc');
expect(promptSpan.attributes['mcp.method.name']?.value).toBe('prompts/get');
});

await test.step('error tool sets span status to error', async () => {
const toolSpanPromise = waitForStreamedSpan('node-express-streaming', span => {
return span.name === 'tools/call always-error' && getSpanOp(span) === 'mcp.server' && span.is_segment;
return span.name === 'tools/call always-error' && getSpanOp(span) === 'rpc' && span.is_segment;
});

try {
Expand All @@ -175,7 +175,7 @@ test.skip('Should record streamed spans for mcp handlers', async ({ baseURL }) =

const toolSpan = await toolSpanPromise;
expect(toolSpan).toBeDefined();
expect(getSpanOp(toolSpan)).toBe('mcp.server');
expect(getSpanOp(toolSpan)).toBe('rpc');
expect(toolSpan.status).toBe('error');
});
});
Expand All @@ -191,7 +191,7 @@ test('Should record streamed spans for streamable HTTP transport (wrapper transp
const initializeSpanPromise = waitForStreamedSpan('node-express-streaming', span => {
return (
span.name === 'initialize' &&
getSpanOp(span) === 'mcp.server' &&
getSpanOp(span) === 'rpc' &&
span.attributes['mcp.server.name']?.value === 'Echo-Streamable'
);
});
Expand All @@ -201,7 +201,7 @@ test('Should record streamed spans for streamable HTTP transport (wrapper transp
await test.step('initialize handshake', async () => {
const initializeSpan = await initializeSpanPromise;
expect(initializeSpan).toBeDefined();
expect(getSpanOp(initializeSpan)).toBe('mcp.server');
expect(getSpanOp(initializeSpan)).toBe('rpc');
expect(initializeSpan.attributes['mcp.method.name']?.value).toBe('initialize');
expect(initializeSpan.attributes['mcp.client.name']?.value).toBe('test-client-streamable');
expect(initializeSpan.attributes['mcp.server.name']?.value).toBe('Echo-Streamable');
Expand All @@ -212,7 +212,7 @@ test('Should record streamed spans for streamable HTTP transport (wrapper transp
const toolSpanPromise = waitForStreamedSpan('node-express-streaming', span => {
return (
span.name === 'tools/call echo' &&
getSpanOp(span) === 'mcp.server' &&
getSpanOp(span) === 'rpc' &&
String(span.attributes['mcp.transport']?.value).includes('StreamableHTTPServerTransport')
);
});
Expand All @@ -235,7 +235,7 @@ test('Should record streamed spans for streamable HTTP transport (wrapper transp

const toolSpan = await toolSpanPromise;
expect(toolSpan).toBeDefined();
expect(getSpanOp(toolSpan)).toBe('mcp.server');
expect(getSpanOp(toolSpan)).toBe('rpc');
expect(toolSpan.attributes['mcp.method.name']?.value).toBe('tools/call');
expect(toolSpan.attributes['mcp.tool.name']?.value).toBe('echo');
expect(toolSpan.attributes['mcp.tool.result.content_count']?.value).toBe(1);
Expand All @@ -245,7 +245,7 @@ test('Should record streamed spans for streamable HTTP transport (wrapper transp
const resourceSpanPromise = waitForStreamedSpan('node-express-streaming', span => {
return (
span.name === 'resources/read echo://streamable-test' &&
getSpanOp(span) === 'mcp.server' &&
getSpanOp(span) === 'rpc' &&
String(span.attributes['mcp.transport']?.value).includes('StreamableHTTPServerTransport')
);
});
Expand All @@ -260,15 +260,15 @@ test('Should record streamed spans for streamable HTTP transport (wrapper transp

const resourceSpan = await resourceSpanPromise;
expect(resourceSpan).toBeDefined();
expect(getSpanOp(resourceSpan)).toBe('mcp.server');
expect(getSpanOp(resourceSpan)).toBe('rpc');
expect(resourceSpan.attributes['mcp.method.name']?.value).toBe('resources/read');
});

await test.step('prompt handler', async () => {
const promptSpanPromise = waitForStreamedSpan('node-express-streaming', span => {
return (
span.name === 'prompts/get echo' &&
getSpanOp(span) === 'mcp.server' &&
getSpanOp(span) === 'rpc' &&
String(span.attributes['mcp.transport']?.value).includes('StreamableHTTPServerTransport')
);
});
Expand All @@ -294,7 +294,7 @@ test('Should record streamed spans for streamable HTTP transport (wrapper transp

const promptSpan = await promptSpanPromise;
expect(promptSpan).toBeDefined();
expect(getSpanOp(promptSpan)).toBe('mcp.server');
expect(getSpanOp(promptSpan)).toBe('rpc');
expect(promptSpan.attributes['mcp.method.name']?.value).toBe('prompts/get');
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import type { AppRouter } from '../src/app';

test('Should record streamed span for trpc query', async ({ baseURL }) => {
const trpcSpanPromise = waitForStreamedSpan('node-express-streaming', span => {
return span.name === 'trpc/getSomething' && getSpanOp(span) === 'rpc.server';
return span.name === 'trpc/getSomething' && getSpanOp(span) === 'rpc';
});

const trpcClient = createTRPCProxyClient<AppRouter>({
Expand All @@ -21,13 +21,13 @@ test('Should record streamed span for trpc query', async ({ baseURL }) => {
const trpcSpan = await trpcSpanPromise;
expect(trpcSpan).toBeDefined();
expect(trpcSpan.name).toBe('trpc/getSomething');
expect(getSpanOp(trpcSpan)).toBe('rpc.server');
expect(getSpanOp(trpcSpan)).toBe('rpc');
expect(trpcSpan.attributes['sentry.origin']?.value).toBe('auto.rpc.trpc');
});

test('Should record streamed span for trpc mutation', async ({ baseURL }) => {
const trpcSpanPromise = waitForStreamedSpan('node-express-streaming', span => {
return span.name === 'trpc/createSomething' && getSpanOp(span) === 'rpc.server';
return span.name === 'trpc/createSomething' && getSpanOp(span) === 'rpc';
});

const trpcClient = createTRPCProxyClient<AppRouter>({
Expand All @@ -43,13 +43,13 @@ test('Should record streamed span for trpc mutation', async ({ baseURL }) => {
const trpcSpan = await trpcSpanPromise;
expect(trpcSpan).toBeDefined();
expect(trpcSpan.name).toBe('trpc/createSomething');
expect(getSpanOp(trpcSpan)).toBe('rpc.server');
expect(getSpanOp(trpcSpan)).toBe('rpc');
expect(trpcSpan.attributes['sentry.origin']?.value).toBe('auto.rpc.trpc');
});

test('Should record streamed span and error for a crashing trpc handler', async ({ baseURL }) => {
const trpcSpanPromise = waitForStreamedSpan('node-express-streaming', span => {
return span.name === 'trpc/crashSomething' && getSpanOp(span) === 'rpc.server';
return span.name === 'trpc/crashSomething' && getSpanOp(span) === 'rpc';
});

const errorEventPromise = waitForError('node-express-streaming', errorEvent => {
Expand Down Expand Up @@ -83,7 +83,7 @@ test('Should record streamed span and error for a crashing trpc handler', async

test('Should record streamed span and error for a trpc handler that returns a status code', async ({ baseURL }) => {
const trpcSpanPromise = waitForStreamedSpan('node-express-streaming', span => {
return span.name === 'trpc/badRequest' && getSpanOp(span) === 'rpc.server';
return span.name === 'trpc/badRequest' && getSpanOp(span) === 'rpc';
});

const errorEventPromise = waitForError('node-express-streaming', errorEvent => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ test('Should record transactions for mcp handlers', async ({ baseURL }) => {
await test.step('initialize handshake', async () => {
const initializeTransaction = await initializeTransactionPromise;
expect(initializeTransaction).toBeDefined();
expect(initializeTransaction.contexts?.trace?.op).toEqual('mcp.server');
expect(initializeTransaction.contexts?.trace?.op).toEqual('rpc');
expect(initializeTransaction.contexts?.trace?.data?.['mcp.method.name']).toEqual('initialize');
expect(initializeTransaction.contexts?.trace?.data?.['mcp.client.name']).toEqual('test-client');
expect(initializeTransaction.contexts?.trace?.data?.['mcp.server.name']).toEqual('Echo');
Expand Down Expand Up @@ -166,7 +166,7 @@ test('Should record transactions for mcp handlers', async ({ baseURL }) => {

const toolTransaction = await toolTransactionPromise;
expect(toolTransaction).toBeDefined();
expect(toolTransaction.contexts?.trace?.op).toEqual('mcp.server');
expect(toolTransaction.contexts?.trace?.op).toEqual('rpc');
expect(toolTransaction.contexts?.trace?.status).toEqual('internal_error');
});
});
Expand Down Expand Up @@ -202,7 +202,7 @@ test('Should record transactions for streamable HTTP transport (wrapper transpor
await test.step('initialize handshake', async () => {
const initializeTransaction = await initializeTransactionPromise;
expect(initializeTransaction).toBeDefined();
expect(initializeTransaction.contexts?.trace?.op).toEqual('mcp.server');
expect(initializeTransaction.contexts?.trace?.op).toEqual('rpc');
expect(initializeTransaction.contexts?.trace?.data?.['mcp.method.name']).toEqual('initialize');
expect(initializeTransaction.contexts?.trace?.data?.['mcp.client.name']).toEqual('test-client-streamable');
expect(initializeTransaction.contexts?.trace?.data?.['mcp.server.name']).toEqual('Echo-Streamable');
Expand Down Expand Up @@ -236,7 +236,7 @@ test('Should record transactions for streamable HTTP transport (wrapper transpor

const toolTransaction = await toolTransactionPromise;
expect(toolTransaction).toBeDefined();
expect(toolTransaction.contexts?.trace?.op).toEqual('mcp.server');
expect(toolTransaction.contexts?.trace?.op).toEqual('rpc');
expect(toolTransaction.contexts?.trace?.data?.['mcp.method.name']).toEqual('tools/call');
expect(toolTransaction.contexts?.trace?.data?.['mcp.tool.name']).toEqual('echo');
// This attribute proves the span was completed with results (sessionId correlation worked)
Expand All @@ -262,7 +262,7 @@ test('Should record transactions for streamable HTTP transport (wrapper transpor

const resourceTransaction = await resourceTransactionPromise;
expect(resourceTransaction).toBeDefined();
expect(resourceTransaction.contexts?.trace?.op).toEqual('mcp.server');
expect(resourceTransaction.contexts?.trace?.op).toEqual('rpc');
expect(resourceTransaction.contexts?.trace?.data?.['mcp.method.name']).toEqual('resources/read');
});

Expand Down Expand Up @@ -295,7 +295,7 @@ test('Should record transactions for streamable HTTP transport (wrapper transpor

const promptTransaction = await promptTransactionPromise;
expect(promptTransaction).toBeDefined();
expect(promptTransaction.contexts?.trace?.op).toEqual('mcp.server');
expect(promptTransaction.contexts?.trace?.op).toEqual('rpc');
expect(promptTransaction.contexts?.trace?.data?.['mcp.method.name']).toEqual('prompts/get');
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ test('Should record span for trpc query', async ({ baseURL }) => {
expect(transaction.spans).toContainEqual(
expect.objectContaining({
data: expect.objectContaining({
'sentry.op': 'rpc.server',
'sentry.op': 'rpc',
'sentry.origin': 'auto.rpc.trpc',
}),
description: `trpc/getSomething`,
Expand Down Expand Up @@ -59,7 +59,7 @@ test('Should record transaction for trpc mutation', async ({ baseURL }) => {
expect(transaction.spans).toContainEqual(
expect.objectContaining({
data: expect.objectContaining({
'sentry.op': 'rpc.server',
'sentry.op': 'rpc',
'sentry.origin': 'auto.rpc.trpc',
}),
description: `trpc/createSomething`,
Expand Down
Loading
Loading