|
9 | 9 | import logging |
10 | 10 | import threading |
11 | 11 | import inspect |
12 | | -from typing import List, Dict, Any, Optional, Callable, Iterable, AsyncIterator |
| 12 | +from typing import List, Dict, Any, Optional, Iterable, AsyncIterator |
13 | 13 | import httpx |
14 | 14 | from mcp import ClientSession |
15 | | -from mcp.client.session import BaseSession |
16 | | -from mcp.shared.context import RequestContext |
17 | | -from mcp.types import Tool |
18 | 15 |
|
19 | 16 | logger = logging.getLogger("mcp-http-streaming") |
20 | 17 |
|
@@ -259,14 +256,54 @@ async def _async_call(self, **kwargs) -> Any: |
259 | 256 | logger.error(f"Error calling tool {self.name}: {e}") |
260 | 257 | raise |
261 | 258 |
|
| 259 | + def _fix_array_schemas(self, schema): |
| 260 | + """ |
| 261 | + Fix array schemas by adding missing 'items' attribute required by OpenAI. |
| 262 | + |
| 263 | + This ensures compatibility with OpenAI's function calling format which |
| 264 | + requires array types to specify the type of items they contain. |
| 265 | + |
| 266 | + Args: |
| 267 | + schema: The schema dictionary to fix |
| 268 | + |
| 269 | + Returns: |
| 270 | + dict: The fixed schema |
| 271 | + """ |
| 272 | + if not isinstance(schema, dict): |
| 273 | + return schema |
| 274 | + |
| 275 | + # Create a copy to avoid modifying the original |
| 276 | + fixed_schema = schema.copy() |
| 277 | + |
| 278 | + # Fix array types at the current level |
| 279 | + if fixed_schema.get("type") == "array" and "items" not in fixed_schema: |
| 280 | + # Add a default items schema for arrays without it |
| 281 | + fixed_schema["items"] = {"type": "string"} |
| 282 | + |
| 283 | + # Recursively fix nested schemas |
| 284 | + if "properties" in fixed_schema: |
| 285 | + fixed_properties = {} |
| 286 | + for prop_name, prop_schema in fixed_schema["properties"].items(): |
| 287 | + fixed_properties[prop_name] = self._fix_array_schemas(prop_schema) |
| 288 | + fixed_schema["properties"] = fixed_properties |
| 289 | + |
| 290 | + # Fix items schema if it exists |
| 291 | + if "items" in fixed_schema: |
| 292 | + fixed_schema["items"] = self._fix_array_schemas(fixed_schema["items"]) |
| 293 | + |
| 294 | + return fixed_schema |
| 295 | + |
262 | 296 | def to_openai_tool(self) -> Dict[str, Any]: |
263 | 297 | """Convert this tool to OpenAI function calling format.""" |
| 298 | + # Fix array schemas to include 'items' attribute |
| 299 | + fixed_schema = self._fix_array_schemas(self.input_schema) |
| 300 | + |
264 | 301 | return { |
265 | 302 | "type": "function", |
266 | 303 | "function": { |
267 | 304 | "name": self.name, |
268 | 305 | "description": self.description, |
269 | | - "parameters": self.input_schema |
| 306 | + "parameters": fixed_schema |
270 | 307 | } |
271 | 308 | } |
272 | 309 |
|
|
0 commit comments