
    kKj4o                       d Z ddlmZ ddlZddlZddlZddlZddlmZ ddl	m
Z
mZ ddlmZ ddl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Zdd	lmZ dd
lmZmZm Z  ddl!m"Z"m#Z# ddl!m$Z% ddl&m'Z' ddl(Z(ddl)m*Z*m+Z+ ddl,m-Z-m$Z$ ddl.m/Z/m0Z0m1Z1 ddl2m3Z3m4Z4 ddl5m6Z6m7Z7 ddl8m9Z9 ddl:m;Z; ddl<m=Z= ddl>m?Z?m@Z@mAZA  e;eB      ZCerddlDmEZE ddlFmGZG  G d deH      ZI ed      d0d       ZJ ededef          ZKe G d! d"e             ZL e
d#d#$       G d% d&             ZMd1d'ZN G d( d)e/      ZOed2d*       ZPeddddde?dddddddd#d+	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 d3d,       ZPe	 d4dddddde?dddddddd#d-	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 d5d.       ZP	 d4dddddde?dddddddd#d-	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 d6d/ZPy)7z'Standalone @tool decorator for FastMCP.    )annotationsN)Callable)	dataclassfield)	lru_cache)
MethodType)
TYPE_CHECKING	AnnotatedAnyLiteralProtocolTypeVarcastget_type_hintsoverloadruntime_checkable)McpError)	ErrorDataIconToolAnnotations)FieldTypeAdapter)ValidationError)SkipJsonSchema)get_fastmcp_metaresolve_task_config)FastMCPDeprecationWarningr   )Tool
ToolResultToolResultSerializerType)ParsedFunction_is_object_schema)call_sync_fn_in_threadpoolis_coroutine_function)	AuthCheck)
get_logger)
TaskConfig)NotSetNotSetTget_cached_typeadapter)Docket)	Executionc                      e Zd ZdZy)_ToolBodyErroru4  Marks a ``pydantic.ValidationError`` raised while executing a tool's body.

    Pydantic validates a tool's arguments *before* invoking the body, so a bare
    ``pydantic.ValidationError`` surfacing from the call adapter is unambiguously
    an argument-validation failure (a bad call). Errors a tool raises from its
    own body — e.g. constructing a model from upstream data — are a different
    class of problem (a server-side bug) that must not be reclassified as a bad
    call. We wrap the body so those are tagged and can be told apart. See #4128.
    N)__name__
__module____qualname____doc__     l/Users/ahmed/devFolder/Ultron/claude-voice/.venv/lib/python3.12/site-packages/fastmcp/tools/function_tool.pyr.   r.   >   s    r4   r.   i  )maxsizec                    t               rd fd}nd fd}	 t         d      }t        j                         }i }|j
                  j                         D ]H  \  }}||v r	||   ||<   |j                  t        j                  j                  us:|j                  ||<   J d|v r	|d   |d<   n5|j                  t        j                  j                  ur|j                  |d<   ||_        ||_        t         dd      |_        t         dd	      |_        t         d
