Skip to content

[Bug] Request body handling ignores non-object schemas and suffers from parameter name collisions #319

Description

@saitejabandaru-in

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

  1. 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.
  2. 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions