There are two significant issues with how requestBody parameters and schemas are converted and executed, leading to unreachable endpoints or 422 Unprocessable Entity errors.
1. Non-object request bodies are silently ignored
If a FastAPI endpoint expects a top-level array, primitive, or a custom __root__ object, it is completely omitted from the generated MCP tool schema.
In convert.py (convert_openapi_to_mcp_tools):
if "properties" in schema:
for prop_name, prop_schema in schema["properties"].items():
# ... added to body_params
If schema is {"type": "array", "items": {...}}, it lacks a properties field. The MCP tool will be generated with no input arguments for the body, making it impossible for an LLM to provide the required payload for endpoints like bulk updates.
2. Parameter name collisions cause data loss during execution
Because path_params, query_params, and body_params are flattened into a single properties dictionary for the MCP tool's inputSchema, name collisions (e.g., a path parameter named id and a JSON body field named id) overwrite each other.
Even worse, during tool execution in server.py (_execute_api_tool):
for param in parameters:
if param.get("in") == "path" and param.get("name") in arguments:
param_name = param.get("name", None)
path = path.replace(f"{{{param_name}}}", str(arguments.pop(param_name)))
If an argument matches a path parameter, it is pop()ped from arguments. When the remaining arguments are passed as the request body (body = arguments if arguments else None), the id field is now missing from the body payload, which will likely trigger a 422 Unprocessable Entity error from FastAPI.
Suggested Fixes
- Schema Conversion: Instead of flattening request body properties into the root of
arguments, nest them under a specific key (e.g., requestBody or payload), or explicitly handle non-object schemas by mapping the entire body to a single argument.
- Argument Extraction: Instead of
arguments.pop(param_name), use arguments.get(param_name) to retain the value if it also needs to be passed in the JSON body, or cleanly separate routing parameters from body parameters in the MCP schema.
There are two significant issues with how
requestBodyparameters and schemas are converted and executed, leading to unreachable endpoints or422 Unprocessable Entityerrors.1. Non-object request bodies are silently ignored
If a FastAPI endpoint expects a top-level array, primitive, or a custom
__root__object, it is completely omitted from the generated MCP tool schema.In
convert.py(convert_openapi_to_mcp_tools):If
schemais{"type": "array", "items": {...}}, it lacks apropertiesfield. The MCP tool will be generated with no input arguments for the body, making it impossible for an LLM to provide the required payload for endpoints like bulk updates.2. Parameter name collisions cause data loss during execution
Because
path_params,query_params, andbody_paramsare flattened into a singlepropertiesdictionary for the MCP tool'sinputSchema, name collisions (e.g., a path parameter namedidand a JSON body field namedid) overwrite each other.Even worse, during tool execution in
server.py(_execute_api_tool):If an argument matches a path parameter, it is
pop()ped fromarguments. When the remaining arguments are passed as the request body (body = arguments if arguments else None), theidfield is now missing from the body payload, which will likely trigger a 422 Unprocessable Entity error from FastAPI.Suggested Fixes
arguments, nest them under a specific key (e.g.,requestBodyorpayload), or explicitly handle non-object schemas by mapping the entire body to a single argument.arguments.pop(param_name), usearguments.get(param_name)to retain the value if it also needs to be passed in the JSON body, or cleanly separate routing parameters from body parameters in the MCP schema.