
    U[iG                        d dl Z d dlZd dlZd dlZd dlZd dlZd dl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 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' d dl(m)Z)m*Z* d dl+m,Z,m-Z- d dl.m/Z/m0Z0m1Z1 d dl2m3Z3m4Z4mZ d dl5m6Z6 d dl7m8Z8 d dl9m:Z: er d dl;m<Z< d dl=m>Z> d dl?m@Z@ d dl5mAZAmBZB d dl7mCZC ej                  j                  d      xs   eF e ej                               dz        ZH G d d      ZI	 d'deFdeFdz  d eFdz  fd!ZJd'd"eFdz  deFdz  fd#ZK	 	 	 	 d(d"eFdz  deFdz  d$eLd%eMeFef   dz  fd&ZNy))    N)AsyncIteratorSequence)BytesIO)Path)TYPE_CHECKINGAnyOptionalcast)unquote)run_sync)Clienthandle_file)StatusStatusUpdate)Image)AnyUrl)	Starlette)Request)JSONResponseResponse)MountRoute)ReceiveScopeSend)processing_utilsroute_utilsutils)BlockFunction)State)HeadertypesServerReadResourceContents)BlockContextBlocks)	ComponentGRADIO_TEMP_DIRgradioc                      e Zd ZdZ	 ddlmZ ddlmZ ddlm	Z	 ddl
mZ ddlmZ dBdZed	ed
z  fd       Zded	efdZd	ee   d
z  fdZededee   d	efd       Zd	eeef   fdZdCdZd	efdZdedeeef   d	e eee   eeef   df   fdZ!ded	ee   fdZ"ede#d	ed
z  fd       Z$deded	eeef   fdZ%dDdZ&d e'd!ed"ed	d
fd#Z(d$ed	d%fd&Z)ed	efd'       Z*d(dded	e eeeef   f   fd)Z+ed*e,d+   d,ed	efd-       Z-ed.e,d+   d,ed	efd/       Z.	 dEded0eeef   d
z  d	e eeef   eeee/z        f   fd1Z0d	e1fd2Z2d3eeef   d	e eeef   eeee/z        f   fd4Z3d5ed6eeee/z        d	efd7Z4ed8ed	e5jj                  d
z  fd9       Z6ed:ed	e7d
z  fd;       Z8ed<e5jj                  d=ed	efd>       Z9d,ed?ed	ed@   fdAZ:y
# e$ r Y w xY w)FGradioMCPServerz
    A class for creating an MCP server around a Gradio app. This class
    requires `mcp` to be installed.

    Args:
        blocks: The Blocks app to create the MCP server for.
    r   r"   r$   r&   )SseServerTransport)StreamableHTTPSessionManagerc                    	 dd l }|| _        | j                  j                         | _        | j                         | _        d| _        t        j                         }|r|j                  d      d   dz   nd| _        | j                         | _        | j                          d | _        d | _        | j#                  | j                  dd	      d
t$        dt&        dt(        dd ffd}t*        j,                  dt.        dt0        d    ffd       }|| _        | _        || _        y # t        $ r}t        d      |d }~ww xY w)Nr   zThe `mcp` package is required to use the Gradio MCP integration. Please install it with the `mcp` extra: `pip install gradio[mcp]`. /_FT)appjson_response	statelessscopereceivesendreturnc                    K   | j                  dd      }|j                  d      s$t        d| dd      } || ||       d {    y j                  | ||       d {    y 7 !7 w)Npathr2   )/gradio_api/mcpz/gradio_api/mcp/z/gradio_api/mcp/httpz/gradio_api/mcp/http/zPath 'zD' not found. The MCP HTTP transport is available at /gradio_api/mcp.i  )contentstatus_code)getendswithr   handle_request)r9   r:   r;   r>   responsemanagers        X/var/www/html/chatbot/Makanify-Chatbot-3/venv/lib/python3.12/site-packages/gradio/mcp.pyhandle_streamable_httpz8GradioMCPServer.__init__.<locals>.handle_streamable_httpZ   s      99VR(D== $$TF*no # ugt444((>>> 5 ?s$   AA+A'A+!A)"A+)A+r6   c                   K   j                         4 d{    	 d 	 ddd      d{    y7 # w xY w7 # 1 d{  7  sw Y   yxY ww)z7Context manager for managing session manager lifecycle.N)run)r6   rF   s    rG   lifespanz*GradioMCPServer.__init__.<locals>.lifespano   sR      {{}  	   	   sL   A5A>7>A<A9>AAAAA)mcpImportErrorblocksget_api_infoapi_infocreate_mcp_server
mcp_server	root_pathr   	get_spacesplittool_prefixget_tool_to_endpointtool_to_endpointwarn_about_state_inputs
_local_url_client_instancer0   r   r   r   
contextlibasynccontextmanagerr   r   rK   rF   rH   )selfrN   rL   espace_idrH   rK   rF   s          @rG   __init__zGradioMCPServer.__init__C   sI   	 002002??$<D8>>#.r2S8" $ 9 9 ;$$&&*/333u 4 
	?	?#*	?26	?	?* 
	'	'		 	mD.A 	 
