
    kKjO                         d Z ddlm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 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 ddlmZ ddlmZ ddlmZ  ee      Z G d de      Zy)a  FileSystemProvider for filesystem-based component discovery.

FileSystemProvider scans a directory for Python files, imports them, and
registers any Tool, Resource, ResourceTemplate, or Prompt objects found.

Components are created using the standalone decorators from fastmcp.tools,
fastmcp.resources, and fastmcp.prompts:

Example:
    ```python
    # In mcp/tools.py
    from fastmcp.tools import tool

    @tool
    def greet(name: str) -> str:
        return f"Hello, {name}!"

    # In main.py
    from pathlib import Path

    from fastmcp import FastMCP
    from fastmcp.server.providers import FileSystemProvider

    mcp = FastMCP("MyServer", providers=[FileSystemProvider(Path(__file__).parent / "mcp")])
    ```
    )annotationsN)CallableSequence)Path)Any)Prompt)Resource)ResourceTemplate)discover_and_import)LocalProvider)Tool)FastMCPComponent)
get_logger)VersionSpecc                       e Zd ZdZ	 	 d	 	 	 	 	 d fdZddZddZddZd fdZ	 d	 	 	 	 	 d fdZ	d fdZ
	 d	 	 	 	 	 d fd	Zd fd
Z	 d	 	 	 	 	 d fdZd fdZ	 d	 	 	 	 	 d fdZddZ xZS )FileSystemProvidera  Provider that discovers components from the filesystem.

    Scans a directory for Python files and registers any Tool, Resource,
    ResourceTemplate, or Prompt objects found. Components are created using
    the standalone decorators:
    - @tool from fastmcp.tools
    - @resource from fastmcp.resources
    - @prompt from fastmcp.prompts

    Args:
        root: Root directory to scan. Defaults to current directory.
        reload: If True, re-scan files on every request (dev mode).
            Defaults to False (scan once at init, cache results).

    Example:
        ```python
        # In mcp/tools.py
        from fastmcp.tools import tool

        @tool
        def greet(name: str) -> str:
            return f"Hello, {name}!"

        # In main.py
        from pathlib import Path

        from fastmcp import FastMCP
        from fastmcp.server.providers import FileSystemProvider

        # Path relative to this file
        mcp = FastMCP("MyServer", providers=[FileSystemProvider(Path(__file__).parent / "mcp")])

        # Dev mode - re-scan on every request
        mcp = FastMCP("MyServer", providers=[FileSystemProvider(Path(__file__).parent / "mcp", reload=True)])
        ```
    c                    t         |   d       t        |      j                         | _        || _        d| _        i | _        d | _        d| _	        | j                          y )Nreplace)on_duplicateFr   )super__init__r   resolve_root_reload_loaded_warned_files_reload_lock_reload_generation_load_components)selfrootreload	__class__s      t/Users/ahmed/devFolder/Ultron/claude-voice/.venv/lib/python3.12/site-packages/fastmcp/server/providers/filesystem.pyr   zFileSystemProvider.__init__V   s_    
 	i0$Z'')
 1315'( 	    c                   | j                   r| j                  j                          | j                  j	                         s t
        j                  d| j                         t        | j                        }|j                  j                         D ]m  \  }}	 |j                         j                  }| j                  j                  |      }|||k7  sDt
        j                  d| d|        || j                  |<   o |j                  D ch c]  \  }}|	 }}}|D ]  }| j                  j!                  |d         |j                  D ]  \  }}		 | j#                  |	        d| _         t
        j-                  d	t/        | j                         d
| j                          y# t        $ r d}Y w xY wc c}}w # t$        $ r. t
        j'                  dt)        |	dt+        |	            |       Y w xY w)z9Discover and register all components from the filesystem.z*FileSystemProvider root does not exist: %sg        NzFailed to import z: zFailed to register %s from %snameTzFileSystemProvider loaded z components from )r   _componentsclearr   existsloggerwarningr   failed_filesitemsstatst_mtimeOSErrorr   get
componentspop_register_component	Exception	exceptiongetattrreprdebuglen)
r    result	file_patherrorcurrent_mtimelast_warned_mtimefp_successful_files	components
             r$   r   z#FileSystemProvider._load_componentsj   s   <<""$zz  "NNGT$TZZ0 !' 3 3 9 9 ;Iu$ ) 0 9 9
 !% 2 2 6 6y A (,=,N!29+RwGH0=""9- !< -3,=,=>,=52qB,=>"B""2t, # %+$5$5 Iy((3 %6 (T-=-=)>(??PQUQ[Q[P\]	
3  $ #$ ?    3IvtI?s*   F'F9F?'F65F6?4G65G6c                R   t        |t              r| j                  |       yt        |t              r| j	                  |       yt        |t
              r| j                  |       yt        |t              r| j                  |       yt        j                  dt        |             y)z.Register a single component based on its type.z#Ignoring unknown component type: %rN)
