
    $j3<                       d Z ddlmZ ddlmZmZmZ ddlmZm	Z	m
Z
mZ ddlZddlmZ ddlm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 ddlmZmZ erddlm Z   ee!          Z" e
d          Z#ddZ$ G d d          Z%dS )zGMCP protocol handler setup and wire-format handlers for FastMCP Server.    )annotations)	AwaitableCallableSequence)TYPE_CHECKINGAnyTypeVarcastN)McpError)ContentBlock)AnyUrl)DisabledErrorNotFoundError)TaskMeta)
get_logger)paginate_sequence)VersionSpecdedupe_with_versions)FastMCP	PaginateTitemsSequence[PaginateT]cursor
str | None	page_size
int | Nonereturn"tuple[list[PaginateT], str | None]c           	         |t          |           dfS 	 t          | ||          S # t          $ rA}t          t          j                            dt          |                              |d}~ww xY w)zApply pagination to items, raising McpError for invalid cursors.

    If page_size is None, returns all items without pagination.
    Nicodemessage)listr   
ValueErrorr   mcptypes	ErrorDatastr)r   r   r   es       l/home/rurouni/.hermes/hermes-agent/venv/lib/python3.11/site-packages/fastmcp/server/mixins/mcp_operations.py_apply_paginationr+      s     E{{D  P 	::: P P Psy**A*GGHHaOPs   & 
A1<A,,A1c                  b    e Zd ZdZd*dZd+d
Zd,dZd-dZd.dZd/dZ	d0dZ
d1d!Zd2d%Zd3d(Zd)S )4MCPOperationsMixina  Mixin providing MCP protocol handler setup and wire-format handlers.

    Note: Methods registered with SDK decorators (e.g., _list_tools_mcp, _call_tool_mcp)
    cannot use `self: FastMCP` type hints because the SDK's `get_type_hints()` fails
    to resolve FastMCP at runtime (it's only available under TYPE_CHECKING). When
    type hints fail to resolve, the SDK falls back to calling handlers with no arguments.
    These methods use untyped `self` to avoid this issue.
    selfr   r   Nonec                    | j                                         | j                    | j                                         | j                    | j                                         | j                   |                     | j                  | j         j	        t          j        j        <    | j                             | j                  | j                    | j                                         | j                    | j                                         | j                    | j                                         | j                   |                                  dS )aR  Set up core MCP protocol handlers.

        List handlers use SDK decorators that pass the request object to our handler
        (needed for pagination cursor). The SDK also populates caches like _tool_cache.

        Exception: list_resource_templates SDK decorator doesn't pass the request,
        so we register that handler directly.

        The call_tool decorator is from the SDK (supports CreateTaskResult + validate_input).
        The read_resource and get_prompt decorators are from LowLevelServer to add
        CreateTaskResult support until the SDK provides it natively.
        )validate_inputN)_mcp_server
list_tools_list_tools_mcplist_resources_list_resources_mcplist_prompts_list_prompts_mcp_wrap_list_handler_list_resource_templates_mcprequest_handlersr%   r&   ListResourceTemplatesRequest	call_toolstrict_input_validation_call_tool_mcpread_resource_read_resource_mcp
get_prompt_get_prompt_mcpset_logging_level_set_logging_level_mcp_setup_task_protocol_handlers)r.   s    r*   _setup_handlersz"MCPOperationsMixin._setup_handlers6   sK    	&##%%d&:;;;)''))$*BCCC'%%''(>???
 ##D$EFF 	)#)*PQ 	P""$2N"OO	
 	
 	
 	)&&(()@AAA%##%%d&:;;;,**,,T-HIII 	**,,,,,    handlerCallable[..., Awaitable[Any]]0Callable[..., Awaitable[mcp.types.ServerResult]]c                    dfd}|S )z@Wrap a list handler to pass the request and return ServerResult.requestr   r   mcp.types.ServerResultc                h   K    |            d {V }t           j                            |          S N)r%   r&   ServerResult)rM   resultrI   s     r*   wrapperz6MCPOperationsMixin._wrap_list_handler.<locals>.wrapper\   s>      "77++++++++F9))&111rH   )rM   r   r   rN    )r.   rI   rS   s    ` r*   r9   z%MCPOperationsMixin._wrap_list_handlerW   s(    
	2 	2 	2 	2 	2 	2 rH   rM   mcp.types.ListToolsRequestmcp.types.ListToolsResultc                  K   t          d|           }t                              d|j         d           t	          t          |                                 d{V           d           }d |D             }||j        r|j        j        nd}t          |||j
                  \  }}t          j                            ||          S )z
        List all available tools, in the format expected by the low-level MCP
        server. Supports pagination when list_page_size is configured.
        r   [z] Handler called: list_toolsNc                    | j         S rP   namets    r*   <lambda>z4MCPOperationsMixin._list_tools_mcp.<locals>.<lambda>n   s
    PQPV rH   c                D    g | ]}|                     |j                   S rZ   )to_mcp_toolr[   ).0tools     r*   
