Summary
Replace the current regex-based profile module loading with FastMCP v3 tags + mcp.disable(tags=...) so all tools are registered at startup and profile filtering happens via tag-based enable/disable with automatic list_tools updates.
Background
Currently, profiles determine which tools are registered via regex pattern matching on tool name prefixes in module_loader.py. Disabling a tool post-startup is not supported. FastMCP v3 allows attaching tags at registration time and calling mcp.disable(tags=...) to hide tools from clients dynamically — disabled tools are excluded from list_tools and trigger notifications/tools/list_changed automatically.
Proposed Approach
TAG_MAP = {"base_": "base", "dba_": "dba", "rag_": "rag", ...}
def tag_for(tool_name: str) -> set[str]:
for prefix, tag in TAG_MAP.items():
if tool_name.startswith(prefix):
return {tag}
return set()
# Register all tools with tags
mcp.tool(name=name, tags=tag_for(name))(wrapped)
# Apply profile: disable tools not in the allowed set
allowed_tags = profile_allowed_tags(profile_name)
mcp.disable(tags=all_tags - allowed_tags)
Files to Change
app.py:80-116 (feature flags)
app.py:530-583 (registration loop)
module_loader.py (can be simplified)
tools/__init__.py
Value
- Dynamic enable/disable at runtime without re-registration.
list_tools automatically excludes disabled tools — progressive disclosure is simplified.
notifications/tools/list_changed sent automatically when tools are enabled/disabled.
- Simplifies
module_loader.py — regex matching replaced by tag lookup.
Dependencies
Should be done together with Lifespan management (#9). The profile filter needs the lifespan-supplied connection to discover analytic functions.
Summary
Replace the current regex-based profile module loading with FastMCP v3
tags+mcp.disable(tags=...)so all tools are registered at startup and profile filtering happens via tag-based enable/disable with automaticlist_toolsupdates.Background
Currently, profiles determine which tools are registered via regex pattern matching on tool name prefixes in
module_loader.py. Disabling a tool post-startup is not supported. FastMCP v3 allows attaching tags at registration time and callingmcp.disable(tags=...)to hide tools from clients dynamically — disabled tools are excluded fromlist_toolsand triggernotifications/tools/list_changedautomatically.Proposed Approach
Files to Change
app.py:80-116(feature flags)app.py:530-583(registration loop)module_loader.py(can be simplified)tools/__init__.pyValue
list_toolsautomatically excludes disabled tools — progressive disclosure is simplified.notifications/tools/list_changedsent automatically when tools are enabled/disabled.module_loader.py— regex matching replaced by tag lookup.Dependencies
Should be done together with Lifespan management (#9). The profile filter needs the lifespan-supplied connection to discover analytic functions.