
    jKj:                    (   d Z ddlmZ ddlZddlZddlmZmZmZm	Z	 ddl
mZ ddlmZmZmZ ddlmZmZmZ ddlmZmZmZmZmZmZmZmZmZmZ dd	l m!Z! dd
l"m#Z# ddl$m%Z&m'Z'm(Z( dZ)ddZ*ddZ+ddZ,ddZ-ddZ.ddZ/ddZ0ddZ1ddZ2ddZ3d dZ4y)!u  FastMCP adapter.

Rather than wrap each tool individually (as the TS high-level adapter does with a
Proxy), we wrap two *central* seams the ``mcp`` SDK routes everything through:

* ``ToolManager.call_tool`` — every tool call dispatches here. We strip the
  injected ``context`` before Pydantic validation, time the call, capture the
  result/exception, and re-raise. Late-registered tools are covered automatically.
* the low-level ``ListToolsRequest`` handler — every ``tools/list`` response is
  built here. We capture ``$mcp_tools_list`` and inject the ``context`` parameter
  into each advertised tool schema.

``$mcp_initialize`` is emitted lazily on the first tool call (the Python SDK
handles ``initialize`` in the session layer, not via ``request_handlers``).
    )annotationsN)AnyDictOptionalTuple   )add_context_parameter_to_schemaget_context_descriptionis_context_enabled)add_conversation_id_to_schemabuild_prompt_backresolve_conversation_id)
_to_jsonableappend_get_more_toolsbuild_tool_call_requestextract_toolsprepare_requestread_tool_categoryrecord_missing_capabilityrecord_tool_callrecord_tools_listrequest_to_dict)MCPAnalyticsData)log)GET_MORE_TOOLS_NAMEget_more_tools_result_text$resolve_missing_capability_tool_name__posthog_mcp_wrapped__c                    t        | dd       xs t        t        | dd       dd       |_        t        t        | dd       dd       |_        t        | |       t	        | |       y )Nname_mcp_serverversion)getattrserver_nameserver_version_wrap_tool_manager_call_wrap_list_tools_handler)serverdatas     p/Users/ahmed/devFolder/Ultron/claude-voice/.venv/lib/python3.12/site-packages/posthog/mcp/_instrument_fastmcp.pyinstrument_fastmcpr+   >   s`    vvt4 t,fd9D "'&-"F	SWXDFD)VT*    c                     t         dd       }|t        d       y |j                  t        t        d      ry 	 	 d	 	 	 	 	 	 	 	 	 d fd}t	        |t        d       ||_        y )N_tool_managerzNWarning: FastMCP server has no _tool_manager; tool calls will not be captured.Fc                  K   t        |      \  }}t        |      }t        | |      }d|i}t        |||||       d {   }	t	        j
                        }
j
                  j                  rS| |
k(  rNt        |	|
|xs i j                  d      ||||       d {    t        j                  dt                     gS t        j
                  j                  || |
      \  }}|}t        |t              rt!               }t#        | d      s|j%                  d       j
                  j                  rt#        | d      s|j%                  d       |r(|j'                         D ci c]  \  }}||vs|| }}}t)        j*                         }	  | |||       d {   }|}|r|rt1        ||      }||u rd }|}t/        |	| ||t)        j*                         |z
  d	z  ||||
       d {    |S 7 7 _c c}}w 7 a# t,        $ r@}t/        |	| ||t)        j*                         |z
  d	z  |||rd n||

       d {  7    d }~ww xY w7 `w)N
