firecrawl-mcp 3.29.1 → 3.30.0

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.
package/dist/server.js CHANGED
@@ -80,7 +80,7 @@ var alexandriaSessionFeedbackSchema = z.strictObject({
80
80
  // src/server.ts
81
81
  import FirecrawlApp from "firecrawl";
82
82
 
83
- // node_modules/.pnpm/fastmcp@4.3.2_patch_hash=08f77b633292d9ae4cb022c0fa5bd722dbd5c1aaaad600204f8ed38339bfd37b/node_modules/fastmcp/dist/chunk-LWU5CQGW.js
83
+ // node_modules/.pnpm/fastmcp@4.3.2_patch_hash=37f9a424ae5b0b6202b2b16109a1ea88b69cdcda5407f13eda6654a56489ad70/node_modules/fastmcp/dist/chunk-LWU5CQGW.js
84
84
  import { Server } from "@modelcontextprotocol/sdk/server/index.js";
85
85
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
86
86
  import {
@@ -884,6 +884,7 @@ ${error2 instanceof Error ? error2.stack : JSON.stringify(error2)}`
884
884
  // Top-level Tool.title (MCP 2025-06-18). Clients such as Codex index this
885
885
  // for tool search and do not read annotations.title.
886
886
  ...tool.annotations?.title && { title: tool.annotations.title },
887
+ ...tool.icons && { icons: tool.icons },
887
888
  description: tool.description,
888
889
  inputSchema: tool.parameters ? strictJsonSchema(await toJsonSchema(tool.parameters)) : {
889
890
  additionalProperties: false,
@@ -2059,7 +2060,7 @@ var FastMCP = class extends FastMCPEventEmitter {
2059
2060
  }
2060
2061
  };
2061
2062
 
2062
- // node_modules/.pnpm/fastmcp@4.3.2_patch_hash=08f77b633292d9ae4cb022c0fa5bd722dbd5c1aaaad600204f8ed38339bfd37b/node_modules/fastmcp/dist/chunk-OJG4XYXA.js
2063
+ // node_modules/.pnpm/fastmcp@4.3.2_patch_hash=37f9a424ae5b0b6202b2b16109a1ea88b69cdcda5407f13eda6654a56489ad70/node_modules/fastmcp/dist/chunk-OJG4XYXA.js
2063
2064
  import { z as z3 } from "zod";
2064
2065
  import { createHmac as createHmac2, pbkdf2, randomBytes } from "crypto";
2065
2066
  import { promisify } from "util";
@@ -2072,45 +2073,6 @@ import { randomUUID as randomUUID2 } from "crypto";
2072
2073
  import path from "path";
2073
2074
  import { z as z12 } from "zod";
2074
2075
 
2075
- // src/agent-hints.ts
2076
- var AGENT_HINTS_HEADERS = { "X-Firecrawl-Agent-Hints": "true" };
2077
- function readAgentHints(value) {
2078
- if (!value || typeof value !== "object") return void 0;
2079
- const hints = value.agent_hints;
2080
- return Array.isArray(hints) && hints.every((hint) => typeof hint === "string") ? hints : void 0;
2081
- }
2082
- function preserveAgentHints(data, envelope) {
2083
- const hints = readAgentHints(envelope);
2084
- if (!hints) return data;
2085
- return data && typeof data === "object" && !Array.isArray(data) ? { ...data, agent_hints: hints } : { data, agent_hints: hints };
2086
- }
2087
- function agentHintsText(hints) {
2088
- return `Firecrawl API agent_hints (response guidance, separate from page content):
2089
- ${JSON.stringify(hints, null, 2)}`;
2090
- }
2091
- function withAgentHints(result, response, separateText = false) {
2092
- const hints = readAgentHints(response);
2093
- if (!hints) return result;
2094
- return {
2095
- ...result,
2096
- content: separateText && hints.length ? [...result.content, { type: "text", text: agentHintsText(hints) }] : result.content,
2097
- structuredContent: { ...result.structuredContent, agent_hints: hints }
2098
- };
2099
- }
2100
- function readErrorAgentHints(error2) {
2101
- const hints = readAgentHints(error2);
2102
- if (hints) return hints;
2103
- if (!error2 || typeof error2 !== "object") return void 0;
2104
- const extras = error2.extras;
2105
- const extrasHints = readAgentHints(extras);
2106
- if (extrasHints) return extrasHints;
2107
- const details = error2.details;
2108
- const detailsHints = readAgentHints(details);
2109
- if (detailsHints) return detailsHints;
2110
- const response = error2.response;
2111
- return readAgentHints(response?.data);
2112
- }
2113
-
2114
2076
  // src/tool-output.ts
2115
2077
  import { z as z4 } from "zod";
2116
2078
  function isRecord(value) {
@@ -2139,9 +2101,6 @@ var unknown = (description) => z4.unknown().optional().describe(description);
2139
2101
  var success = bool("Whether the API call succeeded.");
2140
2102
  var error = unknown("Error message or error object when the call did not succeed.");
2141
2103
  var warning = str("Non-fatal warning about the result.");
2142
- var agentHints = {
2143
- agent_hints: z4.array(z4.string()).optional().describe("Optional response guidance from the Firecrawl API.")
2144
- };
2145
2104
  var alexandriaEnvelope = {
2146
2105
  requestId: str("Identifier of this Alexandria execution."),
2147
2106
  scrape_id: str("Identifier of the underlying scrape."),
@@ -2159,7 +2118,6 @@ var alexandriaEnvelope = {
2159
2118
  feedbackTool: unknown("Pointer to the feedback tool for reporting how this result served the task.")
2160
2119
  };
2161
2120
  var scrapeOutputSchema = z4.object({
2162
- ...agentHints,
2163
2121
  // URL mode: the scraped document, with the formats that were requested.
2164
2122
  markdown: str("Page content as markdown."),
2165
2123
  html: str("Processed HTML of the page."),
@@ -2191,7 +2149,6 @@ var scrapeOutputSchema = z4.object({
2191
2149
  ...alexandriaEnvelope
2192
2150
  }).describe("A scraped document, or the Alexandria execution envelope when `alexandria` was passed.");
2193
2151
  var mapOutputSchema = z4.object({
2194
- ...agentHints,
2195
2152
  links: unknown("URLs discovered under the website."),
2196
2153
  success,
2197
2154
  error,
@@ -2199,7 +2156,6 @@ var mapOutputSchema = z4.object({
2199
2156
  id: str("Identifier of the map run, for optional map feedback.")
2200
2157
  }).describe("URLs indexed under the requested website.");
2201
2158
  var searchOutputSchema = z4.object({
2202
- ...agentHints,
2203
2159
  success,
2204
2160
  data: unknown("Ranked results grouped by source, such as `web`, `news`, `images`, and `alexandria`."),
2205
2161
  error,
@@ -2211,14 +2167,12 @@ var searchOutputSchema = z4.object({
2211
2167
  feedbackTool: unknown("Pointer to the feedback tool for this search.")
2212
2168
  }).describe("Ranked search results grouped by source.");
2213
2169
  var findToolsOutputSchema = z4.object({
2214
- ...agentHints,
2215
2170
  success,
2216
2171
  data: unknown("Discovery page in `data.alexandria[0].data`, with `level`, `items`, `total`, and an optional `nextTool`."),
2217
2172
  error,
2218
2173
  ...alexandriaEnvelope
2219
2174
  }).describe("One page of the Alexandria catalogue: categories, providers, tools, or one contract.");
2220
2175
  var feedbackOutputSchema = z4.object({
2221
- ...agentHints,
2222
2176
  success,
2223
2177
  error,
2224
2178
  status: num("HTTP status when the submission was rejected."),
@@ -2237,7 +2191,6 @@ var feedbackOutputSchema = z4.object({
2237
2191
  raw: str("Response body when it was not JSON.")
2238
2192
  }).describe("Result of submitting feedback.");
2239
2193
  var crawlOutputSchema = z4.object({
2240
- ...agentHints,
2241
2194
  success,
2242
2195
  error,
2243
2196
  warning,
@@ -2252,7 +2205,6 @@ var crawlOutputSchema = z4.object({
2252
2205
  data: unknown("Scraped documents collected by the crawl.")
2253
2206
  }).describe("Crawl job state and the documents collected so far.");
2254
2207
  var agentOutputSchema = z4.object({
2255
- ...agentHints,
2256
2208
  success,
2257
2209
  error,
2258
2210
  id: str("Agent job identifier, for `firecrawl_agent_status`."),
@@ -2261,7 +2213,6 @@ var agentOutputSchema = z4.object({
2261
2213
  threadTurn: num("Turn number of this job within its thread.")
2262
2214
  }).describe("The queued research job. The result is read with `firecrawl_agent_status`.");
2263
2215
  var agentStatusOutputSchema = z4.object({
2264
- ...agentHints,
2265
2216
  success,
2266
2217
  error,
2267
2218
  id: str("Agent job identifier."),
@@ -2289,7 +2240,6 @@ var agentStatusOutputSchema = z4.object({
2289
2240
  )
2290
2241
  }).describe("Progress or final result of a research agent job.");
2291
2242
  var interactOutputSchema = z4.object({
2292
- ...agentHints,
2293
2243
  success,
2294
2244
  error: unknown("Why the interaction or the session could not run."),
2295
2245
  url: str("The URL the session was opened from, when opening failed."),
@@ -2304,14 +2254,12 @@ var interactOutputSchema = z4.object({
2304
2254
  liveUrl: str("URL for viewing the live session.")
2305
2255
  }).describe("Result of a browser interaction, with the session identifier to continue or stop it.");
2306
2256
  var interactStopOutputSchema = z4.object({
2307
- ...agentHints,
2308
2257
  success,
2309
2258
  error,
2310
2259
  message: str("Confirmation that the session was stopped."),
2311
2260
  scrapeId: str("Session that was stopped.")
2312
2261
  }).describe("Confirmation that the interact session was stopped.");
2313
2262
  var parseOutputSchema = z4.object({
2314
- ...agentHints,
2315
2263
  success,
2316
2264
  error,
2317
2265
  warning,
@@ -2339,39 +2287,33 @@ var deprecatedToolOutputSchema = z4.object({
2339
2287
  docs_url: str("Documentation for the replacement.")
2340
2288
  }).describe("A pointer to the replacement tool. This entry point is deprecated and always errors.");
2341
2289
  var monitorOutputSchema = z4.object({
2342
- ...agentHints,
2343
2290
  success,
2344
2291
  error,
2345
2292
  data: unknown("The monitor record: configuration, schedule, targets, and current state.")
2346
2293
  }).describe("One monitor record.");
2347
2294
  var monitorListOutputSchema = z4.object({
2348
- ...agentHints,
2349
2295
  success,
2350
2296
  error,
2351
2297
  data: unknown("One page of monitor records."),
2352
2298
  pagination: unknown("Pagination metadata for the listing.")
2353
2299
  }).describe("One page of monitors for the authenticated account.");
2354
2300
  var monitorDeleteOutputSchema = z4.object({
2355
- ...agentHints,
2356
2301
  success,
2357
2302
  error,
2358
2303
  data: unknown("Deletion details, when the API returns any.")
2359
2304
  }).describe("Deletion status for the monitor.");
2360
2305
  var monitorRunOutputSchema = z4.object({
2361
- ...agentHints,
2362
2306
  success,
2363
2307
  error,
2364
2308
  data: unknown("The queued check.")
2365
2309
  }).describe("The check queued outside the monitor schedule.");
2366
2310
  var monitorChecksOutputSchema = z4.object({
2367
- ...agentHints,
2368
2311
  success,
2369
2312
  error,
2370
2313
  data: unknown("One page of check summaries."),
2371
2314
  pagination: unknown("Pagination metadata for the listing.")
2372
2315
  }).describe("One page of historical checks for the monitor.");
2373
2316
  var monitorCheckOutputSchema = z4.object({
2374
- ...agentHints,
2375
2317
  success,
2376
2318
  error,
2377
2319
  data: unknown("The check and its page-level results: each page reports `same`, `new`, `changed`, `removed`, or `error`, with diffs and any goal judgment."),
@@ -2390,25 +2332,20 @@ var paperSchema = z4.looseObject({
2390
2332
  updateDate: str("Date the paper was last updated.")
2391
2333
  });
2392
2334
  var researchSearchOutputSchema = z4.object({
2393
- ...agentHints,
2394
2335
  results: z4.array(paperSchema).describe("Ranked papers, in the order the text block lists them.")
2395
2336
  }).describe("Ranked papers with canonical IDs, titles, authors, and abstracts.");
2396
2337
  var researchPaperOutputSchema = z4.object({
2397
- ...agentHints,
2398
2338
  paper: paperSchema.optional().describe("Canonical metadata for the requested paper, absent when it was not found.")
2399
2339
  }).describe("Canonical metadata for one paper.");
2400
2340
  var researchRelatedOutputSchema = z4.object({
2401
- ...agentHints,
2402
2341
  results: z4.array(paperSchema).describe("Ranked citation-graph candidates."),
2403
2342
  poolSize: z4.number().describe("Number of candidates evaluated before ranking."),
2404
2343
  note: str("Note about how the candidates were produced.")
2405
2344
  }).describe("Ranked citation-graph candidates and the size of the evaluated pool.");
2406
2345
  var researchReadOutputSchema = z4.object({
2407
- ...agentHints,
2408
2346
  passages: z4.array(z4.looseObject({ text: str("Passage text.") })).describe("In-body passages relevant to the question; empty when no full text is indexed.")
2409
2347
  }).describe("Full-text passages from one paper.");
2410
2348
  var developerSearchOutputSchema = z4.object({
2411
- ...agentHints,
2412
2349
  results: z4.array(
2413
2350
  z4.looseObject({
2414
2351
  id: str("Stable result id, such as `issue:owner/repo#123` or `doc:<hash>`; its prefix gives the source type."),
@@ -2419,7 +2356,6 @@ var developerSearchOutputSchema = z4.object({
2419
2356
  ).describe("Ranked results, in the order the text block lists them.")
2420
2357
  }).describe("Ranked developer-index results with their matched passages.");
2421
2358
  var govSearchOutputSchema = z4.object({
2422
- ...agentHints,
2423
2359
  results: z4.array(
2424
2360
  z4.looseObject({
2425
2361
  url: str("Source URL."),
@@ -2668,7 +2604,7 @@ Returns ranked results with an ID, source type, URL, title, and the matched pass
2668
2604
  const client = getClient(session);
2669
2605
  const res = await client.http.get(`${BASE}?${params.toString()}`, originHeaders(requestOrigin(mcpClient, session)));
2670
2606
  const results = res.data?.results ?? [];
2671
- return withAgentHints(withStructured(fmtDeveloper(results), { results }), res.data, true);
2607
+ return withStructured(fmtDeveloper(results), { results });
2672
2608
  }
2673
2609
  });
2674
2610
  }
@@ -2717,11 +2653,7 @@ Returns ranked results with a position, title, URL, and matched snippet. Results
2717
2653
  originHeaders(requestOrigin(mcpClient, session))
2718
2654
  );
2719
2655
  const results = res.data?.data?.web ?? [];
2720
- return withAgentHints(
2721
- withStructured(fmtGov(results), { results }),
2722
- res.data,
2723
- true
2724
- );
2656
+ return withStructured(fmtGov(results), { results });
2725
2657
  }
2726
2658
  });
