diff --git a/fastapi_mcp/openapi/convert.py b/fastapi_mcp/openapi/convert.py index fb0ff21..439d9a0 100644 --- a/fastapi_mcp/openapi/convert.py +++ b/fastapi_mcp/openapi/convert.py @@ -202,11 +202,13 @@ def convert_openapi_to_mcp_tools( param_desc = param.get("description", "") param_required = param.get("required", True) # Path params are usually required - properties[param_name] = { - "type": param_schema.get("type", "string"), - "title": param_name, - "description": param_desc, - } + properties[param_name] = param_schema.copy() + properties[param_name]["title"] = param_name + if param_desc: + properties[param_name]["description"] = param_desc + + if "type" not in properties[param_name]: + properties[param_name]["type"] = param_schema.get("type", "string") if param_required: required_props.append(param_name) @@ -217,11 +219,14 @@ def convert_openapi_to_mcp_tools( param_desc = param.get("description", "") param_required = param.get("required", False) - properties[param_name] = { - "type": get_single_param_type_from_schema(param_schema), - "title": param_name, - "description": param_desc, - } + properties[param_name] = param_schema.copy() + properties[param_name]["title"] = param_name + if param_desc: + properties[param_name]["description"] = param_desc + + if "type" not in properties[param_name]: + properties[param_name]["type"] = get_single_param_type_from_schema(param_schema) + if "default" in param_schema: properties[param_name]["default"] = param_schema["default"] @@ -233,10 +238,14 @@ def convert_openapi_to_mcp_tools( param_schema = param.get("schema", {}) param_required = param.get("required", False) - properties[param_name] = { - "type": get_single_param_type_from_schema(param_schema), - "title": param_name, - } + properties[param_name] = param_schema.copy() + properties[param_name]["title"] = param_name + if param_desc: + properties[param_name]["description"] = param_desc + + if "type" not in properties[param_name]: + properties[param_name]["type"] = get_single_param_type_from_schema(param_schema) + if "default" in param_schema: properties[param_name]["default"] = param_schema["default"] diff --git a/tests/test_openapi_conversion.py b/tests/test_openapi_conversion.py index 193ef8c..9f02081 100644 --- a/tests/test_openapi_conversion.py +++ b/tests/test_openapi_conversion.py @@ -271,3 +271,28 @@ def test_request_body_handling(complex_fastapi_app: FastAPI): assert "create_order" in operation_map assert operation_map["create_order"]["path"] == "/orders" assert operation_map["create_order"]["method"] == "post" + + +def test_missing_type_handling(complex_fastapi_app: FastAPI): + openapi_schema = get_openapi( + title=complex_fastapi_app.title, + version=complex_fastapi_app.version, + openapi_version=complex_fastapi_app.openapi_version, + description=complex_fastapi_app.description, + routes=complex_fastapi_app.routes, + ) + + # Remove the type field from the product_id schema + params = openapi_schema["paths"]["/products/{product_id}"]["get"]["parameters"] + for param in params: + if param.get("name") == "product_id" and "schema" in param: + param["schema"].pop("type", None) + break + + tools, operation_map = convert_openapi_to_mcp_tools(openapi_schema) + + get_product_tool = next(tool for tool in tools if tool.name == "get_product") + get_product_props = get_product_tool.inputSchema["properties"] + + assert "product_id" in get_product_props + assert get_product_props["product_id"].get("type") == "string" # Default type applied