2.3 KiB
Consolidating Discovery Methods
This document captures the design decisions around component listing methods in FastMCP 3.0.
Problem
The server had parallel implementations for listing components:
get_tools()/_list_tools()get_resources()/_list_resources()get_prompts()/_list_prompts()get_resource_templates()/_list_resource_templates()
These were nearly identical but with subtle differences in dedup keys, logging, and return types. The _list_* methods were internal and used by the MCP protocol handlers, while get_* methods were the public API.
Solution
The duplicate methods were consolidated into a single set of list_* methods. The old get_* plural methods and _list_* internal methods were both removed.
This happened in two phases:
- Consolidation (Dec 2025): Merged
get_*and_list_*into a singleget_*method with anapply_middlewareparameter. - Rename (Jan 2026): When
FastMCPwas refactored to inherit fromProvider, the methods were renamed tolist_*to align with theProviderinterface. Theapply_middlewareparameter was renamed torun_middlewarewith a default ofTrue.
async def list_tools(self, *, run_middleware: bool = True) -> Sequence[Tool]:
"""Canonical method for listing tools."""
...
Key Changes
Return Type: dict → list
The dict return type was removed because the key was redundant—components already have .name or .uri attributes.
# Before (v2.x)
tools = await server.get_tools()
tool = tools["my_tool"]
# After (v3.0)
tools = await server.list_tools()
tool = next(t for t in tools if t.name == "my_tool")
Middleware via Parameter
The run_middleware=True parameter (default) applies the middleware chain. This replaces the separate _list_*_middleware() methods.
Benefits
- Single source of truth - One method, not two
- Consistent behavior - Same dedup key, same visibility filtering
- Clearer API - Public method with explicit middleware opt-in
- Provider alignment -
FastMCP.list_tools()overridesProvider.list_tools() - Less code - Deleted ~200 lines of duplicate implementation
Implementation Files
src/fastmcp/server/server.py- Canonicallist_*methodssrc/fastmcp/server/providers/- Provider base class defines the interface