(	 !&<#i  	 V	s   D& &	E /D;;E r<   Nc                     | j                   S N)rZ   r^   s    rG   	local_urlzGradioMCPServer.local_url|   s        requestc                     t        j                  t        |j                              }|j	                  d      }t        |      j                  d      }|j                  d      ryy)z
        Gets the route path of the MCP server based on the incoming request.
        Can be different depending on whether the request is coming from the MCP SSE transport or the HTTP transport.
        N)queryr3   z/gradio_api/mcp/messagesr?   )httpxURLstrurl	copy_withrstriprC   )r^   rg   rm   s      rG   get_route_pathzGradioMCPServer.get_route_path   sP    
 iiGKK()mm$m'#hooc"<<23-$rf   c                     | j                   j                  j                  }|yt        t	        |di             }d|v r2|d   j                  d      }|D cg c]  }| j                  |z    }}|S yc c}w )z
        Extract the selected tools from the request query parameters and return the full tool names (with the tool prefix).
        Returns None if no tools parameter is specified (meaning all tools are available).
        Nquery_paramstools,)rR   request_contextrg   dictgetattrrU   rV   )r^   context_requestrr   rs   toolfull_tool_namess         rG   get_selected_tools_from_requestz/GradioMCPServer.get_selected_tools_from_request   s    
 +///*I*I*Q*Q"GO^RHIl" )//4ECHI4t//$6IOI"" Js   A1	tool_nameexisting_tool_namesc                 r    t        j                  dd|       } | dd } | }d}| |v r|d| z   } |dz  }| |v r| S )z
        Sanitizes a tool name to make it a valid MCP tool name (only
        alphanumeric characters, underscores, <= 128 characters)
        and is unique among the existing tool names.
        z[^a-zA-Z0-9]r5   Nx      )resub)r|   r}   tool_name_basesuffixs       rG   valid_and_unique_tool_namez*GradioMCPServer.valid_and_unique_tool_name   s`     FF?C;	dsO	"..&1VH5IaKF .. rf   c                    i }| j                   d   D ]  }| j                  |      }||j                  #t        |j                  dd      xsL t	        |j                  d      xr! t        |j                  j
                  dd      xs |j                  d      }| j                  |z   }| j                  |t        |j                                     }|||<    |S )z
        Gets all of the tools that are exposed by the Gradio app and also
        creates a mapping from the tool names to the endpoint names in the API docs.
        named_endpointsN__name__	__class__r3   )rP   get_block_fn_from_endpoint_namefnrw   hasattrr   lstriprV   r   setkeys)r^   rX   endpoint_nameblock_fnfn_namer|   s         rG   rW   z$GradioMCPServer.get_tool_to_endpoint   s    
 !]]+<= 	8M;;MJH8;;#6Z6 -HKK5 I 5 5z4H-
 !'',  ((72I773/4467I +8Y'!	8"  rf   c                     | j                   j                         D ]K  \  }}| j                  |      }|st        d |j                  D              s7t        j                  d       M y)z=
        Warn about tools that have gr.State inputs.
        c              3   <   K   | ]  }t        |t                y wrc   )
isinstancer    ).0inputs     rG   	<genexpr>z:GradioMCPServer.warn_about_state_inputs.<locals>.<genexpr>   s     VU
5% 8Vs   zThis MCP server includes a tool that has a gr.State input, which will not be updated between tool calls. The original, default value of the State will be used each time.N)rX   itemsr   anyinputswarningswarn)r^   r5   r   r   s       rG   rY   z'GradioMCPServer.warn_about_state_inputs   s\     !% 5 5 ; ; = 	A};;MJHCVhooVV&	rf   c           
      @   | j                   | j                  j                  j                  }|t	        d      | j                  |      }t        j                  ||| j                        }t        | j                  xs |dddddddi      | _         | j                   S )NCould not find the request object in the MCP server context. This is not expected to happen. Please raise an issue: https://github.com/gradio-app/gradio.rg   
route_pathrS   Fx-gradio-userrL   )download_filesverboseanalytics_enabled
ssl_verify_skip_componentsheaders)r[   rR   ru   rg   
ValueErrorrp   r   get_root_urlrS   r   re   )r^   rx   r   root_urls       rG   _get_or_create_clientz%GradioMCPServer._get_or_create_client   s      (.2oo.M.M.U.UO&  p  ,,_=J"//'%..H
 %+*($"' !&(%0%D! $$$rf   name	argumentsr   c                    | j                         }| j                  |      \  }}| j                  ||      }| j                  j	                  |      }|t        d|       |||vrt        d| d      | j                  |      }|J || j                  d   v r-| j                  d   |   d   }	t        j                  |	d|      }
ng }
| j                  j                  j                  }|t        d      t        |j                  j                               }|j!                  d	d       |j!                  d
d       ||
||fS )z
        Prepare and validate arguments for a tool call.

        Returns:
            A tuple of (endpoint_name, processed_args, request_headers, block_fn)
        N"Unknown tool for this Gradio app: zTool 'z#' is not in the selected tools listr   
parameters r   zcontent-lengthr   )r{   get_input_schemaconvert_strings_to_filedatarX   rB   r   r   rP   client_utilsconstruct_argsrR   ru   rg   rv   r   r   pop)r^   r   r   selected_toolsr5   filedata_positionsprocessed_kwargsr   r   parameters_infoprocessed_argsrx   request_headerss                rG   _prepare_tool_call_argsz'GradioMCPServer._prepare_tool_call_args   sw    ==? $ 5 5d ;;;)
 --11$7 A$HII%$n*DvdV+NOPP77F###DMM*;<<"mm,=>}MO *88 N  N*.//*I*I*Q*Q" l  66<<>?,d3OT2noxGGrf   jobc                 N   K   t        |j                         d{   }|gS 7 w)z
        Execute a tool call without progress tracking (fast path).

        Calls job.result() to get the final output without processing
        intermediate status updates.

        Returns:
            The output data as a list.
        N)r   result)r^   r   r   s      rG   _execute_tool_without_progressz.GradioMCPServer._execute_tool_without_progress  s%       

++x ,s   %#%updatec                    | j                   t        j                  t        j                  fv ry| j                   t        j                  fv r>d| j
                   d| j                   d}| j                  |d| j                   dz  }|S | j                   t        j                  fv r| j                  xs g D ]  }|j                  dnd	|j                   }|j                  ,|j                   | d
|j                   d|j                   c S |j                  e|j                  r| d
|j                   c S  y| j                   t        j                  t        j                  fv ryy)z
        Format a status update into a human-readable progress message.

        Returns:
            A formatted message string, or None if no message should be shown.
        zJoined server queue.zIn queue. Position z out of .Nz Estimated time remaining: z	 seconds.Progressz	Progress z: Step z of 
Processing)coder   JOINING_QUEUESTARTINGIN_QUEUErank
queue_sizeetaPROGRESSprogress_datadescindexlength
PROCESSING	ITERATING)r   messageprogress_unittitles       rG   _format_progress_messagez(GradioMCPServer._format_progress_message(  so    ;;6//AA)[[V__--+FKK=ARAR@SSTUGzz%8INNN[[V__--!'!5!5!; B %))1 $]%7%7$89 
 !&&2}7K7K7W ')<)<(=T-BVBVAWX #((49M9M9U#WGM,?,?+@AAB  [[V..0@0@AArf   progress_tokenc           	        K   d}|2 3 d{   }|j                   dk(  rt        t        |      }| j                  |      }| j                  j
                  j                  j                  |||t        | j                  j
                  j                               d{    |dz  }|j                   dk(  s|j                  s|j                  }|j                  r|j                  d      }|j                  d      }|r|r| d	| }	t        |	      |r|}	t        |	      |r|}	t        |	      d
}	t        |	      7 67 6 |j                         r|j                         d   S w)z
        Execute a tool call with progress tracking (streaming path).

        Iterates through job updates to send progress notifications to the client.

        Returns:
            The output data as a list.
        r   Nstatus)r   progressr   related_request_idr   outputr   errorz: zError!data)typer
   r   r   rR   ru   sessionsend_progress_notificationrl   
request_idfinaloutputssuccessrB   RuntimeError	exception)
r^   r   r   stepr   r   r   error_titleerror_messagemsgs
             rG   _execute_tool_with_progressz+GradioMCPServer._execute_tool_with_progressH  su      	, 	,&{{h&lF377? OO33;;VV'5!% '+. OO;;FF,	 W 	 	 	(V\\~~"(**W"5K$*JJw$7M"}!,R? 's++ '+
 's++	 %) 's++ '&s++;	,
	  < ==?--/!f~sK   E,EEEBE,EE,8E,E,A#E,EE,&E,c                      j                  t         j                  j                  xs d            }|j	                         dt        dt
        t        t        f   d j                  j                  f fd       }|j                         dt         j                  j                     f fd       }|j                         dt         j                  j                     f fd       }|j                         dt         j                  j                     f fd       }|j!                         d	t"        t        z  dt         j$                     f fd
       }|j'                         dt         j                  j(                     f fd       }|j+                         	 ddt        dt
        t        t        f   dz  d j                  j,                  f fd       }|S )z
        Create an MCP server for the given Gradio Blocks app.

        Parameters:
            blocks: The Blocks app to create the MCP server for.

        Returns:
            The MCP server.
        z
Gradio Appr   r   r<   c           	        K   d}j                   j                  j                  *j                   j                  j                  j                  }t	        j
                         d{   }j                  | |      \  }}}}j                  |j                  |      } |j                  |||d}||j                  sj                  |       d{   }	nj                  ||       d{   }	j                  |j                  |	      }	j                   j                  j                  }
j!                  |
      }t#        j$                  |
|j&                        }j)                  |	|      }t+        |j,                  dd      rd|i}nd}j.                  j1                  ||t+        |j,                  dd            S 7 _7 7 ۭw)	z
            Call a tool on the Gradio app.

            Args:
                name: The name of the tool to call.
                arguments: The arguments to pass to the tool.
            N)api_namer   r   _mcp_structured_outputFr   	_mcp_meta)r@   structuredContent_meta)rR   ru   metaprogressTokenr   r   r   insert_empty_stater   submitqueuer   r   pop_returned_stater   rg   rp   r   r   rS   postprocess_output_datarw   r   r#   CallToolResult)r   r   r   clientr   r   r   r   r   output_datarx   r   r   r@   structured_contentr^   s                  rG   	call_toolz4GradioMCPServer.create_mcp_server.<locals>.call_tool  s     "N..33?!%!@!@!E!E!S!S#D$>$>??F,,T9= EM>?H "44X__nUN&---C %X^^$($G$G$LL$($D$D"% 
 11(2B2BKPK.2oo.M.M.U.UO,,_=J"//'%..H
 22;IGx{{$<eD&.%8"%)"::,,"4hkk;= -  ? @ Ms8   A%G(G)A,GG
G0G1CG
GGc            	        K   
j                         } g }
j                  j                         D ]  \  }}| || vr
j                  |      }|;|j                  /t        |j                  d      r|j                  j                  dk7  r\
j                  ||      \  }}
j                  ||      \  }}t        |j                  dd      }	|j                  
j                  j                  ||||	              |S w)z;
            List all tools on the Gradio app.
            N	_mcp_typery   r   )r   descriptioninputSchemar   )r{   rX   r   r   r   r   r  get_fn_descriptionr   rw   appendr#   Tool)r   rs   r|   r   r   r  r   schemar5   	tool_metar^   s             rG   
list_toolsz5GradioMCPServer.create_mcp_server.<locals>.list_tools  s    
 "AACNE,0,A,A,G,G,I (	=!-)>2Q??N${{*[9$KK11V; *.*A*A(I*V'Z 11)ZH	#HKKdC	JJOO&$/$*'	 $ '6 Ls   C<C?c            	      ~  K   g } 	j                         }	j                  j                         D ]  \  }}|||vr	j                  |      }|s"|j                  s/t        |j                  d      sF|j                  j                  dk(  s`|j                  j                  }t        j                  d|      }t        j                  |j                        \  }}}|r| j                  	j                  j                  ||j                  j                  ||j                  j                                
 | S w)z7
            List all available resources.
            r  resource\{([^}]+)\})urir   r  mimeType)r{   rX   r   r   r   r   r  _mcp_uri_templater   findallr   get_function_descriptionr  r#   Resourcer   _mcp_mime_type)
	resourcesr   r|   r   r   uri_templater   r  r5   r^   s
            rG   list_resourcesz9GradioMCPServer.create_mcp_server.<locals>.list_resources  s    
 I!AACN,0,A,A,G,G,I (	=!-)>2Q??N [9 --;#+;;#@#@L!#NL!IJ161O1O 2.KQ &!(( JJ//$0%-[[%9%9,7)1)C)C	 0 #2 &   AD=D=D=6D=AD="AD=c            	      ~  K   g } 	j                         }	j                  j                         D ]  \  }}|||vr	j                  |      }|s"|j                  s/t        |j                  d      sF|j                  j                  dk(  s`|j                  j                  }t        j                  d|      }t        j                  |j                        \  }}}|s| j                  	j                  j                  ||j                  j                  ||j                  j                                
 | S w)z@
            List all available resource templates.
            r  r  r  )uriTemplater   r  r  )r{   rX   r   r   r   r   r  r  r   r  r   r  r  r#   ResourceTemplater   r  )
	templatesr   r|   r   r   r  r   r  r5   r^   s
            rG   list_resource_templateszBGradioMCPServer.create_mcp_server.<locals>.list_resource_templates  s    
 I!AACN,0,A,A,G,G,I (	=!-)>2Q??N [9 --;#+;;#@#@L!#NL!IJ161O1O 2.KQ "!(( JJ77,8%-[[%9%9,7)1)C)C	 8 #2 r  r  c                   K   t        |       } t        j                         d{   }j                  j	                         D ]  }j                  |      }|s|j                  s%t        |j                  d      s<|j                  j                  dk(  sV|j                  j                  }t        j                  d|      }i }d}|ret        j                  |      }|D ]  }	|j                  d|	 dd|	 d	      } t        j                  d
| d|       }
|
r|
j                         }d}n|| k(  rd}|s|j                   d   v r-j                   d   |   d   }t#        j$                  |d|      }nt'        |j	                               } |j(                  |d|i2 3 d{   }|j*                  dk(  s|j,                  s&|j.                  }|d   d   } |j                  j0                  }|r5|j3                  d      s$t5        j6                  j9                  d            }j;                  |      gc S  t=        d|        7 ,7 6 yw)z:
            Read a specific resource by URI.
            Nr  r  r  Fz\{z\}z(?P<z>[^/]+)^$Tr   r   r   r   r   r   r   ztext/ascii)r@   	mime_typezResource not found: )rl   r   r   rX   valuesr   r   r   r  r  r   r  escapereplacematch	groupdictrP   r   r   listr   r   r   r   r  