session_idmcp_session_idclient_nameclient_versionrequestextracontext)	tool_namer7   	argumentsr3   r4   r6   texttyper:   conversation_id)r7   convert_result  )r    r9   errorduration_msr3   r4   r=   r6   )r    r9   resultrA   r3   r4   r=   r6   )_client_info_mcp_session_idr   r   r   optionsreport_missingr   get	mcp_typesTextContentr   r   enable_conversation_id
isinstancedictset_tool_owns_paramadditemstime	monotonic	Exceptionr   _inject_prompt_back)r    r9   r7   r>   r3   r4   r2   r5   r6   r0   missing_namer=   mintedcall_arguments
strip_keyskvstartrB   r@   delivered_conversation_idinjectedr)   originalr(   s                         r*   wrappedz(_wrap_tool_manager_call.<locals>.wrappedV   s     '37&;#^(1)$	:!-~ >*)#)
 

 <DLLI<<&&4<+?+&"b--i8#'-	 	 	 %%68R8TU  #:LL//D,#
 #i&J#FD)<y)||22;K/< 01%.__%6"%6TQ!::MAqD%6  "  	#ngn F, %4!o*6?CH6! * F)E1T9#)5
 	
 	
 w
	>"  	 ##!^^-5='-(.O   	8	
s   >IG;AIG> CI,H9H>IH	 %H&H	 *A
I4I5I>IIH	 		I4II	IIIT)NF)
r    strr9   zDict[str, Any]r7   r   r>   boolreturnr   )r#   r   	call_tool_WRAPPED_FLAGsetattr)r(   r)   tool_managerr_   r^   s   ``  @r*   r&   r&   J   s    6?D9L\	
 	%%Hx.
 $	ff!f f 	f
 
fP G]D)$Lr,   c                     t         dd       }|y |j                  }|j                  t        j                        t        t
        d      ry d fd}t        |t
        d       ||t        j                  <   y )Nr!   Fc                  K   |  |        d {   S t              \  }}t              }t        |       }d|i}t        |||||       d {   }t	        j
                         }	  |        d {   }t	        j
                         |z
  dz  }
t        |      }t        |      dk(  }g }|D ]t  }|j                  |j                         t        |dd       r#|j                  j                  |j                  <   t        |      }|s\|j                   |j                  <   v t#        j$                  j&                        }t)        j$                  j&                        }|D ]  }|j                  t*        k(  rt-        |j                        }t        |dd       }|r|st/        ||j                  |      }j$                  j0                  rt3        ||j                        }|t        |dd       us	 ||_         j$                  j8                  rFt;        j$                        t=        fd
|D              st?        |       |j                         t        |||tA        |      |
||rdnd |||       d {    |S 7 }7 ?7 # t        $ r<}	t        |g |t	        j
                         |z
  dz  d|	|||
       d {  7    d }	~	ww xY w# t        $ r t7        d	|j                          Y w xY w7 w)Nr0   r1   r?   T)namesr5   rA   is_errorr@   r3   r4   r6   r   descriptioninputSchemaz(WARN: could not set inputSchema on tool c              3  <   K   | ]  }|j                   k(    y w)N)r    ).0trU   s     r*   	<genexpr>zA_wrap_list_tools_handler.<locals>.list_handler.<locals>.<genexpr>  s     =u!qvv-us   ztools/list returned no tools)	ri   r5   responserA   rj   r@   r3   r4   r6   )!_low_level_client_info_low_level_session_idr   r   rQ   rR   rS   r   r   lenappendr    r#   rk   tool_descriptionsr   tool_categoriesr   rE   r7   r
   _GET_MORE_TOOLS_NAME_tool_owns_contextr	   rJ   r   rl   r   rF   r   anyr   r   )reqr3   r4   r2   r5   r6   r0   r[   rB   r@   rA   toolsemptyri   toolcategorycontext_enabledrk   owns_contextschemarU   r)   r^   r(   s                       @r*   list_handlerz._wrap_list_tools_handler.<locals>.list_handler   s     ;!#&&&<V&D#^.v6!#&!-~ > +)#)
 

  	#C=(F ~~'%/47f% E
aDLL#t]D1484D4D&&tyy1)$/H2:$$TYY/  -T\\-A-AB-dll.B.BCDyy00-fdii@LT=$7F|8KX||226vtyyIWT=$??P'-D$  <<&&?ML=u==%fl;\*!&)#490t#)
 	
 	
 m '
 ) 	#!^^-5='-   	V ! PB499+NOP	
s   L
JA L
JL
-J 8J9J =BL
C+L
=K BL
L	L
L
J 	K!0KKKKL
 !LL
