Skip to content

fix(schema): replace anyOf unions with flat params for Gemini compatibility#165

Open
firecrawl-spring[bot] wants to merge 1 commit intomainfrom
fix/gemini-anyof-schema-compat
Open

fix(schema): replace anyOf unions with flat params for Gemini compatibility#165
firecrawl-spring[bot] wants to merge 1 commit intomainfrom
fix/gemini-anyof-schema-compat

Conversation

@firecrawl-spring
Copy link
Contributor

Summary

Google Gemini's function calling API rejects the MCP server's tool schemas because anyOf is used alongside other fields in the formats and parsers parameters. Gemini requires that when anyOf is present in a schema node, it must be the only property — no sibling fields are allowed.

This PR removes all z.union() (which produces anyOf in JSON Schema) from the tool definitions and replaces them with flat parameter alternatives that are compatible with all LLM providers.

Changes

  • formats: Changed from z.union([enum, object, object]) to a simple z.enum() array. Added 'json' to the enum values.
  • jsonOptions: New optional param for JSON extraction prompt and schema (used when 'json' is in formats).
  • screenshotOptions: New optional param for screenshot fullPage, quality, and viewport (used when 'screenshot' is in formats).
  • parsers: Changed from z.union([enum, object]) to a simple z.enum(['pdf']) array.
  • pdfOptions: New optional param for maxPages (used when 'pdf' is in parsers).
  • webhook (crawl tool): Changed from z.union([string, object]) to a simple z.string(), with a new webhookHeaders param.
  • Added helper functions (buildFormatsArray, buildParsersArray, buildWebhook, transformScrapeParams) that reassemble the nested format the Firecrawl API expects from the flat MCP params at execution time.
  • Updated tool description examples to use the new flat param style.

How it works

The MCP schema now uses simple, flat parameters that all LLM function-calling implementations can handle. At execution time, helper functions transform these flat params back into the nested format the Firecrawl API expects. This is transparent to both the LLM and the API.

Before (breaks Gemini):

{ "formats": [{ "type": "json", "prompt": "Extract data", "schema": {...} }] }

After (works everywhere):

{ "formats": ["json"], "jsonOptions": { "prompt": "Extract data", "schema": {...} } }

Testing

  • Build passes (npm run build)
  • No remaining z.union() calls in source
  • Backward compatible: simple format usage like ["markdown"] works unchanged

Closes #164

@firecrawl-spring firecrawl-spring bot force-pushed the fix/gemini-anyof-schema-compat branch 2 times, most recently from 546b948 to 2f05302 Compare February 20, 2026 04:06
…bility

Google Gemini's function calling API rejects tool schemas that use
anyOf alongside other fields. This replaces all z.union() usages with
flat parameter alternatives:

- formats: now a simple string enum array (added 'json' to the enum)
- jsonOptions: new param for JSON extraction prompt/schema
- screenshotOptions: new param for screenshot fullPage/quality/viewport
- parsers: now a simple string enum array
- pdfOptions: new param for PDF maxPages
- webhook (crawl): now a simple string, with separate webhookHeaders

Helper functions (buildFormatsArray, buildParsersArray, buildWebhook,
transformScrapeParams) reassemble the nested format the API expects
from the flat MCP params at execution time.

Closes #164
@firecrawl-spring firecrawl-spring bot force-pushed the fix/gemini-anyof-schema-compat branch from 2f05302 to 4e8da30 Compare February 20, 2026 04:09
@Chadha93
Copy link

I've verified this fix locally

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Gemini function calling rejects firecrawl_scrape due to anyOf schema conflict in formats parameter

1 participant