Ensure MCP works when inputSchema.properties is missing (#454)

Resolves #449 - TLDR, [OpenAI's
API](https://platform.openai.com/docs/api-reference/responses/create)
expects the properties field to be present, whereas the MCP schema
explicitly allows omitting the properties field. [MCP
Spec](https://github.com/modelcontextprotocol/specification/blob/main/schema/2025-03-26/schema.json)
This commit is contained in:
Rohan Mehta 2025-04-07 18:38:36 -04:00 committed by GitHub
parent 064e25b01b
commit 50bbfdd8be
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 41 additions and 7 deletions

View file

@ -59,6 +59,11 @@ class MCPUtil:
"""Convert an MCP tool to an Agents SDK function tool."""
invoke_func = functools.partial(cls.invoke_mcp_tool, server, tool)
schema, is_strict = tool.inputSchema, False
# MCP spec doesn't require the inputSchema to have `properties`, but OpenAI spec does.
if "properties" not in schema:
schema["properties"] = {}
if convert_schemas_to_strict:
try:
schema = ensure_strict_json_schema(schema)

View file

@ -63,6 +63,9 @@ async def test_get_all_function_tools():
for idx, tool in enumerate(tools):
assert isinstance(tool, FunctionTool)
if schemas[idx] == {}:
assert tool.params_json_schema == snapshot({"properties": {}})
else:
assert tool.params_json_schema == schemas[idx]
assert tool.name == names[idx]
@ -167,10 +170,7 @@ async def test_agent_convert_schemas_true():
# Checks that additionalProperties is set to False
assert bar_tool.params_json_schema == snapshot(
{
"type": "object",
"additionalProperties": {"type": "string"},
}
{"type": "object", "additionalProperties": {"type": "string"}, "properties": {}}
)
assert bar_tool.strict_json_schema is False, "bar_tool should not be strict"
@ -220,7 +220,9 @@ async def test_agent_convert_schemas_false():
assert foo_tool.params_json_schema == strict_schema
assert foo_tool.strict_json_schema is False, "Shouldn't be converted unless specified"
assert bar_tool.params_json_schema == non_strict_schema
assert bar_tool.params_json_schema == snapshot(
{"type": "object", "additionalProperties": {"type": "string"}, "properties": {}}
)
assert bar_tool.strict_json_schema is False
assert baz_tool.params_json_schema == possible_to_convert_schema
@ -255,8 +257,35 @@ async def test_agent_convert_schemas_unset():
assert foo_tool.params_json_schema == strict_schema
assert foo_tool.strict_json_schema is False, "Shouldn't be converted unless specified"
assert bar_tool.params_json_schema == non_strict_schema
assert bar_tool.params_json_schema == snapshot(
{"type": "object", "additionalProperties": {"type": "string"}, "properties": {}}
)
assert bar_tool.strict_json_schema is False
assert baz_tool.params_json_schema == possible_to_convert_schema
assert baz_tool.strict_json_schema is False, "Shouldn't be converted unless specified"
@pytest.mark.asyncio
async def test_util_adds_properties():
"""The MCP spec doesn't require the inputSchema to have `properties`, so we need to add it
if it's missing.
"""
schema = {
"type": "object",
"description": "Test tool",
}
server = FakeMCPServer()
server.add_tool("test_tool", schema)
tools = await MCPUtil.get_all_function_tools([server], convert_schemas_to_strict=False)
tool = next(tool for tool in tools if tool.name == "test_tool")
assert isinstance(tool, FunctionTool)
assert "properties" in tool.params_json_schema
assert tool.params_json_schema["properties"] == {}
assert tool.params_json_schema == snapshot(
{"type": "object", "description": "Test tool", "properties": {}}
)