LL
T)r{   r   rb   r   )r#   request_handlersrG   rH   ListToolsRequestrd   re   )r(   r)   	low_levelhandlersr   r^   s   ``   @r*   r'   r'      sr    t4I))H||I667H78]EBZx L-.+7HY''(r,   c                   t        j                  dt        |      d         }t        | t              r/t        |       dk(  r!t        | d   t              rg | d   || d   fS t        | t              rg | |S t        | t              r?t        | j                  d      t              r | j                  d      si | dg | d   |iS | S )a  Append the conversation_id prompt-back to a tool result so the agent echoes
    it on later calls. Handles every shape ToolManager.call_tool can return:
    a ``(content_list, structured)`` tuple (the convert_result=True production path),
    a bare content list, or a ``{content: [...]}`` dict. Returns the result unchanged
    (so the caller can detect non-delivery) for shapes we can't append to.r:   r;      r   r   contentisError)	rH   rI   r   rK   tuplert   listrL   rG   )rB   r=   blocks      r*   rT   rT   1  s     !!+O<VDE &% S[A%5*VAYPT:U#&)#U#VAY//&$64 vzz),d3

9%A&A)%@vi'8%@%%@AAMr,   c                    t        | dd      }|y|j                  |      }t        |dd      }|y	 |t        j                  |      j                  v S # t
        t        f$ r Y yw xY w)u   True when the tool's own function declares ``param`` — then it's a real tool
    argument we must neither inject nor strip (the agent's value belongs to the tool).r.   NFfn)r#   get_toolinspect	signature
parameters	TypeError
ValueError)r(   r    paramrf   r~   r   s         r*   rN   rN   G  sy     6?D9L  &D	tT	"B	z))"-8888z" s    A A&%A&c                    t        | |d      S )Nr7   )rN   )r(   r    s     r*   ry   ry   W  s    FD)44r,   c                f    t        | dd      }|y	 |j                  S # t        t        f$ r Y yw xY w)zThe underlying low-level server's request_context, set during a request. The
    tools/list handler runs on ``server._mcp_server``, so client info / session id
    come from there rather than from a FastMCP ``Context`` (which only the call path has).r!   N)r#   request_contextLookupErrorAttributeError)r(   r   s     r*   _low_level_request_contextr   [  sC     t4I(((( s    00c                    t        |       }	 |j                  j                  }|r8|j                  r,|j                  j                  |j                  j
                  fS y# t        $ r Y yw xY wN)NN)r   sessionclient_params
clientInfor    r"   rS   )r(   ctxr   s      r*   rr   rr   h  sj    
$V
,C11]55 ++00-2J2J2R2RRR   s   AA 	A*)A*c                    t        |       }	 t        |dd       }t        |dd       }||j                  d      S 	 y # t        $ r Y y w xY w)Nr5   headersmcp-session-id)r   r#   rG   rS   )r(   r   r5   r   s       r*   rs   rs   s  sd    
$V
,C#y$/'9d3;;/00    s   ,< 	AAc                    	 | j                   j                  j                  }|r8|j                  r,|j                  j                  |j                  j
                  fS y# t        $ r Y yw xY wr   )r   r   r   r   r    r"   rS   )r7   r   s     r*   rC   rC     sh    //77EE]55 ++00-2J2J2R2RRR   s   AA 	A)(A)c                    	 t        | j                  dd      }t        |dd      }||j                  d      S 	 y# t        $ r Y yw xY w)zBest-effort transport session id (e.g. the ``Mcp-Session-Id`` header on the
    streamable-HTTP transport). Returns ``None`` for stdio, where the SDK-generated
    session is used instead.r5   Nr   r   )r#   r   rG   rS   )r7   r5   r   s      r*   rD   rD     s`    '119dC'9d3;;/00    s   6; 	AA)r(   r   r)   r   rb   None)rB   r   r=   r`   rb   r   )r(   r   r    r`   r   r`   rb   ra   )r(   r   r    r`   rb   ra   )r(   r   rb   r   )r(   r   rb   #Tuple[Optional[str], Optional[str]])r(   r   rb   Optional[str])r7   r   rb   r   )r7   r   rb   r   )5__doc__
__future__r   r   rQ   typingr   r   r   r   	mcp.typestypesrH   _context_parametersr	   r
   r   _conversation_idr   r   r   _instrumentationr   r   r   r   r   r   r   r   r   r   	_internalr   loggerr   r|   r   rx   r   r   rd   r+   r&   r'   rT   rN   ry   r   rr   rs   rC   rD    r,   r*   <module>r      s   
  #   - -  
 
   (   *+u%vf8X, 5
	r,   