
    fiTN                     0   d Z ddlZddlmZ ddlmZ ddlZddlmZ ddl	m
Z
mZ ddlmZmZ ddlmZ dd	lmZ 	 dd
lmZ ddlmZ n# e$ r  ed          w xY wer
ddlmZmZmZ  G d de          Zd Zd Zd Zd Zd Z d Z!d Z"d Z#d Z$d Z%d Z&dS )a  
Sentry integration for MCP (Model Context Protocol) servers.

This integration instruments MCP servers to create spans for tool, prompt,
and resource handler execution, and captures errors that occur during execution.

Supports the low-level `mcp.server.lowlevel.Server` API.
    N)wraps)TYPE_CHECKING)get_start_span_function)OPSPANDATA)IntegrationDidNotEnable)safe_serialize)should_send_default_pii)Server)request_ctxzMCP SDK not installed)AnyCallableOptionalc                   4    e Zd ZdZdZddZed             ZdS )MCPIntegrationmcpzauto.ai.mcpTc                     || _         dS )z
        Initialize the MCP integration.

        Args:
            include_prompts: Whether to include prompts (tool results and prompt content)
                             in span data. Requires send_default_pii=True. Default is True.
        N)include_prompts)selfr   s     k/var/www/html/Pagina-Ingenieria-Requisitos/venv/lib/python3.11/site-packages/sentry_sdk/integrations/mcp.py__init__zMCPIntegration.__init__$   s      /    c                  "    t                       dS )zM
        Patches MCP server classes to instrument handler execution.
        N)_patch_lowlevel_server r   r   
setup_oncezMCPIntegration.setup_once/   s     	     r   N)T)__name__
__module____qualname__
identifieroriginr   staticmethodr   r   r   r   r   r       sM        JF	/ 	/ 	/ 	/ ! ! \! ! !r   r   c                     d} d}d}	 t          j                    }||j        } t          |d          r|j        |j        }t          |d          r7|j                            d          rd}|j                            d          }nFt          |d          r6|j                            d          rd	}|j                            d          }n# t          $ r Y nw xY w| ||fS )
a8  
    Extract request ID, session ID, and MCP transport type from the request context.

    Returns:
        Tuple of (request_id, session_id, mcp_transport).
        - request_id: May be None if not available
        - session_id: May be None if not available
        - mcp_transport: "http", "sse", "stdio"
    Nstdiorequestquery_params
session_idsseheaderszmcp-session-idhttp)r   get
request_idhasattrr&   r'   r*   LookupError)r-   r(   mcp_transportctxr&   s        r   _get_request_context_datar2   8   s    JJMo?JsI&& G3;+B+7N33 G8L8P8P 9 9 G %*M!(!5!9!9,!G!GJJWi00 GW_5H5H$6 6 G %+M!(!4!45E!F!FJ    z=00s   CC 
CCc                     | dk    rt           j        }d}t           j        }n1| dk    rt           j        }d}t           j        }nt           j        }d}d}| d| }||||fS )z
    Get span configuration based on handler type.

    Returns:
        Tuple of (span_data_key, span_name, mcp_method_name, result_data_key)
        Note: result_data_key is None for resources
    toolz
tools/callpromptzprompts/getzresources/readN )r   MCP_TOOL_NAMEMCP_TOOL_RESULT_CONTENTMCP_PROMPT_NAME!MCP_PROMPT_RESULT_MESSAGE_CONTENTMCP_RESOURCE_URI)handler_type	item_namespan_data_keymcp_method_nameresult_data_key	span_names         r   _get_span_configrB   c   s|     v .&":		!	! 0'"D 1*"00Y00I)_oEEr   c                 
   |                      ||           |                      t          j        |           |                      t          j        |dk    rdnd           |                      t          j        |           |r |                      t          j        |           |r |                      t          j        |           |                                D ]+\  }}	|                      d| t          |	                     ,dS )z%Set input span data for MCP handlers.r%   pipetcpzmcp.request.argument.N)	set_datar   MCP_METHOD_NAMENETWORK_TRANSPORTMCP_TRANSPORTMCP_REQUEST_IDMCP_SESSION_IDitemsr
   )