startswithbase64	b64decodeencoder'   r   )r  r   r   r   r  r   kwargsmatchedpatternparamr(  r   r   r   r   r   r$  r^   s                    rG   read_resourcez8GradioMCPServer.create_mcp_server.<locals>.read_resource   sa    
 c(C#D$>$>??F!%!6!6!=!=!? 8??N  [9 --;#+;;#@#@L!#NL!IJF#G!"$))L"9%/ E&-oo"&ugT 2d5'4I'G !#1WIQ = %*__%6F&*G%,"&(DMM:K,LL.2mm<M.N -/*/,O .:-H-H / " &.N .2&--/-BN,9FMM+-6C- & &&  &{{h66<<)/)/): %$,KK$>$>	$Y-A-A'-J%+%5%5fmmG6L%MF 55(.) 6   i8t 3C59::w @T& -s`   $II5II+IIB I=A)I&I*I+I.I?IBIIIc                    K   g } j                         }j                  j                         D ]  \  }}|||vrj                  |      }|s"|j                  s/t        |j                  d      sF|j                  j                  dk(  s`t        j                  |j                        \  }}}t        j                  |j                        }|D 	
cg c]6  \  }	}
}}j                  j                  |	|j                  |	d      |
       8 }}
}	}| j                  j                  j                  |||              | S c c}}
}	w w)z5
            List all available prompts.
            r  promptr2   )r   r  required)r   r  r   )r{   rX   r   r   r   r   r  r   r  get_function_paramsr#   PromptArgumentrB   r  Prompt)promptsr   r|   r   r   r  r   r5   function_params
param_namehas_defaultr   r^   s               rG   list_promptsz7GradioMCPServer.create_mcp_server.<locals>.list_promptsc  sP    
 G!AACN,0,A,A,G,G,I (	=!-)>2Q??N [9 --9161O1O 2.KQ ',&?&?&LO >M! ! :JQ 

11!+(2z2(F)4_ 2 !I ! NN

))!*(3&/ * /< N!s+   AEEE6EAE;E	
=ENc                   K   t        
j                         d{   }d}
j                  j                         D ]o  }
j	                  |      }|s|j
                  s$t        |j
                  d      s;|j
                  j                  dk(  sU|j
                  j                  | k(  so n |st        d|        |xs i }
j	                  |      }|J |
j                  d   v r-
j                  d   |   d   }t        j                  |d|      }nt        |j                               } |j                  |d|i2 3 d{   }|j                  d	k(  s|j                   s&|j"                  }|d
   d   }	 
