
    $j>                         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	 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dS )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)Sequence)Path)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d0 fdZ	 d,d1 fd!Zd2 fd#Z	 d,d3 fd%Zd4d&Z xZS )5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)])
        ```
    .Froot
str | PathreloadboolreturnNonec                    t                                          d           t          |                                          | _        || _        d| _        i | _        d | _        | 	                                 d S )Nreplace)on_duplicateF)
super__init__r   resolve_root_reload_loaded_warned_files_reload_lock_load_components)selfr   r   	__class__s      k/home/rurouni/.hermes/hermes-agent/venv/lib/python3.11/site-packages/fastmcp/server/providers/filesystem.pyr   zFileSystemProvider.__init__U   ss    
 	i000$ZZ''))
 1315 	    c                R   | j         r| j                                         t          | j                  }|j                                        D ]~\  }}	 |                                j        }n# t          $ r d}Y nw xY w| j
                            |          }|||k    r*t                              d| d|            || j
        |<   d |j        D             }|D ]}| j
                            |d           |j        D ]c\  }}	 |                     |           # t"          $ r; t                              dt'          |dt)          |                    |           Y `w xY wd| _         t                              d	t-          | j                   d
| j                    dS )z9Discover and register all components from the filesystem.g        NzFailed to import z: c                    h | ]\  }}|S  r*   ).0fp_s      r&   	<setcomp>z6FileSystemProvider._load_components.<locals>.<setcomp>}   s    >>>52qB>>>r'   zFailed to register %s from %snameTzFileSystemProvider loaded z components from )r    _componentsclearr	   r   failed_filesitemsstatst_mtimeOSErrorr!   getloggerwarning
componentspop_register_component	Exception	exceptiongetattrreprdebuglen)	r$   result	file_patherrorcurrent_mtimelast_warned_mtimesuccessful_filesr,   	components	            r&   r#   z#FileSystemProvider._load_componentsg   s	    < 	%""$$$$TZ00 !' 3 9 9 ; ; 
	> 
	>Iu$ ) 0 0 9 $ $ $ #$ !% 2 6 6y A A (,=,N,NG9GGGGHHH0="9- ?>F,=>>>" 	- 	-B""2t,,,,$*$5 	 	 Iy((3333     3IvtI??     ]T-=)>)>]]QUQ[]]	
 	
 	
 	
 	
s%   A..A=<A=D!!AE&%E&rI   r   c                   t          |t                    r|                     |           dS t          |t                    r|                     |           dS t          |t
                    r|                     |           dS t          |t                    r|                     |           dS t          
                    dt          |                     dS )z.Register a single component based on its type.z#Ignoring unknown component type: %rN)
isinstancer   add_toolr   add_templater   add_resourcer   
add_promptr8   rA   type)r$   rI   s     r&   r<   z&FileSystemProvider._register_component   s    i&& 		QMM)$$$$$	#344 	Qi(((((	8,, 	Qi(((((	6** 	QOOI&&&&&LL>YPPPPPr'   c                &  K   | j         s	| j        rdS | j        t          j                    | _        | j        4 d{V  | j         s| j        st          j        | j                   d{V  ddd          d{V  dS # 1 d{V swxY w Y   dS )zEnsure components are loaded, reloading if in reload mode.

        Uses a lock to serialize concurrent reload operations and runs
        filesystem I/O off the event loop using asyncio.to_thread.
        N)r   r    r"   asyncioLock	to_threadr#   r$   s    r&   _ensure_loadedz!FileSystemProvider._ensure_loaded   s9      | 	 	F $ 'D$ 	? 	? 	? 	? 	? 	? 	? 	?| ?4< ?'(=>>>>>>>>>	? 	? 	? 	? 	? 	? 	? 	? 	? 	? 	? 	? 	? 	? 	? 	? 	? 	? 	? 	? 	? 	? 	? 	? 	? 	? 	? 	? 	? 	?s   .B  
