firecrawl-mcp 3.23.7 → 3.23.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +24 -2
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1088,6 +1088,14 @@ async function authenticateRequest(request, profile) {
1088
1088
  if (process.env.CLOUD_SERVICE === "true") {
1089
1089
  if (!headerCred && !managedCred) {
1090
1090
  if (resolved?.invalid) {
1091
+ if (profile.allowKeyless) {
1092
+ return {
1093
+ authType: "api-key",
1094
+ credentialError: "CREDENTIAL_INVALID",
1095
+ firecrawlApiKey: void 0,
1096
+ keylessClientIp: extractClientIp(request)
1097
+ };
1098
+ }
1091
1099
  throw new InvalidFirecrawlCredentialError();
1092
1100
  }
1093
1101
  if (profile.allowKeyless) {
@@ -1477,7 +1485,12 @@ function recoveryPayload(code, requestId = randomUUID(), options = {}) {
1477
1485
  request_id: requestId,
1478
1486
  auth_mode: code === "CREDENTIAL_INVALID" ? "credential_error" : "keyless",
1479
1487
  message: code === "CREDENTIAL_INVALID" ? `The supplied Firecrawl credential is invalid or revoked. ${HUMAN_CONNECTION_GUIDANCE}` : isQuotaExhausted ? `The free daily limit for this network has been reached${retryAfterSeconds ? `; try again in about ${retryAfterSeconds} seconds` : ""}. To continue now: ${HUMAN_CONNECTION_GUIDANCE}` : isToolUnavailable ? ACCOUNT_ONLY_TOOL_GUIDANCE : isKeylessAccessUnavailable ? `Anonymous keyless access is unavailable for this request. To continue: ${HUMAN_CONNECTION_GUIDANCE}` : isKeylessEligibilityUnavailable ? "The anonymous keyless eligibility check is temporarily unavailable. Retry shortly." : `This tool requires a Firecrawl account or API key. ${HUMAN_CONNECTION_GUIDANCE}`,
1480
- ...isKeylessAccessUnavailable ? {} : { available_tools: [...KEYLESS_TOOL_NAMES] },
1488
+ // CREDENTIAL_INVALID sessions gate every tool call (including keyless
1489
+ // tools) on the credentialError check before the keyless branch ever
1490
+ // runs, so none of KEYLESS_TOOL_NAMES are actually callable here. Listing
1491
+ // them as available_tools would send the agent into a retry loop against
1492
+ // tools that will just return this same recovery payload.
1493
+ ...isKeylessAccessUnavailable || code === "CREDENTIAL_INVALID" ? {} : { available_tools: [...KEYLESS_TOOL_NAMES] },
1481
1494
  docs_url: MCP_CONNECTION_GUIDE_URL,
1482
1495
  ...retryAfterSeconds ? { retry_after_seconds: retryAfterSeconds } : {},
1483
1496
  next_actions: isKeylessEligibilityUnavailable ? [{ kind: "retry_later", after_seconds: 30 }] : isQuotaExhausted || isKeylessAccessUnavailable ? HUMAN_CONNECTION_ACTIONS : isToolUnavailable ? [
@@ -1549,7 +1562,16 @@ function guardHostedTool(tool, { logActions }) {
1549
1562
  const beforeValidate = tool.beforeValidate;
1550
1563
  return {
1551
1564
  ...tool,
1552
- canList: (session) => !session?.credentialError && (!isHostedKeylessSession(session) || keylessTool) && (canList?.(session) ?? true),
1565
+ canList: (session) => (
1566
+ // A credentialError session lists the keyless tool surface (same as a
1567
+ // real keyless session, not the full authenticated schema) so the
1568
+ // client proceeds past tools/list and calling any listed tool returns
1569
+ // the CREDENTIAL_INVALID recovery payload (below). An empty list would
1570
+ // leave MCP clients that stop after tools/list unable to ever surface
1571
+ // the recovery guidance; the full non-keyless schema would over-disclose
1572
+ // to a request carrying an unrecognized or invalid credential.
1573
+ (session?.credentialError || isHostedKeylessSession(session) ? keylessTool : true) && (canList?.(session) ?? true)
1574
+ ),
1553
1575
  beforeValidate: async (args2, session) => {
1554
1576
  const code = session?.credentialError ? "CREDENTIAL_INVALID" : isHostedKeylessSession(session) && !keylessTool ? "KEYLESS_TOOL_NOT_AVAILABLE" : void 0;
1555
1577
  if (code) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "firecrawl-mcp",
3
- "version": "3.23.7",
3
+ "version": "3.23.8",
4
4
  "description": "MCP server for Firecrawl — search, scrape, and interact with the web. Supports both cloud and self-hosted instances. Features include web search, scraping, page interaction, batch processing, and LLM-powered content analysis.",
5
5
  "type": "module",
6
6
  "mcpName": "io.github.firecrawl/firecrawl-mcp-server",