{"record":{"id":"54af1b7506dc1666","repo":"PrefectHQ/fastmcp","slug":"mcp-tool-got-unexpected-keyword-argument-s-so","errorCode":null,"errorMessage":"mcp_tool() got unexpected keyword argument(s): {sorted(unknown)!r}. Valid keyword arguments are: {sorted(_TOOL_VALID_KWARGS)}","messagePattern":"mcp_tool\\(\\) got unexpected keyword argument\\(s\\): (.+?)\\. Valid keyword arguments are: (.+?)","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"fastmcp_slim/fastmcp/contrib/mcp_mixin/mcp_mixin.py","lineNumber":68,"sourceCode":"\n    Accepts all parameters supported by ``Tool.from_function``.  Any new\n    parameters added to ``Tool.from_function`` are automatically forwarded\n    without requiring changes here.\n\n    Args:\n        name: Tool name.  Defaults to the decorated method name.\n        enabled: If ``False``, the tool is skipped during registration.\n        **kwargs: Additional keyword arguments forwarded verbatim to\n            ``Tool.from_function`` (e.g. ``description``, ``tags``,\n            ``annotations``, ``auth``, ``timeout``, ``version``, …).\n\n    Raises:\n        TypeError: If an unrecognised keyword argument is supplied.  The error\n            is raised immediately at decoration time rather than later.\n    \"\"\"\n    unknown = set(kwargs) - _TOOL_VALID_KWARGS\n    if unknown:\n        raise TypeError(\n            f\"mcp_tool() got unexpected keyword argument(s): {sorted(unknown)!r}. \"\n            f\"Valid keyword arguments are: {sorted(_TOOL_VALID_KWARGS)}\"\n        )\n\n    def decorator(func: Callable[..., Any]) -> Callable[..., Any]:\n        call_args: dict[str, Any] = {\"name\": name or get_fn_name(func), **kwargs}\n        if enabled is not None:\n            call_args[_MIXIN_ENABLED_KEY] = enabled\n        setattr(func, _MCP_REGISTRATION_TOOL_ATTR, call_args)\n        return func\n\n    return decorator\n\n\ndef mcp_resource(\n    uri: str,\n    *,\n    name: str | None = None,","sourceCodeStart":50,"sourceCodeEnd":86,"githubUrl":"https://github.com/PrefectHQ/fastmcp/blob/1f021142978e0861cd910c8df4e8074bc7cf3978/fastmcp_slim/fastmcp/contrib/mcp_mixin/mcp_mixin.py#L50-L86","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Read the 'Valid keyword arguments are:' list in the message and replace/remove the listed kwarg(s)","Check the signature of Tool.from_function for your installed fastmcp version (inspect.signature) and use only those names","Fix misspellings (e.g. descripton -> description)","If the option belongs to the registration layer rather than the tool itself, move it out of mcp_tool()"],"exampleFix":"// before\n@mcp_tool(name=\"greet\", descripton=\"say hi\")\ndef greet(self, who: str) -> str: ...\n\n// after\n@mcp_tool(name=\"greet\", description=\"say hi\")\ndef greet(self, who: str) -> str: ...","handlingStrategy":"validation","validationCode":"import inspect\nfrom fastmcp.tools.base import Tool\nvalid = set(inspect.signature(Tool.from_function).parameters) - {\"fn\"}\nbad = set(my_kwargs) - valid\nif bad:\n    raise TypeError(f\"Invalid mcp_tool kwargs: {bad}\")","typeGuard":"def has_valid_tool_kwargs(kwargs: dict) -> bool:\n    import inspect\n    from fastmcp.tools.base import Tool\n    valid = set(inspect.signature(Tool.from_function).parameters) - {\"fn\"}\n    return set(kwargs) <= valid","tryCatchPattern":null,"preventionTips":["Never invent kwarg names; copy them from Tool.from_function's signature","Add an import-time smoke test that applies your decorators to dummy methods","After upgrading fastmcp, re-run tests that import decorated mixin classes"],"tags":["python","decorator","type-error","fastmcp"],"backgroundTag":"unexpected-keyword-argument","analyzedSha":"1f021142978e0861cd910c8df4e8074bc7cf3978","analyzedAt":"2026-08-29T14:31:16.082Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}