firecrawl-mcp 3.27.3 → 3.28.1

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 (3) hide show
  1. package/README.md +33 -5
  2. package/dist/index.js +362 -286
  3. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -48,7 +48,7 @@ var alexandriaFeedbackFields = {
48
48
  };
49
49
  var ALEXANDRIA_FEEDBACK_HINT = {
50
50
  name: "firecrawl_feedback",
51
- when: "Optional after task completion; at most once per website, including uncovered sites. Free; no job ID or deadline.",
51
+ when: "After task completion. Free, optional, refunds 1 credit, No job ID needed.",
52
52
  arguments: {
53
53
  endpoint: "alexandria",
54
54
  rating: "<good | partial | bad>",
@@ -2073,7 +2073,7 @@ import { readFile } from "fs/promises";
2073
2073
  import { createRequire as createRequire2 } from "module";
2074
2074
  import { randomUUID } from "crypto";
2075
2075
  import path from "path";
2076
- import { z as z10 } from "zod";
2076
+ import { z as z11 } from "zod";
2077
2077
 
2078
2078
  // src/agent-hints.ts
2079
2079
  var AGENT_HINTS_HEADERS = { "X-Firecrawl-Agent-Hints": "true" };
@@ -2233,6 +2233,7 @@ var feedbackOutputSchema = z4.object({
2233
2233
  creditsRefundedToday: num("Credits refunded to the team so far this UTC day."),
2234
2234
  dailyRefundCap: num("The team's daily refund cap in credits."),
2235
2235
  dailyCapReached: bool("Whether the daily refund cap is reached; further feedback today still records but refunds nothing."),
2236
+ websiteCapReached: bool("Alexandria only: whether this website's daily refund cap is reached; feedback about other websites can still refund."),
2236
2237
  alreadySubmitted: bool("Whether feedback for this job was already recorded."),
2237
2238
  warning,
2238
2239
  data: unknown("Payload returned with the accepted feedback."),
@@ -2420,6 +2421,17 @@ var developerSearchOutputSchema = z4.object({
2420
2421
  })
2421
2422
  ).describe("Ranked results, in the order the text block lists them.")
2422
2423
  }).describe("Ranked developer-index results with their matched passages.");
2424
+ var govSearchOutputSchema = z4.object({
2425
+ ...agentHints,
2426
+ results: z4.array(
2427
+ z4.looseObject({
2428
+ url: str("Source URL."),
2429
+ title: str("Result title."),
2430
+ description: str("Matched snippet."),
2431
+ position: num("Rank of the result, starting at 1.")
2432
+ })
2433
+ ).describe("Ranked results, in the order the text block lists them.")
2434
+ }).describe("Ranked Government Index results with their matched snippets.");
2423
2435
  var creditUsageOutputSchema = z4.object({
2424
2436
  // Current view.
2425
2437
  remainingCredits: num("Credits left in the current billing period; can exceed `planCredits` when extra credits were purchased or granted."),
@@ -2664,6 +2676,59 @@ Returns ranked results with an ID, source type, URL, title, and the matched pass
2664
2676
  });
2665
2677
  }
2666
2678
 
2679
+ // src/gov.ts
2680
+ import { z as z7 } from "zod";
2681
+ var BASE2 = "/v2/search/gov";
2682
+ function fmtGov(results) {
2683
+ if (!results || results.length === 0) return "(no results)";
2684
+ return results.map((r, i) => {
2685
+ const lines = [`## ${r.position ?? i + 1}. ${r.title ?? "(untitled)"}`];
2686
+ if (r.url) lines.push(r.url);
2687
+ if (r.description) lines.push(r.description);
2688
+ return lines.join("\n");
2689
+ }).join("\n\n");
2690
+ }
2691
+ function registerGovTools(server2, getClient2) {
2692
+ server2.addTool({
2693
+ name: "firecrawl_gov_search",
2694
+ annotations: {
2695
+ title: "Firecrawl Government Index search",
2696
+ readOnlyHint: true,
2697
+ openWorldHint: true,
2698
+ destructiveHint: false
2699
+ },
2700
+ description: `
2701
+ Search an index of primary law and regulatory material from US federal, state, and local government sources (statutes, regulations, codes, court opinions, and other government publications) for legal or regulatory questions that need the governing text or an official source.
2702
+
2703
+ Returns ranked results with a position, title, URL, and matched snippet.
2704
+ `,
2705
+ outputSchema: govSearchOutputSchema,
2706
+ parameters: z7.object({
2707
+ query: z7.string().min(1).describe(
2708
+ "Natural-language legal or regulatory question or search phrase, including the jurisdiction, agency, or citation when relevant."
2709
+ ),
2710
+ k: z7.number().int().min(1).max(100).optional().describe("Number of ranked results to return (default 10).")
2711
+ }),
2712
+ execute: async (args2, { session, client: mcpClient }) => {
2713
+ const { query, k } = args2;
2714
+ const params = new URLSearchParams();
2715
+ params.append("query", query);
2716
+ if (k != null) params.append("k", String(k));
2717
+ const client = getClient2(session);
2718
+ const res = await client.http.get(
2719
+ `${BASE2}?${params.toString()}`,
2720
+ originHeaders(requestOrigin(mcpClient, session))
2721
+ );
2722
+ const results = res.data?.data?.web ?? [];
2723
+ return withAgentHints(
2724
+ withStructured(fmtGov(results), { results }),
2725
+ res.data,
2726
+ true
2727
+ );
2728
+ }
2729
+ });
2730
+ }
2731
+
2667
2732
  // src/keyless-client-ip.ts
2668
2733
  import net from "net";
2669
2734
  function extractSingleTrustedClientIp(rawForwardedFor) {
@@ -2711,7 +2776,7 @@ function checkKeylessSignupUrl(value) {
2711
2776
  }
2712
2777
 
2713
2778
  // src/monitor.ts
2714
- import { z as z7 } from "zod";
2779
+ import { z as z8 } from "zod";
2715
2780
 
2716
2781
  // src/session-credential.ts
2717
2782
  import { createHmac } from "crypto";
@@ -2845,8 +2910,8 @@ async function monitorRequest(session, origin, path2, init = {}) {
2845
2910
  function monitorResult(data) {
2846
2911
  return withAgentHints(structuredText(data), data);
2847
2912
  }
2848
- var pageStatusSchema = z7.enum(["same", "new", "changed", "removed", "error"]);
2849
- var checkStatusSchema = z7.enum([
2913
+ var pageStatusSchema = z8.enum(["same", "new", "changed", "removed", "error"]);
2914
+ var checkStatusSchema = z8.enum([
2850
2915
  "queued",
2851
2916
  "running",
2852
2917
  "completed",
@@ -2940,22 +3005,22 @@ Create a recurring scrape, crawl, or search monitor that compares each check wit
2940
3005
  In the simple form, a \`goal\` is required. If \`queries\` contains one or more non-empty values and is supplied with \`page\`/\`pages\`, \`queries\` create the search target and page targets are ignored. A monitor schedules future network checks and can send configured email or webhook notifications. Returns the created monitor.
2941
3006
  `,
2942
3007
  outputSchema: monitorOutputSchema,
2943
- parameters: z7.object({
2944
- body: z7.record(z7.string(), z7.any()).optional(),
2945
- page: z7.string().optional(),
2946
- pages: z7.array(z7.string()).optional(),
2947
- queries: z7.array(z7.string()).optional(),
2948
- searchWindow: z7.enum(["5m", "15m", "1h", "6h", "24h", "7d"]).optional(),
2949
- maxResults: z7.number().int().min(1).max(50).optional(),
2950
- includeDomains: z7.array(z7.string()).optional(),
2951
- excludeDomains: z7.array(z7.string()).optional(),
2952
- goal: z7.string().optional(),
2953
- name: z7.string().optional(),
2954
- scheduleText: z7.string().optional(),
2955
- timezone: z7.string().optional(),
2956
- email: z7.string().optional(),
2957
- includeDiffs: z7.boolean().optional(),
2958
- webhookUrl: z7.string().optional()
3008
+ parameters: z8.object({
3009
+ body: z8.record(z8.string(), z8.any()).optional(),
3010
+ page: z8.string().optional(),
3011
+ pages: z8.array(z8.string()).optional(),
3012
+ queries: z8.array(z8.string()).optional(),
3013
+ searchWindow: z8.enum(["5m", "15m", "1h", "6h", "24h", "7d"]).optional(),
3014
+ maxResults: z8.number().int().min(1).max(50).optional(),
3015
+ includeDomains: z8.array(z8.string()).optional(),
3016
+ excludeDomains: z8.array(z8.string()).optional(),
3017
+ goal: z8.string().optional(),
3018
+ name: z8.string().optional(),
3019
+ scheduleText: z8.string().optional(),
3020
+ timezone: z8.string().optional(),
3021
+ email: z8.string().optional(),
3022
+ includeDiffs: z8.boolean().optional(),
3023
+ webhookUrl: z8.string().optional()
2959
3024
  }),
2960
3025
  execute: async (args2, { session, log, client: mcpClient }) => {
2961
3026
  const body = buildMonitorCreateBody(args2);
@@ -2987,9 +3052,9 @@ In the simple form, a \`goal\` is required. If \`queries\` contains one or more
2987
3052
  List monitors for the authenticated account with optional pagination controls. Returns one page of monitor records and pagination metadata.
2988
3053
  `,
2989
3054
  outputSchema: monitorListOutputSchema,
2990
- parameters: z7.object({
2991
- limit: z7.number().int().positive().optional(),
2992
- offset: z7.number().int().nonnegative().optional()
3055
+ parameters: z8.object({
3056
+ limit: z8.number().int().positive().optional(),
3057
+ offset: z8.number().int().nonnegative().optional()
2993
3058
  }),
2994
3059
  execute: async (args2, { session, client: mcpClient }) => {
2995
3060
  const { limit, offset } = args2;
@@ -3019,7 +3084,7 @@ List monitors for the authenticated account with optional pagination controls. R
3019
3084
  Retrieve one monitor by ID, including its configuration and current state. This does not run or modify the monitor.
3020
3085
  `,
3021
3086
  outputSchema: monitorOutputSchema,
3022
- parameters: z7.object({ id: z7.string() }),
3087
+ parameters: z8.object({ id: z8.string() }),
3023
3088
  execute: async (args2, { session, client: mcpClient }) => {
3024
3089
  const { id } = args2;
3025
3090
  const res = await monitorRequest(
@@ -3047,9 +3112,9 @@ Patch an existing monitor by ID. The body can change its name, active/paused sta
3047
3112
  Returns the updated monitor.
3048
3113
  `,
3049
3114
  outputSchema: monitorOutputSchema,
3050
- parameters: z7.object({
3051
- id: z7.string(),
3052
- body: z7.record(z7.string(), z7.any())
3115
+ parameters: z8.object({
3116
+ id: z8.string(),
3117
+ body: z8.record(z8.string(), z8.any())
3053
3118
  }),
3054
3119
  execute: async (args2, { session, client: mcpClient }) => {
3055
3120
  const { id, body } = args2;
@@ -3077,7 +3142,7 @@ Returns the updated monitor.
3077
3142
  Permanently delete a monitor by ID and stop its future schedule. This operation cannot be undone and returns deletion status.
3078
3143
  `,
3079
3144
  outputSchema: monitorDeleteOutputSchema,
3080
- parameters: z7.object({ id: z7.string() }),
3145
+ parameters: z8.object({ id: z8.string() }),
3081
3146
  execute: async (args2, { session, log, client: mcpClient }) => {
3082
3147
  const { id } = args2;
3083
3148
  log.info("Deleting monitor", { id });
@@ -3105,7 +3170,7 @@ Permanently delete a monitor by ID and stop its future schedule. This operation
3105
3170
  Queue an immediate check for a monitor outside its normal schedule. This starts network work for the monitor's configured targets and returns the queued check.
3106
3171
  `,
3107
3172
  outputSchema: monitorRunOutputSchema,
3108
- parameters: z7.object({ id: z7.string() }),
3173
+ parameters: z8.object({ id: z8.string() }),
3109
3174
  execute: async (args2, { session, client: mcpClient }) => {
3110
3175
  const { id } = args2;
3111
3176
  const res = await monitorRequest(
@@ -3132,10 +3197,10 @@ Queue an immediate check for a monitor outside its normal schedule. This starts
3132
3197
  List historical checks for a monitor, optionally filtered by status and bounded by a result limit. Returns one page of check summaries and pagination metadata.
3133
3198
  `,
3134
3199
  outputSchema: monitorChecksOutputSchema,
3135
- parameters: z7.object({
3136
- id: z7.string(),
3137
- limit: z7.number().int().positive().optional(),
3138
- offset: z7.number().int().nonnegative().optional(),
3200
+ parameters: z8.object({
3201
+ id: z8.string(),
3202
+ limit: z8.number().int().positive().optional(),
3203
+ offset: z8.number().int().nonnegative().optional(),
3139
3204
  status: checkStatusSchema.optional()
3140
3205
  }),
3141
3206
  execute: async (args2, { session, client: mcpClient }) => {
@@ -3166,11 +3231,11 @@ Retrieve one monitor check and its page-level results, optionally filtered by pa
3166
3231
  Markdown tracking returns a unified text diff, JSON tracking returns field paths with previous/current values and a current snapshot, and mixed tracking returns both. Returns one page of results plus a \`next\` URL when more pages exist.
3167
3232
  `,
3168
3233
  outputSchema: monitorCheckOutputSchema,
3169
- parameters: z7.object({
3170
- id: z7.string(),
3171
- checkId: z7.string(),
3172
- limit: z7.number().int().positive().optional(),
3173
- skip: z7.number().int().nonnegative().optional(),
3234
+ parameters: z8.object({
3235
+ id: z8.string(),
3236
+ checkId: z8.string(),
3237
+ limit: z8.number().int().positive().optional(),
3238
+ skip: z8.number().int().nonnegative().optional(),
3174
3239
  pageStatus: pageStatusSchema.optional()
3175
3240
  }),
3176
3241
  execute: async (args2, { session, client: mcpClient }) => {
@@ -3187,8 +3252,8 @@ Markdown tracking returns a unified text diff, JSON tracking returns field paths
3187
3252
  }
3188
3253
 
3189
3254
  // src/research.ts
3190
- import { z as z8 } from "zod";
3191
- var BASE2 = "/v2/search/research";
3255
+ import { z as z9 } from "zod";
3256
+ var BASE3 = "/v2/search/research";
3192
3257
  function researchHeaders(origin) {
3193
3258
  return { ...originHeaders(origin), ...AGENT_HINTS_HEADERS };
3194
3259
  }
@@ -3306,21 +3371,21 @@ Several distinct framings of the same question surface different papers than a s
3306
3371
  Returns ranked papers with canonical IDs, titles, authors, and abstracts.
3307
3372
  `,
3308
3373
  outputSchema: researchSearchOutputSchema,
3309
- parameters: z8.object({
3310
- query: z8.string().min(1).describe(
3374
+ parameters: z9.object({
3375
+ query: z9.string().min(1).describe(
3311
3376
  "Natural-language research topic or question, including methods, systems, conditions, populations, interventions, or outcomes when relevant."
3312
3377
  ),
3313
- k: z8.number().int().min(1).max(500).optional().describe("Number of ranked papers to return (default 40)."),
3314
- authors: z8.array(z8.string()).optional().describe(
3378
+ k: z9.number().int().min(1).max(500).optional().describe("Number of ranked papers to return (default 40)."),
3379
+ authors: z9.array(z9.string()).optional().describe(
3315
3380
  "Author substring filter(s); ALL must match (case-insensitive)."
3316
3381
  ),
3317
- categories: z8.array(z8.string()).optional().describe(
3382
+ categories: z9.array(z9.string()).optional().describe(
3318
3383
  "Paper category filter(s) (e.g. `cs.LG`); ALL provided values must match."
3319
3384
  ),
3320
- from: z8.string().optional().describe(
3385
+ from: z9.string().optional().describe(
3321
3386
  "Inclusive lower bound on created/updated date (`YYYY-MM-DD`)."
3322
3387
  ),
3323
- to: z8.string().optional().describe(
3388
+ to: z9.string().optional().describe(
3324
3389
  "Inclusive upper bound on created/updated date (`YYYY-MM-DD`)."
3325
3390
  )
3326
3391
  }),
@@ -3335,7 +3400,7 @@ Returns ranked papers with canonical IDs, titles, authors, and abstracts.
3335
3400
  appendParam(params, "to", to);
3336
3401
  const client = getClient2(session);
3337
3402
  const res = await client.http.get(
3338
- withQuery(`${BASE2}/papers`, params),
3403
+ withQuery(`${BASE3}/papers`, params),
3339
3404
  researchHeaders(requestOrigin(mcpClient, session))
3340
3405
  );
3341
3406
  const results = res.data?.results ?? [];
@@ -3357,8 +3422,8 @@ Returns ranked papers with canonical IDs, titles, authors, and abstracts.
3357
3422
  Retrieve canonical metadata for one paper ID, such as an arXiv, PMC, PMID, or DOI identifier. Returns the title, abstract, authors, categories, source IDs, and dates as markdown.
3358
3423
  `,
3359
3424
  outputSchema: researchPaperOutputSchema,
3360
- parameters: z8.object({
3361
- paperId: z8.string().min(1).describe(
3425
+ parameters: z9.object({
3426
+ paperId: z9.string().min(1).describe(
3362
3427
  "Canonical paperId or primaryId such as `arxiv:1706.03762`, `pmcid:PMC12530322`, `pmid:40953549`, or `doi:10.1016/j.neunet.2025.108095`."
3363
3428
  )
3364
3429
  }),
@@ -3366,7 +3431,7 @@ Retrieve canonical metadata for one paper ID, such as an arXiv, PMC, PMID, or DO
3366
3431
  const { paperId } = args2;
3367
3432
  const client = getClient2(session);
3368
3433
  const res = await client.http.get(
3369
- `${BASE2}/papers/${encodeURIComponent(paperId)}`,
3434
+ `${BASE3}/papers/${encodeURIComponent(paperId)}`,
3370
3435
  researchHeaders(requestOrigin(mcpClient, session))
3371
3436
  );
3372
3437
  const paper = res.data?.paper;
@@ -3393,12 +3458,12 @@ Find citation-graph candidates from one to ten \`seed_ids\`; the first ID is the
3393
3458
  Returns ranked candidates and the evaluated pool size.
3394
3459
  `,
3395
3460
  outputSchema: researchRelatedOutputSchema,
3396
- parameters: z8.object({
3397
- seed_ids: z8.array(z8.string()).min(1).max(10),
3398
- intent: z8.string().min(1),
3399
- mode: z8.enum(["similar", "citers", "references"]).optional(),
3400
- k: z8.number().int().min(1).max(500).optional(),
3401
- rerank: z8.boolean().optional().describe("Apply an additional rerank over the fused candidates.")
3461
+ parameters: z9.object({
3462
+ seed_ids: z9.array(z9.string()).min(1).max(10),
3463
+ intent: z9.string().min(1),
3464
+ mode: z9.enum(["similar", "citers", "references"]).optional(),
3465
+ k: z9.number().int().min(1).max(500).optional(),
3466
+ rerank: z9.boolean().optional().describe("Apply an additional rerank over the fused candidates.")
3402
3467
  }),
3403
3468
  execute: async (args2, { session, client: mcpClient }) => {
3404
3469
  const { seed_ids, intent, mode, k, rerank } = args2;
@@ -3412,7 +3477,7 @@ Returns ranked candidates and the evaluated pool size.
3412
3477
  const client = getClient2(session);
3413
3478
  const res = await client.http.get(
3414
3479
  withQuery(
3415
- `${BASE2}/papers/${encodeURIComponent(primary)}/similar`,
3480
+ `${BASE3}/papers/${encodeURIComponent(primary)}/similar`,
3416
3481
  params
3417
3482
  ),
3418
3483
  researchHeaders(requestOrigin(mcpClient, session))
@@ -3445,12 +3510,12 @@ Retrieve in-body passages from one paper that are relevant to a specific questio
3445
3510
  Returns matching passages or a notice when full text is unavailable.
3446
3511
  `,
3447
3512
  outputSchema: researchReadOutputSchema,
3448
- parameters: z8.object({
3449
- paperId: z8.string().min(1).describe(
3513
+ parameters: z9.object({
3514
+ paperId: z9.string().min(1).describe(
3450
3515
  "Canonical paperId or primaryId such as `arxiv:1706.03762`, `pmcid:PMC12530322`, `pmid:40953549`, or `doi:10.1016/j.neunet.2025.108095`."
3451
3516
  ),
3452
- question: z8.string().min(1),
3453
- k: z8.number().int().min(1).max(50).optional().describe("Number of passages to return (default 4).")
3517
+ question: z9.string().min(1),
3518
+ k: z9.number().int().min(1).max(50).optional().describe("Number of passages to return (default 4).")
3454
3519
  }),
3455
3520
  execute: async (args2, { session, client: mcpClient }) => {
3456
3521
  const { paperId, question, k } = args2;
@@ -3459,7 +3524,7 @@ Returns matching passages or a notice when full text is unavailable.
3459
3524
  appendParam(params, "k", k);
3460
3525
  const client = getClient2(session);
3461
3526
  const res = await client.http.get(
3462
- withQuery(`${BASE2}/papers/${encodeURIComponent(paperId)}`, params),
3527
+ withQuery(`${BASE3}/papers/${encodeURIComponent(paperId)}`, params),
3463
3528
  researchHeaders(requestOrigin(mcpClient, session))
3464
3529
  );
3465
3530
  const passages = res.data?.passages ?? [];
@@ -3481,9 +3546,9 @@ Returns matching passages or a notice when full text is unavailable.
3481
3546
  Deprecated compatibility entry point. Use firecrawl_developer_search for GitHub issues, pull requests, and READMEs, plus code documentation, returned as matched passages.
3482
3547
  `,
3483
3548
  outputSchema: deprecatedToolOutputSchema,
3484
- parameters: z8.object({
3485
- query: z8.string().min(1),
3486
- k: z8.number().int().min(1).max(100).optional()
3549
+ parameters: z9.object({
3550
+ query: z9.string().min(1),
3551
+ k: z9.number().int().min(1).max(100).optional()
3487
3552
  }),
3488
3553
  canList: () => false,
3489
3554
  beforeValidate: () => {
@@ -3502,7 +3567,7 @@ Deprecated compatibility entry point. Use firecrawl_developer_search for GitHub
3502
3567
  }
3503
3568
 
3504
3569
  // src/usage.ts
3505
- import { z as z9 } from "zod";
3570
+ import { z as z10 } from "zod";
3506
3571
  function assertSuccessful(status, response, operation) {
3507
3572
  if (status === 200 && response.success) return;
3508
3573
  throw new Error(response.error || `Failed to ${operation}`);
@@ -3524,11 +3589,11 @@ The current view returns \`remainingCredits\`, \`planCredits\`, \`billingPeriodS
3524
3589
  The historical view returns periods sorted by start date with \`startDate\`, \`endDate\`, and \`creditsUsed\`. Set \`byApiKey\` to include separate periods per API key, identified by the optional \`apiKey\` field. The newest period's \`endDate\` can be null.
3525
3590
  `,
3526
3591
  outputSchema: creditUsageOutputSchema,
3527
- parameters: z9.object({
3528
- view: z9.enum(["current", "historical"]).optional().describe(
3592
+ parameters: z10.object({
3593
+ view: z10.enum(["current", "historical"]).optional().describe(
3529
3594
  "Select current balance or historical monthly usage. Defaults to current."
3530
3595
  ),
3531
- byApiKey: z9.boolean().optional().describe(
3596
+ byApiKey: z10.boolean().optional().describe(
3532
3597
  'Break historical usage down by API key. When view is omitted, true selects the historical view; it cannot be combined with view "current".'
3533
3598
  )
3534
3599
  }),
@@ -4151,32 +4216,32 @@ function removeEmptyTopLevel(obj) {
4151
4216
  }
4152
4217
  return out;
4153
4218
  }
4154
- var searchDomainSchema = z10.string().trim().toLowerCase().min(1).max(253).regex(
4219
+ var searchDomainSchema = z11.string().trim().toLowerCase().min(1).max(253).regex(
4155
4220
  /^(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z0-9][a-z0-9-]{0,61}[a-z0-9]$/,
4156
4221
  "Domain must be a valid hostname without protocol or path"
4157
4222
  );
4158
4223
  var searchToolBaseFields = {
4159
- toolDetail: z10.enum(["compact", "summary", "full"]).optional().describe("Compact by default. Compact returns only provider, capability and description; full includes contracts. Inspect selected compact tools with firecrawl_find_tools providers and capabilities."),
4160
- query: z10.string().min(1).describe("Query for web and semantic tool discovery. Operators include quoted phrases, `-term`, `site:host`, `inurl:term`, `intitle:term`, and `related:host`; the set is non-exhaustive. Catalogue browsing is available through firecrawl_find_tools."),
4161
- objective: z10.string().trim().min(1).max(5e3).optional().describe("Optional broader goal for this search, if known. Avoid sensitive information."),
4162
- clientModel: z10.string().trim().min(1).max(128).optional().describe("Optional model identifier, if known."),
4163
- domainTools: z10.boolean().optional().describe(
4224
+ toolDetail: z11.enum(["compact", "summary", "full"]).optional().describe("Compact by default. Compact returns only provider, capability and description; full includes contracts. Inspect selected compact tools with firecrawl_find_tools providers and capabilities."),
4225
+ query: z11.string().min(1).describe("Query for web and semantic tool discovery. Operators include quoted phrases, `-term`, `site:host`, `inurl:term`, `intitle:term`, and `related:host`; the set is non-exhaustive. Catalogue browsing is available through firecrawl_find_tools."),
4226
+ objective: z11.string().trim().min(1).max(5e3).optional().describe("Optional broader goal for this search, if known. Avoid sensitive information."),
4227
+ clientModel: z11.string().trim().min(1).max(128).optional().describe("Optional model identifier, if known."),
4228
+ domainTools: z11.boolean().optional().describe(
4164
4229
  "Include domain-matched tools for result URLs. Defaults to true when Alexandria is combined with web, news or images; semantic-only search leaves domain matching off."
4165
4230
  ),
4166
- highlights: z10.boolean().optional().describe(
4231
+ highlights: z11.boolean().optional().describe(
4167
4232
  "Return query-relevant page excerpts for web and news results when available (default). Highlights appear in web `description` and news `snippet`; otherwise, original snippets are returned. Set to false to keep the original search snippets."
4168
4233
  ),
4169
- limit: z10.number().int().min(1).max(100).optional(),
4170
- tbs: z10.string().optional(),
4171
- filter: z10.string().optional(),
4172
- location: z10.string().optional(),
4173
- includeDomains: z10.array(searchDomainSchema).optional().describe("Hostnames to restrict results to. Mutually exclusive with excludeDomains."),
4174
- excludeDomains: z10.array(searchDomainSchema).optional().describe("Hostnames to leave out of results. Mutually exclusive with includeDomains."),
4175
- sources: z10.array(searchSourceSchema).optional().describe("Search sources; authenticated sessions default to web + alexandria, keyless sessions to web only. " + ALEXANDRIA_SOURCES_OPT_OUT + ' Use ["alexandria"] alone for provider discovery without web results.'),
4176
- categories: z10.array(z10.enum(["research", "pdf", "developer"])).optional().describe(
4177
- 'Limit results to specific source types. `research` restricts ordinary web results to research-affiliated websites and returns page snippets, which is separate from the `firecrawl_research_*` tools that search paper abstracts and full text across biomedical (PubMed, bioRxiv, medRxiv) and arXiv literature; `pdf` searches PDF results; `developer` searches an index built for coding agents over public repositories, GitHub issues, merged pull requests, repository READMEs, and code documentation. `developer` returns hits in `data.web` with `category: "developer"`; the other categories also filter `data.web`.'
4234
+ limit: z11.number().int().min(1).max(100).optional(),
4235
+ tbs: z11.string().optional(),
4236
+ filter: z11.string().optional(),
4237
+ location: z11.string().optional(),
4238
+ includeDomains: z11.array(searchDomainSchema).optional().describe("Hostnames to restrict results to. Mutually exclusive with excludeDomains."),
4239
+ excludeDomains: z11.array(searchDomainSchema).optional().describe("Hostnames to leave out of results. Mutually exclusive with includeDomains."),
4240
+ sources: z11.array(searchSourceSchema).optional().describe("Search sources; authenticated sessions default to web + alexandria, keyless sessions to web only. " + ALEXANDRIA_SOURCES_OPT_OUT + ' Use ["alexandria"] alone for provider discovery without web results.'),
4241
+ categories: z11.array(z11.enum(["research", "pdf", "developer", "gov"])).optional().describe(
4242
+ "Limit results to specific source types. `research` restricts ordinary web results to research-affiliated websites and returns page snippets, which is separate from the `firecrawl_research_*` tools that search paper abstracts and full text across biomedical (PubMed, bioRxiv, medRxiv) and arXiv literature; `pdf` searches PDF results; `developer` searches an index built for coding agents over public repositories, GitHub issues, merged pull requests, repository READMEs, and code documentation; `gov` searches the Government Index of US federal, state, and local legal and regulatory sources, the index behind firecrawl_gov_search, and cannot be combined with other categories. `developer` and `gov` return hits in `data.web` with `category` set to their name; the other categories also filter `data.web`."
4178
4243
  ),
4179
- enterprise: z10.array(z10.enum(["default", "anon", "zdr"])).optional()
4244
+ enterprise: z11.array(z11.enum(["default", "anon", "zdr"])).optional()
4180
4245
  };
4181
4246
  function searchDomainsAreExclusive(args2) {
4182
4247
  return !(args2.includeDomains?.length && args2.excludeDomains?.length);
@@ -4184,15 +4249,15 @@ function searchDomainsAreExclusive(args2) {
4184
4249
  var SEARCH_DOMAINS_CONFLICT_MESSAGE = "includeDomains and excludeDomains cannot both be specified";
4185
4250
  var EXCHANGE_KEY_REQUIRED_MESSAGE = "Alexandria requires an API key on a team with Alexandria access";
4186
4251
  var EXCHANGE_MAX_CALLS = 10;
4187
- var exchangeCallSchema = z10.object({
4188
- provider: z10.string().min(1).describe('Provider slug, e.g. "fred".'),
4189
- capability: z10.string().min(1).describe(
4252
+ var exchangeCallSchema = z11.object({
4253
+ provider: z11.string().min(1).describe('Provider slug, e.g. "fred".'),
4254
+ capability: z11.string().min(1).describe(
4190
4255
  'Capability address as returned by search or discover, e.g. "series/observations".'
4191
4256
  ),
4192
- version: z10.string().trim().min(1).max(128).optional().describe("Optional published workflow version. Omit to use the latest version."),
4193
- options: z10.record(z10.string(), z10.any()).optional().describe("Capability options as declared by its contract.")
4257
+ version: z11.string().trim().min(1).max(128).optional().describe("Optional published workflow version. Omit to use the latest version."),
4258
+ options: z11.record(z11.string(), z11.any()).optional().describe("Capability options as declared by its contract.")
4194
4259
  });
4195
- var exchangeCallsSchema = z10.array(exchangeCallSchema).min(1).max(EXCHANGE_MAX_CALLS);
4260
+ var exchangeCallsSchema = z11.array(exchangeCallSchema).min(1).max(EXCHANGE_MAX_CALLS);
4196
4261
  function assertExchangeCredential(session) {
4197
4262
  if (hasCredential(session)) return;
4198
4263
  const payload = {
@@ -4368,12 +4433,13 @@ var ConsoleLogger = class {
4368
4433
  var openAiAppsChallengeToken = normalizeHeader(
4369
4434
  process.env.OPENAI_APPS_CHALLENGE_TOKEN
4370
4435
  );
4371
- var FULL_PROFILE_INSTRUCTIONS = `Firecrawl provides web search, page retrieval, site URL discovery, multi-page collection, structured page data, monitoring, and multi-source research that returns structured data. Match the requested operation to the tool boundary: firecrawl_scrape retrieves one supplied page and can return JSON matching a supplied schema, firecrawl_map enumerates URLs under a site without retrieving their content, and firecrawl_agent runs multi-source research and returns structured data when the URLs are not known or the answer spans several sites (an entity plus its fields, a list, a dataset); its result is read with firecrawl_agent_status. Authenticated firecrawl_search returns web results together with matching Alexandria providers in data.tools. ${ALEXANDRIA_CATALOGUE_SENTENCE} A matching provider can return the same fields across several entities, provenance, exact figures or timestamps, or a large set of records through firecrawl_scrape with its published contract. If web results already answer the question, use them. For the same fields across multiple pages, firecrawl_find_tools offers free provider discovery. Use firecrawl_find_tools to read a contract that was not returned in full or to browse the catalogue by category. ${ALEXANDRIA_SOURCES_OPT_OUT} If no provider fits, continue with web search or firecrawl_agent. For biomedical, life-science, clinical, or arXiv literature, the firecrawl_research_* tools search a paper index of abstracts and full text; firecrawl_search with categories: ["research"] is a website filter over ordinary web results and reaches different sources. For a programming question (code behaviour, a library or framework, an API contract, an error message, or a known bug), firecrawl_developer_search (or firecrawl_search with categories: ["developer"]) searches an index of public repositories, GitHub issues, merged pull requests, READMEs, and code documentation. firecrawl_search with sources: [{type: "alexandria"}] returns compact tool summaries in data.tools; toolDetail: "full" includes contracts, firecrawl_find_tools starts with categories, lists providers, then compact tools, and expands the selected full contract, and firecrawl_scrape with alexandria: [{provider, capability, options}] executes up to ten capabilities and returns their results. Alexandria access needs an API key on a team with it enabled. Provide only the required inputs and account for stated network or external side effects.`;
4372
- var KEYLESS_PROFILE_INSTRUCTIONS = `Hosted keyless sessions expose firecrawl_search, firecrawl_scrape, and firecrawl_parse with usage limits. firecrawl_search searches the web. For programming questions, firecrawl_search with categories: ["developer"] searches indexed public repositories, GitHub issues, merged pull requests, repository READMEs, and code documentation. For biomedical, life-science, clinical, or arXiv literature, firecrawl_search with categories: ["research"] filters ordinary web results to research-affiliated websites. firecrawl_scrape retrieves one supplied page and can return JSON matching a supplied schema. firecrawl_parse processes supported local files through its two-phase upload flow. An Authorization bearer API key can provide higher usage limits and expose additional tools, subject to plan, deployment, and team policy, including firecrawl_map for site URL discovery, firecrawl_agent and firecrawl_agent_status for multi-source research that returns structured data when the URLs are not known, firecrawl_research_* for paper-index and repository research, and firecrawl_find_tools as the progressive Alexandria catalogue lookup alongside the Alexandria options of firecrawl_search and firecrawl_scrape for catalogued data providers.`;
4373
- var SEARCH_PROFILE_INSTRUCTIONS = ALEXANDRIA_SEARCH_INSTRUCTIONS + ` Firecrawl provides web, developer, and research search, and executes catalogued Alexandria data providers. Use firecrawl_search to find relevant results across the web and specialized indexes; authenticated searches also return matching Alexandria providers in data.tools. firecrawl_find_tools provides catalogue browsing and provider contracts; firecrawl_scrape with an alexandria body executes a selected capability; firecrawl_scrape with a url retrieves one supplied page. For a programming question, firecrawl_developer_search searches indexed public repositories, GitHub issues, merged pull requests, READMEs, and code documentation and returns the matched passages, and skills: "only" narrows it to agent-skill files; firecrawl_search with categories: ["developer"] reaches the same index beside ordinary web results, returning the hits in the web group rather than as passages and offering no skills filter. For a biomedical, life-science, clinical, or arXiv literature question, the firecrawl_research_* tools search the paper index, while categories: ["research"] on firecrawl_search filters ordinary web results to research-affiliated websites. Use the firecrawl_research_* tools to search academic and research literature, expand from anchor papers via the citation graph, and read full-text passages from a specific paper. Search and discovery tools are read-only and return ranked results. Billing: web, developer and research search are billed per request; Alexandria discovery (firecrawl_search with sources ["alexandria"] alone, and firecrawl_find_tools) is free; firecrawl_scrape is billed, as a page retrieval in url mode or at each executed capability's listed price in alexandria mode.`;
4436
+ var FULL_PROFILE_INSTRUCTIONS = `Firecrawl provides web search, page retrieval, site URL discovery, multi-page collection, structured page data, monitoring, and multi-source research that returns structured data. Match the requested operation to the tool boundary: firecrawl_scrape retrieves one supplied page and can return JSON matching a supplied schema, firecrawl_map enumerates URLs under a site without retrieving their content, and firecrawl_agent runs multi-source research and returns structured data when the URLs are not known or the answer spans several sites (an entity plus its fields, a list, a dataset); its result is read with firecrawl_agent_status. Authenticated firecrawl_search returns web results together with matching Alexandria providers in data.tools. ${ALEXANDRIA_CATALOGUE_SENTENCE} A matching provider can return the same fields across several entities, provenance, exact figures or timestamps, or a large set of records through firecrawl_scrape with its published contract. If web results already answer the question, use them. For the same fields across multiple pages, firecrawl_find_tools offers free provider discovery. Use firecrawl_find_tools to read a contract that was not returned in full or to browse the catalogue by category. ${ALEXANDRIA_SOURCES_OPT_OUT} If no provider fits, continue with web search or firecrawl_agent. For biomedical, life-science, clinical, or arXiv literature, the firecrawl_research_* tools search a paper index of abstracts and full text; firecrawl_search with categories: ["research"] is a website filter over ordinary web results and reaches different sources. For a programming question (code behaviour, a library or framework, an API contract, an error message, or a known bug), firecrawl_developer_search (or firecrawl_search with categories: ["developer"]) searches an index of public repositories, GitHub issues, merged pull requests, READMEs, and code documentation. For a legal or regulatory question, firecrawl_gov_search searches primary law and regulatory material from US federal, state, and local government sources: statutes, regulations, codes, court opinions, and other government publications; firecrawl_search with categories: ["gov"] reaches the same sources and cannot be combined with other categories. firecrawl_search with sources: [{type: "alexandria"}] returns compact tool summaries in data.tools; toolDetail: "full" includes contracts, firecrawl_find_tools starts with categories, lists providers, then compact tools, and expands the selected full contract, and firecrawl_scrape with alexandria: [{provider, capability, options}] executes up to ten capabilities and returns their results. Alexandria access needs an API key on a team with it enabled. Provide only the required inputs and account for stated network or external side effects.`;
4437
+ var KEYLESS_PROFILE_INSTRUCTIONS = `Hosted keyless sessions expose firecrawl_search, firecrawl_scrape, and firecrawl_parse with usage limits. firecrawl_search searches the web. For programming questions, firecrawl_search with categories: ["developer"] searches indexed public repositories, GitHub issues, merged pull requests, repository READMEs, and code documentation. For legal or regulatory questions, firecrawl_search with categories: ["gov"] searches US government legal and regulatory sources and cannot be combined with other categories. For biomedical, life-science, clinical, or arXiv literature, firecrawl_search with categories: ["research"] filters ordinary web results to research-affiliated websites. firecrawl_scrape retrieves one supplied page and can return JSON matching a supplied schema. firecrawl_parse processes supported local files through its two-phase upload flow. An Authorization bearer API key can provide higher usage limits and expose additional tools, subject to plan, deployment, and team policy, including firecrawl_map for site URL discovery, firecrawl_agent and firecrawl_agent_status for multi-source research that returns structured data when the URLs are not known, firecrawl_research_* for paper-index and repository research, and firecrawl_find_tools as the progressive Alexandria catalogue lookup alongside the Alexandria options of firecrawl_search and firecrawl_scrape for catalogued data providers.`;
4438
+ var SEARCH_PROFILE_INSTRUCTIONS = ALEXANDRIA_SEARCH_INSTRUCTIONS + ` Firecrawl provides web, developer, government, and research search, and executes catalogued Alexandria data providers. Use firecrawl_search to find relevant results across the web and specialized indexes; authenticated searches also return matching Alexandria providers in data.tools. firecrawl_find_tools provides catalogue browsing and provider contracts; firecrawl_scrape with an alexandria body executes a selected capability; firecrawl_scrape with a url retrieves one supplied page. For a programming question, firecrawl_developer_search searches indexed public repositories, GitHub issues, merged pull requests, READMEs, and code documentation and returns the matched passages, and skills: "only" narrows it to agent-skill files; firecrawl_search with categories: ["developer"] reaches the same index beside ordinary web results, returning the hits in the web group rather than as passages and offering no skills filter. For a legal or regulatory question, firecrawl_gov_search searches primary law and regulatory material from US federal, state, and local government sources: statutes, regulations, codes, court opinions, and other government publications; firecrawl_search with categories: ["gov"] reaches the same sources in the web group and cannot be combined with other categories. For a biomedical, life-science, clinical, or arXiv literature question, the firecrawl_research_* tools search the paper index, while categories: ["research"] on firecrawl_search filters ordinary web results to research-affiliated websites. Use the firecrawl_research_* tools to search academic and research literature, expand from anchor papers via the citation graph, and read full-text passages from a specific paper. Search and discovery tools are read-only and return ranked results. Billing: web, developer, and research search are billed per request; government search is free; Alexandria discovery (firecrawl_search with sources ["alexandria"] alone, and firecrawl_find_tools) is free; firecrawl_scrape is billed, as a page retrieval in url mode or at each executed capability's listed price in alexandria mode.`;
4374
4439
  var SEARCH_PROFILE_TOOLS = /* @__PURE__ */ new Set([
4375
4440
  "firecrawl_search",
4376
4441
  "firecrawl_developer_search",
4442
+ "firecrawl_gov_search",
4377
4443
  "firecrawl_research_search_papers",
4378
4444
  "firecrawl_research_inspect_paper",
4379
4445
  "firecrawl_research_related_papers",
@@ -4968,10 +5034,10 @@ function transformScrapeParams(args2) {
4968
5034
  delete out.pdfOptions;
4969
5035
  return out;
4970
5036
  }
4971
- var scrapeParamsSchema = z10.object({
4972
- url: z10.string().url(),
4973
- formats: z10.array(
4974
- z10.enum([
5037
+ var scrapeParamsSchema = z11.object({
5038
+ url: z11.string().url(),
5039
+ formats: z11.array(
5040
+ z11.enum([
4975
5041
  "markdown",
4976
5042
  "html",
4977
5043
  "rawHtml",
@@ -4985,71 +5051,77 @@ var scrapeParamsSchema = z10.object({
4985
5051
  "audio"
4986
5052
  ])
4987
5053
  ).optional(),
4988
- jsonOptions: z10.object({
4989
- prompt: z10.string().optional(),
4990
- schema: z10.record(z10.string(), z10.any()).optional()
5054
+ jsonOptions: z11.object({
5055
+ prompt: z11.string().optional(),
5056
+ schema: z11.record(z11.string(), z11.any()).optional()
4991
5057
  }).optional(),
4992
- queryOptions: z10.object({
4993
- prompt: z10.string().max(1e4),
4994
- mode: z10.enum(["directQuote", "freeform"]).default("freeform")
5058
+ queryOptions: z11.object({
5059
+ prompt: z11.string().max(1e4),
5060
+ mode: z11.enum(["directQuote", "freeform"]).default("freeform")
4995
5061
  }).optional(),
4996
- screenshotOptions: z10.object({
4997
- fullPage: z10.boolean().optional(),
4998
- quality: z10.number().optional(),
4999
- viewport: z10.object({ width: z10.number(), height: z10.number() }).optional()
5062
+ screenshotOptions: z11.object({
5063
+ fullPage: z11.boolean().optional(),
5064
+ quality: z11.number().optional(),
5065
+ viewport: z11.object({ width: z11.number(), height: z11.number() }).optional()
5000
5066
  }).optional(),
5001
- parsers: z10.array(z10.enum(["pdf"])).optional(),
5002
- pdfOptions: z10.object({
5003
- maxPages: z10.number().int().min(1).max(1e4).optional()
5067
+ parsers: z11.array(z11.enum(["pdf"])).optional(),
5068
+ pdfOptions: z11.object({
5069
+ maxPages: z11.number().int().min(1).max(1e4).optional()
5004
5070
  }).optional(),
5005
- onlyMainContent: z10.boolean().optional(),
5006
- redactPII: z10.boolean().optional(),
5007
- includeTags: z10.array(z10.string()).optional(),
5008
- excludeTags: z10.array(z10.string()).optional(),
5009
- waitFor: z10.number().optional(),
5071
+ onlyMainContent: z11.boolean().optional(),
5072
+ redactPII: z11.boolean().optional(),
5073
+ includeTags: z11.array(z11.string()).optional(),
5074
+ excludeTags: z11.array(z11.string()).optional(),
5075
+ waitFor: z11.number().optional(),
5010
5076
  ...SAFE_MODE ? {} : {
5011
- actions: z10.array(
5012
- z10.object({
5013
- type: z10.enum(allowedActionTypes),
5014
- selector: z10.string().optional(),
5015
- milliseconds: z10.number().optional(),
5016
- text: z10.string().optional(),
5017
- key: z10.string().optional(),
5018
- direction: z10.enum(["up", "down"]).optional(),
5019
- script: z10.string().optional(),
5020
- fullPage: z10.boolean().optional()
5077
+ actions: z11.array(
5078
+ z11.object({
5079
+ type: z11.enum(allowedActionTypes),
5080
+ selector: z11.string().optional(),
5081
+ milliseconds: z11.number().optional(),
5082
+ text: z11.string().optional(),
5083
+ key: z11.string().optional(),
5084
+ direction: z11.enum(["up", "down"]).optional(),
5085
+ script: z11.string().optional(),
5086
+ fullPage: z11.boolean().optional()
5021
5087
  })
5022
5088
  ).optional()
5023
5089
  },
5024
- mobile: z10.boolean().optional(),
5025
- skipTlsVerification: z10.boolean().optional(),
5026
- removeBase64Images: z10.boolean().optional(),
5027
- location: z10.object({
5028
- country: z10.string().optional(),
5029
- languages: z10.array(z10.string()).optional()
5090
+ mobile: z11.boolean().optional(),
5091
+ skipTlsVerification: z11.boolean().optional(),
5092
+ removeBase64Images: z11.boolean().optional(),
5093
+ location: z11.object({
5094
+ country: z11.string().optional(),
5095
+ languages: z11.array(z11.string()).optional()
5030
5096
  }).optional(),
5031
- storeInCache: z10.boolean().optional(),
5032
- zeroDataRetention: z10.boolean().optional(),
5033
- maxAge: z10.number().optional(),
5034
- lockdown: z10.boolean().optional(),
5035
- proxy: z10.enum(["basic", "stealth", "enhanced", "auto"]).optional(),
5036
- profile: z10.object({
5037
- name: z10.string(),
5038
- saveChanges: z10.boolean().optional()
5097
+ storeInCache: z11.boolean().optional(),
5098
+ zeroDataRetention: z11.boolean().optional(),
5099
+ maxAge: z11.number().optional(),
5100
+ lockdown: z11.boolean().optional(),
5101
+ proxy: z11.enum(["basic", "stealth", "enhanced", "auto"]).optional(),
5102
+ profile: z11.object({
5103
+ name: z11.string(),
5104
+ saveChanges: z11.boolean().optional()
5039
5105
  }).optional()
5040
5106
  });
5107
+ var readOnlyProfileSchema = z11.object({ name: z11.string() }).describe("Loads a saved browser profile without saving changes to it.");
5108
+ function withReadOnlyProfile(options) {
5109
+ const profile = options.profile;
5110
+ return SAFE_MODE && profile ? { ...options, profile: { name: profile.name, saveChanges: false } } : options;
5111
+ }
5041
5112
  var ALEXANDRIA_IGNORED_SCRAPE_OPTIONS = /* @__PURE__ */ new Set(["toolDetail", "domainTools"]);
5042
5113
  var scrapeToolParamsSchema = scrapeParamsSchema.extend({
5043
- url: z10.string().url().optional(),
5044
- timeout: z10.number().int().positive().optional().describe("Execution timeout in milliseconds."),
5045
- requestId: z10.string().regex(/^[A-Za-z0-9._:-]{1,128}$/).optional().describe(
5114
+ ...SAFE_MODE ? { profile: readOnlyProfileSchema.optional() } : {},
5115
+ url: z11.string().url().optional(),
5116
+ timeout: z11.number().int().positive().optional().describe("Execution timeout in milliseconds."),
5117
+ requestId: z11.string().regex(/^[A-Za-z0-9._:-]{1,128}$/).optional().describe(
5046
5118
  "Idempotency key bound to one Alexandria execution payload. Generated when omitted and returned with the result."
5047
5119
  ),
5048
- alexandria: z10.union([exchangeCallSchema, exchangeCallsSchema]).optional().describe(
5120
+ alexandria: z11.union([exchangeCallSchema, exchangeCallsSchema]).optional().describe(
5049
5121
  "Catalogued Alexandria capability invocation, mutually exclusive with url. One {provider, capability, options} object or an array of 1-10, with contracts available through firecrawl_search or firecrawl_find_tools. Each call may include version to pin a published workflow; omitting it uses latest. Only requestId and timeout are supported alongside alexandria. " + ALEXANDRIA_CONTRACT_GUIDANCE + " Returns per-capability results in data.alexandria with data, records, or an error with a code; individual capabilities can fail even when the outer response succeeds. Requires an API key on a team with Alexandria enabled. Some providers require accepted terms; blocked requests return the applicable requirements."
5050
5122
  ),
5051
- toolDetail: z10.enum(["compact", "summary", "full"]).optional().describe("URL mode only: domain discovery detail, summary by default; compact returns provider/capability/description, full includes contracts. Ignored with alexandria."),
5052
- domainTools: z10.boolean().optional().describe(
5123
+ toolDetail: z11.enum(["compact", "summary", "full"]).optional().describe("URL mode only: domain discovery detail, summary by default; compact returns provider/capability/description, full includes contracts. Ignored with alexandria."),
5124
+ domainTools: z11.boolean().optional().describe(
5053
5125
  "URL mode only: include domain-matched Alexandria tools for the page in tools on the returned document. Ignored with alexandria."
5054
5126
  )
5055
5127
  }).refine(
@@ -5069,9 +5141,9 @@ var scrapeToolParamsSchema = scrapeParamsSchema.extend({
5069
5141
  (args2) => !args2.requestId || !!args2.alexandria,
5070
5142
  "requestId applies to Alexandria execution only"
5071
5143
  );
5072
- var parseOptionParamsSchema = z10.object({
5073
- formats: z10.array(
5074
- z10.enum([
5144
+ var parseOptionParamsSchema = z11.object({
5145
+ formats: z11.array(
5146
+ z11.enum([
5075
5147
  "markdown",
5076
5148
  "html",
5077
5149
  "rawHtml",
@@ -5081,48 +5153,48 @@ var parseOptionParamsSchema = z10.object({
5081
5153
  "query"
5082
5154
  ])
5083
5155
  ).optional(),
5084
- jsonOptions: z10.object({
5085
- prompt: z10.string().optional(),
5086
- schema: z10.record(z10.string(), z10.any()).optional()
5156
+ jsonOptions: z11.object({
5157
+ prompt: z11.string().optional(),
5158
+ schema: z11.record(z11.string(), z11.any()).optional()
5087
5159
  }).optional(),
5088
- queryOptions: z10.object({
5089
- prompt: z10.string().max(1e4),
5090
- mode: z10.enum(["directQuote", "freeform"]).default("freeform")
5160
+ queryOptions: z11.object({
5161
+ prompt: z11.string().max(1e4),
5162
+ mode: z11.enum(["directQuote", "freeform"]).default("freeform")
5091
5163
  }).optional(),
5092
- parsers: z10.array(z10.enum(["pdf"])).optional(),
5093
- pdfOptions: z10.object({
5094
- maxPages: z10.number().int().min(1).max(1e4).optional()
5164
+ parsers: z11.array(z11.enum(["pdf"])).optional(),
5165
+ pdfOptions: z11.object({
5166
+ maxPages: z11.number().int().min(1).max(1e4).optional()
5095
5167
  }).optional(),
5096
- onlyMainContent: z10.boolean().optional(),
5097
- redactPII: z10.boolean().optional(),
5098
- includeTags: z10.array(z10.string()).optional(),
5099
- excludeTags: z10.array(z10.string()).optional(),
5100
- removeBase64Images: z10.boolean().optional(),
5101
- skipTlsVerification: z10.boolean().optional(),
5102
- storeInCache: z10.boolean().optional(),
5103
- zeroDataRetention: z10.boolean().optional(),
5104
- maxAge: z10.number().optional().describe("Ignored: parse never reuses or stores indexed content."),
5105
- proxy: z10.enum(["basic", "auto"]).optional()
5168
+ onlyMainContent: z11.boolean().optional(),
5169
+ redactPII: z11.boolean().optional(),
5170
+ includeTags: z11.array(z11.string()).optional(),
5171
+ excludeTags: z11.array(z11.string()).optional(),
5172
+ removeBase64Images: z11.boolean().optional(),
5173
+ skipTlsVerification: z11.boolean().optional(),
5174
+ storeInCache: z11.boolean().optional(),
5175
+ zeroDataRetention: z11.boolean().optional(),
5176
+ maxAge: z11.number().optional().describe("Ignored: parse never reuses or stores indexed content."),
5177
+ proxy: z11.enum(["basic", "auto"]).optional()
5106
5178
  });
5107
5179
  var localParseParamsSchema = parseOptionParamsSchema.extend({
5108
- filePath: z10.string().min(1).describe(
5180
+ filePath: z11.string().min(1).describe(
5109
5181
  "Absolute or relative path to a local file to parse. Supported: .html, .htm, .pdf, .docx, .doc, .odt, .rtf, .xlsx, .xls"
5110
5182
  ),
5111
- contentType: z10.string().optional().describe(
5183
+ contentType: z11.string().optional().describe(
5112
5184
  "Optional MIME type override. If omitted, the server infers the file kind from the extension."
5113
5185
  )
5114
5186
  });
5115
5187
  var hostedParseParamsSchema = parseOptionParamsSchema.extend({
5116
- filePath: z10.string().min(1).optional().describe(
5188
+ filePath: z11.string().min(1).optional().describe(
5117
5189
  "Phase 1 only: path to the local file on the caller/harness machine. Hosted MCP will not read or stat this path; it is used only to produce upload instructions."
5118
5190
  ),
5119
- uploadRef: z10.string().min(1).optional().describe(
5191
+ uploadRef: z11.string().min(1).optional().describe(
5120
5192
  "Phase 2 only: short-lived upload reference returned by phase 1 after the local PUT upload completes."
5121
5193
  ),
5122
- contentType: z10.string().optional().describe(
5194
+ contentType: z11.string().optional().describe(
5123
5195
  "Phase 1 MIME type override. If omitted, the server infers it from the file extension without reading the file."
5124
5196
  ),
5125
- declaredSizeBytes: z10.number().int().positive().optional().describe(
5197
+ declaredSizeBytes: z11.number().int().positive().optional().describe(
5126
5198
  "Optional phase 1 size declaration. Hosted MCP does not stat the file; provide this only if the caller already knows it."
5127
5199
  )
5128
5200
  }).superRefine((value, ctx) => {
@@ -5130,7 +5202,7 @@ var hostedParseParamsSchema = parseOptionParamsSchema.extend({
5130
5202
  const hasUploadRef = typeof value.uploadRef === "string" && value.uploadRef.length > 0;
5131
5203
  if (hasFilePath === hasUploadRef) {
5132
5204
  ctx.addIssue({
5133
- code: z10.ZodIssueCode.custom,
5205
+ code: z11.ZodIssueCode.custom,
5134
5206
  message: "Hosted firecrawl_parse requires exactly one of filePath (phase 1) or uploadRef (phase 2).",
5135
5207
  path: hasFilePath && hasUploadRef ? ["uploadRef"] : ["filePath"]
5136
5208
  });
@@ -5335,8 +5407,8 @@ var scrapeTool = {
5335
5407
  name: "firecrawl_scrape",
5336
5408
  annotations: {
5337
5409
  title: "Firecrawl scrape",
5338
- // Hosted scrape omits browser actions and refuses provider terms writes
5339
- // before execution.
5410
+ // Hosted scrape omits browser actions, loads profiles without saving,
5411
+ // and refuses provider terms writes before execution.
5340
5412
  readOnlyHint: SAFE_MODE,
5341
5413
  openWorldHint: true,
5342
5414
  // Accepts any user-supplied URL on the public web.
@@ -5346,7 +5418,7 @@ var scrapeTool = {
5346
5418
  description: `
5347
5419
  Scrape one URL and return its content: markdown by default, or HTML, links, screenshots, branding data, a targeted answer, or JSON matching a supplied schema. Use it when the request identifies a page and needs its content or defined fields. Use \`firecrawl_search\` when additional web sources are needed; on an authenticated session, \`firecrawl_map\` lists a site's URLs and \`firecrawl_crawl\` collects a set of pages.
5348
5420
 
5349
- Firecrawl may serve recently indexed content; set \`maxAge: 0\` for a live fetch or a smaller \`maxAge\` to bound staleness. A successful response does not by itself confirm the page is still current. Browser actions can change the live page when interactive actions are enabled. Authenticated responses can include a \`metadata.scrapeId\` for optional scrape feedback.
5421
+ Firecrawl may serve recently indexed content; set \`maxAge: 0\` for a live fetch or a smaller \`maxAge\` to bound staleness. A successful response does not by itself confirm the page is still current. ${SAFE_MODE ? "A named browser profile loads saved session data without saving changes to it." : "Browser actions can change the live page when interactive actions are enabled."} Authenticated responses can include a \`metadata.scrapeId\` for optional scrape feedback.
5350
5422
 
5351
5423
  On an authenticated session with Alexandria access, \`firecrawl_search\` with \`sources\` unset and \`firecrawl_find_tools\` can discover providers for the same fields across several pages; a matching provider returns typed records in one call. Keyless sessions have no provider matches.
5352
5424
 
@@ -5377,7 +5449,7 @@ Alexandria mode, on an authenticated session with Alexandria access: \`alexandri
5377
5449
  const transformed = transformScrapeParams(
5378
5450
  options
5379
5451
  );
5380
- const cleaned = removeEmptyTopLevel(transformed);
5452
+ const cleaned = withReadOnlyProfile(removeEmptyTopLevel(transformed));
5381
5453
  if (cleaned.lockdown) {
5382
5454
  log.info("Scraping URL (lockdown)");
5383
5455
  } else {
@@ -5430,13 +5502,13 @@ Enumerate URLs indexed under one website through Firecrawl without fetching each
5430
5502
  Returns matching URLs rather than page bodies. Retrieve one page with \`firecrawl_scrape\`; collect content across multiple pages with \`firecrawl_crawl\`. Authenticated responses can include an \`id\` for optional map feedback.
5431
5503
  `,
5432
5504
  outputSchema: mapOutputSchema,
5433
- parameters: z10.object({
5434
- url: z10.string().url(),
5435
- search: z10.string().optional(),
5436
- sitemap: z10.enum(["include", "skip", "only"]).optional(),
5437
- includeSubdomains: z10.boolean().optional(),
5438
- limit: z10.number().optional(),
5439
- ignoreQueryParameters: z10.boolean().optional()
5505
+ parameters: z11.object({
5506
+ url: z11.string().url(),
5507
+ search: z11.string().optional(),
5508
+ sitemap: z11.enum(["include", "skip", "only"]).optional(),
5509
+ includeSubdomains: z11.boolean().optional(),
5510
+ limit: z11.number().optional(),
5511
+ ignoreQueryParameters: z11.boolean().optional()
5440
5512
  }),
5441
5513
  execute: async (args2, { session, log, client: mcpClient }) => {
5442
5514
  const { url, ...options } = args2;
@@ -5472,12 +5544,12 @@ ${ALEXANDRIA_SEARCH_LEAD}
5472
5544
 
5473
5545
  On an authenticated session, tool matches describe available capabilities; \`firecrawl_find_tools\` returns their contracts and \`firecrawl_scrape\` with an \`alexandria\` body executes a selected capability. Keyless sessions get no Alexandria matches in data.tools.
5474
5546
 
5475
- For a programming question, add \`categories: ["developer"]\`; its hits return in \`data.web\` with \`category: "developer"\`. \`categories: ["research"]\` restricts web results to research-affiliated websites; the \`firecrawl_research_*\` tools are a separate surface over paper abstracts and full text (PubMed, bioRxiv, medRxiv, arXiv). Query operators, domain filters, \`categories\`, \`toolDetail\` and \`scrapeOptions\` are described on their parameters. Returns source-type result groups and usage metadata. Authenticated responses can include an \`id\` for optional search feedback.
5547
+ For a programming question, add \`categories: ["developer"]\`; its hits return in \`data.web\` with \`category: "developer"\`. For a legal or regulatory question, \`categories: ["gov"]\` returns hits in \`data.web\` with \`category: "gov"\` and cannot be combined with other categories; authenticated sessions also have \`firecrawl_gov_search\` as the dedicated tool. \`categories: ["research"]\` restricts web results to research-affiliated websites; the \`firecrawl_research_*\` tools are a separate surface over paper abstracts and full text (PubMed, bioRxiv, medRxiv, arXiv). Query operators, domain filters, \`categories\`, \`toolDetail\` and \`scrapeOptions\` are described on their parameters. Returns source-type result groups and usage metadata. Authenticated responses can include an \`id\` for optional search feedback.
5476
5548
  `,
5477
5549
  outputSchema: searchOutputSchema,
5478
- parameters: z10.object({
5550
+ parameters: z11.object({
5479
5551
  ...searchToolBaseFields,
5480
- scrapeOptions: scrapeParamsSchema.omit({ url: true }).partial().optional().describe("Attach page content for web results in the same call. These fetches ignore maxAge, so use firecrawl_scrape when you need a live fetch. scrapeOptions fetches web pages, never Alexandria provider tools.")
5552
+ scrapeOptions: scrapeParamsSchema.omit({ url: true }).extend(SAFE_MODE ? { profile: readOnlyProfileSchema } : {}).partial().optional().describe("Attach page content for web results in the same call. These fetches ignore maxAge, so use firecrawl_scrape when you need a live fetch. scrapeOptions fetches web pages, never Alexandria provider tools.")
5481
5553
  }).refine(searchDomainsAreExclusive, SEARCH_DOMAINS_CONFLICT_MESSAGE).refine(
5482
5554
  searchQueryIsValid,
5483
5555
  "A query is required. Use Find Tools for catalogue lookup."
@@ -5493,8 +5565,8 @@ For a programming question, add \`categories: ["developer"]\`; its hits return i
5493
5565
  searchOpts.domainTools ??= defaultDomainTools(searchOpts.sources);
5494
5566
  searchOpts.toolDetail ??= "compact";
5495
5567
  if (searchOpts.scrapeOptions) {
5496
- searchOpts.scrapeOptions = transformScrapeParams(
5497
- searchOpts.scrapeOptions
5568
+ searchOpts.scrapeOptions = withReadOnlyProfile(
5569
+ transformScrapeParams(searchOpts.scrapeOptions)
5498
5570
  );
5499
5571
  }
5500
5572
  const cleaned = removeEmptyTopLevel(searchOpts);
@@ -5614,7 +5686,7 @@ var findToolsTool = {
5614
5686
  };
5615
5687
  server.addTool(findToolsTool);
5616
5688
  var SEARCH_SURFACE_SCRAPE_DESCRIPTION = `
5617
- Scrape one URL and return its content, or execute catalogued Alexandria capabilities. URL mode returns markdown by default, or HTML, links, screenshots, branding data, a targeted answer, or JSON matching a supplied schema, plus page metadata. Firecrawl may serve recently indexed content; set \`maxAge: 0\` for a live fetch. A successful response does not by itself confirm the page is still current. A named browser profile loads saved session data.
5689
+ Scrape one URL and return its content, or execute catalogued Alexandria capabilities. URL mode returns markdown by default, or HTML, links, screenshots, branding data, a targeted answer, or JSON matching a supplied schema, plus page metadata. Firecrawl may serve recently indexed content; set \`maxAge: 0\` for a live fetch. A successful response does not by itself confirm the page is still current. ${SAFE_MODE ? "A named browser profile loads saved session data without saving changes to it." : "Browser actions can change the live page, and a named browser profile can load saved session data and overwrite its stored state."}
5618
5690
 
5619
5691
  \`firecrawl_search\` with \`sources\` unset and \`firecrawl_find_tools\` can discover providers for the same fields across several pages; a matching Alexandria provider returns typed records in one call.
5620
5692
 
@@ -5795,17 +5867,17 @@ async function waitForCrawlCompletionWithOrigin(client, jobId, origin, pollInter
5795
5867
  );
5796
5868
  }
5797
5869
  }
5798
- var feedbackIssueSchema = z10.string().trim().min(1).max(80).regex(
5870
+ var feedbackIssueSchema = z11.string().trim().min(1).max(80).regex(
5799
5871
  /^[a-z0-9][a-z0-9_-]*$/,
5800
5872
  "Issue codes must use lowercase letters, numbers, underscores, or hyphens"
5801
5873
  );
5802
- var valuableSourceSchema = z10.object({
5803
- url: z10.string().url(),
5804
- reason: z10.string().max(1e3).optional()
5874
+ var valuableSourceSchema = z11.object({
5875
+ url: z11.string().url(),
5876
+ reason: z11.string().max(1e3).optional()
5805
5877
  });
5806
- var missingContentSchema = z10.object({
5807
- topic: z10.string().min(1, "topic must not be empty").max(200, "topic must be 200 characters or fewer"),
5808
- description: z10.string().max(2e3).optional()
5878
+ var missingContentSchema = z11.object({
5879
+ topic: z11.string().min(1, "topic must not be empty").max(200, "topic must be 200 characters or fewer"),
5880
+ description: z11.string().max(2e3).optional()
5809
5881
  });
5810
5882
  var FEEDBACK_DISABLED_VALUES = /* @__PURE__ */ new Set(["1", "true", "yes", "on"]);
5811
5883
  function feedbackEnvEnabled(...keys) {
@@ -5844,24 +5916,24 @@ Records schema-validated quality feedback for a prior \`firecrawl_search\` UUID
5844
5916
  Eligibility is limited to successful searches within the feedback age window. The record is idempotent per search ID. Eligible first feedback for a search can refund 1 credit; refunds are subject to the team's daily cap. The response reports whether a refund was applied, along with submission and daily-cap status.
5845
5917
  `,
5846
5918
  outputSchema: feedbackOutputSchema,
5847
- parameters: z10.object({
5848
- searchId: z10.string().uuid("searchId must be the UUID returned by firecrawl_search"),
5849
- rating: z10.enum(["good", "bad", "partial"]),
5850
- valuableSources: z10.array(
5851
- z10.object({
5852
- url: z10.string().url(),
5853
- reason: z10.string().max(1e3).optional()
5919
+ parameters: z11.object({
5920
+ searchId: z11.string().uuid("searchId must be the UUID returned by firecrawl_search"),
5921
+ rating: z11.enum(["good", "bad", "partial"]),
5922
+ valuableSources: z11.array(
5923
+ z11.object({
5924
+ url: z11.string().url(),
5925
+ reason: z11.string().max(1e3).optional()
5854
5926
  })
5855
5927
  ).max(50).optional(),
5856
- missingContent: z10.array(
5857
- z10.object({
5858
- topic: z10.string().min(1, "topic must not be empty").max(200, "topic must be 200 characters or fewer"),
5859
- description: z10.string().max(2e3).optional()
5928
+ missingContent: z11.array(
5929
+ z11.object({
5930
+ topic: z11.string().min(1, "topic must not be empty").max(200, "topic must be 200 characters or fewer"),
5931
+ description: z11.string().max(2e3).optional()
5860
5932
  })
5861
5933
  ).max(20).optional().describe(
5862
5934
  "Array of specific pieces of content the agent expected to find but did not. One entry per distinct topic. Each entry has a short `topic` and optional longer `description`."
5863
5935
  ),
5864
- querySuggestions: z10.string().max(2e3).optional()
5936
+ querySuggestions: z11.string().max(2e3).optional()
5865
5937
  }),
5866
5938
  execute: async (args2, { session, log, client: mcpClient }) => {
5867
5939
  const origin = requestOrigin(mcpClient, session);
@@ -5953,30 +6025,30 @@ if (alexandriaFeedbackAvailable()) {
5953
6025
  openWorldHint: true,
5954
6026
  // Feedback is tied to jobs that processed open-web URLs.
5955
6027
  destructiveHint: false
5956
- // Additive only; submits ratings and notes, does not delete jobs or external content.
6028
+ // Additive only; submits ratings and notes and may refund credits, does not delete jobs or external content.
5957
6029
  },
5958
6030
  description: `
5959
6031
  Submit concise quality feedback for a completed search, scrape, parse, or map job. Provide the endpoint, job ID, rating, and relevant issue codes or small contextual fields; omit large page contents and raw outputs.
5960
6032
 
5961
- For an Alexandria session, set endpoint to \`alexandria\`, omit jobId, and provide requestedWebsite (url and requestedFunctionality), objective, rationale, and rating. objective is the underlying goal behind the session: what you or your user were ultimately trying to accomplish (for example, "shortlist federal IT contracts to bid on this quarter"), not only what was needed from this website. Optional providerFeedback and capabilityFeedback describe gaps or errors. Capability issues: new_capability_request (requires requestedFunctionality), missing_capability, insufficient_functionality, incorrect_result, execution_error, other. Alexandria feedback has no job-age deadline and no credit refund.
6033
+ For an Alexandria session, set endpoint to \`alexandria\`, omit jobId, and provide requestedWebsite (url and requestedFunctionality), objective, rationale, and rating. objective is the underlying goal behind the session: what you or your user were ultimately trying to accomplish (for example, "shortlist federal IT contracts to bid on this quarter"), not only what was needed from this website. Optional providerFeedback and capabilityFeedback describe gaps or errors. Capability issues: new_capability_request (requires requestedFunctionality), missing_capability, insufficient_functionality, incorrect_result, execution_error, other. Alexandria feedback must arrive within about 2 minutes of the team's latest Alexandria search, discovery, or execution; later feedback is rejected. Eligible feedback can refund 1 credit; refunds are subject to daily caps per website and per team.
5962
6034
 
5963
6035
  Returns submission status, feedback ID, and accounting fields.
5964
6036
  `,
5965
6037
  outputSchema: feedbackOutputSchema,
5966
- parameters: z10.object({
5967
- endpoint: z10.enum(["search", "scrape", "parse", "map", "alexandria"]),
5968
- jobId: z10.string().uuid("jobId must be the UUID returned by Firecrawl").optional(),
6038
+ parameters: z11.object({
6039
+ endpoint: z11.enum(["search", "scrape", "parse", "map", "alexandria"]),
6040
+ jobId: z11.string().uuid("jobId must be the UUID returned by Firecrawl").optional(),
5969
6041
  ...alexandriaFeedbackFields,
5970
- rating: z10.enum(["good", "bad", "partial"]),
5971
- issues: z10.array(feedbackIssueSchema).max(20).optional(),
5972
- tags: z10.array(feedbackIssueSchema).max(20).optional(),
5973
- note: z10.string().max(4e3).optional(),
5974
- valuableSources: z10.array(valuableSourceSchema).max(50).optional(),
5975
- missingContent: z10.array(missingContentSchema).max(50).optional(),
5976
- querySuggestions: z10.string().max(2e3).optional(),
5977
- url: z10.string().url().optional(),
5978
- pageNumbers: z10.array(z10.number().int().positive()).max(100).optional(),
5979
- metadata: z10.record(z10.string(), z10.unknown()).optional()
6042
+ rating: z11.enum(["good", "bad", "partial"]),
6043
+ issues: z11.array(feedbackIssueSchema).max(20).optional(),
6044
+ tags: z11.array(feedbackIssueSchema).max(20).optional(),
6045
+ note: z11.string().max(4e3).optional(),
6046
+ valuableSources: z11.array(valuableSourceSchema).max(50).optional(),
6047
+ missingContent: z11.array(missingContentSchema).max(50).optional(),
6048
+ querySuggestions: z11.string().max(2e3).optional(),
6049
+ url: z11.string().url().optional(),
6050
+ pageNumbers: z11.array(z11.number().int().positive()).max(100).optional(),
6051
+ metadata: z11.record(z11.string(), z11.unknown()).optional()
5980
6052
  }).superRefine((value, ctx) => {
5981
6053
  if (value.endpoint === "alexandria") {
5982
6054
  const parsed = alexandriaSessionFeedbackSchema.safeParse(value);
@@ -6088,25 +6160,25 @@ Start a multi-page crawl at a website URL, poll it to a terminal state, and retu
6088
6160
 
6089
6161
  Crawl results can be large; use conservative limits when full-site coverage is unnecessary. Webhooks and interactive scrape actions are unavailable in safe mode. Returns the crawl ID, status, and page data.
6090
6162
  `,
6091
- parameters: z10.object({
6092
- url: z10.string(),
6093
- prompt: z10.string().optional(),
6094
- excludePaths: z10.array(z10.string()).optional(),
6095
- includePaths: z10.array(z10.string()).optional(),
6096
- maxDiscoveryDepth: z10.number().optional(),
6097
- sitemap: z10.enum(["skip", "include", "only"]).optional(),
6098
- limit: z10.number().optional(),
6099
- allowExternalLinks: z10.boolean().optional(),
6100
- allowSubdomains: z10.boolean().optional(),
6101
- crawlEntireDomain: z10.boolean().optional(),
6102
- delay: z10.number().optional(),
6103
- maxConcurrency: z10.number().optional(),
6163
+ parameters: z11.object({
6164
+ url: z11.string(),
6165
+ prompt: z11.string().optional(),
6166
+ excludePaths: z11.array(z11.string()).optional(),
6167
+ includePaths: z11.array(z11.string()).optional(),
6168
+ maxDiscoveryDepth: z11.number().optional(),
6169
+ sitemap: z11.enum(["skip", "include", "only"]).optional(),
6170
+ limit: z11.number().optional(),
6171
+ allowExternalLinks: z11.boolean().optional(),
6172
+ allowSubdomains: z11.boolean().optional(),
6173
+ crawlEntireDomain: z11.boolean().optional(),
6174
+ delay: z11.number().optional(),
6175
+ maxConcurrency: z11.number().optional(),
6104
6176
  ...SAFE_MODE ? {} : {
6105
- webhook: z10.string().optional(),
6106
- webhookHeaders: z10.record(z10.string(), z10.string()).optional()
6177
+ webhook: z11.string().optional(),
6178
+ webhookHeaders: z11.record(z11.string(), z11.string()).optional()
6107
6179
  },
6108
- deduplicateSimilarURLs: z10.boolean().optional(),
6109
- ignoreQueryParameters: z10.boolean().optional(),
6180
+ deduplicateSimilarURLs: z11.boolean().optional(),
6181
+ ignoreQueryParameters: z11.boolean().optional(),
6110
6182
  scrapeOptions: scrapeParamsSchema.omit({ url: true }).partial().optional()
6111
6183
  }),
6112
6184
  outputSchema: crawlOutputSchema,
@@ -6163,7 +6235,7 @@ server.addTool({
6163
6235
  Retrieve the current status, progress, and available results for an existing crawl ID. This only reads Firecrawl job state and does not start or modify the crawl.
6164
6236
  `,
6165
6237
  outputSchema: crawlOutputSchema,
6166
- parameters: z10.object({ id: z10.string() }),
6238
+ parameters: z11.object({ id: z11.string() }),
6167
6239
  execute: async (args2, {
6168
6240
  session,
6169
6241
  client: mcpClient
@@ -6190,13 +6262,13 @@ server.addTool({
6190
6262
  Deprecated compatibility entry point. Use firecrawl_scrape once per known URL with formats: ["json"] and jsonOptions containing the prompt and schema. Use firecrawl_agent for multi-source research when the URLs are not known or the data spans several sites.
6191
6263
  `,
6192
6264
  outputSchema: deprecatedToolOutputSchema,
6193
- parameters: z10.object({
6194
- urls: z10.array(z10.string()),
6195
- prompt: z10.string().optional(),
6196
- schema: z10.record(z10.string(), z10.any()).optional(),
6197
- allowExternalLinks: z10.boolean().optional(),
6198
- enableWebSearch: z10.boolean().optional(),
6199
- includeSubdomains: z10.boolean().optional()
6265
+ parameters: z11.object({
6266
+ urls: z11.array(z11.string()),
6267
+ prompt: z11.string().optional(),
6268
+ schema: z11.record(z11.string(), z11.any()).optional(),
6269
+ allowExternalLinks: z11.boolean().optional(),
6270
+ enableWebSearch: z11.boolean().optional(),
6271
+ includeSubdomains: z11.boolean().optional()
6200
6272
  }),
6201
6273
  canList: () => false,
6202
6274
  beforeValidate: () => {
@@ -6212,24 +6284,24 @@ Deprecated compatibility entry point. Use firecrawl_scrape once per known URL wi
6212
6284
  throw new UserError(payload.message, payload);
6213
6285
  }
6214
6286
  });
6215
- var agentExchangeSchema = z10.strictObject({
6216
- enabled: z10.boolean().optional().describe("Let the agent call Alexandria providers. On by default."),
6217
- toolkits: z10.array(z10.string()).max(5).optional().describe("Pin up to 5 providers the agent may use, by slug. Omitted means the whole catalog."),
6218
- maxCalls: z10.number().int().min(1).max(30).optional().describe("Most provider calls the agent may make in this turn."),
6219
- requireApproval: z10.boolean().optional().describe(
6287
+ var agentExchangeSchema = z11.strictObject({
6288
+ enabled: z11.boolean().optional().describe("Let the agent call Alexandria providers. On by default."),
6289
+ toolkits: z11.array(z11.string()).max(5).optional().describe("Pin up to 5 providers the agent may use, by slug. Omitted means the whole catalog."),
6290
+ maxCalls: z11.number().int().min(1).max(30).optional().describe("Most provider calls the agent may make in this turn."),
6291
+ requireApproval: z11.boolean().optional().describe(
6220
6292
  'End the turn with a paid-call pendingApproval before any paid provider call. Requires mode "chat" on the same request, even on a follow-up.'
6221
6293
  ),
6222
- approve: z10.strictObject({
6223
- approvalId: z10.string().uuid(),
6224
- callIds: z10.array(z10.string()).optional(),
6225
- always: z10.boolean().optional()
6294
+ approve: z11.strictObject({
6295
+ approvalId: z11.string().uuid(),
6296
+ callIds: z11.array(z11.string()).optional(),
6297
+ always: z11.boolean().optional()
6226
6298
  }).optional().describe(
6227
6299
  "Answer yes to the pendingApproval the previous turn of this thread ended on (its id, also exchange.requiresAction.approvalId). Needs threadId. For a terms offer, send it only after an organization admin confirms acceptance in the Firecrawl dashboard; this does not accept terms. callIds and always are ignored on terms offers. For paid calls, callIds picks a subset (default all) and always stops asking for the rest of the thread."
6228
6300
  ),
6229
- decline: z10.strictObject({ approvalId: z10.string().uuid() }).optional().describe(
6301
+ decline: z11.strictObject({ approvalId: z11.string().uuid() }).optional().describe(
6230
6302
  "Answer no to that pendingApproval. Needs threadId. A declined terms offer keeps those providers out of the rest of the thread."
6231
6303
  ),
6232
- onTermsRequired: z10.enum(["skip", "ask"]).optional().describe(
6304
+ onTermsRequired: z11.enum(["skip", "ask"]).optional().describe(
6233
6305
  `What to do when a provider the agent would use needs data terms the team has not accepted. Gated providers are never called. "skip" (default): answer with accepted providers and list the rest in exchange.skippedProviders. "ask": the same, plus a terms pendingApproval and exchange.requiresAction. Read terms with terms/show; an organization admin accepts them in the Firecrawl dashboard. There is no auto-accept. Omitted on a follow-up keeps the previous turn's value.`
6234
6306
  )
6235
6307
  }).describe(
@@ -6256,21 +6328,21 @@ The job also returns a \`threadId\`. To continue that thread, pass it with a fol
6256
6328
  The agent only calls Alexandria providers whose terms the team has accepted. \`exchange.skippedProviders\` lists gated providers. With \`exchange.onTermsRequired\` "ask", a terms \`pendingApproval\` and \`exchange.requiresAction\` carry the \`approvalId\` and provider requirements. Read terms/show through \`firecrawl_scrape\`. An organization admin must accept terms in the Firecrawl dashboard at the provider URL or ${DATA_SOURCES_SETTINGS_URL}. Ignore any terms/accept call in the API response. Only after the admin confirms acceptance, resume with the same \`threadId\` and \`exchange.approve: {approvalId}\`; this does not accept terms. To decline, use \`exchange.decline: {approvalId}\`. Never infer acceptance from a data request.
6257
6329
  `,
6258
6330
  outputSchema: agentOutputSchema,
6259
- parameters: z10.object({
6260
- prompt: z10.string().min(1).max(1e4),
6261
- urls: z10.array(z10.string().url()).optional(),
6262
- schema: z10.record(z10.string(), z10.any()).optional(),
6263
- effort: z10.enum(["low", "medium", "high"]).optional().describe("Reasoning budget for the agent task."),
6264
- maxCredits: z10.number().int().positive().optional().describe(
6331
+ parameters: z11.object({
6332
+ prompt: z11.string().min(1).max(1e4),
6333
+ urls: z11.array(z11.string().url()).optional(),
6334
+ schema: z11.record(z11.string(), z11.any()).optional(),
6335
+ effort: z11.enum(["low", "medium", "high"]).optional().describe("Reasoning budget for the agent task."),
6336
+ maxCredits: z11.number().int().positive().optional().describe(
6265
6337
  "Spending limit in credits for this run. Defaults to 2500 on the API."
6266
6338
  ),
6267
- strictConstrainToURLs: z10.boolean().optional().describe(
6339
+ strictConstrainToURLs: z11.boolean().optional().describe(
6268
6340
  "If true, agent will only visit URLs provided in the urls array."
6269
6341
  ),
6270
- threadId: z10.string().uuid().optional().describe(
6342
+ threadId: z11.string().uuid().optional().describe(
6271
6343
  "Continue this thread: the threadId from an earlier firecrawl_agent or firecrawl_agent_status result. Omit to start a new thread."
6272
6344
  ),
6273
- mode: z10.enum(["extract", "chat"]).optional().describe(
6345
+ mode: z11.enum(["extract", "chat"]).optional().describe(
6274
6346
  `"extract" (default) returns the complete structured result every turn. "chat" lets a follow-up that asks no new data get a short reply in message instead of a re-run; required for exchange.requireApproval. Omitted on a follow-up keeps the previous turn's mode.`
6275
6347
  ),
6276
6348
  exchange: agentExchangeSchema.optional()
@@ -6340,7 +6412,7 @@ Retrieve progress or final results for a \`firecrawl_agent\` job ID. A \`process
6340
6412
  Returns job status, progress information, and result data when completed.
6341
6413
  `,
6342
6414
  outputSchema: agentStatusOutputSchema,
6343
- parameters: z10.object({ id: z10.string() }),
6415
+ parameters: z11.object({ id: z11.string() }),
6344
6416
  execute: async (args2, { session, log, client: mcpClient }) => {
6345
6417
  const client = getClient(session);
6346
6418
  const { id } = args2;
@@ -6401,13 +6473,13 @@ Open or reuse a live browser session to navigate a page, click controls, fill fi
6401
6473
  This acts on the live site, so actions such as form submission can create persistent external side effects. Returns execution output, stdout/stderr, exit status, and session viewing URLs.
6402
6474
  `,
6403
6475
  outputSchema: interactOutputSchema,
6404
- parameters: z10.object({
6405
- scrapeId: z10.string().trim().min(1).optional(),
6406
- url: z10.string().trim().url().optional(),
6407
- prompt: z10.string().trim().min(1).optional(),
6408
- code: z10.string().trim().min(1).optional(),
6409
- language: z10.enum(["bash", "python", "node"]).optional(),
6410
- timeout: z10.number().min(1).max(300).optional(),
6476
+ parameters: z11.object({
6477
+ scrapeId: z11.string().trim().min(1).optional(),
6478
+ url: z11.string().trim().url().optional(),
6479
+ prompt: z11.string().trim().min(1).optional(),
6480
+ code: z11.string().trim().min(1).optional(),
6481
+ language: z11.enum(["bash", "python", "node"]).optional(),
6482
+ timeout: z11.number().min(1).max(300).optional(),
6411
6483
  scrapeOptions: scrapeParamsSchema.omit({ url: true }).partial().optional()
6412
6484
  }).refine((data) => Boolean(data.scrapeId) !== Boolean(data.url), {
6413
6485
  message: "Provide either 'url' (interact directly) or 'scrapeId' (reuse a previous scrape), not both."
@@ -6486,8 +6558,8 @@ server.addTool({
6486
6558
  Stop the live interact session associated with a \`scrapeId\` and release its resources. Returns a success confirmation.
6487
6559
  `,
6488
6560
  outputSchema: interactStopOutputSchema,
6489
- parameters: z10.object({
6490
- scrapeId: z10.string()
6561
+ parameters: z11.object({
6562
+ scrapeId: z11.string()
6491
6563
  }),
6492
6564
  execute: async (args2, { session, log, client: mcpClient }) => {
6493
6565
  const client = getClient(session);
@@ -6602,16 +6674,18 @@ function registerMarketplaceSearchTool(registrar, getClientFn) {
6602
6674
  destructiveHint: false
6603
6675
  },
6604
6676
  description: `
6605
- Search web and specialized indexes, returning ranked results with query-relevant highlights. Each web result is a title, URL, and description. Operators include quoted phrases, \`-term\`, \`site:host\`, \`inurl:term\`, \`intitle:term\`, and \`related:host\`; the set is non-exhaustive. \`includeDomains\` and \`excludeDomains\` are mutually exclusive hostname filters; categories limit result types to \`research\`, \`pdf\`, or \`developer\`.
6677
+ Search web and specialized indexes, returning ranked results with query-relevant highlights. Each web result is a title, URL, and description. Operators include quoted phrases, \`-term\`, \`site:host\`, \`inurl:term\`, \`intitle:term\`, and \`related:host\`; the set is non-exhaustive. \`includeDomains\` and \`excludeDomains\` are mutually exclusive hostname filters; categories limit result types to \`research\`, \`pdf\`, \`developer\`, or \`gov\`.
6606
6678
 
6607
6679
  For a programming question, add \`categories: ["developer"]\`. It searches an index of public repositories, GitHub issues, merged pull requests, repository READMEs, and code documentation, and returns the results in \`data.web\` with \`category: "developer"\`.
6608
6680
 
6681
+ For a legal or regulatory question, \`categories: ["gov"]\` returns results in \`data.web\` with \`category: "gov"\` and cannot be combined with other categories; \`firecrawl_gov_search\` is the dedicated tool.
6682
+
6609
6683
  ${ALEXANDRIA_SEARCH_INSTRUCTIONS}
6610
6684
 
6611
6685
  Returns result groups in \`data\` and an operation \`id\`.
6612
6686
  `,
6613
6687
  outputSchema: searchOutputSchema,
6614
- parameters: z10.object({ ...searchToolBaseFields }).strict().refine(searchDomainsAreExclusive, SEARCH_DOMAINS_CONFLICT_MESSAGE).refine(
6688
+ parameters: z11.object({ ...searchToolBaseFields }).strict().refine(searchDomainsAreExclusive, SEARCH_DOMAINS_CONFLICT_MESSAGE).refine(
6615
6689
  searchQueryIsValid,
6616
6690
  "A query is required. Use firecrawl_find_tools to browse the catalogue."
6617
6691
  ),
@@ -6691,6 +6765,7 @@ if (process.env.CLOUD_SERVICE === "true" || process.env.SSE_LOCAL === "true" ||
6691
6765
  registerMonitorTools(server);
6692
6766
  registerResearchTools(server, getClient);
6693
6767
  registerDeveloperTools(server, getClient);
6768
+ registerGovTools(server, getClient);
6694
6769
  registerUsageTools(server, getClient);
6695
6770
  if (process.env.CLOUD_SERVICE === "true" && primaryProfile.allowKeyless && !normalizeHeader(process.env.KEYLESS_PROXY_SECRET)) {
6696
6771
  console.warn(
@@ -6725,6 +6800,7 @@ if (searchProfileEnabled) {
6725
6800
  };
6726
6801
  registerResearchTools(searchRegistrar, getClient);
6727
6802
  registerDeveloperTools(searchRegistrar, getClient);
6803
+ registerGovTools(searchRegistrar, getClient);
6728
6804
  registerMarketplaceSearchTool(searchRegistrar, getClient);
6729
6805
  searchRegistrar.addTool(searchSurfaceFindToolsTool);
6730
6806
  searchRegistrar.addTool(searchSurfaceScrapeTool);