fix(fetch): make fetch tool schema Gemini/OpenAPI 3.0 compatible - #3812
fix(fetch): make fetch tool schema Gemini/OpenAPI 3.0 compatible#3812Dharit13 wants to merge 3 commits into
Conversation
26d0503 to
067766b
Compare
|
@claude review |
|
Claude finished @cliffhall's task in 1m 7s —— View job PR Review: fix(fetch): make fetch tool schema Gemini/OpenAPI 3.0 compatibleTodo:
This is a clean, well-scoped fix for a real compatibility issue with OpenAPI 3.0-only providers like Google Gemini. Here's my analysis:
|
…port The Fetch model's JSON schema used keywords incompatible with LLM providers that only support OpenAPI 3.0 (e.g. Google Gemini 2.5 Pro), causing 400 INVALID_ARGUMENT errors: 1. max_length field used gt=0/lt=1000000 (Pydantic Field constraints), which generated exclusiveMinimum/exclusiveMaximum — not recognized by Gemini. Changed to ge=1/le=999999 (identical semantics for integers), which emits the supported minimum/maximum keywords. 2. url field used AnyUrl, which generated format: "uri" and minLength: 1 — Gemini only supports "enum" and "date-time" for string format. Added WithJsonSchema override to emit a plain string schema while preserving AnyUrl runtime validation. Fixes modelcontextprotocol#1624 Made-with: Cursor
Verifies that AnyUrl runtime validation is preserved after the WithJsonSchema override — invalid URLs still raise ValidationError, valid URLs parse successfully. Addresses review feedback on modelcontextprotocol#3812.
067766b to
14e4107
Compare
Pyright doesn't recognize Pydantic's Annotated + Field(default=...) pattern as making __init__ args optional, so Fetch(url="...") flags max_length/start_index/raw as missing. Switch to Fetch.model_validate which accepts a dict and avoids the false positive. Same behavior, same coverage.
LuuOW
left a comment
There was a problem hiding this comment.
Technical audit: Verified MCP server implementation for consistency with current SDK patterns.
Summary
Fixes the fetch server's tool schema to be compatible with LLM providers that only support OpenAPI 3.0 schema keywords (e.g. Google Gemini 2.5 Pro), which currently reject the schema with a
400 INVALID_ARGUMENTerror.Two incompatibilities are addressed:
max_lengthfield usedgt=0/lt=1000000Pydantic constraints, which generateexclusiveMinimum/exclusiveMaximumin the JSON Schema. Gemini does not recognize these keywords. Changed toge=1/le=999999— identical semantics for integers — which emits the universally supportedminimum/maximumkeywords instead.urlfield usedAnyUrl, which generatesformat: \"uri\"andminLength: 1. Gemini only supports\"enum\"and\"date-time\"for stringformat, and does not supportminLength. Added aWithJsonSchemaoverride to emit a plain{"type": "string"}schema while preservingAnyUrlruntime validation — so invalid URLs are still rejected with a proper error, but the schema no longer contains unsupported keywords.Fixes #1624
Changes
src/fetch/src/mcp_server_fetch/server.pymax_lengthfield:gt=0→ge=1,lt=1000000→le=999999urlfield: addedWithJsonSchema({"type": "string", "description": "URL to fetch"})to override schema output while keepingAnyUrlruntime validationsrc/fetch/tests/test_server.pyTestFetchToolSchema.test_schema_uses_inclusive_bounds— assertsminimum/maximumpresent,exclusiveMinimum/exclusiveMaximumabsentTestFetchToolSchema.test_url_schema_omits_unsupported_keywords— assertsformatandminLengthabsent from url schemaEvidence
Live Gemini validation was run against
gemini-2.5-prousing the exact generated tool schema sent togenerateContent.Pre-fix schema (reproduced locally):
HTTP 400INVALID_ARGUMENTUnknown name "exclusiveMaximum"Unknown name "exclusiveMinimum"Current PR schema:
HTTP 200Acknowledged.Test plan
uv run python -m pytest tests/test_server.py -v)exclusiveMinimum,exclusiveMaximum,format, orminLengthin outputAnyUrlruntime validation confirmed: valid URLs accepted, invalid URLs rejected withValidationErrorgemini-2.5-proviagenerateContent; request was accepted withHTTP 200and returnedAcknowledged.