<listcomp>z6MCPOperationsMixin._list_tools_mcp.<locals>.<listcomp>o   s+    HHH$T%%49%55HHHrH   )tools
nextCursor)r
   loggerdebugr[   r   r#   r3   paramsr   r+   _list_page_sizer%   r&   ListToolsResult)r.   rM   serverre   	sdk_toolsr   pagenext_cursors           r*   r4   z"MCPOperationsMixin._list_tools_mcpb   s       i&&BBBBCCC$T0A0A0C0C*C*C*C*C*C*C%D%DFVFVWWHH%HHH	 &-%8W^%8GN!!QU 	 .iAWXXky((t(LLLrH   mcp.types.ListResourcesRequestmcp.types.ListResourcesResultc                  K   t          d|           }t                              d|j         d           t	          t          |                                 d{V           d           }d |D             }|j        r|j        j        nd}t          |||j
                  \  }}t          j                            ||          S )z
        List all available resources, in the format expected by the low-level MCP
        server. Supports pagination when list_page_size is configured.
        r   rX   z ] Handler called: list_resourcesNc                *    t          | j                  S rP   )r(   uri)rs    r*   r^   z8MCPOperationsMixin._list_resources_mcp.<locals>.<lambda>   s    3qu:: rH   c                ^    g | ]*}|                     t          |j                             +S ))rt   )to_mcp_resourcer(   rt   )rb   resources     r*   rd   z:MCPOperationsMixin._list_resources_mcp.<locals>.<listcomp>   s@     
 
 
@HH$$X\):):$;;
 
 
rH   )	resourcesrf   )r
   rg   rh   r[   r   r#   r5   ri   r   r+   rj   r%   r&   ListResourcesResult)r.   rM   rl   ry   sdk_resourcesr   rn   ro   s           r*   r6   z&MCPOperationsMixin._list_resources_mcpx   s       i&&FFFFGGG(v,,........//1E1E
 
	
 
LU
 
 
 +2.B&&d-66#9
 
k y,,t,TTTrH   &mcp.types.ListResourceTemplatesRequest%mcp.types.ListResourceTemplatesResultc                  K   t          d|           }t                              d|j         d           t	          t          |                                 d{V           d           }d |D             }|j        r|j        j        nd}t          |||j
                  \  }}t          j                            ||          S )z
        List all available resource templates, in the format expected by the low-level MCP
        server. Supports pagination when list_page_size is configured.
        r   rX   z)] Handler called: list_resource_templatesNc                    | j         S rP   )uri_templater\   s    r*   r^   zAMCPOperationsMixin._list_resource_templates_mcp.<locals>.<lambda>   s    AN rH   c                D    g | ]}|                     |j                   S ))uriTemplate)to_mcp_templater   )rb   templates     r*   rd   zCMCPOperationsMixin._list_resource_templates_mcp.<locals>.<listcomp>   s<     
 
 
 $$1F$GG
 
 