j$                  j'                  
j$                  j)                  d
j$                  j+                  dt-        	                  g      S 7 7 6 cw)zI
            Get a specific prompt with filled-in arguments.
            Nr  r5  zPrompt not found: r   r   r   r   r   r   r   usertextr   rA  )roler@   )messages)r   r   rX   r%  r   r   r   r  	_mcp_namer   rP   r   r   r*  r   r   r   r   r#   GetPromptResultPromptMessageTextContentrl   )r   r   r   r   r   r   r   r   r   r   r^   s             rG   
get_promptz5GradioMCPServer.create_mcp_server.<locals>.get_prompt  s     $D$>$>??F M!%!6!6!=!=!? 	??N [9 --9 --5	 ! #5dV!<==!RI;;MJH'''.? @@"&--0A"B="Q # ".!<!<#" "&i&6&6&8!9 -~ V V  f;;(*v||#^^F#F^A.F::--JJ,,# $

 6 6FV 6 U -  .  Q @D Vs_   G!G6G!G!!G!8G!G!,BG!GGGG!G!)A2G!GG!rc   )r%   rl   rN   r   r  rv   r   r#   r   r  r*  r	  r  r  r  r  r3  r   r'   r>  r9  rI  rF  )	r^   serverr  r  r  r  r3  r>  rI  s	   `        rG   rQ   z!GradioMCPServer.create_mcp_serverv  s    S!2!2!BlCD				1	1	"&sCx.1	ZZ&&1	 
