Reject positional-only tool parameters (#4524)

This commit is contained in:
Jeremiah Lowin 2026-07-17 17:37:28 -04:00 committed by GitHub
commit 918b85f9b2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 35 additions and 1 deletions

View file

@ -182,8 +182,16 @@ class ParsedFunction:
) -> ParsedFunction:
if validate:
sig = inspect.signature(fn)
# Reject functions with *args or **kwargs
# Reject signatures that cannot be represented by MCP's
# object-shaped tool arguments.
for param in sig.parameters.values():
if param.kind == inspect.Parameter.POSITIONAL_ONLY:
raise ValueError(
"Functions with positional-only parameters are not "
"supported as tools because MCP passes tool arguments by "
"name. Replace them with standard parameters that can be "
"passed as keywords."
)
if param.kind == inspect.Parameter.VAR_POSITIONAL:
raise ValueError("Functions with *args are not supported as tools")
if param.kind == inspect.Parameter.VAR_KEYWORD:

View file

@ -341,6 +341,32 @@ class TestToolFromFunction:
):
Tool.from_function(func)
def test_tool_with_positional_only_parameters_not_allowed(self):
def func(a: int, /, b: int) -> int:
return a + b
with pytest.raises(
ValueError,
match=(
"Functions with positional-only parameters are not supported as "
"tools.*standard parameters"
),
):
Tool.from_function(func)
def test_tool_with_keyword_capable_parameters(self):
def func(a: int, *, b: int) -> int:
return a + b
tool = Tool.from_function(func)
assert tool.parameters["type"] == "object"
assert tool.parameters["required"] == ["a", "b"]
assert tool.parameters["properties"] == {
"a": {"type": "integer"},
"b": {"type": "integer"},
}
def test_tool_with_varkwargs_not_allowed(self):
def func(a: int, b: int, **kwargs: int) -> int:
"""Add two numbers."""