Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,13 @@

- `firecrawl_agent` now exposes the optional `effort` (`low`, `medium`, `high`), `maxCredits`, and `strictConstrainToURLs` parameters that `POST /v2/agent` already accepts, and forwards them in the request body.
- `firecrawl_agent` can continue a thread: it accepts `threadId` and `mode` (`"extract"` or `"chat"`) and forwards them to `POST /v2/agent` through the SDK. On a follow-up, omitted `mode`, `urls` and `schema` carry over from the previous turn. `firecrawl_agent_status` now keeps `message` and `suggestions` in its structured content, next to `threadId` and `threadTurn`.
- `firecrawl_agent` accepts an `exchange` object that mirrors the API's (`enabled`, `toolkits` (at most 5), `maxCalls`, `requireApproval`, `approve: { approvalId, callIds?, always? }`, `decline: { approvalId }`, `onTermsRequired`) and forwards it to `POST /v2/agent` through the SDK. `exchange.onTermsRequired` (`"skip"` or `"ask"`) controls Alexandria providers whose data terms the team has not accepted; they are never called. After an ask-mode terms offer and the user's explicit consent to `terms/accept`, a caller answers the offer on the same thread with `exchange.approve: { approvalId }` (or `exchange.decline`) instead of starting over. `approve` and `decline` require `threadId` and cannot be sent together, and `exchange.requireApproval` requires `mode: "chat"` on the same call. There is no auto-accept. `firecrawl_agent_status` now keeps `exchange` (including `skippedProviders` and `requiresAction`, whose provider `digest` is `string | null` and always present) and `pendingApproval` in its structured content.
- `firecrawl_agent` accepts an `exchange` object that mirrors the API's (`enabled`, `toolkits` (at most 5), `maxCalls`, `requireApproval`, `approve: { approvalId, callIds?, always? }`, `decline: { approvalId }`, `onTermsRequired`) and forwards it to `POST /v2/agent` through the SDK. `exchange.onTermsRequired` (`"skip"` or `"ask"`) controls Alexandria providers whose data terms the team has not accepted; they are never called. After an ask-mode terms offer and an organization admin's confirmed dashboard acceptance, a caller resumes the same thread with `exchange.approve: { approvalId }` (or declines with `exchange.decline`) instead of starting over. Approval does not accept terms. `approve` and `decline` require `threadId` and cannot be sent together, and `exchange.requireApproval` requires `mode: "chat"` on the same call. There is no auto-accept. `firecrawl_agent_status` now keeps `exchange` (including `skippedProviders` and `requiresAction`, whose provider `digest` is `string | null` and always present) and `pendingApproval` in its structured content.

### Changed

- Server instructions are one short string per surface (full, search, keyless). Each stays under 1,024 characters, routes search and scrape within its first 512, and names only tools that session lists. Hosted `/v2/mcp` now selects them per session, so a session with an API key or OAuth token gets the full-surface instructions instead of the keyless ones. Locally, only stdio without an API key, OAuth token, or `FIRECRAWL_API_URL` gets the keyless instructions; a self-hosted `FIRECRAWL_API_URL` and the local HTTP transport, which requires credentials or `FIRECRAWL_API_URL`, get the full-surface instructions.
- An organization admin now accepts Alexandria provider terms in the Firecrawl dashboard. `firecrawl_scrape` refuses `terms/accept` and every other `terms/*` capability except `terms/show`, and terms errors link to `requiresAction.url` or the data sources settings page. Reading terms with `terms/show` is unchanged.
- On the hosted server, `firecrawl_scrape` is annotated `readOnlyHint: true` again. There, `firecrawl_scrape` uses the top-level `profile` parameter and `firecrawl_search` uses `scrapeOptions.profile` to load saved browser state without saving changes to it; save browser state with `firecrawl_interact` and `scrapeOptions.profile`. Local scrape and search keep browser actions and writable profiles and are annotated `readOnlyHint: false`.
- `tools/list` now sends each tool's top-level `title` (MCP 2025-06-18), copied from `annotations.title`. The title wording is unchanged. Clients that read only the top-level field, such as Codex's tool search, now see the same display names.
- The npm package now bundles the pnpm-patched fastmcp. npm does not apply pnpm patches, so `npx firecrawl-mcp` installs were loading unpatched fastmcp from the registry, without the top-level titles or the `canList` and `beforeValidate` hooks. fastmcp's runtime imports (`@modelcontextprotocol/sdk`, `fuse.js`, `hono`, `mcp-proxy`, `undici`, `uri-templates`, `xsschema`) are now direct dependencies so they resolve under pnpm's non-hoisted layout too.
- Keyless recovery messages now link to the caller's own signup link, `https://firecrawl.dev/k/<token>` (a 12-character encrypted token), instead of `/app/api-keys`. The API issues the link (the `signup_url` of a keyless 429, or `signupUrl` from the eligibility check, which the server now also asks for when a keyless session calls an account-only tool) and the site decrypts it to MCP keyless attribution. When the API can't give one it sends the regular keyless signup link, which is relayed as is; with no API link at all the message uses the regular MCP signup link (`signin?utm_source=keyless&utm_medium=mcp`). Recovery payloads carry the link as `signup_url`. Signed-in users who open it land on the API keys page.
Expand Down
36 changes: 18 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ A Model Context Protocol (MCP) server that brings [Firecrawl](https://github.com
- Use `firecrawl_credit_usage` to check credits left or monthly consumption, optionally broken down by API key.
- 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.

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).
This server lists 27 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).

