-
Notifications
You must be signed in to change notification settings - Fork 878
Description
Here is sample code:
from fastapi_mcp.openapi.convert import convert_openapi_to_mcp_tools
from jsonschema import validate
openapi_schema = {
"openapi": "3.0.3",
"info": {
"title": "Union Test",
"version": "1.0.0"
},
"paths": {
"/test": {
"post": {
"operationId": "test_union",
"summary": "Test endpoint with a union type",
"requestBody": {
"required": True,
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"value": {
"anyOf": [
{"type": "string", "maxLength": 2000},
{"type": "null"}
],
"title": "value"
}
},
"required": ["value"]
}
}
}
},
"responses": {
"200": {
"description": "OK"
}
}
}
}
}
}
mcp_tools = convert_openapi_to_mcp_tools(openapi_schema=openapi_schema)
first_tool = mcp_tools[0][0]
mcp_input_schema = first_tool.inputSchema
# Validate using original OpenAPI schema (works)
validate(instance={"value": None}, schema=openapi_schema)
# Validate using MCP-generated schema (fails)
validate(instance={"value": None}, schema=mcp_input_schema)
# jsonschema.exceptions.ValidationError: None is not of type 'string'I am new in the field and maybe that is expected behaviour but still for me it was very confusing.
The unexpected behaviour happens inside the convert_openapi_to_mcp_tools function. It modifies the schema
from:
{
"value": {
"anyOf": [
{"type": "string", "maxLength": 2000},
{"type": "null"}
],
"title": "value"
}
}
to:
{
"value": {
"anyOf": [
{"type": "string", "maxLength": 2000},
{"type": "null"}
],
"title": "value",
"type": "string"
}
}
In my use case, I had a FastAPI app and added MCP. When sending requests via LangChain, I ran into issues because the LLM sometimes sent None, which then triggered a validation error. This caused a lot of debugging time.
If it's not a bug and is expected behavior, It might be helpful if the function issued a warning in such cases to alert users about potential type conflicts, which could significantly reduce debugging effort.
For now, I believe the solution is to make the original field non-nullable. If there is a more appropriate approach, I would appreciate suggestions.