1	f 
			"	$tzz"7 "	 
"	H 
			  	d4::+>+>&?  	 
! 	D 
	'	'	)	tDJJ4O4O/P 	 
*	B 
			@	;Vc\ @	;d4;T;T6U @	; 
 @	;D 
			$	D):):$; $	 
$	L 
			:>5	5	"&sCx.4"75	ZZ''5	 
5	n rf   r6   subpathrS   c                     d} j                  |      | _         fd}|j                  |t        t	        d j
                        t	        d|      t        dj                        t        d j                        g             y	)
a!  
        Launch the MCP server on the SSE transport.

        Parameters:
            app: The Gradio app to mount the MCP server on.
            subpath: The subpath to mount the MCP server on. E.g. "/gradio_api/mcp"
            root_path: The root path of the Gradio Blocks app.
        z
/messages/c                   K   	 j                  | j                  | j                  | j                        4 d {   }j                  j                  |d   |d   j                  j                                d {    d d d       d {    t               S 7 a7  7 # 1 d {  7  sw Y   t               S xY w# t        $ r}t        dt        |               d }~ww xY ww)Nr   r   zMCP SSE connection error: )connect_sser9   r:   _sendrR   rJ   create_initialization_optionsr   	Exceptionprintrl   )rg   streamsr_   r^   sses      rG   
handle_ssez5GradioMCPServer.launch_mcp_on_sse.<locals>.handle_sse  s     ??MM7??GMM  //--

EEG     z!     z! 23q6(;<s   C)5C  BC  ?B"=B>B"C  B C  C)C  B" C  "B=(B+)B=0C  <C)=C   	C&	C!!C&&C)z/schema)endpointz/sse)r6   r3   )routesN)	r/   rS   mountr   r   get_complete_schemar   handle_post_messagerH   )r^   r6   rK  rS   messages_pathrU  rT  s   `     @rG   launch_mcp_on_ssez!GradioMCPServer.launch_mcp_on_sse  s     %%%m4"	 			!!%!9!9 &:6,C,C,CD#4#>#>?
	
rf   r   zBlockFunction | Nonec                 v    t        fd| j                  j                  j                         D        d      }|S )a$  
        Get the BlockFunction for a given endpoint name (e.g. "/predict").

        Parameters:
            endpoint_name: The name of the endpoint to get the BlockFunction for.

        Returns:
            The BlockFunction for the given endpoint name, or None if it is not found.
        c              3   ^   K   | ]$  }|j                   j                  d       k(  r| & yw)r3   N)r   r   )r   r   r   s     rG   r   zBGradioMCPServer.get_block_fn_from_endpoint_name.<locals>.<genexpr>  s0      ;;-"6"6s";; s   *-N)nextrN   fnsr%  )r^   r   r   s    ` rG   r   z/GradioMCPServer.get_block_fn_from_endpoint_name  s9     ++//002
 
 rf   c                      y)zu
        Sentence prompting the agent to use the upload_file_to_gradio tool if a file is passed as an input.
        z If a user passes a file as an input, use the upload_file_to_gradio tool, if present, to upload the file to the gradio app and create a Gradio File Input. Then use the returned path as the input to the toolr   rd   s    rG   _file_data_tool_descriptionz+GradioMCPServer._file_data_tool_description  s    
 `rf   r   c                    t        j                  |j                        \  }}}| j                  ||      \  }}|j                  du rd}n|j                  Mt        |      dkD  r|| j                  z  }|rW||j                  d      rdnddz   dj                  |      z   z  }n)|j                  }t        |      dkD  r|| j                  z  }t        |t              sJ ||fS )z
        Get the description of a function, which is used to describe the tool in the MCP server.
        Also returns the description of each parameter of the function as a dictionary.
        Fr2   r   r   z
 Returns: z, )r   r  r   r   api_descriptionlenrb  rC   joinr   rl   )r^   r   r|   r  r   returnsr5   r   s           rG   r  z"GradioMCPServer.get_fn_description  s     ,1+I+I(+++V(Z $ 5 5i L##u,K%%-%&*t???&//4R#"#ii() #22K%&*t???+s+++J&&rf   r   zComponent | BlockContextr   c                 r    t        |       D ](  \  }}t        |t              s|j                  |d       * |S )z
        Insert None placeholder values for any State input components, as State inputs
        are not included in the endpoint schema.
        N)	enumerater   r    insert)r   r   iinput_component_types       rG   r   z"GradioMCPServer.insert_empty_state'  s>     (1'8 	%#A#.6At$	% rf   
componentsc                 p    t        |       D ]'  \  }}t        |t              s|j                  |       ) |S )z
        Remove any values corresponding to State output components from the data
        as State outputs are not included in the endpoint schema.
        )ri  r   r    r   )rm  r   rk  component_types       rG   r   z"GradioMCPServer.pop_returned_state4  s9     "+:!6 	A~.%0	 rf   r   c           
      X   | j                   j                  |      }|t        d|       | j                  d   }|j                  |      }|J d|d   D ci c]4  }|d   i |d   |r|d   |v r
d||d      ini d|v r|d   rd	|d   ini 6 c}d
}| j	                  |      S c c}w )a  
        Get the input schema of the Gradio app API, appropriately formatted for MCP.

        Parameters:
            tool_name: The name of the tool to get the schema for, e.g. "predict"
            parameters: The description and parameters of the tool to get the schema for.
        Returns:
            - The input schema of the Gradio app API.
            - A list of positions of FileData objects in the input schema.
        r   r   objectr   parameter_namer   r  parameter_defaultdefault)r   
properties)rX   rB   r   rP   simplify_filedata_schema)r^   r|   r   r   r   endpoint_infopr
  s           rG   r   z GradioMCPServer.get_input_schemaA  s    --11)< A)MNN--(9:'++M:(((  '|4  "# &i& &!,<*=*K '
15E3F(GH& /!3:M8N #A&9$:;& 
& ,,V44#s   9B'c                   K   | j                   st        i       S t        t        |di             }d}d|v r|d   j	                  d      }t        |      }d}g }| j                  j                         D ]I  \  }}|||vr| j                  |      }	|	|	j                  J | j                  |	|      \  }
}| j                  ||      \  }}t        |      dkD  r|sd}t        j                  |	j                        }g }|j                         D ]N  \  }}|t        u s|t         t           u s|j#                  dd	      j%                         }|j'                  |       P d
}t)        |	j                  d      r|	j                  j*                  }|||	j,                  d}|r||d<   ||
||d}|j'                  |       L t        |      S w)a  
        Get the complete schema of the Gradio app API. For debugging purposes, also used by
        the Hugging Face MCP server to get the schema for MCP Spaces without needing to
        establish an SSE connection.

        Parameters:
            request: The Starlette request object.

        Returns:
            A JSONResponse containing a dictionary mapping tool names to their input schemas.
        rr   Nrs   rt   Fr   Tr5   -ry   r  )file_data_presentmcp_typer   r   )r   r  r  r   )rP   r   rv   rw   rU   r   rX   r   r   r   r  r   re  r   get_type_hintsr!   r	   r'  lowerr  r   r  r   )r^   rg   rr   r   rs   r{  schemasr|   r   r   r  r   r
  r   
type_hintsrequired_headersr<  	type_hintheader_namer|  r   infos                         rG   rY  z#GradioMCPServer.get_complete_schemal  s     }}##GG^R@Al" )//4E ZN!(,(=(=(C(C(E $	!$I})i~.M;;MJH'HKK,CCC&*&=&=h	&R#K)-)>)>y*)U&F&%&*3D$(!--hkk:J!)3)9)9); 9%
I&)x7G*G","4"4S#">"D"D"FK$++K89
 Hx{{K0#;;00 &7$!)!2!2D
  "2Y "*%	D NN4 I$	!L G$$s   D*G-BGr
  c           	          dt         dt        t        t         f   dt        fd	 	 d	dt         dt        t        t
        z     dz  dt        t        t         f   dz  dt         ffdg  |      }|fS )
a  
        Parses a schema of a Gradio app API to identify positions of FileData objects. Replaces them with base64
        strings while keeping track of their positions so that they can be converted back to FileData objects
        later.

        Parameters:
            schema: The original schema of the Gradio app API.

        Returns:
            A tuple containing the simplified schema and the positions of the FileData objects.
        objdefsr<   c                 0   t        | t              syd| v r>| d   }|j                  d      r'|j                  d      d   }|j	                  |i       } ny| j	                  di       }|j	                  di       }d|v r>|d   }|j                  d      r'|j                  d      d   }|j	                  |i       }ny|j	                  di       j	                  di       }|j	                  d	i       j	                  d      }|j	                  d
      dk(  xs |dk(  S )NFz$refz#/$defs/r3   r4   ru  r   _typert  constzgradio.FileData)r   rv   r+  rU   rB   )r  r  refkeypropsr   
type_fielddefault_types           rG   is_gradio_filedatazDGradioMCPServer.simplify_filedata_schema.<locals>.is_gradio_filedata  s   c4(}&k>>*-))C.,C((3+C GGL"-E99VR(D~6l>>*-))C.,C88C,D ,377DJ88Ir266w?Lw'+<< 5#44rf   Nnoder>   c                    |g }|i }t        j                  |       } t        | t              rd| v r|j	                  | d           
| |      rB	j                  |j                                dD ]  }| j                  |d         d| d<   d| d<   i }d| v xr d| v }| j                         D ]H  \  }}|r|dk(  r |||      ||<   |j                  |        |||      ||<   |j                          J |S t        | t              rQg }t        |       D ]?  \  }}|j                  |       |j                   |||             |j                          A |S | S )N$defs)ru  additional_descriptionr  stringr   z1Gradio File Input - a http or https url to a fileformatru  )
copydeepcopyr   rv   r   r  r   r   r*  ri  )r  r>   r  r  r   is_schema_rootvaluerk  itemr   r  traverses            rG   r  z:GradioMCPServer.simplify_filedata_schema.<locals>.traverse  sk   
 ||==&D$%d?KKW.%dD1&--diik:P ,d+,#+DL%XDN!'4!HLD4H"&**, #JC%#*=&.udD&AsC(&.udD&As
# D$'( GAtKKNMM(4t"<=HHJ Krf   NN)r   rv   rl   boolr*  int)r^   r
  simplified_schemar   r  r  s      @@@rG   rv  z(GradioMCPServer.simplify_filedata_schema  s    	C 	tCH~ 	$ 	@ ,0*.*	*	sSy/D(*	 sCx.4'*	 	*	X 57$V, "444rf   r  r   c                 l    ddt         dt        t        t        z     dz  dt         ffd |      S )a'  
        Convert specific string values back to FileData objects based on their positions.
        This is used to convert string values (as base64 encoded strings) to FileData
        dictionaries so that they can be passed into .preprocess() logic of a Gradio app.

        Parameters:
            value: The input data to process, which can be an arbitrary nested data structure
                that may or may not contain strings that should be converted to FileData objects.
            filedata_positions: List of paths to positions in the input data that should be converted to FileData objects.

        Returns:
            The processed data with strings converted to FileData objects where appropriate. Base64
            encoded strings are first saved to a temporary file and then converted to a FileData object.

        Example:
            >>> convert_strings_to_filedata(
                {"image": "data:image/jpeg;base64,..."},
                [["image"]]
            )
            >>> {'image': FileData(path='<temporary file path>')},
        Nr  r>   r<   c           
         |g }t        | t              r/| j                         D ci c]  \  }}| |||gz          c}}S t        | t              r)t	        |       D cg c]  \  }} |||gz          c}}S t        | t
              rb|v r^| j                  d      r#t        t        j                  | t                    S | j                  d      rt        |       S t        d|        | S c c}}w c c}}w )Nzdata:)zhttp://zhttps://zSInvalid file data format, provide a url ('http://...' or 'https://...'). Received: )r   rv   r   r*  ri  rl   r+  r   r   save_base64_to_cacheDEFAULT_TEMP_DIRr   )r  r>   r  r  rk  r  r   r  s         rG   r  z=GradioMCPServer.convert_strings_to_filedata.<locals>.traverse"  s    |$%IM;E3C%66  D$'BKD/Rwq$tqcz2RRD#&43E+E??7+ '(==dDTU  __%<=&t,,$mnrmst  K% Ss   C2#C8rc   )r   r*  rl   r  )r^   r  r   r  s     `@rG   r   z+GradioMCPServer.convert_strings_to_filedata	  s6    2	3 	d39o&< 	 	2 rf   	file_pathc                    t         j                  j                  |       syt         j                  j                  | j	                               d   }|t        j                         vry	 t        j                  |       S # t        $ r Y yw xY w)ze
        If a filepath is a valid image, returns a PIL Image object. Otherwise returns None.
        Nr   )	osr>   existssplitextr~  r   registered_extensionsopenrQ  )r  exts     rG   	get_imagezGradioMCPServer.get_image=  sq    
 ww~~i(ggy01!4e1133	::i(( 		s   )A> >	B
	B
	file_datac                     t        | t              ra| j                  d      x}rNt        |t              r=|j	                  d      r,t        |j                  dd      d         j                         S yy)z
        If a file_data is a valid FileDataDict with a url that is a data:image/svg+xml, returns bytes of the svg. Otherwise returns None.
        rm   zdata:image/svgrt   r   N)r   rv   rB   rl   r+  r   rU   r.  )r  rm   s     rG   get_svgzGradioMCPServer.get_svgL  sa    
 i&9==3G,GC,G#s#7G(Hsyya034;;==rf   imager  c                     t               }| j                  ||       t        j                  |j	                               j                  d      S )z?
        Returns a base64 encoded string of the image.
        )r  utf-8)r   saver,  	b64encodegetvaluedecode)r  r  buffers      rG   get_base64_datazGradioMCPServer.get_base64_dataY  s>    
 

6&
) 1299'BBrf   r   z&types.TextContent | types.ImageContentc                    g }t        j                  ||d      }|D ]  }| j                  |      x}rt        j                  |      j                  d      }d}t        j                  ||d    t              }| d| }	| j                  j                  d||      | j                  j                  dd	|	 
      g}
nt        j                  |      r| j                  |d         x}r~|j                  xs d}| j                  ||      }d|j!                          }| j                  j                  d||      | j                  j                  dd|d   xs |d    
      g}
nY| j                  j                  dt#        |d   xs |d         
      g}
n'| j                  j                  dt#        |      
      g}
|j%                  |
        |S )z
        Postprocess the output data from the Gradio app to convert FileData objects back to base64 encoded strings.

        Parameters:
            data: The output data to postprocess.
        Nr  zimage/svg+xml	orig_namez/gradio_api/file=r  )r   r   r  rA  zSVG Image URL: rB  r>   pngzimage/zImage URL: rm   )r   add_root_urlr  r,  r  r  save_bytes_to_cacher  r#   ImageContentrH  r   is_file_obj_with_metar  r  r  r~  rl   extend)r^   r   r   return_valuesr   	svg_bytesbase64_datamimetypesvg_pathsvg_urlreturn_valuer  image_formats                rG   r   z'GradioMCPServer.postprocess_output_datab  s    ,,T8TB '	/F LL00y0$..y9@@I*+??&"5!69I &J&7zBJJ++$; ,  JJ**#.wi8 + 	  33F; NN6&>::5:#(<<#85L"&"6"6ul"KK!'(:(:(<'=>H

