firecrawl-mcp 3.25.1 → 3.25.3

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 +7 -7
  2. package/dist/index.js +79 -54
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -37,7 +37,7 @@ A Model Context Protocol (MCP) server that brings [Firecrawl](https://github.com
37
37
  - Use `firecrawl_credit_usage` to check credits left or monthly consumption, optionally broken down by API key.
38
38
  - Consider something else when you need to hold a browser session open across many of your own steps with your own retry and termination logic: each `firecrawl_interact` call runs one `prompt` or `code` turn to completion and returns control — the session can persist across calls via `scrapeId` and ends with `firecrawl_interact_stop`, but you cannot drive it interactively step-by-step from the client side within a single call.
39
39
 
40
- This server lists 26 tools when the full profile registers with default settings (feedback tools included, not running in local-keyless mode). Setting `FIRECRAWL_NO_SEARCH_FEEDBACK=1` and/or `FIRECRAWL_NO_ENDPOINT_FEEDBACK=1` removes the corresponding feedback tools and reduces this count, as does local keyless startup. For clients with a tool-slot limit: the hosted keyless endpoint (`https://mcp.firecrawl.dev/v2/mcp`, no API key) exposes only 3 — `firecrawl_scrape`, `firecrawl_search`, `firecrawl_parse` — and the dedicated [search-only endpoint](#search-only-endpoint) (`https://mcp.firecrawl.dev/v2/mcp-search`) exposes a fixed 6 read-only tools.
40
+ This server lists 26 tools when the full profile registers with default settings (feedback tools included, not running in local-keyless mode). Setting `FIRECRAWL_NO_SEARCH_FEEDBACK=1` and/or `FIRECRAWL_NO_ENDPOINT_FEEDBACK=1` removes the corresponding feedback tools and reduces this count, as does local keyless startup. For clients with a tool-slot limit: the hosted keyless endpoint (`https://mcp.firecrawl.dev/v2/mcp`, no API key) exposes only 3 — `firecrawl_scrape`, `firecrawl_search`, `firecrawl_parse` — and the dedicated [search-only endpoint](#search-only-endpoint) (`https://mcp.firecrawl.dev/v2/mcp-search`) exposes a fixed set of 8 tools (search, developer and research search, plus Alexandria catalogue lookup and execution).
41
41
 
42
42
  ## Installation
43
43
 
@@ -75,13 +75,13 @@ Never put an API key in the server URL. Never put an API key in an agent chat. C
75
75
 
76
76
  #### Search-only endpoint
77
77
 
78
- A read-only, search-only surface is also hosted at:
78
+ A fixed-scope search surface is also hosted at:
79
79
 
80
80
  ```
81
81
  https://mcp.firecrawl.dev/v2/mcp-search
82
82
  ```
83
83
 
84
- It exposes a fixed set of six read-only tools: `firecrawl_search`, `firecrawl_developer_search`, and the four `firecrawl_research_*` tools. It performs no page-content fetching and has its own OAuth identity; the full endpoint above is unchanged. It is the connector listed in Anthropic's Claude directory, so its tool set is a reviewed contract rather than a profile to tune. See [docs/search-profile.md](docs/search-profile.md) for the full contract and what a change to it involves.
84
+ It exposes a fixed set of eight tools: `firecrawl_search`, `firecrawl_developer_search`, the four `firecrawl_research_*` tools, and the two Alexandria tools `firecrawl_find_tools` and `firecrawl_scrape`. Its `firecrawl_search` fetches no page content, and the surface has its own OAuth identity; the full endpoint above is unchanged. It backs a published connector listing, so its tool set is a contract rather than a profile to tune. See [docs/search-profile.md](docs/search-profile.md) for the full contract and what a change to it involves.
85
85
 
86
86
  ### Running with npx
87
87
 
@@ -498,7 +498,7 @@ Search the web and optionally extract content from search results.
498
498
 
499
499
  Set `highlights` to `true` to request query-relevant highlights or `false` to keep the original search snippets. Omit it to use the API's default behavior.
500
500
 
501
- Add `"sources": ["alexandria"]` for semantic tool discovery in `data.tools`, optionally mixed with web/news/images. A query is required. Use `firecrawl_find_tools` on the full MCP surface for contextual lookup and progressive disclosure; see [Alexandria Tools](#15-alexandria-tools).
501
+ Add `"sources": ["alexandria"]` for semantic tool discovery in `data.tools`, optionally mixed with web/news/images. A query is required. Use `firecrawl_find_tools` for contextual lookup and progressive disclosure; see [Alexandria Tools](#15-alexandria-tools).
502
502
 
503
503
  For scientific papers, see [Research Tools](#12-research-tools-firecrawl_research_): they search paper abstracts and full text, while `categories: ["research"]` here filters ordinary web results to research-affiliated websites.
504
504
 
@@ -933,7 +933,7 @@ Pass `body` when you need crawl targets, JSON change tracking, custom retention,
933
933
 
934
934
  ### 14. Developer Search Tool (`firecrawl_developer_search`)
935
935
 
936
- Search an index built for coding agents. The index covers GitHub issues, merged pull requests, repository READMEs, and curated documentation sites.
936
+ Search an index built for coding agents. The index covers GitHub issues, merged pull requests, repository READMEs, and code documentation.
937
937
 
938
938
  **Best for:** A programming question — code behaviour, a library or framework, an API contract, an error message, or a known bug.
939
939
 
@@ -983,7 +983,7 @@ query mentions and result URLs in that same array. Check `warning` for unavailab
983
983
  discovery. Search requires a query and does not accept catalogue traversal filters.
984
984
  This discovery works on both the full and search-only MCP surfaces.
985
985
 
986
- **Progressive disclosure (`firecrawl_find_tools`, full MCP surface):**
986
+ **Progressive disclosure (`firecrawl_find_tools`):**
987
987
 
988
988
  ```json
989
989
  {
@@ -1192,7 +1192,7 @@ The CLI discovery sequence maps to these MCP calls:
1192
1192
  | Selected contract | `firecrawl_find_tools` | `{"providers":["<provider-id>"],"capabilities":["<capability-id>"]}` |
1193
1193
  | Execute | `firecrawl_scrape` | `{"alexandria":{"provider":"<provider-id>","capability":"<capability-id>","options":{"<required-field>":"<value>"}}}` |
1194
1194
 
1195
- Use the full MCP surface for Find Tools and execution; the dedicated search-only surface does not expose them. Reuse a complete contract from search when present rather than making another discovery call. Follow returned `nextTool` navigation only when more results are needed.
1195
+ Find Tools and execution are available on both the full surface and the search surface. Reuse a complete contract from search when present rather than making another discovery call. Follow returned `nextTool` navigation only when more results are needed.
1196
1196
 
1197
1197
  ### Alexandria session feedback
1198
1198
 
package/dist/index.js CHANGED
@@ -130,7 +130,10 @@ var findToolsSchema = z2.object({
130
130
  limit: z2.number().int().min(1).max(100).optional(),
131
131
  offset: z2.number().int().nonnegative().optional()
132
132
  }).strict();
133
- var ALEXANDRIA_INSTRUCTIONS = 'Start with the user\u2019s actual question and constraints. On the full MCP surface, first check firecrawl_find_tools for structured records, filterable listings, transcripts, or datasets. Use ordinary search for web research and scrape for a known page; if discovery has no suitable match, continue with web search or Agent. Authenticated search defaults to web + semantic Alexandria tools + domain-matched tools. Keyless search defaults to web only. Alexandria contains ready-made website workflows, API providers and specialized indexes for structured records, listings, company/financial data, research and public records. Coverage varies; discover current tools rather than assuming one exists. Semantic discovery matches the data you need to capabilities even without a provider website in the web results. Domain matching connects result websites to tools that may fetch richer details, related records or collections beyond the linked page. Inspect coverage and required inputs; a matching domain alone does not guarantee a fit. Use sources: ["alexandria"] for semantic tools only, sources: ["web"] for web only, or sources: ["web"], domainTools: true for web plus domain tools. domainTools: false disables domain matching. Results in data.tools describe available tools, not executed data. Search defaults to toolDetail: "compact", returning only provider, capability and description; "summary" adds metadata and navigation. Inspect selected tools with firecrawl_find_tools using their providers and capabilities plus expand:["options","response"]; request examples only when the input shape is unclear. Batch related contract inspections and reuse complete contracts. Alternatively set toolDetail: "full" for contracts upfront. On the full MCP surface, firecrawl_find_tools supports semantic query lookup and is the list equivalent: {} lists categories; {categories:["<category-id>"]} lists providers; {providers:["<provider-id>"]} lists compact tools; adding capabilities:["<capability-id>"] expands the selected contract. Avoid expanding the entire catalogue. Read required inputs and requiresOneOf groups (at least one member per group), example.request/example.response when present, and response.key in the selected contract. Do not assume records is the result key. Follow the declared pagination input and response cursor, preserving filters; catalogue next is separate from provider pagination. Execute through firecrawl_scrape with alexandria:{provider,capability,options}. Search scrapeOptions fetches web pages, never provider tools. Use web results when sufficient, tools when they offer a direct route to deeper data. ' + ALEXANDRIA_FEEDBACK_GUIDANCE;
133
+ var ALEXANDRIA_CATALOGUE_VERTICALS = "companies, people, jobs, finance and filings, public records and government spending, real estate, places and restaurants, retail and prices, package registries and developer data, news, research, and more";
134
+ var ALEXANDRIA_CATALOGUE_SENTENCE = "Alexandria is Firecrawl's catalogue of data providers and workflows across " + ALEXANDRIA_CATALOGUE_VERTICALS + "; providers return typed, sourced records through published contracts.";
135
+ var ALEXANDRIA_SOURCES_OPT_OUT = 'Passing sources without alexandria in it (for example ["web"] or ["news"]) excludes Alexandria provider matches; omit sources unless you specifically need web-only or news-only results, or include "alexandria" alongside them.';
136
+ var ALEXANDRIA_INSTRUCTIONS = "Start with the user\u2019s actual question and constraints. Authenticated search returns matching Alexandria providers beside web results; prefer a provider over page scraping when the task needs the same fields across several entities, provenance, exact figures, or many records, and use web results when they already answer the question. Authenticated search defaults to web + semantic Alexandria tools + domain-matched tools. Keyless search defaults to web only. " + ALEXANDRIA_CATALOGUE_SENTENCE + " Coverage varies; discover current tools rather than assuming one exists. Semantic discovery matches the data you need to capabilities even without a provider website in the web results. Domain matching connects result websites to tools that may fetch richer details, related records or collections beyond the linked page. Inspect coverage and required inputs; a matching domain alone does not guarantee a fit. " + ALEXANDRIA_SOURCES_OPT_OUT + ' Use sources: ["alexandria"] for semantic tools only, sources: ["web"] for web only, or sources: ["web"], domainTools: true for web plus domain tools. domainTools: false disables domain matching. Results in data.tools describe available tools, not executed data. Search defaults to toolDetail: "compact", returning only provider, capability and description; "summary" adds metadata and navigation. Inspect selected tools with firecrawl_find_tools using their providers and capabilities plus expand:["options","response"]; request examples only when the input shape is unclear. Batch related contract inspections and reuse complete contracts. Alternatively set toolDetail: "full" for contracts upfront. On the full MCP surface, firecrawl_find_tools supports semantic query lookup and is the list equivalent: {} lists categories; {categories:["<category-id>"]} lists providers; {providers:["<provider-id>"]} lists compact tools; adding capabilities:["<capability-id>"] expands the selected contract. Avoid expanding the entire catalogue. Read required inputs and requiresOneOf groups (at least one member per group), example.request/example.response when present, and response.key in the selected contract. Do not assume records is the result key. Follow the declared pagination input and response cursor, preserving filters; catalogue next is separate from provider pagination. Execute through firecrawl_scrape with alexandria:{provider,capability,options}. Search scrapeOptions fetches web pages, never provider tools. Use web results when sufficient, tools when they offer a direct route to deeper data. ' + ALEXANDRIA_FEEDBACK_GUIDANCE;
134
137
  function findToolsOptions(args2) {
135
138
  const level = args2.level ?? (args2.query || args2.capabilities?.length || args2.providers?.length || args2.groups?.length || args2.urls?.length ? "tools" : args2.categories?.length ? "providers" : "categories");
136
139
  if (level === "categories" && (args2.query || args2.providers?.length || args2.categories?.length || args2.groups?.length || args2.capabilities?.length || args2.urls?.length || args2.expand !== void 0)) {
@@ -160,7 +163,7 @@ function withFindToolsNavigation(envelope) {
160
163
  if (link(page.next)) page.nextTool = link(page.next);
161
164
  return envelope;
162
165
  }
163
- var ALEXANDRIA_SEARCH_INSTRUCTIONS = 'Authenticated search combines web results, semantic tool summaries and domain matches. Use sources: ["alexandria"] for semantic tools only, or sources: ["web"] for web only. domainTools: false disables domain matching. Tool matches describe available structured-data capabilities, not executed data. toolDetail: "compact" (default) returns only provider, capability and description; "summary" adds metadata; "full" includes their input and output contracts. This search-only surface cannot execute tools or progressively browse the catalogue; those actions require the full MCP surface at /v2/mcp.';
166
+ var ALEXANDRIA_SEARCH_INSTRUCTIONS = 'Authenticated search combines web results, semantic tool summaries and domain matches. Use sources: ["alexandria"] for semantic tools only, or sources: ["web"] for web only. domainTools: false disables domain matching. Tool matches describe available structured-data capabilities, not executed data. toolDetail: "compact" (default) returns only provider, capability and description; "summary" adds metadata; "full" includes their input and output contracts. Execute a matched tool through firecrawl_scrape with an alexandria body; use firecrawl_find_tools to browse the catalogue or read a full contract.';
164
167
 
165
168
  // src/alexandria-output.ts
166
169
  var INLINE_TOKEN_BUDGET = 2e4;
@@ -289,7 +292,7 @@ function registerDeveloperTools(server2, getClient2) {
289
292
  // Query-only; no writes to external sources or the developer index.
290
293
  },
291
294
  description: `
292
- For a developer question \u2014 code behaviour, a library or framework, an API contract, an error message, or a known bug \u2014 search an index built for coding agents. The index covers repositories, GitHub issues, merged pull requests, repository READMEs, and curated documentation sites. Set skills to "only" to limit the search to agent-skill files.
295
+ Search an index of public repositories, GitHub issues, merged pull requests, repository READMEs, and code documentation for programming questions that need external documentation or upstream evidence.
293
296
 
294
297
  Returns ranked results with an ID, source type, URL, title, and the matched passages in markdown.
295
298
  `,
@@ -876,7 +879,7 @@ function fmtPaperMetadata(paper) {
876
879
  function deprecatedGithubPayload() {
877
880
  return {
878
881
  code: "DEPRECATED_TOOL",
879
- message: "firecrawl_research_search_github is deprecated and unavailable through MCP. Use firecrawl_developer_search, which searches GitHub issues, pull requests, and READMEs plus curated documentation sites and returns matched passages. It does not carry over this tool's score breakdown or its web fallback results.",
882
+ message: "firecrawl_research_search_github is deprecated and unavailable through MCP. Use firecrawl_developer_search, which searches GitHub issues, pull requests, and READMEs plus code documentation and returns matched passages. It does not carry over this tool's score breakdown or its web fallback results.",
880
883
  replacement: {
881
884
  name: "firecrawl_developer_search",
882
885
  instructions: 'Pass the same natural-language query. Optionally set k to control the number of results, or set skills to "only" to search only agent-skill files.',
@@ -1062,7 +1065,7 @@ Returns matching passages or a notice when full text is unavailable.
1062
1065
  destructiveHint: false
1063
1066
  },
1064
1067
  description: `
1065
- Deprecated compatibility entry point. Use firecrawl_developer_search for GitHub issues, pull requests, and READMEs, plus curated documentation sites, returned as matched passages.
1068
+ Deprecated compatibility entry point. Use firecrawl_developer_search for GitHub issues, pull requests, and READMEs, plus code documentation, returned as matched passages.
1066
1069
  `,
1067
1070
  parameters: z5.object({
1068
1071
  query: z5.string().min(1),
@@ -1579,6 +1582,7 @@ function makeAuthenticate(profile) {
1579
1582
  return request[authResultByRequest];
1580
1583
  }
1581
1584
  const authResult = authenticateRequest(request, profile).then((session) => {
1585
+ session.profile = profile.id;
1582
1586
  const userAgent = request?.headers?.["user-agent"];
1583
1587
  if (typeof userAgent === "string" && userAgent !== "") {
1584
1588
  session.clientUserAgent = userAgent;
@@ -1643,23 +1647,14 @@ var searchDomainSchema = z7.string().trim().toLowerCase().min(1).max(253).regex(
1643
1647
  /^(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z0-9][a-z0-9-]{0,61}[a-z0-9]$/,
1644
1648
  "Domain must be a valid hostname without protocol or path"
1645
1649
  );
1646
- function buildSearchQueryWithDomains(query, includeDomains, excludeDomains) {
1647
- if (includeDomains?.length) {
1648
- return `${query} (${includeDomains.map((domain) => `site:${domain}`).join(" OR ")})`;
1649
- }
1650
- if (excludeDomains?.length) {
1651
- return `${query} ${excludeDomains.map((domain) => `-site:${domain}`).join(" ")}`;
1652
- }
1653
- return query;
1654
- }
1655
1650
  var searchToolBaseFields = {
1656
- toolDetail: z7.enum(["compact", "summary", "full"]).optional().describe("Compact by default. Compact returns only provider, capability and description; full includes contracts. Inspect selected compact tools on the full MCP surface using firecrawl_find_tools providers and capabilities."),
1657
- query: z7.string().min(1).describe("Query for web and semantic tool discovery. Catalogue browsing is available on the full MCP surface."),
1651
+ toolDetail: z7.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."),
1652
+ query: z7.string().min(1).describe("Query for web and semantic tool discovery. Catalogue browsing is available through firecrawl_find_tools."),
1658
1653
  domainTools: z7.boolean().optional().describe(
1659
1654
  "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."
1660
1655
  ),
1661
1656
  highlights: z7.boolean().optional().describe(
1662
- "Return query-relevant highlights for each search result. Set to false to keep the original search snippets."
1657
+ "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."
1663
1658
  ),
1664
1659
  limit: z7.number().int().min(1).max(100).optional(),
1665
1660
  tbs: z7.string().optional(),
@@ -1667,9 +1662,9 @@ var searchToolBaseFields = {
1667
1662
  location: z7.string().optional(),
1668
1663
  includeDomains: z7.array(searchDomainSchema).optional(),
1669
1664
  excludeDomains: z7.array(searchDomainSchema).optional(),
1670
- sources: z7.array(searchSourceSchema).optional().describe("Search sources; authenticated sessions default to web + alexandria, keyless sessions to web only. Use alexandria alone for semantic tool discovery."),
1671
- categories: z7.array(z7.enum(["github", "research", "pdf", "developer"])).optional().describe(
1672
- 'Limit results to specific source types. `github` searches GitHub repositories, code, issues, and docs; `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 repositories, GitHub issues, merged pull requests, repository READMEs, and curated documentation sites. `developer` returns hits in `data.web` with `category: "developer"`; the other categories also filter `data.web`.'
1665
+ sources: z7.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.'),
1666
+ categories: z7.array(z7.enum(["research", "pdf", "developer"])).optional().describe(
1667
+ '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`.'
1673
1668
  ),
1674
1669
  enterprise: z7.array(z7.enum(["default", "anon", "zdr"])).optional()
1675
1670
  };
@@ -1849,9 +1844,10 @@ var ConsoleLogger = class {
1849
1844
  var openAiAppsChallengeToken = normalizeHeader(
1850
1845
  process.env.OPENAI_APPS_CHALLENGE_TOKEN
1851
1846
  );
1852
- var FULL_PROFILE_INSTRUCTIONS = `Execution with firecrawl_scrape alexandria uses requestId; reuse the returned ID for retries of the same payload, never a new ID to bypass a pending or uncertain 409. 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. 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 \u2014 code behaviour, a library or framework, an API contract, an error message, or a known bug \u2014 firecrawl_developer_search (or firecrawl_search with categories: ["developer"]) searches an index of repositories, GitHub issues, merged pull requests, READMEs, and curated documentation sites. For structured records, filterable listings, transcripts, or datasets, first check firecrawl_find_tools for a suitable workflow or data provider. Use firecrawl_search for ordinary web research and firecrawl_scrape for a known page. If discovery has no suitable match, continue with web search or firecrawl_agent. 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. A terms-gated Alexandria provider fails with code THIRD_PARTY_DATA_TERMS_REQUIRED and a requiresAction.url. Follow the returned terms/show and terms/accept calls through firecrawl_scrape; acceptance requires explicit user authorization for the reviewed version and digest and confirmed:true. Otherwise direct an organization admin to the dashboard URL. Do not repeat successful provider calls just because the client could not display their output. Provide only the required inputs and account for stated network or external side effects. ${ALEXANDRIA_FEEDBACK_GUIDANCE}`;
1853
- 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 repositories, GitHub issues, merged pull requests, repository READMEs, and curated documentation sites. 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.`;
1854
- var SEARCH_PROFILE_INSTRUCTIONS = ALEXANDRIA_SEARCH_INSTRUCTIONS + ` Firecrawl provides web, developer, and research search. Use firecrawl_search to find relevant results across the web and specialized indexes. For a programming question, firecrawl_developer_search searches indexed repositories, GitHub issues, merged pull requests, READMEs, and curated documentation sites 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. All tools are read-only and return ranked results.`;
1847
+ var FULL_PROFILE_INSTRUCTIONS = `Execution with firecrawl_scrape alexandria uses requestId; reuse the returned ID for retries of the same payload, never a new ID to bypass a pending or uncertain 409. 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. 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 \u2014 code behaviour, a library or framework, an API contract, an error message, or a known bug \u2014 firecrawl_developer_search (or firecrawl_search with categories: ["developer"]) searches an index of public repositories, GitHub issues, merged pull requests, READMEs, and code documentation. Authenticated firecrawl_search returns web results together with matching Alexandria providers in data.tools. ${ALEXANDRIA_CATALOGUE_SENTENCE} When a provider matches, prefer it over scraping pages if the task needs the same fields across several entities, provenance, exact figures or timestamps, or a large set of records; execute it through firecrawl_scrape with the returned contract. If web results already answer the question, use them. Before scraping more than one page for the same fields, spend one free firecrawl_find_tools call to check for a provider. 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. 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. A terms-gated Alexandria provider fails with code THIRD_PARTY_DATA_TERMS_REQUIRED and a requiresAction.url. Follow the returned terms/show and terms/accept calls through firecrawl_scrape; acceptance requires explicit user authorization for the reviewed version and digest and confirmed:true. Otherwise direct an organization admin to the dashboard URL. Do not repeat successful provider calls just because the client could not display their output. Provide only the required inputs and account for stated network or external side effects.
1848
+ ${ALEXANDRIA_FEEDBACK_GUIDANCE}`;
1849
+ 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.`;
1850
+ 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. Use firecrawl_find_tools to browse the Alexandria catalogue or read a provider's full contract, and firecrawl_scrape with an alexandria body to execute a capability discovered that way; 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.`;
1855
1851
  var SEARCH_PROFILE_TOOLS = /* @__PURE__ */ new Set([
1856
1852
  "firecrawl_search",
1857
1853
  "firecrawl_developer_search",
@@ -1859,10 +1855,18 @@ var SEARCH_PROFILE_TOOLS = /* @__PURE__ */ new Set([
1859
1855
  "firecrawl_research_inspect_paper",
1860
1856
  "firecrawl_research_related_papers",
1861
1857
  "firecrawl_research_read_paper",
1858
+ // Alexandria: catalogue lookup and provider execution.
1859
+ "firecrawl_find_tools",
1860
+ "firecrawl_scrape",
1862
1861
  // Registered so cached sessions get a DEPRECATED_TOOL payload, hidden from
1863
1862
  // tools/list via canList. See registerResearchTools.
1864
1863
  "firecrawl_research_search_github"
1865
1864
  ]);
1865
+ var SEARCH_SURFACE_VARIANT_TOOLS = /* @__PURE__ */ new Set([
1866
+ "firecrawl_search",
1867
+ "firecrawl_scrape",
1868
+ "firecrawl_find_tools"
1869
+ ]);
1866
1870
  function makeFullProfile() {
1867
1871
  const account = getPrimaryEndpoint() === "/v2/mcp-oauth";
1868
1872
  const hasCredential2 = Boolean(resolveCredentialFromEnv());
@@ -2174,7 +2178,7 @@ server.addTool = ((tool) => {
2174
2178
  if (primaryProfile.toolAllowlist && !primaryProfile.toolAllowlist.has(tool.name)) {
2175
2179
  return;
2176
2180
  }
2177
- if (primaryProfile.id === "search" && tool.name === "firecrawl_search") {
2181
+ if (primaryProfile.id === "search" && SEARCH_SURFACE_VARIANT_TOOLS.has(tool.name)) {
2178
2182
  return;
2179
2183
  }
2180
2184
  addTool(guardHostedTool(tool, { logActions: primaryProfile.id !== "search" }));
@@ -2680,7 +2684,7 @@ async function executeHostedParse(args2, session, log, origin) {
2680
2684
  );
2681
2685
  return asText3(parseJson);
2682
2686
  }
2683
- server.addTool({
2687
+ var scrapeTool = {
2684
2688
  name: "firecrawl_scrape",
2685
2689
  annotations: {
2686
2690
  title: "Firecrawl scrape",
@@ -2694,12 +2698,14 @@ server.addTool({
2694
2698
  description: `
2695
2699
  Retrieve and extract content from one supplied URL through Firecrawl. Use this when the request identifies a page and needs its content or defined fields. It can return markdown, HTML, links, screenshots, branding data, a targeted answer, or JSON matching a supplied schema; JSON is useful when the requested result has defined fields, while markdown preserves readable page content.
2696
2700
 
2697
- This tool operates on a known page. For a set of pages use \`firecrawl_crawl\`, and to discover page URLs use \`firecrawl_map\` or \`firecrawl_search\`. Options include JavaScript render delay, cache age, main-content filtering, PII redaction, and lockdown cache-only retrieval. Browser actions may change the live page when interactive actions are enabled.
2701
+ This tool operates on a known page. Use \`firecrawl_search\` when additional web sources are needed. For a set of pages use \`firecrawl_crawl\`, and to discover page URLs use \`firecrawl_map\`. Options include JavaScript render delay, cache age, main-content filtering, PII redaction, and lockdown cache-only retrieval. Browser actions may change the live page when interactive actions are enabled.
2698
2702
 
2699
2703
  Firecrawl may reuse recently indexed content instead of refetching the page, and the reuse window varies by domain. Set \`maxAge: 0\` to force a live fetch, or a smaller \`maxAge\` to bound how stale reused content may be. A successful response does not by itself confirm that the state it describes is still current.
2700
2704
 
2701
2705
  Returns the selected content formats and page metadata. Authenticated responses can include a \`metadata.scrapeId\` for optional scrape feedback.
2702
2706
 
2707
+ On an authenticated session with Alexandria access, if you are about to scrape the same fields from several pages, first run \`firecrawl_search\` with \`sources\` unset (or \`firecrawl_find_tools\`): a matching Alexandria provider returns those fields as typed records in one call. Keyless sessions have no provider matches; scrape directly.
2708
+ Alexandria mode: pass \`alexandria\` (one \`{provider, capability, options}\` object or an array of 1-10) instead of \`url\` to execute catalogued Alexandria capabilities found through \`firecrawl_search\` sources \`alexandria\` or \`firecrawl_find_tools\`. The optional requestId identifies one logical execution: reuse the returned ID for retries of the identical payload, never a new ID to bypass pending or uncertain execution. Each call may include version to pin a published workflow; omitting it uses latest. Only timeout also applies at the top level in this mode. Returns per-capability results in \`data.alexandria\`, including \`data\`, \`records\`, or an \`error\` with a code. Check each item for errors even when the outer response is successful. Alexandria needs an API key on a team with Alexandria enabled.
2703
2709
  Alexandria mode: pass \`alexandria\` (one \`{provider, capability, options}\` object or an array of 1-10) instead of \`url\` to execute catalogued Alexandria capabilities found through \`firecrawl_search\` sources \`alexandria\` or \`firecrawl_find_tools\`. The optional requestId identifies one logical execution: reuse the returned ID for retries of the identical payload, never a new ID to bypass pending or uncertain execution. Each call may include version to pin a published workflow; omitting it uses latest. Only timeout also applies at the top level in this mode. Returns per-capability results in \`data.alexandria\`, including \`data\`, \`records\`, or an \`error\` with a code. Check each item for errors even when the outer response is successful. Alexandria needs an API key on a team with Alexandria enabled. Alexandria results include a \`feedbackTool\` pointer: after the task, report how the catalogue served the website through \`firecrawl_feedback\` with endpoint \`alexandria\` (free, no job ID).
2704
2710
 
2705
2711
  For potentially large workflow results, supply and preserve a top-level requestId before execution. If a response provides nextTool, follow its instructions to access the result without repeating a successful provider call.
@@ -2755,7 +2761,8 @@ Alexandria execution errors relay a \`code\` and \`chargeId\`: \`request_in_flig
2755
2761
  );
2756
2762
  return asText3(res);
2757
2763
  }
2758
- });
2764
+ };
2765
+ server.addTool(scrapeTool);
2759
2766
  server.addTool({
2760
2767
  name: "firecrawl_map",
2761
2768
  annotations: {
@@ -2804,13 +2811,13 @@ server.addTool({
2804
2811
  // Query-only; no destructive side effects on external entities.
2805
2812
  },
2806
2813
  description: `
2807
- Search web, news, or image sources and return ranked results. 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 results to GitHub, research, PDF, or developer sources.
2814
+ Search web, news, or image sources and return ranked results with query-relevant highlights. 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 results to research, PDF, or developer sources.
2808
2815
 
2809
- For a programming question, add \`categories: ["developer"]\`. It searches an index of repositories, GitHub issues, merged pull requests, repository READMEs, and curated documentation sites, and returns the hits in \`data.web\` with \`category: "developer"\`.
2816
+ 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"\`.
2810
2817
 
2811
2818
  \`categories: ["research"]\` restricts these web results to research-affiliated websites and returns page snippets. The \`firecrawl_research_*\` tools are a separate surface that searches paper abstracts and full text across biomedical (PubMed, bioRxiv, medRxiv) and arXiv literature.
2812
2819
 
2813
- Each web result is a title, URL, and description, not the page. Add \`scrapeOptions\` to attach page content in the same call; those fetches ignore \`maxAge\`, so use \`firecrawl_scrape\` when you need a live fetch. Returns source-type result groups and usage metadata. Authenticated responses can include an \`id\` for optional search feedback.
2820
+ Each web result is a title, URL, and description. Highlights appear in web \`description\` and news \`snippet\`; otherwise, original snippets are returned. If excerpts are insufficient, use \`firecrawl_scrape\` to retrieve content from relevant result URLs. Add \`scrapeOptions\` to attach page content in the same call; those fetches ignore \`maxAge\`, so use \`firecrawl_scrape\` when you need a live fetch. Returns source-type result groups and usage metadata. Authenticated responses can include an \`id\` for optional search feedback.
2814
2821
 
2815
2822
  ${ALEXANDRIA_INSTRUCTIONS}
2816
2823
  `,
@@ -2831,21 +2838,13 @@ ${ALEXANDRIA_INSTRUCTIONS}
2831
2838
  };
2832
2839
  searchOpts.domainTools ??= defaultDomainTools(searchOpts.sources);
2833
2840
  searchOpts.toolDetail ??= "compact";
2834
- const includeDomains = searchOpts.includeDomains;
2835
- const excludeDomains = searchOpts.excludeDomains;
2836
- delete searchOpts.includeDomains;
2837
- delete searchOpts.excludeDomains;
2838
2841
  if (searchOpts.scrapeOptions) {
2839
2842
  searchOpts.scrapeOptions = transformScrapeParams(
2840
2843
  searchOpts.scrapeOptions
2841
2844
  );
2842
2845
  }
2843
2846
  const cleaned = removeEmptyTopLevel(searchOpts);
2844
- const searchQuery = buildSearchQueryWithDomains(
2845
- query ?? "",
2846
- includeDomains,
2847
- excludeDomains
2848
- );
2847
+ const searchQuery = query ?? "";
2849
2848
  log.info("Searching", { query: searchQuery });
2850
2849
  const searchBody = {
2851
2850
  query: searchQuery,
@@ -2905,7 +2904,7 @@ async function executeExchangeCalls(session, alexandria, suppliedRequestId, time
2905
2904
  return result?.data;
2906
2905
  },
2907
2906
  randomUUID(),
2908
- alexandriaFeedbackAvailable() && alexandriaCallsWarrantFeedback(calls) ? { feedbackTool: ALEXANDRIA_FEEDBACK_HINT } : {}
2907
+ alexandriaFeedbackAvailable(session) && alexandriaCallsWarrantFeedback(calls) ? { feedbackTool: ALEXANDRIA_FEEDBACK_HINT } : {}
2909
2908
  );
2910
2909
  } catch (error) {
2911
2910
  if (error?.response?.status === 401) throw error;
@@ -2915,7 +2914,7 @@ async function executeExchangeCalls(session, alexandria, suppliedRequestId, time
2915
2914
  );
2916
2915
  }
2917
2916
  }
2918
- server.addTool({
2917
+ var findToolsTool = {
2919
2918
  name: "firecrawl_find_tools",
2920
2919
  annotations: {
2921
2920
  title: "Find Tools",
@@ -2924,7 +2923,7 @@ server.addTool({
2924
2923
  destructiveHint: false,
2925
2924
  idempotentHint: true
2926
2925
  },
2927
- description: "Find ready-made workflows, data APIs, and indexes for structured data beyond a single webpage. Check here first for filterable records, listings, transcripts, or datasets. Use query for semantic discovery or urls to find tools for a website. With no arguments, browse categories, then providers and tools. Inspect a selected contract before executing through firecrawl_scrape; reuse contracts already returned. Follow nextTool for further discovery or pagination. Discovery does not execute providers. Use firecrawl_search when you also need web results. Results include a feedbackTool pointer: after the task, report how the catalogue served the website through firecrawl_feedback with endpoint alexandria, including when nothing covered it (free, no job ID).",
2926
+ description: "Browse Alexandria data providers and workflows or read a selected contract. Alexandria covers " + ALEXANDRIA_CATALOGUE_VERTICALS + ": typed, sourced records through published contracts. Prefer normal firecrawl_search for a data task; it already returns matching providers. Use this tool when the contract you need was not returned in full, to browse a category when search found nothing, or before scraping the same fields from several pages. Discovery is free. Use query for semantic discovery or urls to find providers for a website. With no arguments, browse categories, then providers and tools. Inspect a selected contract before executing through firecrawl_scrape; reuse contracts already returned. Follow nextTool for further discovery or pagination. Discovery does not execute providers. Use firecrawl_search when you also need web results. Results include a feedbackTool pointer: after the task, report how the catalogue served the website through firecrawl_feedback with endpoint alexandria, including when nothing covered it (free, no job ID).",
2928
2927
  parameters: findToolsSchema,
2929
2928
  execute: async (args2, { session, client: mcpClient }) => {
2930
2929
  const origin = requestOrigin(mcpClient, session);
@@ -2952,12 +2951,36 @@ server.addTool({
2952
2951
  }));
2953
2952
  const page = { level: "categories", items, total: rows.length };
2954
2953
  if (offset + options.limit < rows.length) page.nextTool = { name: "firecrawl_find_tools", arguments: { level: "categories", limit: options.limit, offset: offset + options.limit } };
2955
- return compactText(withAlexandriaFeedbackHint(withFindToolsNavigation({ success: true, data: { creditsCost: 0, alexandria: [{ provider: "firecrawl", capability: "find-tools", creditsCost: 0, data: page }] } }), alexandriaFeedbackAvailable()));
2954
+ return compactText(withAlexandriaFeedbackHint(withFindToolsNavigation({ success: true, data: { creditsCost: 0, alexandria: [{ provider: "firecrawl", capability: "find-tools", creditsCost: 0, data: page }] } }), alexandriaFeedbackAvailable(session)));
2956
2955
  }
2957
2956
  const result = await executeExchangeCalls(session, { provider: "firecrawl", capability: "find-tools", options }, void 0, void 0, origin);
2958
2957
  return compactText(withFindToolsNavigation(JSON.parse(result)));
2959
2958
  }
2960
- });
2959
+ };
2960
+ server.addTool(findToolsTool);
2961
+ var SEARCH_SURFACE_SCRAPE_DESCRIPTION = `
2962
+ Retrieve and extract content from one supplied URL through Firecrawl, or execute catalogued Alexandria capabilities. Use URL mode when the request identifies a page and needs its content or defined fields. It can return markdown, HTML, links, screenshots, branding data, a targeted answer, or JSON matching a supplied schema; JSON is useful when the requested result has defined fields, while markdown preserves readable page content. Options include JavaScript render delay, cache age, main-content filtering, PII redaction, and lockdown cache-only retrieval. Browser actions may change the live page when interactive actions are enabled. A named browser profile can load saved session data and overwrite its stored state.
2963
+
2964
+ Firecrawl may reuse recently indexed content instead of refetching the page, and the reuse window varies by domain. Set \`maxAge: 0\` to force a live fetch, or a smaller \`maxAge\` to bound how stale reused content may be. A successful response does not by itself confirm that the state it describes is still current. URL mode returns the selected content formats and page metadata.
2965
+
2966
+ Before scraping the same fields from several pages, first run \`firecrawl_search\` with \`sources\` unset (or \`firecrawl_find_tools\`): a matching Alexandria provider returns those fields as typed records in one call.
2967
+ Alexandria mode: pass \`alexandria\` (one \`{provider, capability, options}\` object or an array of 1-10) instead of \`url\` to execute catalogued Alexandria capabilities found through \`firecrawl_search\` sources \`alexandria\` or \`firecrawl_find_tools\`. The optional requestId identifies one logical execution: reuse the returned ID for retries of the identical payload, never a new ID to bypass pending or uncertain execution. Each call may include version to pin a published workflow; omitting it uses latest. Only timeout also applies at the top level in this mode. Returns per-capability results in \`data.alexandria\`, including \`data\`, \`records\`, or an \`error\` with a code. Check each item for errors even when the outer response is successful. Alexandria execution is billed at the capability's listed price and needs a team with Alexandria enabled.
2968
+
2969
+ For potentially large workflow results, supply and preserve a top-level requestId before execution. If a response provides nextTool, follow its instructions to access the result without repeating a successful provider call.
2970
+
2971
+ URL mode only: set \`domainTools: true\` to also return domain-matched Alexandria tools for the page in \`tools\` on the returned document.
2972
+
2973
+ Alexandria execution errors relay a \`code\` and \`chargeId\`: \`request_in_flight\` (409) retry the same requestId later; \`request_unresolved\` (503) keep the requestId for reconciliation, never mint a new one; \`duplicate_request\` (409) the requestId belongs to a different payload; \`unknown_provider\` (404), \`insufficient_credits\` (402), and \`billing_unavailable\` (503) mean nothing executed. A terms-gated Alexandria provider returns \`THIRD_PARTY_DATA_TERMS_REQUIRED\` (403) with \`requiresAction.url\`: follow the returned terms/show and terms/accept calls through this tool, only accepting after explicit user authorization for the reviewed version and digest. An organization admin can alternatively accept at the dashboard URL. Retry only after confirmed acceptance.
2974
+ `;
2975
+ var searchSurfaceScrapeTool = {
2976
+ ...scrapeTool,
2977
+ description: SEARCH_SURFACE_SCRAPE_DESCRIPTION
2978
+ };
2979
+ var SEARCH_SURFACE_FIND_TOOLS_DESCRIPTION = "Browse Alexandria data providers and workflows or read a selected contract. Alexandria covers " + ALEXANDRIA_CATALOGUE_VERTICALS + ": typed, sourced records through published contracts. Prefer normal firecrawl_search for a data task; it already returns matching providers. Use this tool when the contract you need was not returned in full, to browse a category when search found nothing, or before scraping the same fields from several pages. Discovery is free. Use query for semantic discovery or urls to find providers for a website. With no arguments, browse categories, then providers and tools. Inspect a selected contract before executing through firecrawl_scrape; reuse contracts already returned. Follow nextTool for further discovery or pagination. Discovery does not execute providers. Use firecrawl_search when you also need web results.";
2980
+ var searchSurfaceFindToolsTool = {
2981
+ ...findToolsTool,
2982
+ description: SEARCH_SURFACE_FIND_TOOLS_DESCRIPTION
2983
+ };
2961
2984
  var DEFAULT_CLOUD_API_URL = "https://api.firecrawl.dev";
2962
2985
  function resolveApiBaseUrl() {
2963
2986
  return (process.env.FIRECRAWL_API_URL || DEFAULT_CLOUD_API_URL).replace(
@@ -3246,8 +3269,8 @@ if (ENDPOINT_FEEDBACK_DISABLED) {
3246
3269
  "[firecrawl-mcp] Endpoint feedback tool disabled by FIRECRAWL_NO_ENDPOINT_FEEDBACK; firecrawl_feedback will not be registered."
3247
3270
  );
3248
3271
  }
3249
- function alexandriaFeedbackAvailable() {
3250
- return !ENDPOINT_FEEDBACK_DISABLED && !isLocalKeylessStartup();
3272
+ function alexandriaFeedbackAvailable(session) {
3273
+ return !ENDPOINT_FEEDBACK_DISABLED && !isLocalKeylessStartup() && session?.profile !== "search";
3251
3274
  }
3252
3275
  if (alexandriaFeedbackAvailable()) {
3253
3276
  server.addTool({
@@ -3782,9 +3805,9 @@ function registerMarketplaceSearchTool(registrar, getClientFn) {
3782
3805
  destructiveHint: false
3783
3806
  },
3784
3807
  description: `
3785
- Search web and specialized indexes, returning ranked results. Each web result is a title, URL, and description, not the page. 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 \`github\`, \`research\`, \`pdf\`, or \`developer\`.
3808
+ 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\`.
3786
3809
 
3787
- For a programming question, add \`categories: ["developer"]\`. It searches an index of repositories, GitHub issues, merged pull requests, repository READMEs, and curated documentation sites, and returns the hits in \`data.web\` with \`category: "developer"\`.
3810
+ 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"\`.
3788
3811
 
3789
3812
  ${ALEXANDRIA_SEARCH_INSTRUCTIONS}
3790
3813
 
@@ -3792,7 +3815,7 @@ Returns result groups in \`data\` and an operation \`id\`.
3792
3815
  `,
3793
3816
  parameters: z7.object({ ...searchToolBaseFields }).strict().refine(searchDomainsAreExclusive, SEARCH_DOMAINS_CONFLICT_MESSAGE).refine(
3794
3817
  searchQueryIsValid,
3795
- "A query is required. Catalogue browsing requires the full MCP surface."
3818
+ "A query is required. Use firecrawl_find_tools to browse the catalogue."
3796
3819
  ),
3797
3820
  execute: async (args2, { session, log, client: mcpClient }) => {
3798
3821
  const {
@@ -3810,15 +3833,13 @@ Returns result groups in \`data\` and an operation \`id\`.
3810
3833
  domainTools,
3811
3834
  toolDetail
3812
3835
  } = args2;
3813
- const searchQuery = buildSearchQueryWithDomains(
3814
- query ?? "",
3815
- includeDomains,
3816
- excludeDomains
3817
- );
3836
+ const searchQuery = query ?? "";
3818
3837
  const searchBody = {
3819
3838
  query: searchQuery,
3820
3839
  ...removeEmptyTopLevel({
3821
3840
  limit,
3841
+ includeDomains,
3842
+ excludeDomains,
3822
3843
  tbs,
3823
3844
  filter,
3824
3845
  location,
@@ -3883,6 +3904,8 @@ if (primaryProfile.id === "search") {
3883
3904
  })
3884
3905
  };
3885
3906
  registerMarketplaceSearchTool(primarySearchRegistrar, getClient);
3907
+ primarySearchRegistrar.addTool(searchSurfaceFindToolsTool);
3908
+ primarySearchRegistrar.addTool(searchSurfaceScrapeTool);
3886
3909
  }
3887
3910
  await server.start(args);
3888
3911
  var searchProfileEnabled = process.env.CLOUD_SERVICE === "true" && primaryProfile.id === "full" && process.env.FIRECRAWL_MCP_SEARCH_ENABLED !== "false";
@@ -3901,6 +3924,8 @@ if (searchProfileEnabled) {
3901
3924
  registerResearchTools(searchRegistrar, getClient);
3902
3925
  registerDeveloperTools(searchRegistrar, getClient);
3903
3926
  registerMarketplaceSearchTool(searchRegistrar, getClient);
3927
+ searchRegistrar.addTool(searchSurfaceFindToolsTool);
3928
+ searchRegistrar.addTool(searchSurfaceScrapeTool);
3904
3929
  try {
3905
3930
  await searchServer.start({
3906
3931
  transportType: "httpStream",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "firecrawl-mcp",
3
- "version": "3.25.1",
3
+ "version": "3.25.3",
4
4
  "description": "MCP server for Firecrawl — search, scrape, and interact with the web, and search scientific papers. Supports both cloud and self-hosted instances. Features include web search, scraping, page interaction, batch processing, LLM-powered content analysis, and research paper search over biomedical and arXiv literature (PubMed, bioRxiv, medRxiv, arXiv) with citation-graph expansion and full-text reading.",
5
5
  "type": "module",
6
6
  "mcpName": "io.github.firecrawl/firecrawl-mcp-server",