Skip to content

Commit 0ce393d

Browse files
committed
update input/output capture logic to depend on sendDefaultPii option to avoid breaking changes
1 parent d2be6ac commit 0ce393d

3 files changed

Lines changed: 70 additions & 19 deletions

File tree

packages/core/src/integrations/mcp-server/index.ts

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { getClient } from '../../currentScopes';
12
import { fill } from '../../utils/object';
23
import { wrapAllMCPHandlers } from './handlers';
34
import { wrapTransportError, wrapTransportOnClose, wrapTransportOnMessage, wrapTransportSend } from './transport';
@@ -22,15 +23,15 @@ const wrappedMcpServerInstances = new WeakSet();
2223
* import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2324
* import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
2425
*
25-
* // Default: inputs and outputs are NOT captured
26+
* // Default: inputs/outputs captured based on sendDefaultPii option
2627
* const server = Sentry.wrapMcpServerWithSentry(
2728
* new McpServer({ name: "my-server", version: "1.0.0" })
2829
* );
2930
*
30-
* // Capture both inputs and outputs
31+
* // Explicitly control input/output capture
3132
* const server = Sentry.wrapMcpServerWithSentry(
3233
* new McpServer({ name: "my-server", version: "1.0.0" }),
33-
* { recordInputs: true, recordOutputs: true }
34+
* { recordInputs: true, recordOutputs: false }
3435
* );
3536
*
3637
* const transport = new StreamableHTTPServerTransport();
@@ -51,8 +52,10 @@ export function wrapMcpServerWithSentry<S extends object>(mcpServerInstance: S,
5152
}
5253

5354
const serverInstance = mcpServerInstance as MCPServerInstance;
54-
const recordInputs = options?.recordInputs ?? false;
55-
const recordOutputs = options?.recordOutputs ?? false;
55+
const client = getClient();
56+
const sendDefaultPii = Boolean(client?.getOptions().sendDefaultPii);
57+
const recordInputs = options?.recordInputs ?? sendDefaultPii;
58+
const recordOutputs = options?.recordOutputs ?? sendDefaultPii;
5659

5760
fill(serverInstance, 'connect', originalConnect => {
5861
return async function (this: MCPServerInstance, transport: MCPTransport, ...restArgs: unknown[]) {

packages/core/src/integrations/mcp-server/types.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -190,8 +190,8 @@ export type SessionData = {
190190
* @internal
191191
*/
192192
export type McpServerWrapperOptions = {
193-
/** Whether to capture tool/prompt input arguments in spans. @default false */
193+
/** Whether to capture tool/prompt input arguments in spans. Defaults to sendDefaultPii. */
194194
recordInputs?: boolean;
195-
/** Whether to capture tool/prompt output results in spans. @default false */
195+
/** Whether to capture tool/prompt output results in spans. Defaults to sendDefaultPii. */
196196
recordOutputs?: boolean;
197197
};

packages/core/test/lib/integrations/mcp-server/transportInstrumentation.test.ts

Lines changed: 60 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -662,7 +662,13 @@ describe('MCP Server Transport Instrumentation', () => {
662662
});
663663

664664
describe('Wrapper Options', () => {
665-
it('should NOT capture request arguments by default (recordInputs: false)', async () => {
665+
it('should NOT capture inputs/outputs when sendDefaultPii is false', async () => {
666+
getClientSpy.mockReturnValue({
667+
getOptions: () => ({ sendDefaultPii: false }),
668+
getDsn: () => ({ publicKey: 'test-key', host: 'test-host' }),
669+
emit: vi.fn(),
670+
} as any);
671+
666672
const mockMcpServer = createMockMcpServer();
667673
const wrappedMcpServer = wrapMcpServerWithSentry(mockMcpServer);
668674
const transport = createMockTransport();
@@ -688,26 +694,68 @@ describe('MCP Server Transport Instrumentation', () => {
688694
);
689695
});
690696

691-
it('should NOT capture tool outputs by default (recordOutputs: false)', async () => {
697+
it('should capture inputs/outputs when sendDefaultPii is true', async () => {
698+
getClientSpy.mockReturnValue({
699+
getOptions: () => ({ sendDefaultPii: true }),
700+
getDsn: () => ({ publicKey: 'test-key', host: 'test-host' }),
701+
emit: vi.fn(),
702+
} as any);
703+
692704
const mockMcpServer = createMockMcpServer();
693705
const wrappedMcpServer = wrapMcpServerWithSentry(mockMcpServer);
694706
const transport = createMockTransport();
695707

696708
await wrappedMcpServer.connect(transport);
697709

698-
const setAttributesSpy = vi.fn();
699-
const mockSpan = { setAttributes: setAttributesSpy, end: vi.fn() };
700-
startInactiveSpanSpy.mockReturnValueOnce(mockSpan as any);
710+
transport.onmessage?.(
711+
{
712+
jsonrpc: '2.0',
713+
method: 'tools/call',
714+
id: 'tool-1',
715+
params: { name: 'weather', arguments: { location: 'London' } },
716+
},
717+
{},
718+
);
701719

702-
transport.onmessage?.({ jsonrpc: '2.0', method: 'tools/call', id: 'tool-1', params: { name: 'weather' } }, {});
720+
expect(startInactiveSpanSpy).toHaveBeenCalledWith(
721+
expect.objectContaining({
722+
attributes: expect.objectContaining({
723+
'mcp.request.argument.location': '"London"',
724+
}),
725+
}),
726+
);
727+
});
703728

704-
await transport.send?.({
705-
jsonrpc: '2.0',
706-
id: 'tool-1',
707-
result: { content: [{ type: 'text', text: 'Sunny' }], isError: false },
708-
});
729+
it('should allow explicit override of defaults', async () => {
730+
getClientSpy.mockReturnValue({
731+
getOptions: () => ({ sendDefaultPii: true }),
732+
getDsn: () => ({ publicKey: 'test-key', host: 'test-host' }),
733+
emit: vi.fn(),
734+
} as any);
709735

710-
expect(setAttributesSpy).not.toHaveBeenCalled();
736+
const mockMcpServer = createMockMcpServer();
737+
const wrappedMcpServer = wrapMcpServerWithSentry(mockMcpServer, { recordInputs: false });
738+
const transport = createMockTransport();
739+
740+
await wrappedMcpServer.connect(transport);
741+
742+
transport.onmessage?.(
743+
{
744+
jsonrpc: '2.0',
745+
method: 'tools/call',
746+
id: 'tool-1',
747+
params: { name: 'weather', arguments: { location: 'London' } },
748+
},
749+
{},
750+
);
751+
752+
expect(startInactiveSpanSpy).toHaveBeenCalledWith(
753+
expect.objectContaining({
754+
attributes: expect.not.objectContaining({
755+
'mcp.request.argument.location': expect.anything(),
756+
}),
757+
}),
758+
);
711759
});
712760
});
713761
});

0 commit comments

Comments
 (0)