PrefectHQ/fastmcp · error · TypeError

The function '{fn_name}' has '{params[0]}' as its first para

Error message

The function '{fn_name}' has '{params[0]}' as its first parameter. Use the standalone @tool decorator and register the bound method:

    from fastmcp.tools import tool

    class MyClass:
        @tool
        def {fn_name}(...):
            ...

    obj = MyClass()
    mcp.add_tool(obj.{fn_name})

See https://gofastmcp.com/servers/tools#using-with-methods

What it means

@tool was applied to an unbound method whose first parameter is `self` (or `cls`). FastMCP does not auto-bind methods at decoration time inside a class body, so it refuses and directs you to decorate with the standalone @tool and register the bound method on the server.

Source

Thrown at fastmcp_slim/fastmcp/server/providers/local_provider/decorators/tools.py:287

            annotations = ToolAnnotations(**annotations)

        if isinstance(name_or_fn, classmethod):
            raise TypeError(
                "To decorate a classmethod, use @classmethod above @tool. "
                "See https://gofastmcp.com/servers/tools#using-with-methods"
            )

        def decorate_and_register(
            fn: AnyFunction, tool_name: str | None
        ) -> FunctionTool | AnyFunction:
            # Check for unbound method
            try:
                params = list(inspect.signature(fn).parameters.keys())
            except (ValueError, TypeError):
                params = []
            if params and params[0] in ("self", "cls"):
                fn_name = getattr(fn, "__name__", "function")
                raise TypeError(
                    f"The function '{fn_name}' has '{params[0]}' as its first parameter. "
                    f"Use the standalone @tool decorator and register the bound method:\n\n"
                    f"    from fastmcp.tools import tool\n\n"
                    f"    class MyClass:\n"
                    f"        @tool\n"
                    f"        def {fn_name}(...):\n"
                    f"            ...\n\n"
                    f"    obj = MyClass()\n"
                    f"    mcp.add_tool(obj.{fn_name})\n\n"
                    f"See https://gofastmcp.com/servers/tools#using-with-methods"
                )

            from fastmcp.tools.function_tool import ToolMeta

            metadata = ToolMeta(
                name=tool_name,
                version=version,
                title=title,

View on GitHub (pinned to 1f02114297)

Solutions

  1. Use the standalone @tool decorator on the method and register the bound method: mcp.add_tool(obj.method).
  2. Make it a staticmethod (no self) if instance state isn't needed, or a module-level function.
  3. For classmethods, place @classmethod above @tool.

Example fix

// before
class MyClass:
    @tool
    def lookup(self, key: str) -> str:
        ...

// after
from fastmcp.tools import tool

class MyClass:
    @tool
    def lookup(self, key: str) -> str:
        ...

obj = MyClass()
mcp.add_tool(obj.lookup)
Defensive patterns

Strategy: validation

Validate before calling

import inspect

def validate_tool_fn(fn):
    params = list(inspect.signature(fn).parameters)
    if params and params[0] in ('self', 'cls'):
        raise TypeError('use standalone @tool and register bound method: mcp.add_tool(obj.fn)')
    return fn

Type guard

def is_unbound_method(fn) -> bool:
    try:
        params = list(inspect.signature(fn).parameters)
    except (ValueError, TypeError):
        return False
    return bool(params) and params[0] in ('self', 'cls')

Try / catch

try:
    mcp.add_tool(svc.lookup)
except TypeError as e:
    if "first parameter" in str(e) and ('self' in str(e) or 'cls' in str(e)):
        logging.error('decorate in class body is not supported for tools')
    raise

Prevention

When it happens

Trigger: Decorating an instance method (def method(self, ...)) or classmethod's underlying function with @tool inside a class body and expecting it to be registered as-is.

Common situations: Class-based tool organization; migrating tools from functions into a class; auto-generated code decorating methods in place.

Related errors


AI-assisted analysis of PrefectHQ/fastmcp@1f02114297 (2026-08-29). Data as JSON: /api/errors/4cf873186a1adda4. Report an issue: GitHub.