Summary
The inputSchema that firecrawl-mcp publishes via tools/list declares
firecrawl_scrape's jsonOptions.schema field as:
{
"type": "object",
"propertyNames": { "type": "string" },
"additionalProperties": false
}
There is no properties declaration, so under JSON Schema semantics this
accepts only the empty object. But this field is where callers pass an
arbitrary JSON Schema describing the extraction output — any legitimate value
necessarily contains keys like type, properties, required, all of which
this declaration rejects.
Any MCP client that validates call arguments against the published
inputSchema before forwarding (a common pattern for gateway/proxy-style
clients) therefore rejects every JSON-extraction call with:
Additional properties are not allowed ('properties', 'required', 'type' were unexpected)
The server itself accepts these calls fine (its internal zod validation treats
the field as a record), so the bug only surfaces in clients that trust the
published schema — which makes it look like a client-side failure. In our
deployment (an MCP gateway serving ~400 workspaces) this rejected 100% of
formats: ["json"] + jsonOptions.schema calls, ~250 failures across 19
users before we traced it back here.
The same signature (propertyNames + additionalProperties: false, no
properties) appears on several other free-form object fields in the
published schemas as well (we count 10 occurrences across the tool list);
firecrawl_scrape.jsonOptions.schema is just the most user-visible one.
Reproduction
export FIRECRAWL_API_KEY=fc-anything # not needed for tools/list
npx -y firecrawl-mcp
Then over stdio:
{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"probe","version":"0.0.1"}}}
{"jsonrpc":"2.0","method":"notifications/initialized"}
{"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}}
Inspect result.tools[] → name == "firecrawl_scrape" → inputSchema.properties.jsonOptions.properties.schema — it is the unsatisfiable
declaration above.
Validating a perfectly normal call against the published schema fails:
from jsonschema import Draft202012Validator
published_json_options = {
"type": "object",
"properties": {
"prompt": {"type": "string"},
"schema": {"type": "object", "propertyNames": {"type": "string"},
"additionalProperties": False},
},
"additionalProperties": False,
}
valid_call = {
"prompt": "Extract the product title.",
"schema": {"type": "object", "required": ["title"],
"properties": {"title": {"type": "string"}}},
}
Draft202012Validator(published_json_options).validate(valid_call)
# jsonschema.exceptions.ValidationError:
# Additional properties are not allowed ('properties', 'required', 'type' were unexpected)
Expected
jsonOptions.schema should be published as a free-form object, e.g.
{"type": "object"} (or {"type": "object", "additionalProperties": true}),
matching what the server actually accepts.
Likely cause
The shape {"type":"object","propertyNames":{"type":"string"}, "additionalProperties":false} looks like a zod z.record(z.string(), ...)
whose value schema was lost during the zod → JSON Schema conversion, leaving
additionalProperties collapsed to false instead of the value schema (or
true).
Environment
firecrawl-mcp 3.24.0 (serverInfo.name: "firecrawl-fastmcp"), via npx -y firecrawl-mcp, stdio transport
- Observed identically in registry snapshots taken since at least 2026-07-19
Summary
The
inputSchemathatfirecrawl-mcppublishes viatools/listdeclaresfirecrawl_scrape'sjsonOptions.schemafield as:{ "type": "object", "propertyNames": { "type": "string" }, "additionalProperties": false }There is no
propertiesdeclaration, so under JSON Schema semantics thisaccepts only the empty object. But this field is where callers pass an
arbitrary JSON Schema describing the extraction output — any legitimate value
necessarily contains keys like
type,properties,required, all of whichthis declaration rejects.
Any MCP client that validates call arguments against the published
inputSchemabefore forwarding (a common pattern for gateway/proxy-styleclients) therefore rejects every JSON-extraction call with:
The server itself accepts these calls fine (its internal zod validation treats
the field as a record), so the bug only surfaces in clients that trust the
published schema — which makes it look like a client-side failure. In our
deployment (an MCP gateway serving ~400 workspaces) this rejected 100% of
formats: ["json"]+jsonOptions.schemacalls, ~250 failures across 19users before we traced it back here.
The same signature (
propertyNames+additionalProperties: false, noproperties) appears on several other free-form object fields in thepublished schemas as well (we count 10 occurrences across the tool list);
firecrawl_scrape.jsonOptions.schemais just the most user-visible one.Reproduction
Then over stdio:
{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"probe","version":"0.0.1"}}} {"jsonrpc":"2.0","method":"notifications/initialized"} {"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}}Inspect
result.tools[] → name == "firecrawl_scrape" → inputSchema.properties.jsonOptions.properties.schema— it is the unsatisfiabledeclaration above.
Validating a perfectly normal call against the published schema fails:
Expected
jsonOptions.schemashould be published as a free-form object, e.g.{"type": "object"}(or{"type": "object", "additionalProperties": true}),matching what the server actually accepts.
Likely cause
The shape
{"type":"object","propertyNames":{"type":"string"}, "additionalProperties":false}looks like a zodz.record(z.string(), ...)whose value schema was lost during the zod → JSON Schema conversion, leaving
additionalPropertiescollapsed tofalseinstead of the value schema (ortrue).Environment
firecrawl-mcp3.24.0 (serverInfo.name: "firecrawl-fastmcp"), vianpx -y firecrawl-mcp, stdio transport