rH   )resourceTemplatesrf   )r
   rg   rh   r[   r   r#   list_resource_templatesri   r   r+   rj   r%   r&   ListResourceTemplatesResult)r.   rM   rl   	templatessdk_templatesr   rn   ro   s           r*   r:   z/MCPOperationsMixin._list_resource_templates_mcp   s       i&&OOOOPPP(v557777777788:R:R
 
	
 
%
 
 
 +2.B&&d-66#9
 
k y44"{ 5 
 
 	
rH   mcp.types.ListPromptsRequestmcp.types.ListPromptsResultc                  K   t          d|           }t                              d|j         d           t	          t          |                                 d{V           d           }d |D             }|j        r|j        j        nd}t          |||j
                  \  }}t          j                            ||          S )z
        List all available prompts, in the format expected by the low-level MCP
        server. Supports pagination when list_page_size is configured.
        r   rX   z] Handler called: list_promptsNc                    | j         S rP   rZ   )ps    r*   r^   z6MCPOperationsMixin._list_prompts_mcp.<locals>.<lambda>   s     rH   c                D    g | ]}|                     |j                   S r`   )to_mcp_promptr[   )rb   prompts     r*   rd   z8MCPOperationsMixin._list_prompts_mcp.<locals>.<listcomp>   s+    TTT&v+++==TTTrH   )promptsrf   )r
   rg   rh   r[   r   r#   r7   ri   r   r+   rj   r%   r&   ListPromptsResult)r.   rM   rl   r   sdk_promptsr   rn   ro   s           r*   r8   z$MCPOperationsMixin._list_prompts_mcp   s       i&&DDDDEEE&v**,,,,,,,,--/?/?
 
 UTGTTT*1.B&&d-!7
 
k y**4K*PPPrH   keyr(   	argumentsdict[str, Any]vlist[ContentBlock] | tuple[list[ContentBlock], dict[str, Any]] | mcp.types.CallToolResult | mcp.types.CreateTaskResultc                V  K   t          d|           }t                              d|j         d||           	 d}d}	 |j        j        }|j        rD|j                            d          }|                    di                               d          }|j	        j
        rE|j	        j        }|                    d          }	t          |	                    d	          
          }n# t          t          f$ r Y nw xY w|rt          |          nd}
|                    |||
|           d{V }t#          |t$          j        j                  r|S |                                S # t,          $ r}t/          d|          |d}~wt.          $ r}t/          d|          |d}~ww xY w)a  
        Handle MCP 'callTool' requests.

        Extracts task metadata from MCP request context and passes it explicitly
        to call_tool(). The tool's _run() method handles the backgrounding decision,
        ensuring middleware runs before Docket.

        Args:
            key: The name of the tool to call
            arguments: Arguments to pass to the tool

        Returns:
            Tool result or CreateTaskResult for background execution
        r   rX   z&] Handler called: call_tool %s with %sNTexclude_nonefastmcpversionttlr   eqr   	task_metazUnknown tool: )r
   rg   rh   r[   r2   request_contextmeta
model_dumpgetexperimentalis_tasktask_metadatar   AttributeErrorLookupErrorr   r=   
isinstancer%   r&   CreateTaskResultto_mcp_resultr   r   )r.   r   r   rl   version_strr   ctx	meta_dictmcp_task_metatask_meta_dictr   rR   r)   s                r*   r?   z!MCPOperationsMixin._call_tool_mcp   s     , i&&CCCCS)	
 	
 	
	A '+K)-I(88 N # 3 3 3 F FI"+--	2">">"B"B9"M"MK#+ H$'$4$BM%2%=%=4%=%P%PN (^-?-?-F-F G G GI"K0    6AJk[1111dG!++Y9 ,        F &#)"<== ''))) 	A 	A 	A 8 8 899q@ 	A 	A 	A 8 8 899q@	AsN   E& B(C' &E& 'C;8E& :C;;AE& E& &
F(0FF(F##F(rt   AnyUrl | str9mcp.types.ReadResourceResult | mcp.types.CreateTaskResultc           
     
  K   t          d|           }t                              d|j         d|           	 d}d}	 |j        j        }|j        rG|j                            d          }|                    d          pi }|                    d          }|j	        j
        rE|j	        j        }|                    d          }	t          |	                    d	          
          }n# t          t          f$ r Y nw xY w|rt          |          nd}
|                    t#          |          |
|           d{V }t%          |t&          j        j                  r|S |                    |          S # t.          $ rD}t1          t&          j                            ddt#          |                              |d}~wt4          $ r7}t1          t&          j                            dd|                     |d}~ww xY w)a  Handle MCP 'readResource' requests.

        Extracts task metadata from MCP request context and passes it explicitly
        to read_resource(). The resource's _read() method handles the backgrounding
        decision, ensuring middleware runs before Docket.

        Args:
            uri: The resource URI

        Returns:
            ReadResourceResult or CreateTaskResult for background execution
        r   rX   z"] Handler called: read_resource %sNTr   r   r   r   r   r   r   izResource not found: r    )r
   rg   rh   r[   r2   r   r   r   r   r   r   r   r   r   r   r   r@   r(   r   r%   r&   r   r   r   r   r'   r   )r.   rt   rl   r   r   r   r   fastmcp_metar   r   r   rR   r)   s                r*   rA   z%MCPOperationsMixin._read_resource_mcp   s^      i&&HHHH#NNN$	&*K)-I(88 > # 3 3 3 F FI#,==#;#;#ArL"."2"29"="=K#+ H$'$4$BM%2%=%=4%=%P%PN (^-?-?-F-F G G GI"K0    6AJk[1111dG!//C'Y 0        F &#)"<== '',,, 	 	 		##)LC)L)L $    	
  	 	 		##9SPQ9S9S#TT 	sN   E5 B+C) (E5 )C=:E5 <C==A"E5  E5 5
H??F>>H2G==Hr[   dict[str, Any] | None6mcp.types.GetPromptResult | mcp.types.CreateTaskResultc                *  K   t          d|           }t                              d|j         d||           	 d}d}	 |j        j        }|j        rD|j                            d          }|                    di                               d          }|j	        j
        rE|j	        j        }|                    d          }	t          |	                    d	          
          }n# t          t          f$ r Y nw xY w|rt          |          nd}
|                    |||
|           d{V }t#          |t$          j        j                  r|S |                                S # t,          $ r}t/          d|          |d}~wt.          $ r  w xY w)a  Handle MCP 'getPrompt' requests.

        Extracts task metadata from MCP request context and passes it explicitly
        to render_prompt(). The prompt's _render() method handles the backgrounding
        decision, ensuring middleware runs before Docket.

        Args:
            name: The prompt name
            arguments: Prompt arguments

        Returns:
            GetPromptResult or CreateTaskResult for background execution
        r   rX   z'] Handler called: get_prompt %s with %sNTr   r   r   r   r   r   r   zUnknown prompt: )r
   rg   rh   r[   r2   r   r   r   r   r   r   r   r   r   r   r   render_promptr   r%   r&   r   to_mcp_prompt_resultr   r   )r.   r[   r   rl   r   r   r   r   r   r   r   rR   r)   s                r*   rC   z"MCPOperationsMixin._get_prompt_mcp0  s       i&&DDDDdI	
 	
 	
	 '+K)-I(88 N # 3 3 3 F FI"+--	2">">"B"B9"M"MK#+ H$'$4$BM%2%=%=4%=%P%PN (^-?-?-F-F G G GI"K0    6AJk[1111dG!//iI 0        F &#)"<== ..000 	D 	D 	D ;4 ; ;<<!C 	 	 		sB   E& B(C' &E& 'C;8E& :C;;AE& E& &
F0FFlevelmcp.types.LoggingLevelc                   K   ddl m} t          d|           }t                              d|j         d|           	 |j        j        }|j        }t          ||          r	||_
        dS dS # t          $ r Y dS w xY w)zHandle MCP 'logging/setLevel' requests.

        Stores the requested minimum log level on the session so that
        subsequent log messages below this level are suppressed.
        r   )MiddlewareServerSessionr   rX   z&] Handler called: set_logging_level %sN)fastmcp.server.low_levelr   r
   rg   rh   r[   r2   r   sessionr   _minimum_logging_levelr   )r.   r   r   rl   r   r   s         r*   rE   z)MCPOperationsMixin._set_logging_level_mcpe  s       	EDDDDDi&&LLLLeTTT	$4CkG'#:;; 716...7 7 	 	 	DD	s   *A, ,
A:9A:N)r.   r   r   r/   )r.   r   rI   rJ   r   rK   )rM   rU   r   rV   )rM   rp   r   rq   )rM   r|   r   r}   )rM   r   r   r   )r   r(   r   r   r   r   )rt   r   r   r   )r[   r(   r   r   r   r   )r   r   r   r/   )__name__
__module____qualname____doc__rG   r9   r4   r6   r:   r8   r?   rA   rC   rE   rT   rH   r*   r-   r-   ,   s         - - - -B	 	 	 	M M M M,U U U U.
 
 
 
2Q Q Q Q(:A :A :A :Ax6 6 6 6p3 3 3 3j     rH   r-   )r   r   r   r   r   r   r   r   )&r   
__future__r   collections.abcr   r   r   typingr   r   r	   r
   	mcp.typesr%   mcp.shared.exceptionsr   r   pydanticr   fastmcp.exceptionsr   r   fastmcp.server.tasks.configr   fastmcp.utilities.loggingr   fastmcp.utilities.paginationr   fastmcp.utilities.versionsr   r   fastmcp.server.serverr   r   rg   r   r+   r-   rT   rH   r*   <module>r      s   M M " " " " " " 9 9 9 9 9 9 9 9 9 9 4 4 4 4 4 4 4 4 4 4 4 4     * * * * * * " " " " " "       ; ; ; ; ; ; ; ; 0 0 0 0 0 0 0 0 0 0 0 0 : : : : : : H H H H H H H H .------	H		GK  	P P P P"I I I I I I I I I IrH   