isinstancer   add_toolr
   add_templater	   add_resourcer   
add_promptr+   r:   type)r    rD   s     r$   r5   z&FileSystemProvider._register_component   sr    i&MM)$	#34i(	8,i(	6*OOI&LL>YPr%   c                   K   | j                   s| j                  r ||  d{   S | j                  t        j                         | _        | j
                  }| j                  4 d{    | j                  r| j                   rK| j
                  |k(  r<t        j                  | j                         d{    | xj
                  dz  c_         ||  d{   cddd      d{    S 7 7 7 ;7 7 # 1 d{  7  sw Y   yxY ww)a  Acquire the reload lock, reload if needed, then run *coro_fn*.

        Holding the lock across both the reload and the read prevents
        concurrent readers from seeing a partially-rebuilt ``_components``
        dict (the ``clear()`` + re-register window).

        A generation counter deduplicates concurrent reload requests:
        if another caller already reloaded while we waited for the lock,
        we skip the redundant reload.
        N   )r   r   r   asyncioLockr   	to_threadr   )r    coro_fnargsgeneration_befores       r$   _with_reloadzFileSystemProvider._with_reload   s      || $'' $ 'D 33$$$<<!8!8<M!M''(=(=>>>''1,' $' %$$ ( % ?' %$$$s}   !DC/AD)C1*D-A
C97C38!C9C5C9D)C7*D1D3C95C97D9D?D DDc                R   K   | j                  t        |          d {   S 7 wN)rT   r   _list_toolsr    r#   s    r$   rW   zFileSystemProvider._list_tools   s#     &&uw':;;;;   '%'c                V   K   | j                  t        |   ||       d {   S 7 wrV   )rT   r   	_get_toolr    r'   versionr#   s      r$   r[   zFileSystemProvider._get_tool   s)      &&uw'8$HHHH   )')c                R   K   | j                  t        |          d {   S 7 wrV   )rT   r   _list_resourcesrX   s    r$   r`   z"FileSystemProvider._list_resources   s#     &&uw'>????rY   c                V   K   | j                  t        |   ||       d {   S 7 wrV   )rT   r   _get_resourcer    urir]   r#   s      r$   rb   z FileSystemProvider._get_resource   s)      &&uw'<c7KKKKr^   c                R   K   | j                  t        |          d {   S 7 wrV   )rT   r   _list_resource_templatesrX   s    r$   rf   z+FileSystemProvider._list_resource_templates   s#     &&uw'GHHHHrY   c                V   K   | j                  t        |   ||       d {   S 7 wrV   )rT   r   _get_resource_templaterc   s      r$   rh   z)FileSystemProvider._get_resource_template   s)      &&uw'EsGTTTTr^   c                R   K   | j                  t        |          d {   S 7 wrV   )rT   r   _list_promptsrX   s    r$   rj   z FileSystemProvider._list_prompts   s#     &&uw'<====rY   c                V   K   | j                  t        |   ||       d {   S 7 wrV   )rT   r   _get_promptr\   s      r$   rl   zFileSystemProvider._get_prompt   s)      &&uw':D'JJJJr^   c                <    d| j                   d| j                   dS )NzFileSystemProvider(root=z	, reload=))r   r   )r    s    r$   __repr__zFileSystemProvider.__repr__   s    )$**yaPPr%   ).F)r!   z
str | Pathr"   boolreturnNone)rr   rs   )rD   r   rr   rs   )rQ   zCallable[..., Any]rR   r   rr   r   )rr   zSequence[Tool]rV   )r'   strr]   VersionSpec | Nonerr   zTool | None)rr   zSequence[Resource])rd   rt   r]   ru   rr   zResource | None)rr   zSequence[ResourceTemplate])rd   rt   r]   ru   rr   zResourceTemplate | None)rr   zSequence[Prompt])r'   rt   r]   ru   rr   zPrompt | None)rr   rt   )__name__
__module____qualname____doc__r   r   r5   rT   rW   r[   r`   rb   rf   rh   rj   rl   ro   __classcell__)r#   s   @r$   r   r   0   s    #N      
	 ()
VQ(<< 8<II"4I	I
@ 7;LL!3L	L
I 7;UU!3U	 U
> 8<KK"4K	K
Qr%   r   ) ry   
__future__r   rN   collections.abcr   r   pathlibr   typingr   fastmcp.prompts.baser   fastmcp.resources.baser	   fastmcp.resources.templater
   -fastmcp.server.providers.filesystem_discoveryr   'fastmcp.server.providers.local_providerr   fastmcp.tools.baser   fastmcp.utilities.componentsr   fastmcp.utilities.loggingr   fastmcp.utilities.versionsr   rv   r+   r    r%   r$   <module>r      sP   6 #  .   ' + 7 M A # 9 0 2	H	qQ qQr%   