o
    c۷iY                     @   s  d Z ddlmZ ddl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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mZmZmZmZmZm Z m!Z!m"Z"m#Z#m$Z$m%Z%m&Z&m'Z'm(Z(m)Z)m*Z*m+Z+m,Z,m-Z-m.Z.m/Z/m0Z0 G dd dZ1dS )z
ServerTaskContext - Server-integrated task context with elicitation and sampling.

This wraps the pure TaskContext and adds server-specific functionality:
- Elicitation (task.elicit())
- Sampling (task.create_message())
- Status notifications
    )AnyN)TaskResultHandler)ServerSession)validate_sampling_tools!validate_tool_use_result_messages)McpError)"require_task_augmented_elicitationrequire_task_augmented_sampling)TaskContext)QueuedMessageTaskMessageQueue)Resolver)	TaskStore)INVALID_REQUESTTASK_STATUS_INPUT_REQUIREDTASK_STATUS_WORKINGClientCapabilitiesCreateMessageResultCreateTaskResultElicitationCapabilityElicitRequestedSchemaElicitResult	ErrorDataIncludeContextModelPreferences	RequestIdResultSamplingCapabilitySamplingMessageServerNotificationTaskTaskMetadataTaskStatusNotificationTaskStatusNotificationParamsTool
ToolChoicec                   @   s<  e Zd ZdZdddedededededB f
d	d
Z	e
defddZe
defddZe
defddZdBddZdddededdfddZdddededdfddZdddededdfddZdBd d!ZdBd"d#ZdBd$d%Zded&edefd'd(Zded)ed*edefd+d,Zddddddddd-d.ee d/ed0edB d1edB d2e dB d3ee dB d4e!ee"f dB d5e#dB d6ee$ dB d7e%dB de&fd8d9Z'd:d;ded&ed<edefd=d>Z(d:ddddddddd?	d.ee d/ed<ed0edB d1edB d2e dB d3ee dB d4e!ee"f dB d5e#dB d6ee$ dB d7e%dB de&fd@dAZ)dS )CServerTaskContextaE  
    Server-integrated task context with elicitation and sampling.

    This wraps a pure TaskContext and adds server-specific functionality:
    - elicit() for sending elicitation requests to the client
    - create_message() for sampling requests
    - Status notifications via the session

    Example:
        async def my_task_work(task: ServerTaskContext) -> CallToolResult:
            await task.update_status("Starting...")

            result = await task.elicit(
                message="Continue?",
                requestedSchema={"type": "object", "properties": {"ok": {"type": "boolean"}}}
            )

            if result.content.get("ok"):
                return CallToolResult(content=[TextContent(text="Done!")])
            else:
                return CallToolResult(content=[TextContent(text="Cancelled")])
    N)handlertaskstoresessionqueuer'   c                C   s*   t ||d| _|| _|| _|| _|| _dS )aH  
        Create a ServerTaskContext.

        Args:
            task: The Task object
            store: The task store
            session: The server session
            queue: The message queue for elicitation/sampling
            handler: The result handler for response routing (required for elicit/create_message)
        )r(   r)   N)r
   _ctx_session_queue_handler_store)selfr(   r)   r*   r+   r'    r2   Z/home/ubuntu/vllm_env/lib/python3.10/site-packages/mcp/server/experimental/task_context.py__init__M   s
   
zServerTaskContext.__init__returnc                 C      | j jS )zThe task identifier.)r,   task_idr1   r2   r2   r3   r7   h      zServerTaskContext.task_idc                 C   r6   )zThe current task state.)r,   r(   r8   r2   r2   r3   r(   m   r9   zServerTaskContext.taskc                 C   r6   )z(Whether cancellation has been requested.)r,   is_cancelledr8   r2   r2   r3   r:   r   r9   zServerTaskContext.is_cancelledc                 C   s   | j   dS )z"Request cancellation of this task.N)r,   request_cancellationr8   r2   r2   r3   r;   w   s   z&ServerTaskContext.request_cancellationT)notifymessager<   c                   .   | j |I dH  |r|  I dH  dS dS )z
        Update the task's status message.

        Args:
            message: The new status message
            notify: Whether to send a notification to the client
        N)r,   update_status_send_notification)r1   r=   r<   r2   r2   r3   r?   }   
   zServerTaskContext.update_statusresultc                   r>   )z
        Mark the task as completed with the given result.

        Args:
            result: The task result
            notify: Whether to send a notification to the client
        N)r,   completer@   )r1   rB   r<   r2   r2   r3   rC      rA   zServerTaskContext.completeerrorc                   r>   )z
        Mark the task as failed with an error message.

        Args:
            error: The error message
            notify: Whether to send a notification to the client
        N)r,   failr@   )r1   rD   r<   r2   r2   r3   rE      rA   zServerTaskContext.failc                    sJ   | j j}| jttt|j|j|j	|j