spanhandler_namer>   r?   	argumentsr-   r(   r0   kvs
             r   _set_span_input_datarR   }   s    	MM-...MM(*O<<< 	MM"mw.F.FFFE   	MM((-888  ;h-z:::  ;h-z::: !! F F11a11>!3D3DEEEEF Fr   c                 &   | dS t          | t                    rt          |           dk    r| d         S t          | t                    r| S t	          | d          rt          | t
          t          t          f          sg }	 | D ]a}t	          |d          r|                    |j                   -t          |t                    rd|v r|                    |d                    bn# t          $ r | cY S w xY w|rd
                    |          n| S | S )a(  
    Extract meaningful content from MCP tool result.

    Tool handlers can return:
    - tuple (UnstructuredContent, StructuredContent): Return the structured content (dict)
    - dict (StructuredContent): Return as-is
    - Iterable (UnstructuredContent): Extract text from content blocks
    N      __iter__textr6   )
isinstancetuplelendictr.   strbytesappendrW   	Exceptionjoin)resulttextsitems      r   _extract_tool_result_contentrd      s?    ~t &%   S[[A%5%5ay &$  vz"" 4:fsE4>P+Q+Q 4		 / /4(( /LL++++d++ /$LLf.../  	 	 	MMM	 #(3sxxV3Ms   A$C& &C54C5c                    |dS t          j                                        t                    }|dS t	                      o|j        }|dk    rt          |          }|i|ri|                     |t          |                     t          |t                    r3|                     t          j        t          |                     dS dS dS dS |dk    r	 d}d}t          |d          r|j        r|j        }t          |          }nAt          |t                    r,|                    d          r|d         }t          |          }|dk    r |                     t          j        |           |dk    rJ|rI|rH|d         }	d}
t          |	d          r|	j        }
n!t          |	t                    rd|	v r|	d         }
|
r |                     t          j        |
           d}t          |	d          rY|	j        }t          |d	          r|j        }nt          |t                    rd	|v r	|d	         }nrt          |t,                    r|}nZt          |	t                    rEd|	v rA|	d         }t          |t                    rd	|v r	|d	         }nt          |t,                    r|}|r|                     ||           dS dS dS dS dS # t.          $ r Y dS w xY wdS )
