New in version 3.0.0FileSystemProvider scans a directory for Python files and automatically registers functions decorated with @tool, @resource, or @prompt. This enables a file-based organization pattern similar to Next.js routing, where your project structure becomes your component registry.
Traditional FastMCP servers require coordination between files. Either your tool files import the server to call @server.tool(), or your server file imports all the tool modules. Both approaches create coupling that some developers prefer to avoid.FileSystemProvider eliminates this coordination. Each file is self-contained—it uses standalone decorators (@tool, @resource, @prompt) that don’t require access to a server instance. The provider discovers these files at startup, so you can add new tools without modifying your server file.This is a convention some teams prefer, not necessarily better for all projects. The tradeoffs:
No coordination: Files don’t import the server; server doesn’t import files
Predictable naming: Function names become component names (unless overridden)
Development mode: Optionally re-scan files on every request for rapid iteration
Create a provider pointing to your components directory, then pass it to your server. Use Path(__file__).parent to make the path relative to your server file.
FastMCP provides standalone decorators that mark functions for discovery: @tool from fastmcp.tools, @resource from fastmcp.resources, and @prompt from fastmcp.prompts. These support the full syntax of server-bound decorators—all the same parameters work identically.
URIs with template parameters create resource templates. The provider automatically detects whether to register a static resource or a template based on whether the URI contains {parameters} or the function has arguments.
Copy
from fastmcp.resources import resource@resource("users://{user_id}/profile")def get_user_profile(user_id: str) -> str: """Get a user's profile by ID.""" return f'{{"id": "{user_id}", "name": "User"}}'
The decorator supports: uri (required), name, title, description, icons, mime_type, tags, annotations, and meta.
The directory structure is purely organizational. The provider recursively scans all .py files regardless of which subdirectory they’re in. Subdirectories like tools/, resources/, and prompts/ are optional conventions that help you organize code.
If your directory contains an __init__.py file, the provider imports files as proper Python package members. This means relative imports work correctly within your components directory.
During development, you may want changes to component files to take effect without restarting the server. Enable reload mode to re-scan the directory on every request.
When a file fails to import (syntax error, missing dependency, etc.), the provider logs a warning and continues scanning other files. Failed imports don’t prevent the server from starting.
Copy
WARNING - Failed to import /path/to/broken.py: No module named 'missing_dep'
The provider tracks which files have failed and only re-logs warnings when the file’s modification time changes. This prevents log spam when a broken file is repeatedly scanned in reload mode.