PrefectHQ/fastmcp · error · TypeError

mcp_tool() got unexpected keyword argument(s): {sorted(unkno

Error message

mcp_tool() got unexpected keyword argument(s): {sorted(unknown)!r}. Valid keyword arguments are: {sorted(_TOOL_VALID_KWARGS)}

What it means

mcp_tool() validates its keyword arguments at decoration time against the live parameter set of Tool.from_function. If you pass a keyword that Tool.from_function does not accept (and that is not the mixin-only `enabled` flag), a TypeError is raised immediately so you learn about the mistake at import time rather than at registration time.

Source

Thrown at fastmcp_slim/fastmcp/contrib/mcp_mixin/mcp_mixin.py:68

    Accepts all parameters supported by ``Tool.from_function``.  Any new
    parameters added to ``Tool.from_function`` are automatically forwarded
    without requiring changes here.

    Args:
        name: Tool name.  Defaults to the decorated method name.
        enabled: If ``False``, the tool is skipped during registration.
        **kwargs: Additional keyword arguments forwarded verbatim to
            ``Tool.from_function`` (e.g. ``description``, ``tags``,
            ``annotations``, ``auth``, ``timeout``, ``version``, …).

    Raises:
        TypeError: If an unrecognised keyword argument is supplied.  The error
            is raised immediately at decoration time rather than later.
    """
    unknown = set(kwargs) - _TOOL_VALID_KWARGS
    if unknown:
        raise TypeError(
            f"mcp_tool() got unexpected keyword argument(s): {sorted(unknown)!r}. "
            f"Valid keyword arguments are: {sorted(_TOOL_VALID_KWARGS)}"
        )

    def decorator(func: Callable[..., Any]) -> Callable[..., Any]:
        call_args: dict[str, Any] = {"name": name or get_fn_name(func), **kwargs}
        if enabled is not None:
            call_args[_MIXIN_ENABLED_KEY] = enabled
        setattr(func, _MCP_REGISTRATION_TOOL_ATTR, call_args)
        return func

    return decorator


def mcp_resource(
    uri: str,
    *,
    name: str | None = None,

View on GitHub (pinned to 1f02114297)

Solutions

  1. Read the 'Valid keyword arguments are:' list in the message and replace/remove the listed kwarg(s)
  2. Check the signature of Tool.from_function for your installed fastmcp version (inspect.signature) and use only those names
  3. Fix misspellings (e.g. descripton -> description)
  4. If the option belongs to the registration layer rather than the tool itself, move it out of mcp_tool()

Example fix

// before
@mcp_tool(name="greet", descripton="say hi")
def greet(self, who: str) -> str: ...

// after
@mcp_tool(name="greet", description="say hi")
def greet(self, who: str) -> str: ...
Defensive patterns

Strategy: validation

Validate before calling

import inspect
from fastmcp.tools.base import Tool
valid = set(inspect.signature(Tool.from_function).parameters) - {"fn"}
bad = set(my_kwargs) - valid
if bad:
    raise TypeError(f"Invalid mcp_tool kwargs: {bad}")

Type guard

def has_valid_tool_kwargs(kwargs: dict) -> bool:
    import inspect
    from fastmcp.tools.base import Tool
    valid = set(inspect.signature(Tool.from_function).parameters) - {"fn"}
    return set(kwargs) <= valid

Prevention

When it happens

Trigger: Decorating a class method with @mcp_tool(...) and passing an unrecognized kwarg such as a misspelled option (e.g. `descripton=`), a parameter removed from Tool.from_function in a newer fastmcp version, or an arbitrary kwarg like `op_description=` meant for another layer.

Common situations: Upgrading fastmcp where Tool.from_function dropped/renamed parameters; copying decorators from FastMCP's @tool to the mixin @mcp_tool with kwargs the mixin path doesn't forward; typos in kwarg names.

Related errors


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