z&Set output span data for MCP handlers.Nr4   r5   r   messagesrU   rolecontentrW   )
sentry_sdk
get_clientget_integrationr   r   r   rd   rF   r
   rX   r[   r   MCP_TOOL_RESULT_CONTENT_COUNTrZ   r.   rf   r,   MCP_PROMPT_RESULT_MESSAGE_COUNTrg   MCP_PROMPT_RESULT_MESSAGE_ROLErh   rW   r\   r_   )rM   ra   r@   r<   integrationshould_include_data	extractedrf   message_countfirst_messagerg   content_textmsg_contents                r   _set_span_output_datarv      s`    ~ '))99.IIK 233S8S v088	 %8 MM/>)+D+DEEE)T** VhDc)nnUUUUU	 !   V V		!	!4	HM vz** .v .!? #HFD)) .fjj.D.D .!*- #H q  hFVVV !!&9!h! (=&11 1(-DDt44 1=9P9P(0D QMM("I4PPP  $=)44 3"/"7K{F33 3'2'7#K66 36[;P;P'26':#K55 3'2t44 3m9S9S"/	":K!+t44 3;9N9N'26':#K55 3'2 AMM/<@@@@@? "!!!!!<A A 	 	 	DD	i 
"	!s   G(K	 	
KKc                 6   | dk    r&|d         }t          |          dk    r|d         ni }nQ| dk    r.|d         }t          |          dk    r|d         ni }d|i|pi }n|d         }|rt          |          nd}i }t          | |          \  }}}}||||||fS )z
    Prepare common handler data for both async and sync wrappers.

    Returns:
        Tuple of (handler_name, arguments, span_data_key, span_name, mcp_method_name, result_data_key)
    r4   r   rU   r5   nameunknown)rZ   r\   rB   )	r<   original_argsrN   rO   urir>   rA   r?   r@   s	            r   _prepare_handler_datar|     s     v$Q'(+M(:(:Q(>(>M!$$B				!	!$Q'(+M(:(:Q(>(>M!$$B	\?io2?		A#&5s3xxxI	 BRlB B>M9o
 	 r   c                   K   t          | |          \  }}}}}} t                      t          j        |t          j                  5 }	t                      \  }
}}t          |	|||||
||           | dk    re|d         }d}t          |d          r|j	        }n!|rd|v r|
                    d          d         }|r |	                    t          j        |           	  ||  d{V }nM# t          $ r@}| dk    r |	                    t          j        d           t!          j        |            d}~ww xY wt%          |	|||            |cddd           S # 1 swxY w Y   dS )	z
    Async wrapper for MCP handlers.

    Args:
        handler_type: "tool", "prompt", or "resource"
        func: The async handler function to wrap
        original_args: Original arguments passed to the handler
    oprx   r"   resourcer   Nscheme://r4   Tr|   r   r   
MCP_SERVERr   r"   r2   rR   r.   r   splitrF   r   MCP_RESOURCE_PROTOCOLr_   MCP_TOOL_RESULT_IS_ERRORri   capture_exceptionrv   r<   funcrz   rN   rO   r>   rA   r?   r@   rM   r-   r(   r0   r{   protocolra   es                    r   _async_handler_wrapperr   B  s     " 	lM:: 
#	 	"	"=$
 
 
 * 
0I0K0K-
J 			
 		
 		
 :%%"CHsH%% 8: 8%<"7"7'--e44Q7 Hh<hGGG	4///////FF 	 	 	v%%h?FFF(+++	 	dFO\JJJU* * * * * * * * * * * * * * * * * *s7   BEC)(E)
D33;D..D33EEEc                    t          | |          \  }}}}}} t                      t          j        |t          j                  5 }	t                      \  }
}}t          |	|||||
||           | dk    re|d         }d}t          |d          r|j	        }n!|rd|v r|
                    d          d         }|r |	                    t          j        |           	  || }nM# t          $ r@}| dk    r |	                    t          j        d           t!          j        |            d}~ww xY wt%          |	|||            |cddd           S # 1 swxY w Y   dS )	z
    Sync wrapper for MCP handlers.

    Args:
        handler_type: "tool", "prompt", or "resource"
        func: The sync handler function to wrap
        original_args: Original arguments passed to the handler
    r~   r   r   Nr   r   r4   Tr   r   s                    r   _sync_handler_wrapperr     s   " 	lM:: 
#	 	"	"=$
 
 
 * 
0I0K0K-
J 			
 		
 		
 :%%"CHsH%% 8: 8%<"7"7'--e44Q7 Hh<hGGG	T=)FF 	 	 	v%%h?FFF(+++	 	dFO\JJJU* * * * * * * * * * * * * * * * * *s7   BEC! E!
D++;D&&D++EEEc                      t          j                  rt                     fd            }|S t                     fd            }|S )as  
    Create an instrumented version of a handler function (async or sync).

    This function wraps the user's handler with a runtime wrapper that will create
    Sentry spans and capture metrics when the handler is actually called.

    The wrapper preserves the async/sync nature of the original function, which is
    critical for Python's async/await to work correctly.

    Args:
        handler_type: "tool", "prompt", or "resource" - determines span configuration
        func: The handler function to instrument (async or sync)

    Returns:
        A wrapped version of func that creates Sentry spans on execution
    c                  6   K   t          |            d {V S N)r   argsr   r<   s    r   async_wrapperz3_create_instrumented_handler.<locals>.async_wrapper  s-       0dDIIIIIIIIIr   c                  &    t          |           S r   )r   r   s    r   sync_wrapperz2_create_instrumented_handler.<locals>.sync_wrapper  s     )tTBBBr   )inspectiscoroutinefunctionr   )r<   r   r   r   s   ``  r   _create_instrumented_handlerr     s    $ "4(( 	t	J 	J 	J 	J 	J 
	J  
t	C 	C 	C 	C 	C 
	C r   c                       fd}|S )a  
    Create an instrumented version of an MCP decorator.

    This function intercepts MCP decorators (like @server.call_tool()) and injects
    Sentry instrumentation into the handler registration flow. The returned decorator
    will:
    1. Receive the user's handler function
    2. Wrap it with instrumentation via _create_instrumented_handler
    3. Pass the instrumented version to the original MCP decorator

    This ensures that when the handler is called at runtime, it's already wrapped
    with Sentry spans and metrics collection.

    Args:
        original_decorator: The original MCP decorator method (e.g., Server.call_tool)
        handler_type: "tool", "prompt", or "resource" - determines span configuration
        decorator_args: Positional arguments to pass to the original decorator (e.g., self)
        decorator_kwargs: Keyword arguments to pass to the original decorator

    Returns:
        A decorator function that instruments handlers before registering them
    c                 F    t          |           }  i |          S r   )r   )r   instrumented_funcdecorator_argsdecorator_kwargsr<   original_decorators     r   instrumented_decoratorz>_create_instrumented_decorator.<locals>.instrumented_decorator  s>     9tLLF!!>F5EFF
 
 	
r   r   )r   r<   r   r   r   s   ```` r   _create_instrumented_decoratorr     s6    6
 
 
 
 
 
 
 
 "!r   c                      t           j        fd} | t           _        t           j        fd}|t           _        t           j        fd}|t           _        dS )zW
    Patches the mcp.server.lowlevel.Server class to instrument handler execution.
    c                       fdS )zEPatched version of Server.call_tool that adds Sentry instrumentation.c                 4     t          dfi |           S )Nr4   r   )r   kwargsoriginal_call_toolr   s    r   <lambda>zC_patch_lowlevel_server.<locals>.patched_call_tool.<locals>.<lambda>  s8     
:
 
06
 

  r   r   )r   r   r   s   ``r   patched_call_toolz1_patch_lowlevel_server.<locals>.patched_call_tool  s(          	r   c                       fdS )zFPatched version of Server.get_prompt that adds Sentry instrumentation.c                 8     t          d          |           S )Nr5   r   )r   original_get_promptr   s    r   r   zD_patch_lowlevel_server.<locals>.patched_get_prompt.<locals>.<lambda>&  s+     
:4
 

  r   r   )r   r   s   `r   patched_get_promptz2_patch_lowlevel_server.<locals>.patched_get_prompt#  "         	r   c                       fdS )zIPatched version of Server.read_resource that adds Sentry instrumentation.c                 8     t          d          |           S )Nr   r   )r   original_read_resourcer   s    r   r   zG_patch_lowlevel_server.<locals>.patched_read_resource.<locals>.<lambda>2  s+     
:"J
 

  r   r   )r   r   s   `r   patched_read_resourcez5_patch_lowlevel_server.<locals>.patched_read_resource/  r   r   N)r   	call_tool
get_promptread_resource)r   r   r   r   r   r   s      @@@r   r   r     s      )     )F !+     +F $1     1Fr   )'__doc__r   	functoolsr   typingr   ri   sentry_sdk.ai.utilsr   sentry_sdk.constsr   r   sentry_sdk.integrationsr   r	   sentry_sdk.utilsr
   sentry_sdk.scoper   mcp.server.lowlevelr   mcp.server.lowlevel.serverr   ImportErrorr   r   r   r   r2   rB   rR   rd   rv   r|   r   r   r   r   r   r   r   r   <module>r      s                           7 7 7 7 7 7 * * * * * * * * = = = = = = = = + + + + + + 4 4 4 4 4 40******6666666 0 0 0
,.
/
//0  /..........! ! ! ! ![ ! ! !0(1 (1 (1VF F F4!F !F !FH& & &RL L Lf" " "J> > >B> > >B! ! !H$" $" $"N'1 '1 '1 '1 '1s   A A