--- title: Local Provider sidebarTitle: Local description: The default provider for decorator-registered components icon: house --- import { VersionBadge } from '/snippets/version-badge.mdx' `LocalProvider` stores components that you define directly on your server. When you use `@mcp.tool`, `@mcp.resource`, or `@mcp.prompt`, you're adding components to your server's `LocalProvider`. ## How It Works Every FastMCP server has a `LocalProvider` as its first provider. Components registered via decorators or direct methods are stored here: ```python from fastmcp import FastMCP mcp = FastMCP("MyServer") # These are stored in the server's `LocalProvider` @mcp.tool def greet(name: str) -> str: """Greet someone by name.""" return f"Hello, {name}!" @mcp.resource("data://config") def get_config() -> str: """Return configuration data.""" return '{"version": "1.0"}' @mcp.prompt def analyze(topic: str) -> str: """Create an analysis prompt.""" return f"Please analyze: {topic}" ``` The `LocalProvider` is always queried first when clients request components, ensuring that your directly-defined components take precedence over those from mounted or proxied servers. ## Component Registration ### Using Decorators The most common way to register components: ```python @mcp.tool def my_tool(x: int) -> str: return str(x) @mcp.resource("data://info") def my_resource() -> str: return "info" @mcp.prompt def my_prompt(topic: str) -> str: return f"Discuss: {topic}" ``` ### Using Direct Methods You can also add pre-built component objects: ```python from fastmcp.tools import Tool # Create a tool object my_tool = Tool.from_function(some_function, name="custom_tool") # Add it to the server mcp.add_tool(my_tool) mcp.add_resource(my_resource) mcp.add_prompt(my_prompt) ``` ### Removing Components Remove components by name or URI: ```python mcp.remove_tool("my_tool") mcp.remove_resource("data://info") mcp.remove_prompt("my_prompt") ``` ## Duplicate Handling When you try to add a component that already exists, the behavior depends on the `on_duplicate` setting: | Mode | Behavior | |------|----------| | `"error"` (default) | Raise `ValueError` | | `"warn"` | Log warning and replace | | `"replace"` | Silently replace | | `"ignore"` | Keep existing component | Configure this when creating the server: ```python mcp = FastMCP("MyServer", on_duplicate="warn") ``` ## Visibility Control You can enable or disable components at runtime. Disabled components don't appear in listings and can't be called. ### Disabling Components Use `disable()` to hide components: ```python # Disable by key mcp.disable(keys=["tool:admin_action"]) # Disable by tag mcp.disable(tags={"internal"}) # Disable multiple mcp.disable(keys=["tool:debug"], tags={"deprecated"}) ``` ### Enabling Components Use `enable()` to re-enable disabled components: ```python # Re-enable by key mcp.enable(keys=["tool:admin_action"]) # Re-enable by tag mcp.enable(tags={"internal"}) ``` ### Allowlist Mode Use `only=True` to switch to allowlist mode, where **only** the specified components are visible: ```python # Only show public tools mcp.enable(tags={"public"}, only=True) # Only show specific tools mcp.enable(keys=["tool:safe_tool", "tool:read_only"], only=True) ``` ### Component Keys Keys follow the format `{type}:{identifier}`: | Component Type | Key Format | Example | |----------------|------------|---------| | Tool | `tool:{name}` | `tool:greet` | | Resource | `resource:{uri}` | `resource:data://config` | | Template | `template:{uri}` | `template:data://{id}` | | Prompt | `prompt:{name}` | `prompt:analyze` | ### Using Tags Add tags when defining components to enable group-based visibility control: ```python @mcp.tool(tags={"admin", "dangerous"}) def delete_all() -> str: """Delete everything.""" return "Deleted" @mcp.tool(tags={"public", "safe"}) def get_status() -> str: """Get system status.""" return "OK" # Hide all admin tools mcp.disable(tags={"admin"}) # Or only show safe tools mcp.enable(tags={"safe"}, only=True) ``` ### Automatic Notifications When you enable or disable components, FastMCP automatically sends `list_changed` notifications to connected clients. Clients that support notifications will refresh their component lists automatically. ## Standalone LocalProvider You can create a LocalProvider independently and attach it to multiple servers: ```python from fastmcp import FastMCP from fastmcp.server.providers import LocalProvider # Create a reusable provider shared_tools = LocalProvider() @shared_tools.tool def greet(name: str) -> str: return f"Hello, {name}!" @shared_tools.resource("data://version") def get_version() -> str: return "1.0.0" # Attach to multiple servers server1 = FastMCP("Server1", providers=[shared_tools]) server2 = FastMCP("Server2", providers=[shared_tools]) ``` This is useful for: - Sharing components across servers - Testing components in isolation - Building reusable component libraries ## Provider-Level Visibility Visibility can be controlled at the provider level as well: ```python from fastmcp.server.providers import LocalProvider provider = LocalProvider() @provider.tool(tags={"internal"}) def internal_tool() -> str: return "Internal" # Disable at provider level provider.disable(tags={"internal"}) # This affects all servers using this provider mcp = FastMCP("Server", providers=[provider]) ``` When a component is disabled at the provider level, it's hidden from all servers using that provider. Server-level visibility adds another layer of filtering on top of provider-level visibility.