Module fastmcp_extensions.tool_filters
Standard tool filters for MCP servers.
This module provides pre-defined config args and filter functions for common
tool filtering use cases. These can be used individually or together via the
include_standard_tool_filters=True parameter on mcp_server().
Key Components
- Config Args: Pre-defined MCPServerConfigArg instances for standard filters
- Filter Functions: Public filter functions that can be used individually
- Constants: Config names, env vars, headers, and annotation keys
Basic Usage
Use standard filters automatically:
from fastmcp_extensions import mcp_server
app = mcp_server(
name="my-server",
include_standard_tool_filters=True,
)
Or use individual filters:
from fastmcp_extensions import mcp_server, ToolFilterMiddleware
from fastmcp_extensions.tool_filters import (
readonly_mode_filter,
READONLY_MODE_CONFIG_ARG,
)
app = mcp_server(
name="my-server",
server_config_args=[READONLY_MODE_CONFIG_ARG],
)
app.add_middleware(ToolFilterMiddleware(app, tool_filter=readonly_mode_filter))
Global variables
var ANNOTATION_DESTRUCTIVE_HINT-
Annotation key for destructive hint (MCP spec).
var ANNOTATION_MCP_MODULE-
Annotation key for MCP module name (set by @mcp_tool decorator).
var ANNOTATION_READ_ONLY_HINT-
Annotation key for read-only hint (MCP spec).
var CONFIG_EXCLUDE_MODULES-
Config name for excluding tools by module name.
var CONFIG_EXCLUDE_TOOLS-
Config name for excluding specific tools by name.
var CONFIG_INCLUDE_MODULES-
Config name for including only specific modules.
var CONFIG_NO_DESTRUCTIVE_TOOLS-
Config name for hiding destructive tools.
var CONFIG_READONLY_MODE-
Config name for read-only mode.
var ENV_EXCLUDE_MODULES-
Environment variable for excluding tools by module name.
var ENV_EXCLUDE_TOOLS-
Environment variable for excluding specific tools by name.
var ENV_INCLUDE_MODULES-
Environment variable for including only specific modules.
var ENV_NO_DESTRUCTIVE_TOOLS-
Environment variable for hiding destructive tools.
var ENV_READONLY_MODE-
Environment variable for read-only mode.
var EXCLUDE_MODULES_CONFIG_ARG-
Standard config arg for excluding tools by module name.
Comma-separated list of module names to exclude. Tools from these modules will be hidden. Can be set via X-MCP-Exclude-Modules HTTP header or MCP_EXCLUDE_MODULES env var. Mutually exclusive with include_modules.
var EXCLUDE_TOOLS_CONFIG_ARG-
Standard config arg for excluding specific tools by name.
Comma-separated list of tool names to exclude. These tools will be hidden. Can be set via X-MCP-Exclude-Tools HTTP header or MCP_EXCLUDE_TOOLS env var.
var HEADER_EXCLUDE_MODULES-
HTTP header for excluding tools by module name.
var HEADER_EXCLUDE_TOOLS-
HTTP header for excluding specific tools by name.
var HEADER_INCLUDE_MODULES-
HTTP header for including only specific modules.
var HEADER_NO_DESTRUCTIVE_TOOLS-
HTTP header for hiding destructive tools.
var HEADER_READONLY_MODE-
HTTP header for read-only mode.
var INCLUDE_MODULES_CONFIG_ARG-
Standard config arg for including only specific modules.
Comma-separated list of module names to include. Only tools from these modules will be visible. Can be set via X-MCP-Include-Modules HTTP header or MCP_INCLUDE_MODULES env var. Mutually exclusive with exclude_modules.
var NO_DESTRUCTIVE_TOOLS_CONFIG_ARG-
Standard config arg for hiding destructive tools.
When set to "1" or "true", tools with destructiveHint=True annotation will be hidden. Can be set via X-No-Destructive-Tools HTTP header or MCP_NO_DESTRUCTIVE_TOOLS env var.
var READONLY_MODE_CONFIG_ARG-
Standard config arg for read-only mode.
When set to "1", only tools with readOnlyHint=True annotation will be visible. Can be set via X-MCP-Readonly-Mode HTTP header or MCP_READONLY_MODE env var.
var STANDARD_CONFIG_ARGS : list[MCPServerConfigArg]-
List of all standard config args for tool filtering.
var STANDARD_TOOL_FILTERS : list[Callable[[mcp.types.Tool, fastmcp.server.server.FastMCP], bool]]-
List of all standard tool filter functions.
var ToolFilterFn-
Type alias for tool filter functions.
A tool filter function takes a Tool object and the FastMCP app, and returns True if the tool should be visible, False to hide it.
The FastMCP app is passed so the filter can call get_mcp_config() to access request-specific configuration values (from HTTP headers, env vars, or defaults).
Example
def readonly_filter(tool: Tool, app: FastMCP) -> bool: if get_mcp_config(app, "readonly_mode") == "1": annotations = tool.annotations if annotations is None: return False return getattr(annotations, "readOnlyHint", False) return True
Functions
def get_annotation(tool_or_asset: Tool, annotation_name: str, default: bool | str | None = None) ‑> bool | str | None-
Expand source code
def get_annotation( tool_or_asset: Tool, annotation_name: str, default: bool | str | None = None, ) -> bool | str | None: """Get an annotation value from a tool or asset. This helper hides the messy getattr implementation needed to access annotations stored in pydantic's model_extra. Args: tool_or_asset: The Tool (or other MCP asset) to get the annotation from. annotation_name: The name of the annotation to retrieve. default: The default value to return if the annotation is not present. Returns: The annotation value, or the default if not present. """ annotations = tool_or_asset.annotations if annotations is None: return default return getattr(annotations, annotation_name, default)Get an annotation value from a tool or asset.
This helper hides the messy getattr implementation needed to access annotations stored in pydantic's model_extra.
Args
tool_or_asset- The Tool (or other MCP asset) to get the annotation from.
annotation_name- The name of the annotation to retrieve.
default- The default value to return if the annotation is not present.
Returns
The annotation value, or the default if not present.
def module_filter(tool: Tool, app: FastMCP) ‑> bool-
Expand source code
def module_filter(tool: Tool, app: FastMCP) -> bool: """Filter tools based on exclude_modules and include_modules config. When exclude_modules is set, hide tools from those modules. When include_modules is set, only show tools from those modules. If both are set, raises ValueError (mutually exclusive). Args: tool: The tool to check. app: The FastMCP app instance. Returns: True if the tool should be visible, False to hide it. Raises: ValueError: If both exclude_modules and include_modules are set. """ exclude_modules = _parse_csv_config(get_mcp_config(app, CONFIG_EXCLUDE_MODULES)) include_modules = _parse_csv_config(get_mcp_config(app, CONFIG_INCLUDE_MODULES)) if exclude_modules and include_modules: raise ValueError( "Cannot specify both exclude_modules and include_modules. " "These options are mutually exclusive." ) # Get the tool's mcp_module from annotations tool_module = get_annotation(tool, ANNOTATION_MCP_MODULE, None) if exclude_modules: # Hide tools from excluded modules return not (tool_module and tool_module in exclude_modules) if include_modules: # Only show tools from included modules return bool(tool_module and tool_module in include_modules) return TrueFilter tools based on exclude_modules and include_modules config.
When exclude_modules is set, hide tools from those modules. When include_modules is set, only show tools from those modules. If both are set, raises ValueError (mutually exclusive).
Args
tool- The tool to check.
app- The FastMCP app instance.
Returns
True if the tool should be visible, False to hide it.
Raises
ValueError- If both exclude_modules and include_modules are set.
def no_destructive_tools_filter(tool: Tool, app: FastMCP) ‑> bool-
Expand source code
def no_destructive_tools_filter(tool: Tool, app: FastMCP) -> bool: """Filter tools based on no_destructive_tools config. When no_destructive_tools is "1" or "true", hide tools with destructiveHint=True. When no_destructive_tools is "0" (default), show all tools. Args: tool: The tool to check. app: The FastMCP app instance. Returns: True if the tool should be visible, False to hide it. """ config_value = get_mcp_config(app, CONFIG_NO_DESTRUCTIVE_TOOLS).lower() if config_value in ("1", "true"): return not bool(get_annotation(tool, ANNOTATION_DESTRUCTIVE_HINT, False)) return TrueFilter tools based on no_destructive_tools config.
When no_destructive_tools is "1" or "true", hide tools with destructiveHint=True. When no_destructive_tools is "0" (default), show all tools.
Args
tool- The tool to check.
app- The FastMCP app instance.
Returns
True if the tool should be visible, False to hide it.
def readonly_mode_filter(tool: Tool, app: FastMCP) ‑> bool-
Expand source code
def readonly_mode_filter(tool: Tool, app: FastMCP) -> bool: """Filter tools based on readonly_mode config. When readonly_mode is "1" or "true", only show tools with readOnlyHint=True. When readonly_mode is "0" (default), show all tools. Args: tool: The tool to check. app: The FastMCP app instance. Returns: True if the tool should be visible, False to hide it. """ config_value = get_mcp_config(app, CONFIG_READONLY_MODE).lower() if config_value in ("1", "true"): return bool(get_annotation(tool, ANNOTATION_READ_ONLY_HINT, False)) return TrueFilter tools based on readonly_mode config.
When readonly_mode is "1" or "true", only show tools with readOnlyHint=True. When readonly_mode is "0" (default), show all tools.
Args
tool- The tool to check.
app- The FastMCP app instance.
Returns
True if the tool should be visible, False to hide it.
def tool_exclusion_filter(tool: Tool, app: FastMCP) ‑> bool-
Expand source code
def tool_exclusion_filter(tool: Tool, app: FastMCP) -> bool: """Filter tools based on exclude_tools config. When exclude_tools is set, hide tools with those names. Args: tool: The tool to check. app: The FastMCP app instance. Returns: True if the tool should be visible, False to hide it. """ exclude_tools = _parse_csv_config(get_mcp_config(app, CONFIG_EXCLUDE_TOOLS)) return not (exclude_tools and tool.name in exclude_tools)Filter tools based on exclude_tools config.
When exclude_tools is set, hide tools with those names.
Args
tool- The tool to check.
app- The FastMCP app instance.
Returns
True if the tool should be visible, False to hide it.