|j|j|jddI dH  dS )z.Send a task status notification to the client.)taskIdstatusstatusMessage	createdAtlastUpdatedAtttlpollInterval)paramsN)r,   r(   r-   send_notificationr   r"   r#   rF   rG   rH   rI   rJ   rK   rL   )r1   r(   r2   r2   r3   r@      s"   z$ServerTaskContext._send_notificationc                 C   (   | j tt dstttdddS )z)Check if the client supports elicitation.)elicitationz.Client does not support elicitation capabilitycoder=   N)r-   check_client_capabilityr   r   r   r   r   r8   r2   r2   r3   _check_elicitation_capability      z/ServerTaskContext._check_elicitation_capabilityc                 C   rO   )z&Check if the client supports sampling.)samplingz+Client does not support sampling capabilityrQ   N)r-   rS   r   r   r   r   r   r8   r2   r2   r3   _check_sampling_capability   rU   z,ServerTaskContext._check_sampling_capabilityrequestedSchemac              	      s   |    | jdu rtd| jj| jtdI dH  | jj||| jd}|j	}t
 }|| jj|< td|||d}| j| j|I dH  z| I dH }| jj| jtdI dH  t|W S  t yr   | jj| jtdI dH   w )a  
        Send an elicitation request via the task message queue.

        This method:
        1. Checks client capability
        2. Updates task status to "input_required"
        3. Queues the elicitation request
        4. Waits for the response (delivered via tasks/result round-trip)
        5. Updates task status back to "working"
        6. Returns the result

        Args:
            message: The message to present to the user
            requestedSchema: Schema defining the expected response structure

        Returns:
            The client's response

        Raises:
            McpError: If client doesn't support elicitation capability
        NzEhandler is required for elicit(). Pass handler= to ServerTaskContext.rG   )r=   rX   related_task_idrequesttyper=   resolveroriginal_request_id)rT   r/   RuntimeErrorr0   update_taskr7   r   r-   _build_elicit_form_requestidr   _pending_requestsr   r.   enqueuewaitr   r   model_validateanyioget_cancelled_exc_class)r1   r=   rX   r[   
request_idr^   queuedresponse_datar2   r2   r3   elicit   s8   
zServerTaskContext.eliciturlelicitation_idc           	   	      s   |    | jdu rtd| jj| jtdI dH  | jj|||| jd}|j	}t
 }|| jj|< td|||d}| j| j|I dH  z| I dH }| jj| jtdI dH  t|W S  t ys   | jj| jtdI dH   w )a  
        Send a URL mode elicitation request via the task message queue.

        This directs the user to an external URL for out-of-band interactions
        like OAuth flows, credential collection, or payment processing.

        This method:
        1. Checks client capability
        2. Updates task status to "input_required"
        3. Queues the elicitation request
        4. Waits for the response (delivered via tasks/result round-trip)
        5. Updates task status back to "working"
        6. Returns the result

        Args:
            message: Human-readable explanation of why the interaction is needed
            url: The URL the user should navigate to
            elicitation_id: Unique identifier for tracking this elicitation

        Returns:
            The client's response indicating acceptance, decline, or cancellation

        Raises:
            McpError: If client doesn't support elicitation capability
            RuntimeError: If handler is not configured
        NzIhandler is required for elicit_url(). Pass handler= to ServerTaskContext.rY   )r=   rn   ro   rZ   r[   r\   )rT   r/   r`   r0   ra   r7   r   r-   _build_elicit_url_requestrc   r   rd   r   r.   re   rf   r   r   rg   rh   ri   )	r1   r=   rn   ro   r[   rj   r^   rk   rl   r2   r2   r3   
elicit_url  s:    
zServerTaskContext.elicit_url)system_promptinclude_contexttemperaturestop_sequencesmetadatamodel_preferencestoolstool_choicemessages
max_tokensrr   rs   rt   ru   rv   rw   rx   ry   c       	            s   |    | jjr| jjjnd}t||	|
 t| | jdu r#td| jj	| j
tdI dH  | jj|||||||||	|
| j
d}|j}t }|| jj|< td|||d}| j| j
|I dH  z| I dH }| jj	| j
tdI dH  t|W S  t y   | jj	| j
tdI dH   w )a  
        Send a sampling request via the task message queue.

        This method:
        1. Checks client capability
        2. Updates task status to "input_required"
        3. Queues the sampling request
        4. Waits for the response (delivered via tasks/result round-trip)
        5. Updates task status back to "working"
        6. Returns the result

        Args:
            messages: The conversation messages for sampling
            max_tokens: Maximum tokens in the response
            system_prompt: Optional system prompt
            include_context: Context inclusion strategy
            temperature: Sampling temperature
            stop_sequences: Stop sequences
            metadata: Additional metadata
            model_preferences: Model selection preferences
            tools: Optional list of tools the LLM can use during sampling
            tool_choice: Optional control over tool usage behavior

        Returns:
            The sampling result from the client

        Raises:
            McpError: If client doesn't support sampling capability or tools
            ValueError: If tool_use or tool_result message structure is invalid
        NzMhandler is required for create_message(). Pass handler= to ServerTaskContext.rY   )rz   r{   rr   rs   rt   ru   rv   rw   rx   ry   rZ   r[   r\   )rW   r-   client_paramscapabilitiesr   r   r/   r`   r0   ra   r7   r   _build_create_message_requestrc   r   rd   r   r.   re   rf   r   r   rg   rh   ri   )r1   rz   r{   rr   rs   rt   ru   rv   rw   rx   ry   client_capsr[   rj   r^   rk   rl   r2   r2   r3   create_messageP  sN   ,
z ServerTaskContext.create_messagei`  rK   rK   c             	      sD  | j jr
| j jjnd}t| | jdu rtd| jj| jt	dI dH  | j j
||| jt|dd}|j}t }|| jj|< td|||d}| j| j|I dH  z9| I dH }	t|	}
|
jj}| j j|2 z3 dH W }qj6 | j j|tI dH }| jj| jtdI dH  |W S  t y   | jj| jtdI dH   w )aJ  
        Send a task-augmented elicitation via the queue, then poll client.

        This is for use inside a task-augmented tool call when you want the client
        to handle the elicitation as its own task. The elicitation request is queued
        and delivered when the client calls tasks/result. After the client responds
        with CreateTaskResult, we poll the client's task until complete.

        Args:
            message: The message to present to the user
            requestedSchema: Schema defining the expected response structure
            ttl: Task time-to-live in milliseconds for the client's task

        Returns:
            The client's elicitation response

        Raises:
            McpError: If client doesn't support task-augmented elicitation
            RuntimeError: If handler is not configured
        Nz(handler is required for elicit_as_task()rY   r   )r=   rX   rZ   r(   r[   r\   )r-   r|   r}   r   r/   r`   r0   ra   r7   r   rb   r!   rc   r   rd   r   r.   re   rf   r   rg   r(   rF   experimental	poll_taskget_task_resultr   r   rh   ri   )r1   r=   rX   rK   r   r[   rj   r^   rk   rl   create_resultclient_task_id_rB   r2   r2   r3   elicit_as_task  sN   


z ServerTaskContext.elicit_as_task)	rK   rr   rs   rt   ru   rv   rw   rx   ry   c       
            sh  | j jr
| j jjnd}t| t||
| t| | jdu r#td| jj	| j
tdI dH  | j j||||||||	|
|| j
t|dd}|j}t }|| jj|< td|||d}| j| j
|I dH  z9| I dH }t|}|jj}| j j|2 z3 dH W }q|6 | j j|tI dH }| jj	| j
tdI dH  |W S  t y   | jj	| j
tdI dH   w )a<  
        Send a task-augmented sampling request via the queue, then poll client.

        This is for use inside a task-augmented tool call when you want the client
        to handle the sampling as its own task. The request is queued and delivered
        when the client calls tasks/result. After the client responds with
        CreateTaskResult, we poll the client's task until complete.

        Args:
            messages: The conversation messages for sampling
            max_tokens: Maximum tokens in the response
            ttl: Task time-to-live in milliseconds for the client's task
            system_prompt: Optional system prompt
            include_context: Context inclusion strategy
            temperature: Sampling temperature
            stop_sequences: Stop sequences
            metadata: Additional metadata
            model_preferences: Model selection preferences
            tools: Optional list of tools the LLM can use during sampling
            tool_choice: Optional control over tool usage behavior

        Returns:
            The sampling result from the client

        Raises:
            McpError: If client doesn't support task-augmented sampling or tools
            ValueError: If tool_use or tool_result message structure is invalid
            RuntimeError: If handler is not configured
        Nz0handler is required for create_message_as_task()rY   r   )rz   r{   rr   rs   rt   ru   rv   rw   rx   ry   rZ   r(   r[   r\   ) r-   r|   r}   r	   r   r   r/   r`   r0   ra   r7   r   r~   r!   rc   r   rd   r   r.   re   rf   r   rg   r(   rF   r   r   r   r   r   rh   ri   )r1   rz   r{   rK   rr   rs   rt   ru   rv   rw   rx   ry   r   r[   rj   r^   rk   rl   r   r   r   rB   r2   r2   r3   create_message_as_task  sb   ,


z(ServerTaskContext.create_message_as_task)r5   N)*__name__
__module____qualname____doc__r    r   r   r   r   r4   propertystrr7   r(   boolr:   r;   r?   r   rC   rE   r@   rT   rW   r   r   rm   rq   listr   intr   floatdictr   r   r$   r%   r   r   r   r   r2   r2   r2   r3   r&   5   s    







A
J
	


c
S
	

r&   )2r   typingr   rh   +mcp.server.experimental.task_result_handlerr   mcp.server.sessionr   mcp.server.validationr   r   mcp.shared.exceptionsr   *mcp.shared.experimental.tasks.capabilitiesr   r	   %mcp.shared.experimental.tasks.contextr
   +mcp.shared.experimental.tasks.message_queuer   r   &mcp.shared.experimental.tasks.resolverr   #mcp.shared.experimental.tasks.storer   	mcp.typesr   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r    r!   r"   r#   r$   r%   r&   r2   r2   r2   r3   <module>   s    	d