Skip to content

Commit b1307d0

Browse files
fix: add missing 'items' attribute for MCP array parameters
This fixes an issue where MCP tools with array parameters were not working correctly with OpenAI-compatible LLMs. The tools were missing the required 'items' attribute that specifies the type of elements in the array. - Added _fix_array_schemas() method to recursively fix array schemas - Updated to_openai_tool() in both mcp.py and mcp_sse.py to apply the fix - Maintains backward compatibility by preserving existing schemas Fixes #619 Co-authored-by: Mervin Praison <[email protected]>
1 parent 53c0b84 commit b1307d0

File tree

2 files changed

+80
-2
lines changed

2 files changed

+80
-2
lines changed

src/praisonai-agents/praisonaiagents/mcp/mcp.py

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -379,6 +379,43 @@ def __iter__(self) -> Iterable[Callable]:
379379
"""
380380
return iter(self._tools)
381381

382+
def _fix_array_schemas(self, schema):
383+
"""
384+
Fix array schemas by adding missing 'items' attribute required by OpenAI.
385+
386+
This ensures compatibility with OpenAI's function calling format which
387+
requires array types to specify the type of items they contain.
388+
389+
Args:
390+
schema: The schema dictionary to fix
391+
392+
Returns:
393+
dict: The fixed schema
394+
"""
395+
if not isinstance(schema, dict):
396+
return schema
397+
398+
# Create a copy to avoid modifying the original
399+
fixed_schema = schema.copy()
400+
401+
# Fix array types at the current level
402+
if fixed_schema.get("type") == "array" and "items" not in fixed_schema:
403+
# Add a default items schema for arrays without it
404+
fixed_schema["items"] = {"type": "string"}
405+
406+
# Recursively fix nested schemas
407+
if "properties" in fixed_schema:
408+
fixed_properties = {}
409+
for prop_name, prop_schema in fixed_schema["properties"].items():
410+
fixed_properties[prop_name] = self._fix_array_schemas(prop_schema)
411+
fixed_schema["properties"] = fixed_properties
412+
413+
# Fix items schema if it exists
414+
if "items" in fixed_schema:
415+
fixed_schema["items"] = self._fix_array_schemas(fixed_schema["items"])
416+
417+
return fixed_schema
418+
382419
def to_openai_tool(self):
383420
"""Convert the MCP tool to an OpenAI-compatible tool definition.
384421
@@ -404,7 +441,8 @@ def to_openai_tool(self):
404441
# Create OpenAI tool definition
405442
parameters = {}
406443
if hasattr(tool, 'inputSchema') and tool.inputSchema:
407-
parameters = tool.inputSchema
444+
# Fix array schemas to include 'items' attribute
445+
parameters = self._fix_array_schemas(tool.inputSchema)
408446
else:
409447
# Create a minimal schema if none exists
410448
parameters = {

src/praisonai-agents/praisonaiagents/mcp/mcp_sse.py

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,14 +88,54 @@ async def _async_call(self, **kwargs):
8888
logger.error(f"Error in _async_call for {self.name}: {e}")
8989
raise
9090

91+
def _fix_array_schemas(self, schema):
92+
"""
93+
Fix array schemas by adding missing 'items' attribute required by OpenAI.
94+
95+
This ensures compatibility with OpenAI's function calling format which
96+
requires array types to specify the type of items they contain.
97+
98+
Args:
99+
schema: The schema dictionary to fix
100+
101+
Returns:
102+
dict: The fixed schema
103+
"""
104+
if not isinstance(schema, dict):
105+
return schema
106+
107+
# Create a copy to avoid modifying the original
108+
fixed_schema = schema.copy()
109+
110+
# Fix array types at the current level
111+
if fixed_schema.get("type") == "array" and "items" not in fixed_schema:
112+
# Add a default items schema for arrays without it
113+
fixed_schema["items"] = {"type": "string"}
114+
115+
# Recursively fix nested schemas
116+
if "properties" in fixed_schema:
117+
fixed_properties = {}
118+
for prop_name, prop_schema in fixed_schema["properties"].items():
119+
fixed_properties[prop_name] = self._fix_array_schemas(prop_schema)
120+
fixed_schema["properties"] = fixed_properties
121+
122+
# Fix items schema if it exists
123+
if "items" in fixed_schema:
124+
fixed_schema["items"] = self._fix_array_schemas(fixed_schema["items"])
125+
126+
return fixed_schema
127+
91128
def to_openai_tool(self):
92129
"""Convert the tool to OpenAI format."""
130+
# Fix array schemas to include 'items' attribute
131+
fixed_schema = self._fix_array_schemas(self.input_schema)
132+
93133
return {
94134
"type": "function",
95135
"function": {
96136
"name": self.name,
97137
"description": self.description,
98-
"parameters": self.input_schema
138+
"parameters": fixed_schema
99139
}
100140
}
101141

0 commit comments

Comments
 (0)