|j"                        |_        t         d|j$                        |_        |S # t        $ r i }Y 8w xY w)u  Wrap ``fn`` so a ``pydantic.ValidationError`` raised by its body is
    re-raised as ``_ToolBodyError``.

    The wrapper preserves ``fn``'s signature and annotations so the cached
    ``TypeAdapter`` validates arguments identically — only body execution is
    affected. Argument validation happens before the wrapper is called, so it
    keeps raising a bare ``pydantic.ValidationError``.
    returnc                 b   K   	  | i | d {   S 7 # t         $ r}t        |d }~ww xY wwNPydanticValidationErrorr.   argskwargsefns      r5   wrapperz"_wrap_body_errors.<locals>.wrapperV   s9     ,00000* ,$!+,s(   /  / 	,',/c                 F    	  | i |S # t         $ r}t        |d }~ww xY wr:   r;   r=   s      r5   rB   z"_wrap_body_errors.<locals>.wrapper]   s0    ,4*6*** ,$!+,s    	  Tinclude_extrasr/   rB   r2   Nr0   r1   r>   r   r?   r   r8   r   )r$   r   	Exceptioninspect	signature
parametersitems
annotation	Parameteremptyreturn_annotation	Signature__signature____annotations__getattrr/   r2   r0   r1   )rA   rB   resolved_hintssigr   
param_nameparams   `      r5   _wrap_body_errorsrX   J   sY    R 	,	,'4@ 

B
C"$K ^^113
E'&4Z&@K
#W%6%6%<%<<&+&6&6K
#	 4
 >! .x 8H			g&7&7&=&=	= # 5 5HG)Gr:y9Gb)T2GO \73E3EFG"2~w7K7KLGN)  s   E E! E!F.)boundc                  $    e Zd ZU dZded<   ddZy)DecoratedToolz,Protocol for functions decorated with @tool.ToolMeta__fastmcp__c                     y r:   r3   )selfr>   r?   s      r5   __call__zDecoratedTool.__call__   s    #r4   NrF   )r/   r0   r1   r2   rR   ra   r3   r4   r5   r\   r\      s    6=r4   r\   T)frozenkw_onlyc                     e Zd ZU dZ edd      Zded<   dZded	<   dZd
ed<   dZ	ded<   dZ
ded<   dZded<   dZded<   eZded<   dZded<   dZded<   dZded<   dZded<   dZded<   dZded<   dZd ed!<   dZd"ed#<   d$Zd%ed&<   d$Zd%ed'<   y)(r]   z6Metadata attached to functions by the @tool decorator.toolF)defaultinitzLiteral['tool']typeN
str | Nonenamestr | int | Noneversiontitledescriptionlist[Icon] | Noneiconsset[str] | Nonetagsdict[str, Any] | NotSetT | Noneoutput_schemaToolAnnotations | Noner   dict[str, Any] | Nonemetar   appbool | TaskConfig | Nonetasklist[str] | Noneexclude_args
Any | None
serializerfloat | Nonetimeout"AuthCheck | list[AuthCheck] | NoneauthTboolenabledrun_in_thread)r/   r0   r1   r2   r   rh   rR   rj   rl   rm   rn   rp   rr   r(   rt   r   rw   rx   rz   r|   r~   r   r   r   r   r3   r4   r5   r]   r]      s    @!&u=D/=D* $G$E:"K"#E# D/ 5;M2;*.K'."&D
&CO%)D
")%)L")!J
! G\ /3D
,3GTM4r4   r]   c                |   	 t        | d      S # t        $ r | }t        |t        j                        r'|j
                  }t        |t        j                        r'	 t        |d      }n# t        $ r i cY cY S w xY wt        j                  |       j                  D ci c]  }||v r|||    nc c}w c}cY S w xY w)ao  Resolve a callable's parameter type hints, tolerating partials.

    ``get_type_hints`` rejects ``functools.partial`` objects (and other
    non-function callables), which the synchronous TypeAdapter path handles
    natively. For those, resolve hints against the underlying function and keep
    only the parameters that remain in the partially-bound signature.
    TrD   )	r   	TypeError
isinstance	functoolspartialfuncrH   rI   rJ   )rA   targetresolvedrj   s       r5   _resolve_param_hintsr      s    
b66 
!2!23[[F !2!23	%fTBH 	I	  ))"-88
8x (4. 8
 	

s@    AB;A*)B;*A:5B;9A::$B;B0/	B;:B;c                     e Zd ZU ded<   dZded<   dZded<   edddddddddeddddddd		 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 dd
       ZddZ		 	 	 	 	 	 	 	 ddZ
edd       ZddZddd	 	 	 	 	 	 	 	 	 	 	 ddZddZy)FunctionToolz"SkipJsonSchema[Callable[..., Any]]rA   Nz3Annotated[SkipJsonSchema[Any], Field(exclude=True)]return_typeTu  Annotated[bool, Field(description="Applies to sync tool functions only. When True (default), sync functions are dispatched to a worker thread so they don't block the event loop. Set to False to run the sync function inline on the event loop thread — useful for libraries with thread affinity (e.g. Windows COM, tkinter). Ignored for async functions, which always run on the event loop. Cannot be combined with `timeout` on a sync function: inline calls have no cancellation checkpoints, so the timeout would be a silent no-op.")]r   )metadatarj   rl   rm   rn   rp   rr   r   r|   rt   r~   rw   rz   r   r   r   c                  t        d |||||||	||||||fD              xs |t        uxs |
du}||rt        d      ||st        |      }t	        |t
              r|}|t        ||||||||	|||
||||dn|      }|j                  6t        j                  j                  rt        j                  dt        d       |j                  r6t        j                  j                  rt        j                  d	t        d       t        j                  ||j                  
      }|j                   xs |j                   }|dk(  rt#        d      |j$                  ;|j&                  s/t)        |      s$t+        j,                  |      st#        d|d      |j.                  }|t1        d      }n(t	        |t2              rt1        j4                  |      }n|}|j7                  ||       t	        |j8                  t:              r|j8                  }n|j8                  }|)t	        |t<              rt?        |      st#        d|       | d#i d|j@                  d|jB                  d|j                   xs |j                   d|jD                  tG        |jD                        ndd|jH                  d|jJ                  |jJ                  n|jJ                  d|jL                  d|jN                  d|d|jP                  d|jR                  xs
 tU               d|j                  d|jV                  d|d |j$                  d!|jX                  d"|j&                  S )$a{  Create a FunctionTool from a function.

        Args:
            fn: The function to wrap
            metadata: ToolMeta object with all configuration. If provided,
                individual parameters must not be passed.
            name, title, etc.: Individual parameters for backwards compatibility.
                Cannot be used together with metadata parameter.
        c              3  8   K   | ]  }|d uxr |t         u  y wr:   )r(   ).0xs     r5   	<genexpr>z-FunctionTool.from_function.<locals>.<genexpr>   s,      A 1!6/1s   Nz|Cannot pass both 'metadata' and individual parameters to from_function(). Use metadata alone or individual parameters alone.Trj   rl   rm   rn   rp   rr   rt   r   rw   rz   r|   r~   r   r   r   zThe `serializer` parameter is deprecated. Return ToolResult from your tools for full control over serialization. See https://gofastmcp.com/servers/tools#custom-serialization for migration examples.   
stacklevelzThe `exclude_args` parameter is deprecated as of FastMCP 2.14. Use dependency injection with `Depends()` instead for better lifecycle management. See https://gofastmcp.com/servers/dependency-injection#using-depends for examples.)r|   z<lambda>z,You must provide a name for lambda functionszTool z: timeout cannot be enforced when run_in_thread=False on a sync function. Inline execution has no cancellation checkpoints, so the timeout would be a no-op. Either drop the timeout or remove run_in_thread=False and accept worker-thread dispatch.	forbidden)modezROutput schemas must represent object types due to MCP spec limitations. Received: rA   r   rj   rl   rm   rn   rp   rJ   rt   r   rr   r~   rw   task_configr   r   r   r3   )-anyr(   r   r   r   r]   r~   fastmcpsettingsdeprecation_warningswarningswarnr   r|   r!   from_functionrj   
ValueErrorr   r   r$   rH   isasyncgenfunctionrz   r'   r   	from_boolvalidate_functionrt   r)   dictr"   rA   r   rl   strrm   rn   rp   input_schemar   rr   setrw   r   )clsrA   r   rj   rl   rm   rn   rp   rr   r   r|   rt   r~   rw   rz   r   r   r   individual_params_providedfmeta	parsed_fn	func_name
task_valuer   final_output_schemas                            r5   r   zFunctionTool.from_function   s   D   !  ($ F*%(& 4') 	#. $>E 
 $>$R(E%*  '+')%&3&;dH$ *w/?/?/T/TMMg *   W%5%5%J%JMMe * #00(BWBWX	MM3Y^^	
"KLL (**)"-..r2	} %1 1  ]]
$+6K
D)$..z:K$K%%b)4 h,,g6"+"9"9"*"8"8*z:Mt/T$%89 !!4 79 
  
||
!--
 0)..
 .6-=-=-IC(()t	

 ..
 ##/ !,,&&
 ..
 !--
 .
 !,,
 '#%
  **
 
  $!
" $$#
$ %
& #00'
 	
r4   c                L  K   ddl m}  || j                  | j                        }t	        |      }t        |      }t        |      }	 | j                  E	 t        j                  | j                        5  | j                  |||       d{   }ddd       n| j                  |||       d{   }| j1                        S 7 9# 1 sw Y   8xY w# t        $ rc t        j                  d| j                   d| j                   d       t        t!        dd| j                   d	| j                   d
            dw xY w7 # t"        $ r*}t%        t'        |      t(        j*                        |d}~wt,        $ r"}|j.                  }	|	J |	|	j.                  d}~ww xY ww)zRun the tool with arguments.r   without_injected_parametersr   NzTool 'z' timed out after z`s. Consider using task=True for long-running operations. See https://gofastmcp.com/servers/tasksi z' execution timed out after s)codemessage	log_level)fastmcp.server.dependenciesr   rA   r   rX   r*   r$   r   anyio
