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/index.js CHANGED
@@ -85,7 +85,7 @@ var alexandriaSessionFeedbackSchema = z.strictObject({
85
85
  // src/server.ts
86
86
  import FirecrawlApp from "firecrawl";
87
87
 
88
- // node_modules/.pnpm/fastmcp@4.3.2_patch_hash=08f77b633292d9ae4cb022c0fa5bd722dbd5c1aaaad600204f8ed38339bfd37b/node_modules/fastmcp/dist/chunk-LWU5CQGW.js
88
+ // node_modules/.pnpm/fastmcp@4.3.2_patch_hash=37f9a424ae5b0b6202b2b16109a1ea88b69cdcda5407f13eda6654a56489ad70/node_modules/fastmcp/dist/chunk-LWU5CQGW.js
89
89
  import { Server } from "@modelcontextprotocol/sdk/server/index.js";
90
90
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
91
91
  import {
@@ -889,6 +889,7 @@ ${error2 instanceof Error ? error2.stack : JSON.stringify(error2)}`
889
889
  // Top-level Tool.title (MCP 2025-06-18). Clients such as Codex index this
890
890
  // for tool search and do not read annotations.title.
891
891
  ...tool.annotations?.title && { title: tool.annotations.title },
892
+ ...tool.icons && { icons: tool.icons },
892
893
  description: tool.description,
893
894
  inputSchema: tool.parameters ? strictJsonSchema(await toJsonSchema(tool.parameters)) : {
894
895
  additionalProperties: false,
@@ -2064,7 +2065,7 @@ var FastMCP = class extends FastMCPEventEmitter {
2064
2065
  }
2065
2066
  };
2066
2067
 
2067
- // node_modules/.pnpm/fastmcp@4.3.2_patch_hash=08f77b633292d9ae4cb022c0fa5bd722dbd5c1aaaad600204f8ed38339bfd37b/node_modules/fastmcp/dist/chunk-OJG4XYXA.js
2068
+ // node_modules/.pnpm/fastmcp@4.3.2_patch_hash=37f9a424ae5b0b6202b2b16109a1ea88b69cdcda5407f13eda6654a56489ad70/node_modules/fastmcp/dist/chunk-OJG4XYXA.js
2068
2069
  import { z as z3 } from "zod";
2069
2070
  import { createHmac as createHmac2, pbkdf2, randomBytes } from "crypto";
2070
2071
  import { promisify } from "util";
@@ -2077,45 +2078,6 @@ import { randomUUID as randomUUID2 } from "crypto";
2077
2078
  import path from "path";
2078
2079
  import { z as z12 } from "zod";
2079
2080
 
2080
- // src/agent-hints.ts
2081
- var AGENT_HINTS_HEADERS = { "X-Firecrawl-Agent-Hints": "true" };
2082
- function readAgentHints(value) {
2083
- if (!value || typeof value !== "object") return void 0;
2084
- const hints = value.agent_hints;
2085
- return Array.isArray(hints) && hints.every((hint) => typeof hint === "string") ? hints : void 0;
2086
- }
2087
- function preserveAgentHints(data, envelope) {
2088
- const hints = readAgentHints(envelope);
2089
- if (!hints) return data;
2090
- return data && typeof data === "object" && !Array.isArray(data) ? { ...data, agent_hints: hints } : { data, agent_hints: hints };
2091
- }
2092
- function agentHintsText(hints) {
2093
- return `Firecrawl API agent_hints (response guidance, separate from page content):
2094
- ${JSON.stringify(hints, null, 2)}`;
2095
- }
2096
- function withAgentHints(result, response, separateText = false) {
2097
- const hints = readAgentHints(response);
2098
- if (!hints) return result;
2099
- return {
2100
- ...result,
2101
- content: separateText && hints.length ? [...result.content, { type: "text", text: agentHintsText(hints) }] : result.content,
2102
- structuredContent: { ...result.structuredContent, agent_hints: hints }
2103
- };
2104
- }
2105
- function readErrorAgentHints(error2) {
2106
- const hints = readAgentHints(error2);
2107
- if (hints) return hints;
2108
- if (!error2 || typeof error2 !== "object") return void 0;
2109
- const extras = error2.extras;
2110
- const extrasHints = readAgentHints(extras);
2111
- if (extrasHints) return extrasHints;
2112
- const details = error2.details;
2113
- const detailsHints = readAgentHints(details);
2114
- if (detailsHints) return detailsHints;
2115
- const response = error2.response;
2116
- return readAgentHints(response?.data);
2117
- }
2118
-
2119
2081
  // src/tool-output.ts
2120
2082
  import { z as z4 } from "zod";
2121
2083
  function isRecord(value) {
@@ -2144,9 +2106,6 @@ var unknown = (description) => z4.unknown().optional().describe(description);
2144
2106
  var success = bool("Whether the API call succeeded.");
2145
2107
  var error = unknown("Error message or error object when the call did not succeed.");
2146
2108
  var warning = str("Non-fatal warning about the result.");
2147
- var agentHints = {
2148
- agent_hints: z4.array(z4.string()).optional().describe("Optional response guidance from the Firecrawl API.")
2149
- };
2150
2109
  var alexandriaEnvelope = {
2151
2110
  requestId: str("Identifier of this Alexandria execution."),
2152
2111
  scrape_id: str("Identifier of the underlying scrape."),
@@ -2164,7 +2123,6 @@ var alexandriaEnvelope = {
2164
2123
  feedbackTool: unknown("Pointer to the feedback tool for reporting how this result served the task.")
2165
2124
  };
2166
2125
  var scrapeOutputSchema = z4.object({
2167
- ...agentHints,
2168
2126
  // URL mode: the scraped document, with the formats that were requested.
2169
2127
  markdown: str("Page content as markdown."),
2170
2128
  html: str("Processed HTML of the page."),
@@ -2196,7 +2154,6 @@ var scrapeOutputSchema = z4.object({
2196
2154
  ...alexandriaEnvelope
2197
2155
  }).describe("A scraped document, or the Alexandria execution envelope when `alexandria` was passed.");
2198
2156
  var mapOutputSchema = z4.object({
2199
- ...agentHints,
2200
2157
  links: unknown("URLs discovered under the website."),
2201
2158
  success,
2202
2159
  error,
@@ -2204,7 +2161,6 @@ var mapOutputSchema = z4.object({
2204
2161
  id: str("Identifier of the map run, for optional map feedback.")
2205
2162
  }).describe("URLs indexed under the requested website.");
2206
2163
  var searchOutputSchema = z4.object({
2207
- ...agentHints,
2208
2164
  success,
2209
2165
  data: unknown("Ranked results grouped by source, such as `web`, `news`, `images`, and `alexandria`."),
2210
2166
  error,
@@ -2216,14 +2172,12 @@ var searchOutputSchema = z4.object({
2216
2172
  feedbackTool: unknown("Pointer to the feedback tool for this search.")
2217
2173
  }).describe("Ranked search results grouped by source.");
2218
2174
  var findToolsOutputSchema = z4.object({
2219
- ...agentHints,
2220
2175
  success,
2221
2176
  data: unknown("Discovery page in `data.alexandria[0].data`, with `level`, `items`, `total`, and an optional `nextTool`."),
2222
2177
  error,
2223
2178
  ...alexandriaEnvelope
2224
2179
  }).describe("One page of the Alexandria catalogue: categories, providers, tools, or one contract.");
2225
2180
  var feedbackOutputSchema = z4.object({
2226
- ...agentHints,
2227
2181
  success,
2228
2182
  error,
2229
2183
  status: num("HTTP status when the submission was rejected."),
@@ -2242,7 +2196,6 @@ var feedbackOutputSchema = z4.object({
2242
2196
  raw: str("Response body when it was not JSON.")
2243
2197
  }).describe("Result of submitting feedback.");
2244
2198
  var crawlOutputSchema = z4.object({
2245
- ...agentHints,
2246
2199
  success,
2247
2200
  error,
2248
2201
  warning,
@@ -2257,7 +2210,6 @@ var crawlOutputSchema = z4.object({
2257
2210
  data: unknown("Scraped documents collected by the crawl.")
2258
2211
  }).describe("Crawl job state and the documents collected so far.");
2259
2212
  var agentOutputSchema = z4.object({
2260
- ...agentHints,
2261
2213
  success,
2262
2214
  error,
2263
2215
  id: str("Agent job identifier, for `firecrawl_agent_status`."),
@@ -2266,7 +2218,6 @@ var agentOutputSchema = z4.object({
2266
2218
  threadTurn: num("Turn number of this job within its thread.")
2267
2219
  }).describe("The queued research job. The result is read with `firecrawl_agent_status`.");
2268
2220
  var agentStatusOutputSchema = z4.object({
2269
- ...agentHints,
2270
2221
  success,
2271
2222
  error,
2272
2223
  id: str("Agent job identifier."),
@@ -2294,7 +2245,6 @@ var agentStatusOutputSchema = z4.object({
2294
2245
  )
2295
2246
  }).describe("Progress or final result of a research agent job.");
2296
2247
  var interactOutputSchema = z4.object({
2297
- ...agentHints,
2298
2248
  success,
2299
2249
  error: unknown("Why the interaction or the session could not run."),
2300
2250
  url: str("The URL the session was opened from, when opening failed."),
@@ -2309,14 +2259,12 @@ var interactOutputSchema = z4.object({
2309
2259
  liveUrl: str("URL for viewing the live session.")
2310
2260
  }).describe("Result of a browser interaction, with the session identifier to continue or stop it.");
2311
2261
  var interactStopOutputSchema = z4.object({
2312
- ...agentHints,
2313
2262
  success,
2314
2263
  error,
2315
2264
  message: str("Confirmation that the session was stopped."),
2316
2265
  scrapeId: str("Session that was stopped.")
2317
2266
  }).describe("Confirmation that the interact session was stopped.");
2318
2267
  var parseOutputSchema = z4.object({
2319
- ...agentHints,
2320
2268
  success,
2321
2269
  error,
2322
2270
  warning,
@@ -2344,39 +2292,33 @@ var deprecatedToolOutputSchema = z4.object({
2344
2292
  docs_url: str("Documentation for the replacement.")
2345
2293
  }).describe("A pointer to the replacement tool. This entry point is deprecated and always errors.");
2346
2294
  var monitorOutputSchema = z4.object({
2347
- ...agentHints,
2348
2295
  success,
2349
2296
  error,
2350
2297
  data: unknown("The monitor record: configuration, schedule, targets, and current state.")
2351
2298
  }).describe("One monitor record.");
2352
2299
  var monitorListOutputSchema = z4.object({
2353
- ...agentHints,
2354
2300
  success,
2355
2301
  error,
2356
2302
  data: unknown("One page of monitor records."),
2357
2303
  pagination: unknown("Pagination metadata for the listing.")
2358
2304
  }).describe("One page of monitors for the authenticated account.");
2359
2305
  var monitorDeleteOutputSchema = z4.object({
2360
- ...agentHints,
2361
2306
  success,
2362
2307
  error,
2363
2308
  data: unknown("Deletion details, when the API returns any.")
2364
2309
  }).describe("Deletion status for the monitor.");
2365
2310
  var monitorRunOutputSchema = z4.object({
2366
- ...agentHints,
2367
2311
  success,
2368
2312
  error,
2369
2313
  data: unknown("The queued check.")
2370
2314
  }).describe("The check queued outside the monitor schedule.");
2371
2315
  var monitorChecksOutputSchema = z4.object({
2372
- ...agentHints,
2373
2316
  success,
2374
2317
  error,
2375
2318
  data: unknown("One page of check summaries."),
2376
2319
  pagination: unknown("Pagination metadata for the listing.")
2377
2320
  }).describe("One page of historical checks for the monitor.");
2378
2321
  var monitorCheckOutputSchema = z4.object({
2379
- ...agentHints,
2380
2322
  success,
2381
2323
  error,
2382
2324
  data: unknown("The check and its page-level results: each page reports `same`, `new`, `changed`, `removed`, or `error`, with diffs and any goal judgment."),
@@ -2395,25 +2337,20 @@ var paperSchema = z4.looseObject({
2395
2337
  updateDate: str("Date the paper was last updated.")
2396
2338
  });
2397
2339
  var researchSearchOutputSchema = z4.object({
2398
- ...agentHints,
2399
2340
  results: z4.array(paperSchema).describe("Ranked papers, in the order the text block lists them.")
2400
2341
  }).describe("Ranked papers with canonical IDs, titles, authors, and abstracts.");
2401
2342
  var researchPaperOutputSchema = z4.object({
2402
- ...agentHints,
2403
2343
  paper: paperSchema.optional().describe("Canonical metadata for the requested paper, absent when it was not found.")
2404
2344
  }).describe("Canonical metadata for one paper.");
2405
2345
  var researchRelatedOutputSchema = z4.object({
2406
- ...agentHints,
2407
2346
  results: z4.array(paperSchema).describe("Ranked citation-graph candidates."),
2408
2347
  poolSize: z4.number().describe("Number of candidates evaluated before ranking."),
2409
2348
  note: str("Note about how the candidates were produced.")
2410
2349
  }).describe("Ranked citation-graph candidates and the size of the evaluated pool.");
2411
2350
  var researchReadOutputSchema = z4.object({
2412
- ...agentHints,
2413
2351
  passages: z4.array(z4.looseObject({ text: str("Passage text.") })).describe("In-body passages relevant to the question; empty when no full text is indexed.")
2414
2352
  }).describe("Full-text passages from one paper.");
2415
2353
  var developerSearchOutputSchema = z4.object({
2416
- ...agentHints,
2417
2354
  results: z4.array(
2418
2355
  z4.looseObject({
2419
2356
  id: str("Stable result id, such as `issue:owner/repo#123` or `doc:<hash>`; its prefix gives the source type."),
@@ -2424,7 +2361,6 @@ var developerSearchOutputSchema = z4.object({
2424
2361
  ).describe("Ranked results, in the order the text block lists them.")
2425
2362
  }).describe("Ranked developer-index results with their matched passages.");
2426
2363
  var govSearchOutputSchema = z4.object({
2427
- ...agentHints,
2428
2364
  results: z4.array(
2429
2365
  z4.looseObject({
2430
2366
  url: str("Source URL."),
@@ -2673,7 +2609,7 @@ Returns ranked results with an ID, source type, URL, title, and the matched pass
2673
2609
  const client = getClient(session);
2674
2610
  const res = await client.http.get(`${BASE}?${params.toString()}`, originHeaders(requestOrigin(mcpClient, session)));
2675
2611
  const results = res.data?.results ?? [];
2676
- return withAgentHints(withStructured(fmtDeveloper(results), { results }), res.data, true);
2612
+ return withStructured(fmtDeveloper(results), { results });
2677
2613
  }
2678
2614
  });
2679
2615
  }
@@ -2722,11 +2658,7 @@ Returns ranked results with a position, title, URL, and matched snippet. Results
2722
2658
  originHeaders(requestOrigin(mcpClient, session))
2723
2659
  );
2724
2660
  const results = res.data?.data?.web ?? [];
2725
- return withAgentHints(
2726
- withStructured(fmtGov(results), { results }),
2727
- res.data,
2728
- true
2729
- );
2661
+ return withStructured(fmtGov(results), { results });
2730
2662
  }
2731
2663
  });
