{"record":{"id":"bab0361b3cb38db3","repo":"PrefectHQ/fastmcp","slug":"methodbinding-cannot-bind-spec-method-self-method","errorCode":null,"errorMessage":"MethodBinding cannot bind spec method {self.method!r}; extension methods are additive. Use ServerExtension.intercept_tool_call or FastMCP middleware to wrap core behaviour.","messagePattern":"MethodBinding cannot bind spec method (.+?); extension methods are additive\\. Use ServerExtension\\.intercept_tool_call or FastMCP middleware to wrap core behaviour\\.","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"fastmcp_slim/fastmcp/server/extensions.py","lineNumber":99,"sourceCode":"    subclass `RequestParams` so `_meta` parses uniformly. `protocol_versions`,\n    when set, restricts the method to those wire versions — a request at any\n    other version is rejected as `METHOD_NOT_FOUND`, mirroring the spec's\n    `(method, version)` boundary. `None` (the default) admits every version.\n\n    Extension methods are additive: `method` must not name a spec-defined\n    request method (`tools/call`, `completion/complete`, ...). Binding one would\n    silently shadow the server's own handler. Both constraints are enforced at\n    construction.\n    \"\"\"\n\n    method: str\n    params_type: type[BaseModel]\n    handler: ExtensionRequestHandler\n    protocol_versions: frozenset[str] | None = None\n\n    def __post_init__(self) -> None:\n        if self.method in SPEC_CLIENT_METHODS:\n            raise ValueError(\n                f\"MethodBinding cannot bind spec method {self.method!r}; extension \"\n                \"methods are additive. Use ServerExtension.intercept_tool_call or \"\n                \"FastMCP middleware to wrap core behaviour.\"\n            )\n        if self.protocol_versions is not None and not self.protocol_versions:\n            raise ValueError(\n                f\"MethodBinding for {self.method!r} has an empty protocol_versions \"\n                \"set, so it could never be served; use None to admit every version.\"\n            )\n\n\nclass ServerExtension:\n    \"\"\"Base class for an opt-in FastMCP server extension (SEP-2133).\n\n    Subclass, set `identifier`, and override the contribution methods that\n    apply. Every method has a default, so a minimal extension overrides only\n    `identifier` and one contribution. `identifier` is validated at\n    subclass-definition time when set as a class attribute, and again at","sourceCodeStart":81,"sourceCodeEnd":117,"githubUrl":"https://github.com/PrefectHQ/fastmcp/blob/1f021142978e0861cd910c8df4e8074bc7cf3978/fastmcp_slim/fastmcp/server/extensions.py#L81-L117","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nbinding = MethodBinding(method=\"tools/call\", handler=my_handler, params_type=CallToolRequestParams)\n// after\nbinding = MethodBinding(method=\"myextension/audit_tool\", handler=my_handler, params_type=MyParams)  # or use ServerExtension.intercept_tool_call","handlingStrategy":"validation","validationCode":"from fastmcp.server.extensions import SPEC_CLIENT_METHODS\nassert binding.method not in SPEC_CLIENT_METHODS, f\"{binding.method!r} is a spec method\"","typeGuard":"def is_additive_method(name: str) -> bool:\n    return name not in SPEC_CLIENT_METHODS","tryCatchPattern":"try:\n    binding = MethodBinding(method=name, handler=h, params_type=P)\nexcept ValueError:\n    binding = None  # fall back to ServerExtension.intercept_tool_call","preventionTips":["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"],"tags":["extensions","method-binding","api-misuse"],"backgroundTag":"spec-method-rebinding-forbidden","analyzedSha":"1f021142978e0861cd910c8df4e8074bc7cf3978","analyzedAt":"2026-08-29T14:31:16.082Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}