PrefectHQ/fastmcp · error · ValueError
MethodBinding cannot bind spec method {self.method!r}; exten
Error message
MethodBinding cannot bind spec method {self.method!r}; extension methods are additive. Use ServerExtension.intercept_tool_call or FastMCP middleware to wrap core behaviour. What it means
MethodBinding is for additive extension methods only. Its __post_init__ rejects any method name found in SPEC_CLIENT_METHODS (methods defined by the MCP specification, e.g. 'tools/call', 'sampling/createMessage') because rebinding spec methods would replace core protocol behavior rather than add to it. The error directs you to ServerExtension.intercept_tool_call or FastMCP middleware for wrapping core behavior.
Source
Thrown at fastmcp_slim/fastmcp/server/extensions.py:99
subclass `RequestParams` so `_meta` parses uniformly. `protocol_versions`,
when set, restricts the method to those wire versions — a request at any
other version is rejected as `METHOD_NOT_FOUND`, mirroring the spec's
`(method, version)` boundary. `None` (the default) admits every version.
Extension methods are additive: `method` must not name a spec-defined
request method (`tools/call`, `completion/complete`, ...). Binding one would
silently shadow the server's own handler. Both constraints are enforced at
construction.
"""
method: str
params_type: type[BaseModel]
handler: ExtensionRequestHandler
protocol_versions: frozenset[str] | None = None
def __post_init__(self) -> None:
if self.method in SPEC_CLIENT_METHODS:
raise ValueError(
f"MethodBinding cannot bind spec method {self.method!r}; extension "
"methods are additive. Use ServerExtension.intercept_tool_call or "
"FastMCP middleware to wrap core behaviour."
)
if self.protocol_versions is not None and not self.protocol_versions:
raise ValueError(
f"MethodBinding for {self.method!r} has an empty protocol_versions "
"set, so it could never be served; use None to admit every version."
)
class ServerExtension:
"""Base class for an opt-in FastMCP server extension (SEP-2133).
Subclass, set `identifier`, and override the contribution methods that
apply. Every method has a default, so a minimal extension overrides only
`identifier` and one contribution. `identifier` is validated at
subclass-definition time when set as a class attribute, and again atView on GitHub (pinned to 1f02114297)
Solutions
- Rename your extension method to a non-spec, additive method name.
- If the goal is to wrap core tool behavior, use ServerExtension.intercept_tool_call instead of MethodBinding.
- Use FastMCP middleware to intercept or modify core request handling.
- Check SPEC_CLIENT_METHODS to confirm your method name does not collide with the MCP spec.
Example fix
// before binding = MethodBinding(method="tools/call", handler=my_handler, params_type=CallToolRequestParams) // after binding = MethodBinding(method="myextension/audit_tool", handler=my_handler, params_type=MyParams) # or use ServerExtension.intercept_tool_call
Defensive patterns
Strategy: validation
Validate before calling
from fastmcp.server.extensions import SPEC_CLIENT_METHODS
assert binding.method not in SPEC_CLIENT_METHODS, f"{binding.method!r} is a spec method" Type guard
def is_additive_method(name: str) -> bool:
return name not in SPEC_CLIENT_METHODS Try / catch
try:
binding = MethodBinding(method=name, handler=h, params_type=P)
except ValueError:
binding = None # fall back to ServerExtension.intercept_tool_call Prevention
- Prefix extension methods with a namespace like 'myext/'
- Check SPEC_CLIENT_METHODS before naming a method
- Use intercept_tool_call or middleware for overriding core behavior
When it happens
Trigger: Constructing MethodBinding(method=<a spec client method name>, handler=..., params_type=...) directly, or registering an extension whose handler method collides with a spec method name.
Common situations: Developers trying to override built-in MCP behavior (e.g. intercept tools/call) via the extension binding API; renaming/refactoring that accidentally reused a spec method string.
Related errors
- Cannot pass both 'metadata' and individual parameters to fro
- The @resource decorator requires a URI. Use @resource('uri')
- Extension {self.identifier!r} is not bound to a FastMCP serv
- METHOD_NOT_FOUND
- Task-enabled tools ({names}) require the tasks extension, bu
AI-assisted analysis of PrefectHQ/fastmcp@1f02114297 (2026-08-29).
Data as JSON: /api/errors/bab0361b3cb38db3.
Report an issue: GitHub.