## Installation

Expand Down Expand Up @@ -419,6 +419,7 @@ Scrape content from a single URL with advanced options.

**Branding format:** Extracts comprehensive brand identity (colors, fonts, typography, spacing, logo, UI components) for design analysis or style replication.
**Privacy:** Set `redactPII: true` to return content with personally identifiable information redacted.
**Hosted server:** On the hosted server (`CLOUD_SERVICE=true`) scrape is read-only. It takes no browser `actions`, and a named `profile` loads saved browser state without saving changes to it. To save browser state to a profile, open the page with `firecrawl_interact` (see below).

**Returns:**

Expand Down Expand Up @@ -747,17 +748,17 @@ The agent performs web searches, follows links, reads pages, and gathers data au
- `enabled`, `toolkits` (up to 5 provider slugs), `maxCalls` (1 to 30), `requireApproval` (paid calls end the turn with a `pendingApproval`; needs `mode: "chat"` on the same call, even on a follow-up)
- `onTermsRequired`: what to do when an Alexandria provider the agent would use needs data terms your team has not accepted. Gated providers are never called in any mode. Omitted on a follow-up keeps the previous turn's value.
- `"skip"` (default): answer with accepted providers only. `exchange.skippedProviders` on the status result lists the gated providers that would have helped.
- `"ask"`: the same, plus a terms `pendingApproval` and `exchange.requiresAction` with the exact `terms/show` and `terms/accept` calls for each provider. Each provider's `digest` is always present and is `string | null`; when it is `null`, `terms/show` returns the current digest to send.
- `"ask"`: the same, plus a terms `pendingApproval` and `exchange.requiresAction` with the approval ID and provider requirements. Read terms with `terms/show`; an organization admin accepts them in the Firecrawl dashboard.
- `approve`: `{ approvalId, callIds?, always? }` answers yes to the `pendingApproval` the previous turn ended on. `callIds` and `always` apply to paid-call approvals only.
- `decline`: `{ approvalId }` answers no. A declined terms offer keeps those providers out of the rest of the thread.
- `approve` and `decline` need `threadId`, and only one of them can be sent.

**Provider terms (ask mode):** there is no auto-accept mode. When a turn ends on a terms offer, the status result carries `pendingApproval` (`kind: "terms"`) and `exchange.requiresAction` with the `approvalId` and the exact `terms/show` and `terms/accept` calls. To use the provider:
**Provider terms (ask mode):** there is no auto-accept mode. When a turn ends on a terms offer, the status result carries `pendingApproval` (`kind: "terms"`) and `exchange.requiresAction` with the `approvalId` and provider requirements. Any `terms/accept` descriptor in that API payload is unavailable through MCP. To use the provider:

1. Show the user the terms (`terms/show` through `firecrawl_scrape` with `alexandria`).
2. Get the user's explicit consent to that provider's terms. A data request is not consent.
3. Run the `terms/accept` call through `firecrawl_scrape`.
4. Continue the same thread: call `firecrawl_agent` with the same `threadId` and `exchange.approve: { "approvalId": "..." }`.
2. Direct an organization admin to accept the terms at the provider's URL, or [data sources settings](https://www.firecrawl.dev/app/settings?tab=data-sources). A data request is not consent.
3. Wait for the admin to confirm acceptance in the dashboard.
4. Continue the same thread: call `firecrawl_agent` with the same `threadId` and `exchange.approve: { "approvalId": "..." }`. This resumes research and does not accept terms.