2727
2659
  }
@@ -2732,12 +2664,10 @@ import { z as z8 } from "zod";
2732
2664
  // src/core-http-error.ts
2733
2665
  var CoreHttpError = class extends Error {
2734
2666
  status;
2735
- agent_hints;
2736
- constructor(message, status, agentHints2) {
2667
+ constructor(message, status) {
2737
2668
  super(message);
2738
2669
  this.name = "CoreHttpError";
2739
2670
  this.status = status;
2740
- if (agentHints2 !== void 0) this.agent_hints = agentHints2;
2741
2671
  }
2742
2672
  };
2743
2673
 
@@ -2760,7 +2690,6 @@ async function monitorRequest(api, session, origin, path2, init = {}) {
2760
2690
  }
2761
2691
  const headers = {
2762
2692
  ...originHeaders(origin),
2763
- ...AGENT_HINTS_HEADERS,
2764
2693
  ...extraHeaders
2765
2694
  };
2766
2695
  if (apiKey) headers.Authorization = `Bearer ${apiKey}`;
@@ -2773,13 +2702,10 @@ async function monitorRequest(api, session, origin, path2, init = {}) {
2773
2702
  const payload = await response.json().catch(() => ({}));
2774
2703
  if (!response.ok || payload?.success === false) {
2775
2704
  const message = payload?.error || `HTTP ${response.status}: ${response.statusText || "Request failed"}`;
2776
- throw new CoreHttpError(message, response.status, readAgentHints(payload));
2705
+ throw new CoreHttpError(message, response.status);
2777
2706
  }
2778
2707
  return payload;
2779
2708
  }
2780
- function monitorResult(data) {
2781
- return withAgentHints(structuredText(data), data);
2782
- }
2783
2709
  var pageStatusSchema = z8.enum(["same", "new", "changed", "removed", "error"]);
2784
2710
  var checkStatusSchema = z8.enum([
2785
2711
  "queued",
@@ -2905,7 +2831,7 @@ In the simple form, a \`goal\` is required. If \`queries\` contains one or more
2905
2831
  body
2906
2832
  }
2907
2833
  );
2908
- return monitorResult(res);
2834
+ return structuredText(res);
2909
2835
  }
2910
2836
  });
2911
2837
  server.addTool({
@@ -2938,7 +2864,7 @@ List monitors for the authenticated account with optional pagination controls. R
2938
2864
  query: { limit, offset }
2939
2865
  }
2940
2866
  );
2941
- return monitorResult(res);
2867
+ return structuredText(res);
2942
2868
  }
2943
2869
  });
2944
2870
  server.addTool({
@@ -2965,7 +2891,7 @@ Retrieve one monitor by ID, including its configuration and current state. This
2965
2891
  requestOrigin(mcpClient, session),
2966
2892
  `/monitor/${encodeURIComponent(id)}`
2967
2893
  );
2968
- return monitorResult(res);
2894
+ return structuredText(res);
2969
2895
  }
2970
2896
  });
2971
2897
  server.addTool({
@@ -2998,7 +2924,7 @@ Returns the updated monitor.
2998
2924
  `/monitor/${encodeURIComponent(id)}`,
2999
2925
  { method: "PATCH", body }
3000
2926
  );
3001
- return monitorResult(res);
2927
+ return structuredText(res);
3002
2928
  }
3003
2929
  });
3004
2930
  server.addTool({
@@ -3027,7 +2953,7 @@ Permanently delete a monitor by ID and stop its future schedule. This operation
3027
2953
  `/monitor/${encodeURIComponent(id)}`,
3028
2954
  { method: "DELETE" }
3029
2955
  );
3030
- return monitorResult(res);
2956
+ return structuredText(res);
3031
2957
  }
3032
2958
  });
3033
2959
  server.addTool({
@@ -3055,7 +2981,7 @@ Queue an immediate check for a monitor outside its normal schedule. This starts
3055
2981
  `/monitor/${encodeURIComponent(id)}/run`,
3056
2982
  { method: "POST" }
3057
2983
  );
3058
- return monitorResult(res);
2984
+ return structuredText(res);
3059
2985
  }
3060
2986
  });
3061
2987
  server.addTool({
@@ -3088,7 +3014,7 @@ List historical checks for a monitor, optionally filtered by status and bounded
3088
3014
  `/monitor/${encodeURIComponent(id)}/checks`,
3089
3015
  { query: { limit, offset, status } }
3090
3016
  );
3091
- return monitorResult(res);
3017
+ return structuredText(res);
3092
3018
  }
3093
3019
  });
3094
3020
  server.addTool({
@@ -3124,7 +3050,7 @@ Markdown tracking returns a unified text diff, JSON tracking returns field paths
3124
3050
  `/monitor/${encodeURIComponent(id)}/checks/${encodeURIComponent(checkId)}`,
3125
3051
  { query: { limit, skip, status: pageStatus } }
3126
3052
  );
3127
- return monitorResult(res);
3053
+ return structuredText(res);
3128
3054
  }
3129
3055
  });
3130
3056
  }
@@ -3132,9 +3058,6 @@ Markdown tracking returns a unified text diff, JSON tracking returns field paths
3132
3058
  // src/research.ts
3133
3059
  import { z as z9 } from "zod";
3134
3060
  var BASE3 = "/v2/search/research";
3135
- function researchHeaders(origin) {
3136
- return { ...originHeaders(origin), ...AGENT_HINTS_HEADERS };
3137
- }
3138
3061
  function appendParam(params, key, value) {
3139
3062
  if (value == null) return;
3140
3063
  if (Array.isArray(value)) {
@@ -3279,10 +3202,10 @@ Returns ranked papers with canonical IDs, titles, authors, and abstracts.
3279
3202
  const client = getClient(session);
3280
3203
  const res = await client.http.get(
3281
3204
  withQuery(`${BASE3}/papers`, params),
3282
- researchHeaders(requestOrigin(mcpClient, session))
3205
+ originHeaders(requestOrigin(mcpClient, session))
3283
3206
  );
3284
3207
  const results = res.data?.results ?? [];
3285
- return withAgentHints(withStructured(fmtHits(results), { results }), res.data, true);
3208
+ return withStructured(fmtHits(results), { results });
3286
3209
  }
3287
3210
  });
3288
3211
  server.addTool({
@@ -3310,13 +3233,13 @@ Retrieve canonical metadata for one paper ID, such as an arXiv, PMC, PMID, or DO
3310
3233
  const client = getClient(session);
3311
3234
  const res = await client.http.get(
3312
3235
  `${BASE3}/papers/${encodeURIComponent(paperId)}`,
3313
- researchHeaders(requestOrigin(mcpClient, session))
3236
+ originHeaders(requestOrigin(mcpClient, session))
3314
3237
  );
3315
3238
  const paper = res.data?.paper;
3316
- return withAgentHints(withStructured(
3239
+ return withStructured(
3317
3240
  fmtPaperMetadata(paper),
3318
3241
  paper ? { paper } : {}
3319
- ), res.data, true);
3242
+ );
3320
3243
  }
3321
3244
  });
3322
3245
  server.addTool({
@@ -3358,17 +3281,17 @@ Returns ranked candidates and the evaluated pool size.
3358
3281
  `${BASE3}/papers/${encodeURIComponent(primary)}/similar`,
3359
3282
  params
3360
3283
  ),
3361
- researchHeaders(requestOrigin(mcpClient, session))
3284
+ originHeaders(requestOrigin(mcpClient, session))
3362
3285
  );
3363
3286
  const results = res.data?.results ?? [];
3364
3287
  const poolSize = res.data?.poolSize ?? 0;
3365
3288
  const note = res.data?.note ? `
3366
3289
  note: ${res.data.note}` : "";
3367
- return withAgentHints(withStructured(
3290
+ return withStructured(
3368
3291
  `${fmtHits(results)}
3369
3292
  (poolSize=${poolSize})${note}`,
3370
3293
  { results, poolSize, ...res.data?.note ? { note: res.data.note } : {} }
3371
- ), res.data, true);
3294
+ );
3372
3295
  }
3373
3296
  });
3374
3297
  server.addTool({
@@ -3403,13 +3326,13 @@ Returns matching passages or a notice when full text is unavailable.
3403
3326
  const client = getClient(session);
3404
3327
  const res = await client.http.get(
3405
3328
  withQuery(`${BASE3}/papers/${encodeURIComponent(paperId)}`, params),
3406
- researchHeaders(requestOrigin(mcpClient, session))
3329
+ originHeaders(requestOrigin(mcpClient, session))
3407
3330
  );
3408
3331
  const passages = res.data?.passages ?? [];
3409
- return withAgentHints(withStructured(
3332
+ return withStructured(
3410
3333
  passages.length ? passages.map((p) => p.text).join("\n---\n") : "(no full-text passages available for this paper)",
3411
3334
  { passages }
3412
- ), res.data, true);
3335
+ );
3413
3336
  }
3414
3337
  });
3415
3338
  server.addTool({
@@ -3635,20 +3558,6 @@ async function runWithCredentialRecovery(run, requestId, session) {
3635
3558
  return await run();
3636
3559
  } catch (error2) {
3637
3560
  if (session?.authType !== "api-key" || !isCoreCredentialRejection(error2, session)) {
3638
- const hints = readErrorAgentHints(error2);
3639
- if (hints) {
3640
- const message = error2 instanceof Error ? error2.message : String(error2);
3641
- throw new UserError(
3642
- hints.length ? `${message}
3643
-
3644
- ${agentHintsText(hints)}` : message,
3645
- {
3646
- ...error2 instanceof UserError ? error2.extras : {},
3647
- error: message,
3648
- agent_hints: hints
3649
- }
3650
- );
3651
- }
3652
3561
  throw error2;
3653
3562
  }
3654
3563
  const payload = recoveryPayload("CREDENTIAL_INVALID", requestId);
@@ -3707,8 +3616,6 @@ var searchDomainSchema = z11.string().trim().toLowerCase().min(1).max(253).regex
3707
3616
  var searchToolBaseFields = {
3708
3617
  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."),
3709
3618
  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."),
3710
- objective: z11.string().trim().min(1).max(5e3).optional().describe("Optional broader goal for this search, if known. Avoid sensitive information."),
3711
- clientModel: z11.string().trim().min(1).max(128).optional().describe("Optional model identifier, if known."),
3712
3619
  domainTools: z11.boolean().optional().describe(
3713
3620
  "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."
3714
3621
  ),
@@ -3774,7 +3681,7 @@ function termsRequiredAction(body) {
3774
3681
  url: action.url
3775
3682
  };
3776
3683
  }
3777
- function termsRequiredError(action, context, hints) {
3684
+ function termsRequiredError(action, context) {
3778
3685
  const requestId = context.requestId;
3779
3686
  const retryIdentity = requestId ? ` and requestId ${requestId}` : "";
3780
3687
  const message = `Alexandria provider terms required. An organization admin must accept the ${action.terms} provider's terms (version ${action.version}) before this request can run.`;
@@ -3789,7 +3696,6 @@ Do not retry until acceptance is confirmed.`,
3789
3696
  code: TERMS_REQUIRED_CODE,
3790
3697
  status: 403,
3791
3698
  message,
3792
- ...hints ? { agent_hints: hints } : {},
3793
3699
  ...requestId ? { requestId } : {},
3794
3700
  requiresAction: action,
3795
3701
  nextTool: {
@@ -3820,8 +3726,7 @@ Do not retry until acceptance is confirmed.`,
3820
3726
  function throwIfTermsRequired(error2, context) {
3821
3727
  const source = error2;
3822
3728
  const action = termsRequiredAction(source?.response?.data ?? source?.details);
3823
- if (action)
3824
- throw termsRequiredError(action, context, readErrorAgentHints(error2));
3729
+ if (action) throw termsRequiredError(action, context);
3825
3730
  }
3826
3731
  async function relayTermsRequired(run, context) {
3827
3732
  try {
@@ -3839,7 +3744,6 @@ async function relayExchangeError(run, context) {
3839
3744
  const response = error2?.response;
3840
3745
  if (!response || response.status === 401) throw error2;
3841
3746
  const data = response.data;
3842
- const hints = readErrorAgentHints(error2);
3843
3747
  const message = typeof data?.error === "string" ? data.error : `Alexandria request failed (HTTP ${response.status})`;
3844
3748
  const disabledProvider = response.status === 403 ? context.providers?.find((provider) => message === `Access to ${provider} is disabled for this organization.`) : void 0;
3845
3749
  if (disabledProvider) {
@@ -3849,7 +3753,6 @@ async function relayExchangeError(run, context) {
3849
3753
  code: typeof data?.code === "string" ? data.code : "exchange_error",
3850
3754
  status: 403,
3851
3755
  message,
3852
- ...hints ? { agent_hints: hints } : {},
3853
3756
  nextTool: {
3854
3757
  name: "firecrawl_scrape",
3855
3758
  arguments: {
@@ -3863,7 +3766,6 @@ async function relayExchangeError(run, context) {
3863
3766
  code: typeof data?.code === "string" ? data.code : "exchange_error",
3864
3767
  status: response.status,
3865
3768
  message,
3866
- ...hints ? { agent_hints: hints } : {},
3867
3769
  ...typeof data?.chargeId === "string" ? { chargeId: data.chargeId } : {}
3868
3770
  });
3869
3771
  }
@@ -3910,10 +3812,6 @@ function copySession(session) {
3910
3812
  Object.getOwnPropertyDescriptors(session ?? {})
3911
3813
  );
3912
3814
  }
3913
- function resultAgentHints(result) {
3914
- return result && typeof result === "object" ? readAgentHints(result.structuredContent) : void 0;
3915
- }
3916
- var warnedMissingAgentHintsInterceptor = false;
3917
3815
  var ConsoleLogger = class {
3918
3816
  constructor(shouldLog) {
3919
3817
  this.shouldLog = shouldLog;
@@ -4065,20 +3963,10 @@ function createFirecrawlMcpServer(options = {}) {
4065
3963
  requestId,
4066
3964
  session
4067
3965
  );
4068
- hooks.onToolResult?.({
4069
- ...call,
4070
- status: "success",
4071
- result,
4072
- agentHints: resultAgentHints(result)
4073
- });
3966
+ hooks.onToolResult?.({ ...call, status: "success", result });
4074
3967
  return result;
4075
3968
  } catch (error2) {
4076
- hooks.onToolResult?.({
4077
- ...call,
4078
- status: "error",
4079
- error: error2,
4080
- agentHints: readErrorAgentHints(error2)
4081
- });
3969
+ hooks.onToolResult?.({ ...call, status: "error", error: error2 });
4082
3970
  throw error2;
4083
3971
  }
4084
3972
  }
@@ -4109,44 +3997,7 @@ function createFirecrawlMcpServer(options = {}) {
4109
3997
  if (apiKey) {
4110
3998
  clientConfig.apiKey = apiKey;
4111
3999
  }
4112
- const client = new FirecrawlApp(clientConfig);
4113
- const axiosInstance = client.http?.instance;
4114
- if (axiosInstance?.interceptors?.request?.use) {
4115
- axiosInstance.interceptors.request.use((request) => {
4116
- if (typeof request.headers?.set === "function") {
4117
- request.headers.set("X-Firecrawl-Agent-Hints", "true");
4118
- } else {
4119
- request.headers = { ...request.headers ?? {}, ...AGENT_HINTS_HEADERS };
4120
- }
4121
- return request;
4122
- });
4123
- } else if (!warnedMissingAgentHintsInterceptor) {
4124
- warnedMissingAgentHintsInterceptor = true;
4125
- console.warn(
4126
- "[firecrawl-mcp] SDK request interceptor unavailable; API agent hints may be absent."
4127
- );
4128
- }
4129
- return client;
4130
- }
4131
- async function sdkResultWithAgentHints(client, execute) {
4132
- const responseInterceptors = client.http?.instance?.interceptors?.response;
4133
- if (!responseInterceptors?.use) return execute();
4134
- let hints;
4135
- const interceptor = responseInterceptors.use((response) => {
4136
- hints = readAgentHints(response?.data) ?? hints;
4137
- return response;
4138
- });
4139
- try {
4140
- const result = await execute();
4141
- return preserveAgentHints(result, { agent_hints: hints });
4142
- } catch (error2) {
4143
- if (hints && error2 && typeof error2 === "object" && !readErrorAgentHints(error2)) {
4144
- error2.agent_hints = hints;
4145
- }
4146
- throw error2;
4147
- } finally {
4148
- responseInterceptors.eject?.(interceptor);
4149
- }
4000
+ return new FirecrawlApp(clientConfig);
4150
4001
  }
4151
4002
  const SAFE_MODE = config.safeMode;
4152
4003
  function getClient(session) {
@@ -4499,7 +4350,6 @@ function createFirecrawlMcpServer(options = {}) {
4499
4350
  const response = await fetch(`${resolveApiBaseUrl()}${pathName}`, {
4500
4351
  method: "POST",
4501
4352
  headers: {
4502
- ...AGENT_HINTS_HEADERS,
4503
4353
  "Content-Type": "application/json",
4504
4354
  ...extraHeaders,
4505
4355
  Authorization: `Bearer ${apiKey}`,
@@ -4517,8 +4367,7 @@ function createFirecrawlMcpServer(options = {}) {
4517
4367
  if (!response.ok) {
4518
4368
  throw new CoreHttpError(
4519
4369
  parsed?.error || parsed?.message || `Firecrawl request failed (HTTP ${response.status})`,
4520
- response.status,
4521
- readAgentHints(parsed)
4370
+ response.status
4522
4371
  );
4523
4372
  }
4524
4373
  return parsed;
@@ -4600,7 +4449,6 @@ function createFirecrawlMcpServer(options = {}) {
4600
4449
  session,
4601
4450
  origin
4602
4451
  );
4603
- const uploadHints = readAgentHints(uploadJson);
4604
4452
  const upload = parseApiData(uploadJson);
4605
4453
  if (!upload?.uploadUrl || !upload?.uploadRef) {
4606
4454
  throw new Error(
@@ -4611,7 +4459,6 @@ function createFirecrawlMcpServer(options = {}) {
4611
4459
  const uploadForCommand = { ...upload, headers: uploadHeaders };
4612
4460
  return asText({
4613
4461
  success: true,
4614
- ...uploadHints ? { agent_hints: uploadHints } : {},
4615
4462
  mode: "hosted-upload-ref-awaiting-upload",
4616
4463
  message: "Hosted MCP cannot read local files. Run the local upload command, then call firecrawl_parse again with uploadRef. No Firecrawl API key is included in this command.",
4617
4464
  upload: {
@@ -4710,17 +4557,14 @@ Alexandria mode, on an authenticated session with Alexandria access: \`alexandri
4710
4557
  },
4711
4558
  session
4712
4559
  );
4713
- return structuredText(preserveAgentHints(json?.data ?? json, json));
4560
+ return structuredText(json?.data ?? json);
4714
4561
  }
4715
4562
  const client = getClient(session);
4716
4563
  const res = await relayTermsRequired(
4717
- () => sdkResultWithAgentHints(
4718
- client,
4719
- () => client.scrape(String(url), {
4720
- ...cleaned,
4721
- origin
4722
- })
4723
- ),
4564
+ () => client.scrape(String(url), {
4565
+ ...cleaned,
4566
+ origin
4567
+ }),
4724
4568
  { tool: "firecrawl_scrape" }
4725
4569
  );
4726
4570
  return structuredText(res);
@@ -4760,13 +4604,10 @@ Returns matching URLs rather than page bodies. Retrieve one page with \`firecraw
4760
4604
  const client = getClient(session);
4761
4605
  const cleaned = removeEmptyTopLevel(options2);
4762
4606
  log.info("Mapping URL", { url: String(url) });
4763
- const res = await sdkResultWithAgentHints(
4764
- client,
4765
- () => client.map(String(url), {
4766
- ...cleaned,
4767
- origin: requestOrigin(mcpClient, session)
4768
- })
4769
- );
4607
+ const res = await client.map(String(url), {
4608
+ ...cleaned,
4609
+ origin: requestOrigin(mcpClient, session)
4610
+ });
4770
4611
  return structuredText(res);
4771
4612
  }
4772
4613
  });
@@ -4946,7 +4787,6 @@ For a programming question, add \`categories: ["developer"]\`; its hits return i
4946
4787
  const origin = originOverride ?? (typeof body.origin === "string" && body.origin.length > 0 ? body.origin : requestOrigin(void 0, session));
4947
4788
  await hooks.beforeKeylessRequest?.(session, origin);
4948
4789
  const headers = {
4949
- ...AGENT_HINTS_HEADERS,
4950
4790
  ...originHeaders(origin),
4951
4791
  "Content-Type": "application/json",
4952
4792
  ...resolveOutbound(session).headers
@@ -4964,14 +4804,11 @@ For a programming question, add \`categories: ["developer"]\`; its hits return i
4964
4804
  retryAfterSeconds: Number.isFinite(json?.retry_after_seconds) && json.retry_after_seconds > 0 ? json.retry_after_seconds : void 0,
4965
4805
  signupUrl: keylessSignupUrlFrom(json?.signup_url)
4966
4806
  });
4967
- const hints = readAgentHints(json);
4968
- if (hints) payload.agent_hints = hints;
4969
4807
  throw new UserError2(String(payload.message), payload);
4970
4808
  }
4971
4809
  throw new CoreHttpError(
4972
4810
  json?.error || `Firecrawl request failed (HTTP ${response.status})`,
4973
- response.status,
4974
- readAgentHints(json)
4811
+ response.status
4975
4812
  );
4976
4813
  }
4977
4814
  return json;
@@ -4992,8 +4829,7 @@ For a programming question, add \`categories: ["developer"]\`; its hits return i
4992
4829
  creditsUsed: body.creditsUsed,
4993
4830
  expiresAt: body.expiresAt,
4994
4831
  next: body.next ?? null,
4995
- data: initialDocs,
4996
- ...readAgentHints(body) ? { agent_hints: readAgentHints(body) } : {}
4832
+ data: initialDocs
4997
4833
  };
4998
4834
  }
4999
4835
  const docs = initialDocs.slice();
@@ -5017,8 +4853,7 @@ For a programming question, add \`categories: ["developer"]\`; its hits return i
5017
4853
  creditsUsed: body.creditsUsed,
5018
4854
  expiresAt: body.expiresAt,
5019
4855
  next: null,
5020
- data: docs,
5021
- ...readAgentHints(body) ? { agent_hints: readAgentHints(body) } : {}
4856
+ data: docs
5022
4857
  };
5023
4858
  }
5024
4859
  async function waitForCrawlCompletionWithOrigin(client, jobId, origin, pollInterval = 2, timeout) {
@@ -5114,7 +4949,6 @@ Eligibility is limited to successful searches within the feedback age window. Th
5114
4949
  }
5115
4950
  if (querySuggestions) body.querySuggestions = querySuggestions;
5116
4951
  const headers = {
5117
- ...AGENT_HINTS_HEADERS,
5118
4952
  ...originHeaders(origin),
5119
4953
  "Content-Type": "application/json"
5120
4954
  };
@@ -5155,8 +4989,7 @@ Eligibility is limited to successful searches within the feedback age window. Th
5155
4989
  status: response.status,
5156
4990
  feedbackErrorCode: parsed?.feedbackErrorCode,
5157
4991
  error: parsed?.error ?? `HTTP ${response.status}`,
5158
- retryable: response.status >= 500,
5159
- ...readAgentHints(parsed) ? { agent_hints: readAgentHints(parsed) } : {}
4992
+ retryable: response.status >= 500
5160
4993
  });
5161
4994
  }
5162
4995
  return structuredText(parsed);
@@ -5240,7 +5073,6 @@ Returns submission status, feedback ID, and accounting fields.
5240
5073
  } = args;
5241
5074
  const apiBase = resolveApiBaseUrl();
5242
5075
  const headers = {
5243
- ...AGENT_HINTS_HEADERS,
5244
5076
  ...originHeaders(origin),
5245
5077
  "Content-Type": "application/json"
5246
5078
  };
@@ -5296,8 +5128,7 @@ Returns submission status, feedback ID, and accounting fields.
5296
5128
  status: response.status,
5297
5129
  feedbackErrorCode: parsed?.feedbackErrorCode,
5298
5130
  error: parsed?.error ?? `HTTP ${response.status}`,
5299
- retryable: response.status >= 500,
5300
- ...readAgentHints(parsed) ? { agent_hints: readAgentHints(parsed) } : {}
5131
+ retryable: response.status >= 500
5301
5132
  });
5302
5133
  }
5303
5134
  return structuredText(parsed);
@@ -5785,7 +5616,6 @@ Set \`redactPII\` to request redaction of personally identifiable information in
5785
5616
  form.append("file", blob, filename);
5786
5617
  form.append("options", JSON.stringify(optionsPayload));
5787
5618
  const headers = {
5788
- ...AGENT_HINTS_HEADERS,
5789
5619
  ...originHeaders(origin)
5790
5620
  };
5791
5621
  const outbound = resolveOutbound(session);
@@ -5807,15 +5637,9 @@ Set \`redactPII\` to request redaction of personally identifiable information in
5807
5637
  });
5808
5638
  const responseText = await response.text();
5809
5639
  if (!response.ok) {
5810
- let parsed;
5811
- try {
5812
- parsed = JSON.parse(responseText);
5813
- } catch {
5814
- }
5815
5640
  throw new CoreHttpError(
5816
5641
  `Parse request failed with status ${response.status}: ${responseText}`,
5817
- response.status,
5818
- readAgentHints(parsed)
5642
+ response.status
5819
5643
  );
5820
5644
  }
5821
5645
  try {
@@ -5843,6 +5667,9 @@ Set \`redactPII\` to request redaction of personally identifiable information in
5843
5667
  builtInTool: (name2) => builtInTools.get(name2)
5844
5668
  }
5845
5669
  );
5670
+ hooks.registerResources?.({
5671
+ addResource: (resource) => server.addResource(resource)
5672
+ });
5846
5673
  return {
5847
5674
  start: (args) => server.start(args),
5848
5675
  stop: () => server.stop()