|
17 | 17 | from sentry_sdk.integrations import Integration, DidNotEnable |
18 | 18 | from sentry_sdk.utils import safe_serialize |
19 | 19 | from sentry_sdk.scope import should_send_default_pii |
| 20 | +from sentry_sdk.utils import nullcontext |
20 | 21 |
|
21 | 22 | try: |
22 | 23 | from mcp.server.lowlevel import Server # type: ignore[import-not-found] |
@@ -80,8 +81,8 @@ def _get_active_http_scopes() -> ( |
80 | 81 | return None |
81 | 82 |
|
82 | 83 | return ( |
83 | | - ctx.request.scope["state"].get("sentry_sdk.current_scope"), |
84 | 84 | ctx.request.scope["state"].get("sentry_sdk.isolation_scope"), |
| 85 | + ctx.request.scope["state"].get("sentry_sdk.current_scope"), |
85 | 86 | ) |
86 | 87 |
|
87 | 88 |
|
@@ -410,17 +411,28 @@ async def _async_handler_wrapper( |
410 | 411 | scopes = _get_active_http_scopes() |
411 | 412 |
|
412 | 413 | if scopes is None: |
413 | | - current_scope = None |
414 | | - isolation_scope = None |
| 414 | + isolation_scope_context = nullcontext() |
| 415 | + current_scope_context = nullcontext() |
415 | 416 | else: |
416 | | - current_scope, isolation_scope = scopes |
| 417 | + isolation_scope, current_scope = scopes |
| 418 | + |
| 419 | + isolation_scope_context = ( |
| 420 | + nullcontext() |
| 421 | + if isolation_scope is None |
| 422 | + else sentry_sdk.scope.use_isolation_scope(isolation_scope) |
| 423 | + ) |
| 424 | + current_scope_context = ( |
| 425 | + nullcontext() |
| 426 | + if current_scope is None |
| 427 | + else sentry_sdk.scope.use_scope(current_scope) |
| 428 | + ) |
417 | 429 |
|
418 | 430 | # Get request ID, session ID, and transport from context |
419 | 431 | request_id, session_id, mcp_transport = _get_request_context_data() |
420 | 432 |
|
421 | 433 | # Start span and execute |
422 | | - with sentry_sdk.scope.use_isolation_scope(isolation_scope): |
423 | | - with sentry_sdk.scope.use_scope(current_scope): |
| 434 | + with isolation_scope_context: |
| 435 | + with current_scope_context: |
424 | 436 | with get_start_span_function()( |
425 | 437 | op=OP.MCP_SERVER, |
426 | 438 | name=span_name, |
@@ -490,50 +502,71 @@ def _sync_handler_wrapper( |
490 | 502 | result_data_key, |
491 | 503 | ) = _prepare_handler_data(handler_type, original_args) |
492 | 504 |
|
493 | | - # Start span and execute |
494 | | - with get_start_span_function()( |
495 | | - op=OP.MCP_SERVER, |
496 | | - name=span_name, |
497 | | - origin=MCPIntegration.origin, |
498 | | - ) as span: |
499 | | - # Get request ID, session ID, and transport from context |
500 | | - request_id, session_id, mcp_transport = _get_request_context_data() |
501 | | - |
502 | | - # Set input span data |
503 | | - _set_span_input_data( |
504 | | - span, |
505 | | - handler_name, |
506 | | - span_data_key, |
507 | | - mcp_method_name, |
508 | | - arguments, |
509 | | - request_id, |
510 | | - session_id, |
511 | | - mcp_transport, |
| 505 | + scopes = _get_active_http_scopes() |
| 506 | + |
| 507 | + if scopes is None: |
| 508 | + isolation_scope_context = nullcontext() |
| 509 | + current_scope_context = nullcontext() |
| 510 | + else: |
| 511 | + isolation_scope, current_scope = scopes |
| 512 | + |
| 513 | + isolation_scope_context = ( |
| 514 | + nullcontext() |
| 515 | + if isolation_scope is None |
| 516 | + else sentry_sdk.scope.use_isolation_scope(isolation_scope) |
| 517 | + ) |
| 518 | + current_scope_context = ( |
| 519 | + nullcontext() |
| 520 | + if current_scope is None |
| 521 | + else sentry_sdk.scope.use_scope(current_scope) |
512 | 522 | ) |
513 | 523 |
|
514 | | - # For resources, extract and set protocol |
515 | | - if handler_type == "resource": |
516 | | - uri = original_args[0] |
517 | | - protocol = None |
518 | | - if hasattr(uri, "scheme"): |
519 | | - protocol = uri.scheme |
520 | | - elif handler_name and "://" in handler_name: |
521 | | - protocol = handler_name.split("://")[0] |
522 | | - if protocol: |
523 | | - span.set_data(SPANDATA.MCP_RESOURCE_PROTOCOL, protocol) |
| 524 | + # Start span and execute |
| 525 | + with isolation_scope_context: |
| 526 | + with current_scope_context: |
| 527 | + with get_start_span_function()( |
| 528 | + op=OP.MCP_SERVER, |
| 529 | + name=span_name, |
| 530 | + origin=MCPIntegration.origin, |
| 531 | + ) as span: |
| 532 | + # Get request ID, session ID, and transport from context |
| 533 | + request_id, session_id, mcp_transport = _get_request_context_data() |
524 | 534 |
|
525 | | - try: |
526 | | - # Execute the sync handler |
527 | | - result = func(*original_args) |
528 | | - except Exception as e: |
529 | | - # Set error flag for tools |
530 | | - if handler_type == "tool": |
531 | | - span.set_data(SPANDATA.MCP_TOOL_RESULT_IS_ERROR, True) |
532 | | - sentry_sdk.capture_exception(e) |
533 | | - raise |
534 | | - |
535 | | - _set_span_output_data(span, result, result_data_key, handler_type) |
536 | | - return result |
| 535 | + # Set input span data |
| 536 | + _set_span_input_data( |
| 537 | + span, |
| 538 | + handler_name, |
| 539 | + span_data_key, |
| 540 | + mcp_method_name, |
| 541 | + arguments, |
| 542 | + request_id, |
| 543 | + session_id, |
| 544 | + mcp_transport, |
| 545 | + ) |
| 546 | + |
| 547 | + # For resources, extract and set protocol |
| 548 | + if handler_type == "resource": |
| 549 | + uri = original_args[0] |
| 550 | + protocol = None |
| 551 | + if hasattr(uri, "scheme"): |
| 552 | + protocol = uri.scheme |
| 553 | + elif handler_name and "://" in handler_name: |
| 554 | + protocol = handler_name.split("://")[0] |
| 555 | + if protocol: |
| 556 | + span.set_data(SPANDATA.MCP_RESOURCE_PROTOCOL, protocol) |
| 557 | + |
| 558 | + try: |
| 559 | + # Execute the sync handler |
| 560 | + result = func(*original_args) |
| 561 | + except Exception as e: |
| 562 | + # Set error flag for tools |
| 563 | + if handler_type == "tool": |
| 564 | + span.set_data(SPANDATA.MCP_TOOL_RESULT_IS_ERROR, True) |
| 565 | + sentry_sdk.capture_exception(e) |
| 566 | + raise |
| 567 | + |
| 568 | + _set_span_output_data(span, result, result_data_key, handler_type) |
| 569 | + return result |
537 | 570 |
|
538 | 571 |
|
539 | 572 | def _create_instrumented_handler( |
|
0 commit comments