B
B
Sequence[Tool]c                   K   |                                   d{V  t                                                       d{V S )z.Return all tools, reloading if in reload mode.N)rV   r   _list_toolsr$   r%   s    r&   rY   zFileSystemProvider._list_tools   sS      !!#########WW((*********r'   Nr/   strversionVersionSpec | NoneTool | Nonec                   K   |                                   d{V  t                                          ||           d{V S )z0Get a tool by name, reloading if in reload mode.N)rV   r   	_get_toolr$   r/   r\   r%   s      r&   r`   zFileSystemProvider._get_tool   sY       !!#########WW&&tW555555555r'   Sequence[Resource]c                   K   |                                   d{V  t                                                       d{V S )z2Return all resources, reloading if in reload mode.N)rV   r   _list_resourcesrZ   s    r&   rd   z"FileSystemProvider._list_resources   sS      !!#########WW,,.........r'   uriResource | Nonec                   K   |                                   d{V  t                                          ||           d{V S )z3Get a resource by URI, reloading if in reload mode.N)rV   r   _get_resourcer$   re   r\   r%   s      r&   rh   z FileSystemProvider._get_resource   sY       !!#########WW**3888888888r'   Sequence[ResourceTemplate]c                   K   |                                   d{V  t                                                       d{V S )z;Return all resource templates, reloading if in reload mode.N)rV   r   _list_resource_templatesrZ   s    r&   rl   z+FileSystemProvider._list_resource_templates   sS      !!#########WW55777777777r'   ResourceTemplate | Nonec                   K   |                                   d{V  t                                          ||           d{V S )z5Get a resource template, reloading if in reload mode.N)rV   r   _get_resource_templateri   s      r&   ro   z)FileSystemProvider._get_resource_template   sY       !!#########WW33CAAAAAAAAAr'   Sequence[Prompt]c                   K   |                                   d{V  t                                                       d{V S )z0Return all prompts, reloading if in reload mode.N)rV   r   _list_promptsrZ   s    r&   rr   z FileSystemProvider._list_prompts   sS      !!#########WW**,,,,,,,,,r'   Prompt | Nonec                   K   |                                   d{V  t                                          ||           d{V S )z2Get a prompt by name, reloading if in reload mode.N)rV   r   _get_promptra   s      r&   ru   zFileSystemProvider._get_prompt   sY       !!#########WW((w777777777r'   c                (    d| j         d| j         dS )NzFileSystemProvider(root=z	, reload=))r   r   rU   s    r&   __repr__zFileSystemProvider.__repr__   s    P$*PPPPPPr'   )r   F)r   r   r   r   r   r   )r   r   )rI   r   r   r   )r   rW   )N)r/   r[   r\   r]   r   r^   )r   rb   )re   r[   r\   r]   r   rf   )r   rj   )re   r[   r\   r]   r   rm   )r   rp   )r/   r[   r\   r]   r   rs   )r   r[   )__name__
__module____qualname____doc__r   r#   r<   rV   rY   r`   rd   rh   rl   ro   rr   ru   rx   __classcell__)r%   s   @r&   r   r   /   s       # #N              $'
 '
 '
 '
RQ Q Q Q? ? ? ?(+ + + + + + 8<6 6 6 6 6 6 6/ / / / / / 7;9 9 9 9 9 9 98 8 8 8 8 8 7;B B B B B B B- - - - - - 8<8 8 8 8 8 8 8Q Q Q Q Q Q Q Qr'   r   )r|   
__future__r   rR   collections.abcr   pathlibr   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   ry   r8   r   r*   r'   r&   <module>r      sI   6 # " " " " "  $ $ $ $ $ $       ' ' ' ' ' ' + + + + + + 7 7 7 7 7 7 M M M M M M A A A A A A # # # # # # 9 9 9 9 9 9 0 0 0 0 0 0 2 2 2 2 2 2	H		sQ sQ sQ sQ sQ sQ sQ sQ sQ sQr'   