Skip to content

Commit 797a50c

Browse files
ref(mcp): Drop send_default_pii support (#7747)
Remove `send_default_pii` branches from the integration. Add the `data_collection` option to all tests for the integration, with `gen_ai` options enabled if `send_default_pii=True` previously, and `gen_ai` options disabled if `send_default_pii=False` previously. When `send_default_pii` was not previously supplied to `sentry_init()`, provide `data_collection={}`. Split tests that were parametrized on `send_default_pii` into two tests with `gen_ai` options enabled and disabled (the latter suffixed with `_no_sensitive_data`). Remove data-collection-specific tests, as existing tests now exercise the same code paths. Closes #7600
1 parent 38385c5 commit 797a50c

3 files changed

Lines changed: 795 additions & 501 deletions

File tree

‎sentry_sdk/integrations/mcp.py‎

Lines changed: 43 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,9 @@
1515
import sentry_sdk
1616
from sentry_sdk.consts import OP, SPANDATA
1717
from sentry_sdk.integrations import DidNotEnable, Integration, _check_minimum_version
18-
from sentry_sdk.scope import should_send_default_pii
1918
from sentry_sdk.utils import (
2019
capture_internal_exceptions,
2120
event_from_exception,
22-
has_data_collection_enabled,
2321
package_version,
2422
safe_serialize,
2523
)
@@ -245,15 +243,9 @@ async def _instrument_tool_call(
245243
client = sentry_sdk.get_client()
246244
handler_name = ctx.params["name"]
247245
arguments = ctx.params.get("arguments")
248-
if arguments is None:
246+
if arguments is None or not client.options["data_collection"]["gen_ai"]["inputs"]:
249247
arguments = {}
250248

251-
if has_data_collection_enabled(client.options):
252-
if not client.options["data_collection"]["gen_ai"]["inputs"]:
253-
# Arguments can contain sensitive data and shouldn't be added to the span
254-
# if the user has opted out via this config.
255-
arguments = {}
256-
257249
# Get request ID, session ID, and transport from context
258250
request_id, session_id, mcp_transport = _get_request_context_data(ctx=ctx)
259251

@@ -287,36 +279,32 @@ async def _instrument_tool_call(
287279
if not isinstance(result, dict):
288280
return result
289281

290-
# Get integration to check PII settings
291282
integration = client.get_integration(MCPIntegration)
292283
if integration is None:
293284
return result
294285

295-
# Check if we should include sensitive data
296-
should_include_result_data = False
297-
if has_data_collection_enabled(client.options):
298-
if client.options["data_collection"]["gen_ai"]["outputs"]:
299-
should_include_result_data = True
300-
elif should_send_default_pii():
301-
should_include_result_data = True
302-
303286
result_content = result
304287
if "structuredContent" in result:
305288
result_content = result["structuredContent"]
306289
elif isinstance(result.get("content"), list):
307290
result_content = _extract_text_from_content_blocks(result["content"])
308291

309-
if result_content is not None and should_include_result_data:
292+
if (
293+
result_content is None
294+
or not client.options["data_collection"]["gen_ai"]["outputs"]
295+
):
296+
return result
297+
298+
span.set_attribute(
299+
SPANDATA.MCP_TOOL_RESULT_CONTENT,
300+
safe_serialize(result_content),
301+
)
302+
# Set content count if result is a dict
303+
if isinstance(result_content, dict):
310304
span.set_attribute(
311-
SPANDATA.MCP_TOOL_RESULT_CONTENT,
312-
safe_serialize(result_content),
305+
SPANDATA.MCP_TOOL_RESULT_CONTENT_COUNT,
306+
len(result_content),
313307
)
314-
# Set content count if result is a dict
315-
if isinstance(result_content, dict):
316-
span.set_attribute(
317-
SPANDATA.MCP_TOOL_RESULT_CONTENT_COUNT,
318-
len(result_content),
319-
)
320308

321309
return result
322310

@@ -337,15 +325,9 @@ async def _instrument_prompt_get(
337325

338326
arguments = ctx.params.get("arguments")
339327

340-
if arguments is None:
328+
if arguments is None or not client.options["data_collection"]["gen_ai"]["inputs"]:
341329
arguments = {}
342330

343-
if has_data_collection_enabled(client.options):
344-
if not client.options["data_collection"]["gen_ai"]["inputs"]:
345-
# Arguments can contain sensitive data and shouldn't be added to the span
346-
# if the user has opted out via this config.
347-
arguments = {}
348-
349331
# Get request ID, session ID, and transport from context
350332
request_id, session_id, mcp_transport = _get_request_context_data(ctx=ctx)
351333

@@ -379,19 +361,10 @@ async def _instrument_prompt_get(
379361
if not isinstance(result, dict):
380362
return result
381363

382-
# Get integration to check PII settings
383364
integration = client.get_integration(MCPIntegration)
384365
if integration is None:
385366
return result
386367

387-
# Check if we should include sensitive data
388-
should_include_result_data = False
389-
if has_data_collection_enabled(client.options):
390-
if client.options["data_collection"]["gen_ai"]["inputs"]:
391-
should_include_result_data = True
392-
elif should_send_default_pii():
393-
should_include_result_data = True
394-
395368
# For prompts, count messages and set role/content only for single-message prompts
396369
try:
397370
messages: "Optional[list[dict[str, Any]]]" = None
@@ -407,28 +380,33 @@ async def _instrument_prompt_get(
407380
SPANDATA.MCP_PROMPT_RESULT_MESSAGE_COUNT, message_count
408381
)
409382

410-
# Only set role and content for single-message prompts if PII is allowed
411-
if message_count == 1 and should_include_result_data and messages:
412-
first_message = messages[0]
413-
# Extract role
414-
role = None
415-
if "role" in first_message:
416-
role = first_message["role"]
417-
418-
if role:
419-
span.set_attribute(SPANDATA.MCP_PROMPT_RESULT_MESSAGE_ROLE, role)
420-
421-
content_text = None
422-
if "content" in first_message:
423-
msg_content = first_message["content"]
424-
if "text" in msg_content:
425-
content_text = msg_content["text"]
426-
427-
if content_text:
428-
span.set_attribute(
429-
SPANDATA.MCP_PROMPT_RESULT_MESSAGE_CONTENT,
430-
content_text,
431-
)
383+
if (
384+
message_count != 1
385+
or not client.options["data_collection"]["gen_ai"]["inputs"]
386+
or not messages
387+
):
388+
return result
389+
390+
first_message = messages[0]
391+
# Extract role
392+
role = None
393+
if "role" in first_message:
394+
role = first_message["role"]
395+
396+
if role:
397+
span.set_attribute(SPANDATA.MCP_PROMPT_RESULT_MESSAGE_ROLE, role)
398+
399+
content_text = None
400+
if "content" in first_message:
401+
msg_content = first_message["content"]
402+
if "text" in msg_content:
403+
content_text = msg_content["text"]
404+
405+
if content_text:
406+
span.set_attribute(
407+
SPANDATA.MCP_PROMPT_RESULT_MESSAGE_CONTENT,
408+
content_text,
409+
)
432410
except Exception:
433411
# Silently ignore if we can't extract message info
434412
pass

0 commit comments

Comments
 (0)