Use this file to discover all available pages before exploring further.
New in version 3.0.0Components can be dynamically enabled or disabled at runtime. A disabled tool disappears from listings and cannot be called. This enables runtime access control, feature flags, and context-aware component exposure.
Every component has a unique key in the format {type}:{identifier}.
Component
Key Format
Example
Tool
tool:{name}
tool:delete_everything
Resource
resource:{uri}
resource:data://config
Template
template:{uri}
template:file://{path}
Prompt
prompt:{name}
prompt:analyze
Use keys to target specific components.
# Disable a specific toolmcp.disable(keys={"tool:delete_everything"})# Disable multiple specific componentsmcp.disable(keys={"tool:reset_system", "resource:data://secrets"})
By default, visibility filtering uses blocklist mode: everything is enabled unless explicitly disabled. The only=True parameter switches to allowlist mode, where only specified components are enabled.
# Start fresh - only enable these specific toolsmcp.enable(keys={"tool:safe_read", "tool:safe_write"}, only=True)# Later, switch to a different allowlistmcp.enable(tags={"production"}, only=True)
Later enable() and disable() calls override earlier ones. This lets you create broad rules with specific exceptions.
mcp.enable(tags={"api"}, only=True) # Allow all api-taggedmcp.disable(keys={"tool:api_admin"}) # Later disable overrides for this tool# api_admin is disabled because the later disable() overrides the allowlist
You can always re-enable something that was disabled by adding another enable() call after it.
Server-level visibility state applies to all components from all providers. When you call mcp.enable() or mcp.disable(), you’re filtering the final view that clients see.
from fastmcp import FastMCPmain = FastMCP("Main")main.mount(sub_server, namespace="api")@main.tool(tags={"internal"})def local_debug() -> str: return "Debug"# Disable internal tools from ALL sourcesmain.disable(tags={"internal"})
Server-level visibility changes affect all connected clients simultaneously. When you need different clients to see different components, use per-session visibility instead.Session visibility lets individual sessions customize their view of available components. When a tool calls ctx.enable_components() or ctx.disable_components(), those rules apply only to the current session. Other sessions continue to see the global defaults. This enables patterns like progressive disclosure, role-based access, and on-demand feature activation.
from fastmcp import FastMCPfrom fastmcp.server.context import Contextmcp = FastMCP("Session-Aware Server")@mcp.tool(tags={"premium"})def premium_analysis(data: str) -> str: """Advanced analysis available to premium users.""" return f"Premium analysis of: {data}"@mcp.toolasync def unlock_premium(ctx: Context) -> str: """Unlock premium features for this session.""" await ctx.enable_components(tags={"premium"}) return "Premium features unlocked"@mcp.toolasync def reset_features(ctx: Context) -> str: """Reset to default feature set.""" await ctx.reset_visibility() return "Features reset to defaults"# Premium tools are disabled globally by defaultmcp.disable(tags={"premium"})
All sessions start with premium_analysis hidden. When a session calls unlock_premium, that session gains access to premium tools while other sessions remain unaffected. Calling reset_features returns the session to the global defaults.
Session rules override global transforms. When listing components, FastMCP first applies global enable/disable rules, then applies session-specific rules on top. Rules within a session accumulate, and later rules override earlier ones for the same component.
@mcp.toolasync def customize_session(ctx: Context) -> str: # Enable finance tools for this session await ctx.enable_components(tags={"finance"}) # Also enable admin tools await ctx.enable_components(tags={"admin"}) # Later: disable a specific admin tool await ctx.disable_components(names={"dangerous_admin_tool"}) return "Session customized"
Each call adds a rule to the session. The dangerous_admin_tool ends up disabled because its disable rule was added after the admin enable rule.
When session visibility changes, FastMCP automatically sends notifications to that session. Clients receive ToolListChangedNotification, ResourceListChangedNotification, and PromptListChangedNotification so they can refresh their component lists. These notifications go only to the affected session.When you specify the components parameter, FastMCP optimizes by sending only the relevant notifications:
# Only sends ToolListChangedNotificationawait ctx.enable_components(tags={"finance"}, components={"tool"})# Sends all three notifications (no components filter)await ctx.enable_components(tags={"finance"})
A common pattern organizes tools into namespaces using tag prefixes, disables them globally, then provides activation tools that unlock namespaces on demand:
Sessions start seeing only the activation tools. Calling activate_finance reveals finance tools for that session only. Multiple namespaces can be activated independently, and deactivate_all returns to the initial state.
When visibility state changes, FastMCP automatically notifies connected clients. Clients supporting the MCP notification protocol receive list_changed events and can refresh their component lists.This happens automatically. You don’t need to trigger notifications manually.
# This automatically notifies clientsmcp.disable(tags={"maintenance"})# Clients receive: tools/list_changed, resources/list_changed, etc.
Understanding the filtering logic helps when debugging visibility state issues.The is_enabled() function checks a component’s internal metadata:
If the component has meta.fastmcp._internal.visibility = False, it’s disabled
If the component has meta.fastmcp._internal.visibility = True, it’s enabled
If no visibility state is set, the component is enabled by default
When multiple enable() and disable() calls are made, transforms are applied in order. Later transforms override earlier ones, so the last matching transform wins.
Under the hood, enable() and disable() add Visibility transforms to the server or provider. The Visibility transform marks components with visibility metadata, and the server applies the final filter after all provider and server transforms complete.
from fastmcp import FastMCPfrom fastmcp.server.transforms import Visibilitymcp = FastMCP("Server")# Using the convenience method (recommended)mcp.disable(names={"secret_tool"})# Equivalent to:mcp.add_transform(Visibility(False, names={"secret_tool"}))
Server-level transforms override provider-level transforms. If a component is disabled at the provider level but enabled at the server level, the server-level enable() can re-enable it.