fail_after_executeTimeoutErrorloggerwarningrj   r   r   r<   r   r   loggingWARNINGr.   	__cause__convert_result)
r`   	argumentsr   
wrapper_fnexec_fntype_adapterexec_is_asyncresultr@   originals
             r5   runzFunctionTool.run  s    K0GG4#5#5


 $J/-g6-j9"	3||' ))$,,7'+}}(-( " 8"  $}}\=)TT  ""6**A" 87 $  NN +=dll^ LB C
 #!!'&,TYYK7STXT`T`Saab$c
     U& 	L "#a&GOOD!K 	3 {{H''' 2 22	3s   AF$	E C 5CCCC E 0E1E 5F$CCC A,E  E 	F!%E33F!?FF!!F$c                X  K   |r|j                  |      }n<| j                  rt        |j                   |       d{   }n|j                  |      }	 t        j                  |      r
| d{   }| j                  |       d{   S 7 O7 7 # t        $ r}t        |d}~ww xY ww)aA  Validate arguments and execute the tool body.

        Argument validation runs first and raises a bare
        ``pydantic.ValidationError`` on bad input. Body execution (awaiting the
        result and materializing generators) is wrapped so any pydantic error it
        raises is tagged as ``_ToolBodyError``.
        N)validate_pythonr   r#   rH   isawaitable_materialize_generatorr<   r.   )r`   r   r   r   r   r@   s         r5   r   zFunctionTool._execute  s       !11)<F5,,i F "11)<F		(""6*% 44V<<< & =& 	( !a'	(sW   :B*BB*B .B/B BB B*B B 	B'B""B''B*c                   K   t        j                  |       r| 2 cg c3 d{   }|t        j                  |       rt        |       S | S 7 )6 c}S c c}w w)a  Consume generators/async generators into lists.

        Without this, async generators pass through as objects (repr string),
        and sync generators get consumed during text serialization but are
        exhausted by the time structured content is built.
        N)rH   
