Add FileSystemProvider for filesystem-based component discovery (#2823)

This commit is contained in:
Jeremiah Lowin 2026-01-09 16:31:29 -05:00 committed by GitHub
commit 87f2edd9c0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
14 changed files with 2419 additions and 4 deletions

View file

@ -0,0 +1,39 @@
"""Assistant prompts."""
from fastmcp.fs import prompt
@prompt
def code_review(code: str, language: str = "python") -> str:
"""Generate a code review prompt.
Args:
code: The code to review.
language: Programming language (default: python).
"""
return f"""Please review this {language} code:
```{language}
{code}
```
Focus on:
- Code quality and readability
- Potential bugs or issues
- Performance considerations
- Best practices"""
@prompt(
name="explain-concept",
description="Generate a prompt to explain a technical concept.",
tags={"education", "explanation"},
)
def explain(topic: str, audience: str = "developer") -> str:
"""Generate an explanation prompt.
Args:
topic: The concept to explain.
audience: Target audience level.
"""
return f"Explain {topic} to a {audience}. Use clear examples and analogies."

View file

@ -0,0 +1,55 @@
"""Configuration resources - static and templated."""
import json
from fastmcp.fs import resource
# Static resource - no parameters in URI
@resource("config://app")
def get_app_config() -> str:
"""Get application configuration."""
return json.dumps(
{
"name": "FilesystemDemo",
"version": "1.0.0",
"features": ["tools", "resources", "prompts"],
},
indent=2,
)
# Resource template - {env} is a parameter
@resource("config://env/{env}")
def get_env_config(env: str) -> str:
"""Get environment-specific configuration.
Args:
env: Environment name (dev, staging, prod).
"""
configs = {
"dev": {"debug": True, "log_level": "DEBUG", "database": "localhost"},
"staging": {"debug": True, "log_level": "INFO", "database": "staging-db"},
"prod": {"debug": False, "log_level": "WARNING", "database": "prod-db"},
}
config = configs.get(env, {"error": f"Unknown environment: {env}"})
return json.dumps(config, indent=2)
# Resource with custom metadata
@resource(
"config://features",
name="feature-flags",
mime_type="application/json",
tags={"config", "features"},
)
def get_feature_flags() -> str:
"""Get feature flags configuration."""
return json.dumps(
{
"dark_mode": True,
"beta_features": False,
"max_upload_size_mb": 100,
},
indent=2,
)

View file

@ -0,0 +1,24 @@
"""Math tools with custom metadata."""
from fastmcp.fs import tool
@tool(
name="add-numbers", # Custom name (default would be "add")
description="Add two numbers together.",
tags={"math", "arithmetic"},
)
def add(a: float, b: float) -> float:
"""Add two numbers."""
return a + b
@tool(tags={"math", "arithmetic"})
def multiply(a: float, b: float) -> float:
"""Multiply two numbers.
Args:
a: First number.
b: Second number.
"""
return a * b

View file

@ -0,0 +1,28 @@
"""Greeting tools - multiple tools in one file."""
from fastmcp.fs import tool
@tool
def greet(name: str) -> str:
"""Greet someone by name.
Args:
name: The person's name.
"""
return f"Hello, {name}!"
@tool
def farewell(name: str) -> str:
"""Say goodbye to someone.
Args:
name: The person's name.
"""
return f"Goodbye, {name}!"
# Helper functions without decorators are ignored
def _format_message(msg: str) -> str:
return msg.strip().capitalize()

View file

@ -0,0 +1,29 @@
"""Filesystem-based MCP server using FileSystemProvider.
This example demonstrates how to use FileSystemProvider to automatically
discover and register tools, resources, and prompts from the filesystem.
Run:
fastmcp run examples/filesystem-provider/server.py
Inspect:
fastmcp inspect examples/filesystem-provider/server.py
Dev mode (re-scan files on every request):
Change reload=True below, then modify files while the server runs.
"""
from pathlib import Path
from fastmcp import FastMCP
from fastmcp.fs import FileSystemProvider
# The provider scans all .py files in the directory recursively.
# Functions decorated with @tool, @resource, or @prompt are registered.
# Directory structure is purely organizational - decorators determine type.
provider = FileSystemProvider(
root=Path(__file__).parent / "mcp",
reload=True, # Set True for dev mode (re-scan on every request)
)
mcp = FastMCP("FilesystemDemo", providers=[provider])