//!({X 0  

..!'#.ve}/Nv.O!P / 	$L 

..!'c&-2Q6&>.R / $L !%

 6 6FV 6 UV  .O'	/P rf   )rN   r)   )r<   N)r<   r%   rc   );r   
__module____qualname____doc__rL   r#   
mcp.serverr%    mcp.server.lowlevel.helper_typesr'   mcp.server.sser/   "mcp.server.streamable_http_managerr0   rM   ra   propertyrl   re   r   rp   r*  r{   staticmethodr   r   rv   rW   rY   r   r   r   tupler   r   r   r   r   rQ   r   r\  r   rb  r  r   r   r   r  r   r   rY  rv  r   r   r  bytesr  r  r   r   rf   rG   r.   r.   .   s   %I5S7=r 3:  %g %# %cT1A  -0X	 " d38n  2%v %0-H-H$(cN-H	sDItCH~>	?-H^ S	   #*  >,,(+,	c3h,\L\
)
Y )
 )
 )
QU )
V 	, `S ` `'''47'	sDcN"	#'6 
34
<@
	
 
 
78
@C
	
 
 -1)5)5 cNT))5 
tCH~tDsO44	5	)5V>%L >%@[538n[5	tCH~tDsO44	5[5z22.24c	?.C2	2h S U[[4%7   
3 
54< 
 
 Cu{{ CC CC C C33#&3	6	73E!  s   G GGr.   r  r  r$  c                       fd}|S )z0Decorator to mark a function as an MCP resource.c                 H    d| _         | _        | _        xs d| _        | S )Nr  z
text/plain)r  r  _mcp_descriptionr  )r   r  r$  r  s    rG   	decoratorzresource.<locals>.decorator  s,    !+)%5	rf   r   )r  r  r$  r  s   ``` rG   r  r    s    
 rf   r   c                       fd}|S )z.Decorator to mark a function as an MCP prompt.c                 N    d| _         xs | j                  | _        | _        | S )Nr5  )r  r   rE  r  )r   r  r   s    rG   r  zprompt.<locals>.decorator  s'    *r{{)	rf   r   )r   r  r  s   `` rG   r5  r5    s     rf   structured_outputr   c                       fd}|S )a  
    Decorator to mark a function as an MCP tool (optional, since functions are registered as tools by default).
    Can be used to configure various aspects of the tool.

    Parameters:
        name: The name of the tool. Overrides the default name of the function.
        description: The description of the tool. Overrides the default description from the function's docstring.
        structured_output: Whether the tool should return structured output (implementation is quite limited at the moment). If True, the output will be wrapped in a dictionary with the key "result" and the value being the output of the function. Recommended to keep this False unless you have a specific reason to need the structured output.
        _meta: Additional metadata for the tool.
    c                 N    d| _         | _        | _        | _        | _        | S )Nry   )r  rE  r   r  r   )r   r   r  r   r  s    rG   r  ztool.<locals>.decorator  s-    $5!)	rf   r   )r   r  r  r   r  s   ```` rG   ry   ry     s    " rf   r  )NNFN)Or,  r\   r  r  r   tempfiler   collections.abcr   r   ior   pathlibr   typingr   r   r	   r
   urllib.parser   gradio_client.utilsr   r   rj   anyio.to_threadr   gradio_clientr   r   r   r   PILr   pydanticr   starlette.applicationsr   starlette.requestsr   starlette.responsesr   r   starlette.routingr   r   starlette.typesr   r   r   r,   r   r   gradio.blocksr   gradio.componentsr    gradio.route_utilsr!   rL   r#   r  r%   r  r'   r(   r)   r*   environrB   rl   
gettempdirr  r.   r  r5  r  rv   ry   r   rf   rG   <module>r     sO      	 	   3   5 5   *  $ - 4   , & 6 * 0 0 7 7 ' # %!E2+ ::>>"34 				(*9 
g g`# PT$'$JBE*	t 	t 	 "##'	
*t  S>D 	rf   