isasyncgenisgeneratorlist)r   items     r5   r   z#FunctionTool._materialize_generator  sP      f%+1224Dv&< 3222s5   AAAA
AA"AAAAc                    | j                   j                         sy|j                  | j                  | j                  g       y)u  Register this tool with docket for background execution.

        Registers the raw function so Docket sees and resolves ALL
        dependencies — both FastMCP's (CurrentContext, Progress) and
        Docket-native ones (Retry, Timeout, ConcurrencyLimit).
        N)names)r   supports_tasksregisterrA   key)r`   dockets     r5   register_with_docketz!FunctionTool.register_with_docket  s3     ..0z2r4   )fn_keytask_keyc               ~   K   |xs | j                   }|r||d<     |j                  |fi |di | d{   S 7 w)a  Schedule this tool for background execution via docket.

        FunctionTool splats the arguments dict since .fn expects **kwargs.

        Args:
            docket: The Docket instance
            arguments: Tool arguments
            fn_key: Function lookup key in Docket registry (defaults to self.key)
            task_key: Redis storage key for the result
            **kwargs: Additional kwargs passed to docket.add()
        r   Nr3   )r   add)r`   r   r   r   r   r?   
lookup_keys          r5   add_to_docketzFunctionTool.add_to_docket  sH     ( 'txx
$F5M5ZVZZ
5f5B	BBBBs   4=;=c                ~   ddl m}  || j                  | j                        }t	        |      }t        |      }|j                         D ]9  \  }}|j                  |      }|t        |      }		 |	j                  |      ||<   ; |S # t        $ r*}
t        t        |
      t        j                        |