2732
2664
  }
@@ -2737,12 +2669,10 @@ import { z as z8 } from "zod";
2737
2669
  // src/core-http-error.ts
2738
2670
  var CoreHttpError = class extends Error {
2739
2671
  status;
2740
- agent_hints;
2741
- constructor(message, status, agentHints2) {
2672
+ constructor(message, status) {
2742
2673
  super(message);
2743
2674
  this.name = "CoreHttpError";
2744
2675
  this.status = status;
2745
- if (agentHints2 !== void 0) this.agent_hints = agentHints2;
2746
2676
  }
2747
2677
  };
2748
2678
 
@@ -2765,7 +2695,6 @@ async function monitorRequest(api, session, origin, path2, init = {}) {
2765
2695
  }
2766
2696
  const headers = {
2767
2697
  ...originHeaders(origin),
2768
- ...AGENT_HINTS_HEADERS,
2769
2698
  ...extraHeaders
2770
2699
  };
2771
2700
  if (apiKey2) headers.Authorization = `Bearer ${apiKey2}`;
@@ -2778,13 +2707,10 @@ async function monitorRequest(api, session, origin, path2, init = {}) {
2778
2707
  const payload = await response.json().catch(() => ({}));
2779
2708
  if (!response.ok || payload?.success === false) {
2780
2709
  const message = payload?.error || `HTTP ${response.status}: ${response.statusText || "Request failed"}`;
2781
- throw new CoreHttpError(message, response.status, readAgentHints(payload));
2710
+ throw new CoreHttpError(message, response.status);
2782
2711
  }
2783
2712
  return payload;
2784
2713
  }
2785
- function monitorResult(data) {
2786
- return withAgentHints(structuredText(data), data);
2787
- }
2788
2714
  var pageStatusSchema = z8.enum(["same", "new", "changed", "removed", "error"]);
2789
2715
  var checkStatusSchema = z8.enum([
2790
2716
  "queued",
@@ -2910,7 +2836,7 @@ In the simple form, a \`goal\` is required. If \`queries\` contains one or more
2910
2836
  body
2911
2837
  }
2912
2838
  );
2913
- return monitorResult(res);
2839
+ return structuredText(res);
2914
2840
  }
2915
2841
  });
2916
2842
  server.addTool({
@@ -2943,7 +2869,7 @@ List monitors for the authenticated account with optional pagination controls. R
2943
2869
  query: { limit, offset }
2944
2870
  }
2945
2871
  );
2946
- return monitorResult(res);
2872
+ return structuredText(res);
2947
2873
  }
2948
2874
  });
2949
2875
  server.addTool({
@@ -2970,7 +2896,7 @@ Retrieve one monitor by ID, including its configuration and current state. This
2970
2896
  requestOrigin(mcpClient, session),
2971
2897
  `/monitor/${encodeURIComponent(id)}`
2972
2898
  );
2973
- return monitorResult(res);
2899
+ return structuredText(res);
2974
2900
  }
2975
2901
  });
2976
2902
  server.addTool({
@@ -3003,7 +2929,7 @@ Returns the updated monitor.
3003
2929
  `/monitor/${encodeURIComponent(id)}`,
3004
2930
  { method: "PATCH", body }
3005
2931
  );
3006
- return monitorResult(res);
2932
+ return structuredText(res);
3007
2933
  }
3008
2934
  });
3009
2935
  server.addTool({
@@ -3032,7 +2958,7 @@ Permanently delete a monitor by ID and stop its future schedule. This operation
3032
2958
  `/monitor/${encodeURIComponent(id)}`,
3033
2959
  { method: "DELETE" }
3034
2960
  );
3035
- return monitorResult(res);
2961
+ return structuredText(res);
3036
2962
  }
3037
2963
  });
3038
2964
  server.addTool({
@@ -3060,7 +2986,7 @@ Queue an immediate check for a monitor outside its normal schedule. This starts
3060
2986
  `/monitor/${encodeURIComponent(id)}/run`,
3061
2987
  { method: "POST" }
3062
2988
  );
3063
- return monitorResult(res);
2989
+ return structuredText(res);
3064
2990
  }
3065
2991
  });
3066
2992
  server.addTool({
@@ -3093,7 +3019,7 @@ List historical checks for a monitor, optionally filtered by status and bounded
3093
3019
  `/monitor/${encodeURIComponent(id)}/checks`,
3094
3020
  { query: { limit, offset, status } }
3095
3021
  );
3096
- return monitorResult(res);
3022
+ return structuredText(res);
3097
3023
  }
3098
3024
  });
3099
3025
  server.addTool({
@@ -3129,7 +3055,7 @@ Markdown tracking returns a unified text diff, JSON tracking returns field paths
3129
3055
  `/monitor/${encodeURIComponent(id)}/checks/${encodeURIComponent(checkId)}`,
3130
3056
  { query: { limit, skip, status: pageStatus } }
3131
3057
  );
3132
- return monitorResult(res);
3058
+ return structuredText(res);
3133
3059
  }
3134
3060
  });
3135
3061
  }
@@ -3137,9 +3063,6 @@ Markdown tracking returns a unified text diff, JSON tracking returns field paths
3137
3063
  // src/research.ts
3138
3064
  import { z as z9 } from "zod";
3139
3065
  var BASE3 = "/v2/search/research";
3140
- function researchHeaders(origin) {
3141
- return { ...originHeaders(origin), ...AGENT_HINTS_HEADERS };
3142
- }
3143
3066
  function appendParam(params, key, value) {
3144
3067
  if (value == null) return;
3145
3068
  if (Array.isArray(value)) {
@@ -3284,10 +3207,10 @@ Returns ranked papers with canonical IDs, titles, authors, and abstracts.
3284
3207
  const client = getClient(session);
3285
3208
  const res = await client.http.get(
3286
3209
  withQuery(`${BASE3}/papers`, params),
3287
- researchHeaders(requestOrigin(mcpClient, session))
3210
+ originHeaders(requestOrigin(mcpClient, session))
3288
3211
  );
3289
3212
  const results = res.data?.results ?? [];
3290
- return withAgentHints(withStructured(fmtHits(results), { results }), res.data, true);
3213
+ return withStructured(fmtHits(results), { results });
3291
3214
  }
3292
3215
  });
3293
3216
  server.addTool({
@@ -3315,13 +3238,13 @@ Retrieve canonical metadata for one paper ID, such as an arXiv, PMC, PMID, or DO
3315
3238
  const client = getClient(session);
3316
3239
  const res = await client.http.get(
3317
3240
  `${BASE3}/papers/${encodeURIComponent(paperId)}`,
3318
- researchHeaders(requestOrigin(mcpClient, session))
3241
+ originHeaders(requestOrigin(mcpClient, session))
3319
3242
  );
3320
3243
  const paper = res.data?.paper;
3321
- return withAgentHints(withStructured(
3244
+ return withStructured(
3322
3245
  fmtPaperMetadata(paper),
3323
3246
  paper ? { paper } : {}
3324
- ), res.data, true);
3247
+ );
3325
3248
  }
3326
3249
  });
3327
3250
  server.addTool({
@@ -3363,17 +3286,17 @@ Returns ranked candidates and the evaluated pool size.
3363
3286
  `${BASE3}/papers/${encodeURIComponent(primary)}/similar`,
3364
3287
  params
3365
3288
  ),
3366
- researchHeaders(requestOrigin(mcpClient, session))
3289
+ originHeaders(requestOrigin(mcpClient, session))
3367
3290
  );
3368
3291
  const results = res.data?.results ?? [];
3369
3292
  const poolSize = res.data?.poolSize ?? 0;
3370
3293
  const note = res.data?.note ? `
3371
3294
  note: ${res.data.note}` : "";
3372
- return withAgentHints(withStructured(
3295
+ return withStructured(
3373
3296
  `${fmtHits(results)}
3374
3297
  (poolSize=${poolSize})${note}`,
3375
3298
  { results, poolSize, ...res.data?.note ? { note: res.data.note } : {} }
3376
- ), res.data, true);
3299
+ );
3377
3300
  }
3378
3301
  });
3379
3302
  server.addTool({
@@ -3408,13 +3331,13 @@ Returns matching passages or a notice when full text is unavailable.
3408
3331
  const client = getClient(session);
3409
3332
  const res = await client.http.get(
3410
3333
  withQuery(`${BASE3}/papers/${encodeURIComponent(paperId)}`, params),
3411
- researchHeaders(requestOrigin(mcpClient, session))
3334
+ originHeaders(requestOrigin(mcpClient, session))
3412
3335
  );
3413
3336
  const passages = res.data?.passages ?? [];
3414
- return withAgentHints(withStructured(
3337
+ return withStructured(
3415
3338
  passages.length ? passages.map((p) => p.text).join("\n---\n") : "(no full-text passages available for this paper)",
3416
3339
  { passages }
3417
- ), res.data, true);
3340
+ );
3418
3341
  }
3419
3342
  });
3420
3343
  server.addTool({
@@ -3640,20 +3563,6 @@ async function runWithCredentialRecovery(run, requestId, session) {
3640
3563
  return await run();
3641
3564
  } catch (error2) {
3642
3565
  if (session?.authType !== "api-key" || !isCoreCredentialRejection(error2, session)) {
3643
- const hints = readErrorAgentHints(error2);
3644
- if (hints) {
3645
- const message = error2 instanceof Error ? error2.message : String(error2);
3646
- throw new UserError(
3647
- hints.length ? `${message}
3648
-
3649
- ${agentHintsText(hints)}` : message,
3650
- {
3651
- ...error2 instanceof UserError ? error2.extras : {},
3652
- error: message,
3653
- agent_hints: hints
3654
- }
3655
- );
3656
- }
3657
3566
  throw error2;
3658
3567
  }
3659
3568
  const payload = recoveryPayload("CREDENTIAL_INVALID", requestId);
@@ -3712,8 +3621,6 @@ var searchDomainSchema = z11.string().trim().toLowerCase().min(1).max(253).regex
3712
3621
  var searchToolBaseFields = {
3713
3622
  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."),
3714
3623
  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."),
3715
- objective: z11.string().trim().min(1).max(5e3).optional().describe("Optional broader goal for this search, if known. Avoid sensitive information."),
3716
- clientModel: z11.string().trim().min(1).max(128).optional().describe("Optional model identifier, if known."),
3717
3624
  domainTools: z11.boolean().optional().describe(
3718
3625
  "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."
3719
3626
  ),
@@ -3779,7 +3686,7 @@ function termsRequiredAction(body) {
3779
3686
  url: action.url
3780
3687
  };
3781
3688
  }
3782
- function termsRequiredError(action, context, hints) {
3689
+ function termsRequiredError(action, context) {
3783
3690
  const requestId = context.requestId;
3784
3691
  const retryIdentity = requestId ? ` and requestId ${requestId}` : "";
3785
3692
  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.`;
@@ -3794,7 +3701,6 @@ Do not retry until acceptance is confirmed.`,
3794
3701
  code: TERMS_REQUIRED_CODE,
3795
3702
  status: 403,
3796
3703
  message,
3797
- ...hints ? { agent_hints: hints } : {},
3798
3704
  ...requestId ? { requestId } : {},
3799
3705
  requiresAction: action,
3800
3706
  nextTool: {
@@ -3825,8 +3731,7 @@ Do not retry until acceptance is confirmed.`,
3825
3731
  function throwIfTermsRequired(error2, context) {
3826
3732
  const source = error2;
3827
3733
  const action = termsRequiredAction(source?.response?.data ?? source?.details);
3828
- if (action)
3829
- throw termsRequiredError(action, context, readErrorAgentHints(error2));
3734
+ if (action) throw termsRequiredError(action, context);
3830
3735
  }
3831
3736
  async function relayTermsRequired(run, context) {
3832
3737
  try {
@@ -3844,7 +3749,6 @@ async function relayExchangeError(run, context) {
3844
3749
  const response = error2?.response;
3845
3750
  if (!response || response.status === 401) throw error2;
3846
3751
  const data = response.data;
3847
- const hints = readErrorAgentHints(error2);
3848
3752
  const message = typeof data?.error === "string" ? data.error : `Alexandria request failed (HTTP ${response.status})`;
3849
3753
  const disabledProvider = response.status === 403 ? context.providers?.find((provider) => message === `Access to ${provider} is disabled for this organization.`) : void 0;
3850
3754
  if (disabledProvider) {
@@ -3854,7 +3758,6 @@ async function relayExchangeError(run, context) {
3854
3758
  code: typeof data?.code === "string" ? data.code : "exchange_error",
3855
3759
  status: 403,
3856
3760
  message,
3857
- ...hints ? { agent_hints: hints } : {},
3858
3761
  nextTool: {
3859
3762
  name: "firecrawl_scrape",
3860
3763
  arguments: {
@@ -3868,7 +3771,6 @@ async function relayExchangeError(run, context) {
3868
3771
  code: typeof data?.code === "string" ? data.code : "exchange_error",
3869
3772
  status: response.status,
3870
3773
  message,
3871
- ...hints ? { agent_hints: hints } : {},
3872
3774
  ...typeof data?.chargeId === "string" ? { chargeId: data.chargeId } : {}
3873
3775
  });
3874
3776
  }
@@ -3915,10 +3817,6 @@ function copySession(session) {
3915
3817
  Object.getOwnPropertyDescriptors(session ?? {})
3916
3818
  );
3917
3819
  }
3918
- function resultAgentHints(result) {
3919
- return result && typeof result === "object" ? readAgentHints(result.structuredContent) : void 0;
3920
- }
3921
- var warnedMissingAgentHintsInterceptor = false;
3922
3820
  var ConsoleLogger = class {
3923
3821
  constructor(shouldLog) {
3924
3822
  this.shouldLog = shouldLog;
@@ -4070,20 +3968,10 @@ function createFirecrawlMcpServer(options2 = {}) {
4070
3968
  requestId,
4071
3969
  session
4072
3970
  );
4073
- hooks.onToolResult?.({
4074
- ...call,
4075
- status: "success",
4076
- result,
4077
- agentHints: resultAgentHints(result)
4078
- });
3971
+ hooks.onToolResult?.({ ...call, status: "success", result });
4079
3972
  return result;
4080
3973
  } catch (error2) {
4081
- hooks.onToolResult?.({
4082
- ...call,
4083
- status: "error",
4084
- error: error2,
4085
- agentHints: readErrorAgentHints(error2)
4086
- });
3974
+ hooks.onToolResult?.({ ...call, status: "error", error: error2 });
4087
3975
  throw error2;
4088
3976
  }
4089
3977
  }
@@ -4114,44 +4002,7 @@ function createFirecrawlMcpServer(options2 = {}) {
4114
4002
  if (apiKey2) {
4115
4003
  clientConfig.apiKey = apiKey2;
4116
4004
  }
4117
- const client = new FirecrawlApp(clientConfig);
4118
- const axiosInstance = client.http?.instance;
4119
- if (axiosInstance?.interceptors?.request?.use) {
4120
- axiosInstance.interceptors.request.use((request) => {
4121
- if (typeof request.headers?.set === "function") {
4122
- request.headers.set("X-Firecrawl-Agent-Hints", "true");
4123
- } else {
4124
- request.headers = { ...request.headers ?? {}, ...AGENT_HINTS_HEADERS };
4125
- }
4126
- return request;
4127
- });
4128
- } else if (!warnedMissingAgentHintsInterceptor) {
4129
- warnedMissingAgentHintsInterceptor = true;
4130
- console.warn(
4131
- "[firecrawl-mcp] SDK request interceptor unavailable; API agent hints may be absent."
4132
- );
4133
- }
4134
- return client;
4135
- }
4136
- async function sdkResultWithAgentHints(client, execute) {
4137
- const responseInterceptors = client.http?.instance?.interceptors?.response;
4138
- if (!responseInterceptors?.use) return execute();
4139
- let hints;
4140
- const interceptor = responseInterceptors.use((response) => {
4141
- hints = readAgentHints(response?.data) ?? hints;
4142
- return response;
4143
- });
4144
- try {
4145
- const result = await execute();
4146
- return preserveAgentHints(result, { agent_hints: hints });
4147
- } catch (error2) {
4148
- if (hints && error2 && typeof error2 === "object" && !readErrorAgentHints(error2)) {
4149
- error2.agent_hints = hints;
4150
- }
4151
- throw error2;
4152
- } finally {
4153
- responseInterceptors.eject?.(interceptor);
4154
- }
4005
+ return new FirecrawlApp(clientConfig);
4155
4006
  }
4156
4007
  const SAFE_MODE = config.safeMode;
4157
4008
  function getClient(session) {
@@ -4504,7 +4355,6 @@ function createFirecrawlMcpServer(options2 = {}) {
4504
4355
  const response = await fetch(`${resolveApiBaseUrl()}${pathName}`, {
4505
4356
  method: "POST",
4506
4357
  headers: {
4507
- ...AGENT_HINTS_HEADERS,
4508
4358
  "Content-Type": "application/json",
4509
4359
  ...extraHeaders,
4510
4360
  Authorization: `Bearer ${apiKey2}`,
@@ -4522,8 +4372,7 @@ function createFirecrawlMcpServer(options2 = {}) {
4522
4372
  if (!response.ok) {
4523
4373
  throw new CoreHttpError(
4524
4374
  parsed?.error || parsed?.message || `Firecrawl request failed (HTTP ${response.status})`,
4525
- response.status,
4526
- readAgentHints(parsed)
4375
+ response.status
4527
4376
  );
4528
4377
  }
4529
4378
  return parsed;
@@ -4605,7 +4454,6 @@ function createFirecrawlMcpServer(options2 = {}) {
4605
4454
  session,
4606
4455
  origin
4607
4456
  );
4608
- const uploadHints = readAgentHints(uploadJson);
4609
4457
  const upload = parseApiData(uploadJson);
4610
4458
  if (!upload?.uploadUrl || !upload?.uploadRef) {
4611
4459
  throw new Error(
@@ -4616,7 +4464,6 @@ function createFirecrawlMcpServer(options2 = {}) {
4616
4464
  const uploadForCommand = { ...upload, headers: uploadHeaders };
4617
4465
  return asText({
4618
4466
  success: true,
4619
- ...uploadHints ? { agent_hints: uploadHints } : {},
4620
4467
  mode: "hosted-upload-ref-awaiting-upload",
4621
4468
  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.",
4622
4469
  upload: {
@@ -4715,17 +4562,14 @@ Alexandria mode, on an authenticated session with Alexandria access: \`alexandri
4715
4562
  },
4716
4563
  session
4717
4564
  );
4718
- return structuredText(preserveAgentHints(json?.data ?? json, json));
4565
+ return structuredText(json?.data ?? json);
4719
4566
  }
4720
4567
  const client = getClient(session);
4721
4568
  const res = await relayTermsRequired(
4722
- () => sdkResultWithAgentHints(
4723
- client,
4724
- () => client.scrape(String(url), {
4725
- ...cleaned,
4726
- origin
4727
- })
4728
- ),
4569
+ () => client.scrape(String(url), {
4570
+ ...cleaned,
4571
+ origin
4572
+ }),
4729
4573
  { tool: "firecrawl_scrape" }
4730
4574
  );
4731
4575
  return structuredText(res);
@@ -4765,13 +4609,10 @@ Returns matching URLs rather than page bodies. Retrieve one page with \`firecraw
4765
4609
  const client = getClient(session);
4766
4610
  const cleaned = removeEmptyTopLevel(options3);
4767
4611
  log.info("Mapping URL", { url: String(url) });
4768
- const res = await sdkResultWithAgentHints(
4769
- client,
4770
- () => client.map(String(url), {
4771
- ...cleaned,
4772
- origin: requestOrigin(mcpClient, session)
4773
- })
4774
- );
4612
+ const res = await client.map(String(url), {
4613
+ ...cleaned,
4614
+ origin: requestOrigin(mcpClient, session)
4615
+ });
4775
4616
  return structuredText(res);
4776
4617
  }
4777
4618
  });
@@ -4951,7 +4792,6 @@ For a programming question, add \`categories: ["developer"]\`; its hits return i
4951
4792
  const origin = originOverride ?? (typeof body.origin === "string" && body.origin.length > 0 ? body.origin : requestOrigin(void 0, session));
4952
4793
  await hooks.beforeKeylessRequest?.(session, origin);
4953
4794
  const headers = {
4954
- ...AGENT_HINTS_HEADERS,
4955
4795
  ...originHeaders(origin),
4956
4796
  "Content-Type": "application/json",
4957
4797
  ...resolveOutbound(session).headers
@@ -4969,14 +4809,11 @@ For a programming question, add \`categories: ["developer"]\`; its hits return i
4969
4809
  retryAfterSeconds: Number.isFinite(json?.retry_after_seconds) && json.retry_after_seconds > 0 ? json.retry_after_seconds : void 0,
4970
4810
  signupUrl: keylessSignupUrlFrom(json?.signup_url)
4971
4811
  });
4972
- const hints = readAgentHints(json);
4973
- if (hints) payload.agent_hints = hints;
4974
4812
  throw new UserError2(String(payload.message), payload);
4975
4813
  }
4976
4814
  throw new CoreHttpError(
4977
4815
  json?.error || `Firecrawl request failed (HTTP ${response.status})`,
4978
- response.status,
4979
- readAgentHints(json)
4816
+ response.status
4980
4817
  );
4981
4818
  }
4982
4819
  return json;
@@ -4997,8 +4834,7 @@ For a programming question, add \`categories: ["developer"]\`; its hits return i
4997
4834
  creditsUsed: body.creditsUsed,
4998
4835
  expiresAt: body.expiresAt,
4999
4836
  next: body.next ?? null,
5000
- data: initialDocs,
5001
- ...readAgentHints(body) ? { agent_hints: readAgentHints(body) } : {}
4837
+ data: initialDocs
5002
4838
  };
5003
4839
  }
5004
4840
  const docs = initialDocs.slice();
@@ -5022,8 +4858,7 @@ For a programming question, add \`categories: ["developer"]\`; its hits return i
5022
4858
  creditsUsed: body.creditsUsed,
5023
4859
  expiresAt: body.expiresAt,
5024
4860
  next: null,
5025
- data: docs,
5026
- ...readAgentHints(body) ? { agent_hints: readAgentHints(body) } : {}
4861
+ data: docs
5027
4862
  };
5028
4863
  }
5029
4864
  async function waitForCrawlCompletionWithOrigin(client, jobId, origin, pollInterval = 2, timeout) {
@@ -5119,7 +4954,6 @@ Eligibility is limited to successful searches within the feedback age window. Th
5119
4954
  }
5120
4955
  if (querySuggestions) body.querySuggestions = querySuggestions;
5121
4956
  const headers = {
5122
- ...AGENT_HINTS_HEADERS,
5123
4957
  ...originHeaders(origin),
5124
4958
  "Content-Type": "application/json"
5125
4959
  };
@@ -5160,8 +4994,7 @@ Eligibility is limited to successful searches within the feedback age window. Th
5160
4994
  status: response.status,
5161
4995
  feedbackErrorCode: parsed?.feedbackErrorCode,
5162
4996
  error: parsed?.error ?? `HTTP ${response.status}`,
5163
- retryable: response.status >= 500,
5164
- ...readAgentHints(parsed) ? { agent_hints: readAgentHints(parsed) } : {}
4997
+ retryable: response.status >= 500
5165
4998
  });
5166
4999
  }
5167
5000
  return structuredText(parsed);
@@ -5245,7 +5078,6 @@ Returns submission status, feedback ID, and accounting fields.
5245
5078
  } = args2;
5246
5079
  const apiBase = resolveApiBaseUrl();
5247
5080
  const headers = {
5248
- ...AGENT_HINTS_HEADERS,
5249
5081
  ...originHeaders(origin),
5250
5082
  "Content-Type": "application/json"
5251
5083
  };
@@ -5301,8 +5133,7 @@ Returns submission status, feedback ID, and accounting fields.
5301
5133
  status: response.status,
5302
5134
  feedbackErrorCode: parsed?.feedbackErrorCode,
5303
5135
  error: parsed?.error ?? `HTTP ${response.status}`,
5304
- retryable: response.status >= 500,
5305
- ...readAgentHints(parsed) ? { agent_hints: readAgentHints(parsed) } : {}
5136
+ retryable: response.status >= 500
5306
5137
  });
5307
5138
  }
5308
5139
  return structuredText(parsed);
@@ -5790,7 +5621,6 @@ Set \`redactPII\` to request redaction of personally identifiable information in
5790
5621
  form.append("file", blob, filename);
5791
5622
  form.append("options", JSON.stringify(optionsPayload));
5792
5623
  const headers = {
5793
- ...AGENT_HINTS_HEADERS,
5794
5624
  ...originHeaders(origin)
5795
5625
  };
5796
5626
  const outbound = resolveOutbound(session);
@@ -5812,15 +5642,9 @@ Set \`redactPII\` to request redaction of personally identifiable information in
5812
5642
  });
5813
5643
  const responseText = await response.text();
5814
5644
  if (!response.ok) {
5815
- let parsed;
5816
- try {
5817
- parsed = JSON.parse(responseText);
5818
- } catch {
5819
- }
5820
5645
  throw new CoreHttpError(
5821
5646
  `Parse request failed with status ${response.status}: ${responseText}`,
5822
- response.status,
5823
- readAgentHints(parsed)
5647
+ response.status
5824
5648
  );
5825
5649
  }
5826
5650
  try {
@@ -5848,6 +5672,9 @@ Set \`redactPII\` to request redaction of personally identifiable information in
5848
5672
  builtInTool: (name2) => builtInTools.get(name2)
5849
5673
  }
5850
5674
  );
5675
+ hooks.registerResources?.({
5676
+ addResource: (resource) => server.addResource(resource)
5677
+ });
5851
5678
  return {
5852
5679
  start: (args2) => server.start(args2),
5853
5680
  stop: () => server.stop()
@@ -6540,6 +6367,13 @@ ${ALEXANDRIA_SEARCH_INSTRUCTIONS}
6540
6367
  Returns result groups in \`data\` and an operation \`id\`.
6541
6368
  `,
6542
6369
  outputSchema: searchOutputSchema,
6370
+ beforeValidate: (args2) => {
6371
+ if (args2 && typeof args2 === "object") {
6372
+ delete args2.objective;
6373
+ delete args2.clientModel;
6374
+ }
6375
+ return void 0;
6376
+ },
6543
6377
  parameters: z13.object({ ...searchToolBaseFields }).strict().refine(searchDomainsAreExclusive, SEARCH_DOMAINS_CONFLICT_MESSAGE).refine(
6544
6378
  searchQueryIsValid,
6545
6379
  "A query is required. Use firecrawl_find_tools to browse the catalogue."
@@ -6547,8 +6381,6 @@ Returns result groups in \`data\` and an operation \`id\`.
6547
6381
  execute: async (args2, { session, log, client: mcpClient }) => {
6548
6382
  const {
6549
6383
  query,
6550
- objective,
6551
- clientModel,
6552
6384
  includeDomains,
6553
6385
  excludeDomains,
6554
6386
  limit,
@@ -6566,8 +6398,6 @@ Returns result groups in \`data\` and an operation \`id\`.
6566
6398
  const searchBody = {
6567
6399
  query: searchQuery,
6568
6400
  ...removeEmptyTopLevel({
6569
- objective,
6570
- clientModel,
6571
6401
  limit,
6572
6402
  includeDomains,
6573
6403
  excludeDomains,