fix(crawl): relay the API's reason when it refuses to start a crawl

Merged
ER
8h ago
+43-11

firecrawl_crawl starts the job with a raw http.post('/v2/crawl'), so an API refusal at start (out of credits, rate limited) reached the model as Tool 'firecrawl_crawl' execution failed: Request failed with status code 402. The API's own reason, including its upgrade link or its "retry after Ns" wait, was in the response body and never shown.

The start call now goes through relayExchangeError, the same relay firecrawl_search uses. A refusal becomes a UserError carrying the API's error text, with status and code in its extras so a hosting layer can read the status. A 401 is still rethrown unchanged, and the polling path from #570 is untouched.

Tests

tests/mcp-crawl-polling.test.mjs gains a 402 and a 429 case against a mock API: the tool result is an error whose text contains the API's reason, never "Request failed with status code", and no status poll is made. The existing polling test now shares the same call helper.

Open in Capy


Summary by cubic

Relays the API's reason when it refuses to start a crawl, so a refusal (out of credits, rate limited) surfaces as a UserError with the API's error text instead of a generic "Request failed with status code". The start call now uses the same relayExchangeError as firecrawl_search, keeping status and code in extras; 401 responses are still rethrown, and the polling path is untouched.

Added tests for 402 and 429 refusals verifying the relayed error, the status and code extras, and that no status poll is made.