d}
~
ww xY w)u  Validate client arguments against their declared parameter types.

        The synchronous ``run()`` path validates arguments through the
        function's Pydantic TypeAdapter, so a parameter typed as a model
        arrives as a model instance. The task path hands the raw arguments to
        Docket, which binds them to the function signature without coercion —
        so without this a model-typed parameter would reach the function as a
        raw dict (#4349). ``submit_to_docket`` calls this up front so coerced
        values are what get queued, and validation errors surface before any
        task state is created. Coerced values survive the trip to the worker
        because Docket serializes task arguments with cloudpickle.

        Injected dependency parameters (Context, Depends()) are excluded via
        the same wrapper used by the synchronous path, so only client-supplied
        arguments are coerced and Docket's dependency resolution is untouched.
        r   r   r   Nr   )r   r   rA   r   r   r   rK   getr*   r   r<   r   r   r   r   )r`   r   r   r   hintscoercedrj   valuerL   adapterr@   s              r5   coerce_task_argumentsz"FunctionTool.coerce_task_arguments  s    " 	L0GG4#5#5

 %Z0y/$??,KD%4J!,Z8GP ' 7 7 > -  + P &c!fHaO	Ps   1B			B<%B77B<)$rA   Callable[..., Any]r   zToolMeta | Nonerj   ri   rl   rk   rm   ri   rn   ri   rp   ro   rr   rq   r   ru   r|   r{   rt   rs   r~   zToolResultSerializerType | Nonerw   rv   rz   ry   r   r   r   r   r   zbool | Noner8   r   )r   dict[str, Any]r8   r   )r   zTypeAdapter[Any]r   r   r   r   r8   r   )r   r   r8   r   )r   r+   r8   None)r   r+   r   r   r   ri   r   ri   r?   r   r8   r,   )r   r   r8   r   )r/   r0   r1   rR   r   r   classmethodr(   r   r   r   staticmethodr   r   r   r   r3   r4   r5   r   r      s   **GKKDK 	     
 %)$( "&#' $.2)-9?6:&*)- $37%))l
l
 "	l
 l
 "l
 l
  l
 !l
 l
 ,l
 'l
 7l
 4l
  $!l
" '#l
$ %l
& 1'l
( #)l
* 
+l
 l
\1+f$(&$( $( "	$(
 
$(L  	3  "#CC "C
 C C C 
C2%r4   r   c                     y r:   r3   )rA   s    r5   re   re   4  s    r4   )rl   rm   rn   rp   rr   rt   r   rw   rz   r|   r~   r   r   r   c                    y r:   r3   )
name_or_fnrl   rm   rn   rp   rr   rt   r   rw   rz   r|   r~   r   r   r   s                  r5   re   re   6  s    $ r4   r   c                    y r:   r3   )r   rj   rl   rm   rn   rp   rr   rt   r   rw   rz   r|   r~   r   r   r   s                   r5   re   re   I  s    & r4   c                 	
 t        t              rt        di t        | t              rt	        d      d		
fdd
	
fdd
fdt        j                  |       r	 | |      S t        | t              r|t	        d      | n| |nt	        dt        |              dfd}|S )u*  Standalone decorator to mark a function as an MCP tool.

    Returns the original function with metadata attached. Register with a server
    using mcp.add_tool().

    Args:
        run_in_thread: Applies to sync tool functions only. When True (default),
            the sync function is dispatched to a worker thread so it does not
            block the event loop. Set to False to run the function inline on the
            event loop thread — useful for libraries with thread affinity
            (e.g. Windows COM via `uiautomation`/`comtypes`/`pywin32`, `tkinter`,
            some GPU/driver bindings). Ignored for async functions. Cannot be
            combined with `timeout` on a sync function: inline calls have no
            cancellation checkpoints, so the timeout would be a silent no-op.
    zsTo decorate a classmethod, use @classmethod above @tool. See https://gofastmcp.com/servers/tools#using-with-methodsc                x    t        |	t              
      }t        j                  | |      S )Nr   )r   )r]   r   r   r   )rA   	tool_name	tool_metar   r   rn   r|   rp   rw   rt   r   r~   rr   rz   r   rm   rl   s      r5   create_toolztool.<locals>.create_tool  sW    #'#$T*%!'
	" ))"y)AAr4   c                    t        |
	      }t        | t        t        z        r| j                  n| }|t        t        |      _        | S )Nr   )r]   r   r   r   __func__r   r   r^   )rA   r   r   r   r   r   rn   r|   rp   rw   rt   r   r~   rr   rz   r   rm   rl   s       r5   attach_metadataztool.<locals>.attach_metadata  si    #'#%!'
" !+2|j/H Ir(0S&%	r4   c                    t         j                  j                  dk(  r%t        j                  dt
        d        | |      S  | |      S )Nobjectzdecorator_mode='object' is deprecated and will be removed in a future version. Decorators now return the original function with metadata attached.   r   )r   r   decorator_moder   r   r   )rA   r   r   r   s     r5   	decoratorztool.<locals>.decorator  sK    **h6MMV)	 r9--r9--r4   z6Cannot specify name both as first argument and keywordzInvalid first argument: c                     |       S r:   r3   )rA   r  r   s    r5   rB   ztool.<locals>.wrapper  s    Y''r4   r3   )rA   r   r   ri   r8   r   )rA   rY   r   ri   r8   rY   rA   rY   r8   rY   )	r   r   r   r   r   rH   	isroutiner   rh   )r   rj   rl   rm   rn   rp   rr   rt   r   rw   rz   r|   r~   r   r   r   rB   r   r   r  r   s     `````````````` @@@@r5   re   re   _  s    D +t$%44*k*I
 	

B B B*  ,	. $T**	J	$TUU				24
3C2DEFF( Nr4   )rA   r   r8   r   )rA   r   r8   r   r  ) r   r   rl   rk   rm   ri   rn   ri   rp   ro   rr   rq   rt   rs   r   'ToolAnnotations | dict[str, Any] | Nonerw   rv   rz   ry   r|   r{   r~   r}   r   r   r   r   r   r   r8   Callable[[F], F]r:   )"r   r   rj   ri   rl   rk   rm   ri   rn   ri   rp   ro   rr   rq   rt   rs   r   r  rw   rv   rz   ry   r|   r{   r~   r}   r   r   r   r   r   r   r8   r  )"r   zstr | Callable[..., Any] | Nonerj   ri   rl   rk   rm   ri   rn   ri   rp   ro   rr   rq   rt   rs   r   r  rw   rv   rz   ry   r|   r{   r~   r}   r   r   r   r   r   r   r8   r   )Qr2   
__future__r   r   rH   r   r   collections.abcr   dataclassesr   r   r   typesr   typingr	   r
   r   r   r   r   r   r   r   r   r   mcp.shared.exceptionsr   	mcp.typesr   r   r   pydanticr   r   r   r<   pydantic.json_schemar   r   fastmcp.decoratorsr   r   fastmcp.exceptionsr   fastmcp.tools.baser   r   r    fastmcp.tools.function_parsingr!   r"   fastmcp.utilities.async_utilsr#   r$   fastmcp.utilities.authorizationr%   fastmcp.utilities.loggingr&   fastmcp.utilities.tasksr'   fastmcp.utilities.typesr(   r)   r*   r/   r   r   r+   docket.executionr,   rG   r.   rX   rY   r\   r]   r   r   re   r3   r4   r5   <module>r     s   - "     $ (      * 6 6 ' ? /  D I 
 M 6 0 .  
H	*	Y 	 44 4n CxS)* >H > > $%  &.
2r4 rj 
  
 	 !%"# 5;;?"&%)%)! /3!  	
    3 9   # #   -  !" # 
$ 
  $"# 5;;?"&%)%)! /3#  	
     3 9   # #    -!" #$ % 
, 37o  $"# 5;;?"&%)%)! /3#o/o o 	o
 o o o o 3o 9o  o #o #o o o  -!o" #o$ 	%or4   