If the user says no, call `firecrawl_agent` with the same `threadId` and `exchange.decline: { "approvalId": "..." }` instead.

Expand Down Expand Up @@ -818,13 +819,13 @@ Then poll with `firecrawl_agent_status` using the returned job ID.
}
```

**Usage Example (continue the thread after the user accepted a provider's terms):**
**Usage Example (continue the thread after an admin confirmed dashboard acceptance):**

```json
{
"name": "firecrawl_agent",
"arguments": {
"prompt": "I accepted the Apollo terms. Continue.",
"prompt": "The admin confirmed acceptance of the Apollo terms in the dashboard. Continue.",
"threadId": "0199a1b2-0000-7000-8000-000000000031",
"exchange": { "approve": { "approvalId": "0199a1b2-0000-7000-8000-000000000033" } }
}
Expand Down Expand Up @@ -867,6 +868,7 @@ Interact with a fresh URL or with a page that was already opened by `firecrawl_s
- Pass `url` to scrape and open a page for interaction in one MCP call.
- Pass `scrapeId` to continue interacting with an existing scraped page.
- Pass exactly one of `url` or `scrapeId`, plus either `prompt` or `code`.
- To save browser state (cookies, localStorage) to a named profile, pass `url` with `scrapeOptions: { "profile": { "name": "my-profile", "saveChanges": true } }`. The state is saved when `firecrawl_interact_stop` ends the session.

**Usage Example:**

Expand Down Expand Up @@ -1113,16 +1115,14 @@ HTTP 403 and this body:
The tool result relays it as an error with `structuredContent` carrying `code`,
`status: 403`, `requestId`, the `requiresAction` object unchanged, and
`next_actions` (`human_action_required` then `retry_same_request`). Accepting
terms is a legal act. Use the returned `nextTool` call to read the agreement through `firecrawl_scrape`
with `alexandria: [{provider: "firecrawl", capability: "terms/show", options: {provider: "<provider>"}}]`.
Present it to the user and obtain explicit authorization to bind their organization
before calling `firecrawl_scrape` with capability `terms/accept` under provider `firecrawl`.
Its options are `provider`, the exact reviewed `version`
and 64-character lowercase hexadecimal `digest`, and `confirmed: true`. A request
for data is not consent. Authority or eligibility errors may require an organization
admin to use `requiresAction.url`. No automatic acceptance or uncertain retries occur.
Send terms calls separately from execution. These are nested capabilities, not top-level MCP tools.
No credits are charged for the blocked retrieval. After confirmed acceptance, call the same
terms is a legal act, so an organization admin accepts them in the Firecrawl dashboard, not
through MCP. Use the returned `nextTool` call to read the agreement through `firecrawl_scrape`
with `alexandria: [{provider: "firecrawl", capability: "terms/show", options: {provider: "<provider>"}}]`,
sent separately from provider execution, and present it to the user. An organization admin then
accepts it at `requiresAction.url`, or at https://www.firecrawl.dev/app/settings?tab=data-sources.
`firecrawl_scrape` refuses every other `terms/*` capability, so it makes no account changes. A request
for data is not consent, and no automatic acceptance or uncertain retries occur.
No credits are charged for the blocked retrieval. After the admin confirms acceptance, call the same
tool again with the identical payload and `requestId`.

### 16. Credit Usage Tool
Expand Down
8 changes: 8 additions & 0 deletions docs/search-profile.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,14 @@ names only tools this surface exposes. `firecrawl_find_tools` is registered the
same way. Alexandria results on this surface carry no `feedbackTool` pointer,
since `firecrawl_feedback` is not registered here.

`firecrawl_scrape` is read-only here (`readOnlyHint: true`): the surface runs in
hosted safe mode, so it takes no browser `actions`, and a named `profile` loads
saved browser state without saving changes to it. Provider terms can be read
with the nested `terms/show` capability. As on the full surface, an organization
admin accepts them in the dashboard: `firecrawl_scrape` refuses every other
`terms/*` capability, and terms errors link to `requiresAction.url` or
https://www.firecrawl.dev/app/settings?tab=data-sources.

## Alexandria source

`sources` entries are source names (`web`, `news`, `images`, `alexandria`) or
Expand Down
Loading
Loading