feat(webui): support Firecrawl keyless MCP preset

This commit is contained in:
Xubin Ren
2026-06-19 01:19:20 +08:00
parent 2d86094fc7
commit d36117de7a
3 changed files with 26 additions and 23 deletions
+6
View File
@@ -88,6 +88,12 @@ nanobot can call from a chat. CLI Apps install local adapters that nanobot runs
on your machine; they do not modify the native apps themselves. MCP presets add
predefined MCP server configurations.
Some MCP presets connect to hosted keyless endpoints. For example, the Firecrawl
preset uses Firecrawl's hosted MCP endpoint for search, scrape, crawl, and
extraction tools without requiring an API key. This does not replace nanobot's
built-in web search provider; mention the Firecrawl MCP preset with `@` when a
turn needs Firecrawl's richer web data tools.
After an App or MCP preset is available, mention it from the composer with `@`
to attach that capability to the next message.
+7 -13
View File
@@ -173,25 +173,19 @@ MCP_PRESETS: tuple[McpPreset, ...] = (
category="web",
description="Scrape, crawl, search, and extract web pages through Firecrawl's MCP server.",
docs_url="https://docs.firecrawl.dev/use-cases/developers-mcp",
transport="stdio",
transport="streamableHttp",
install_supported=True,
brand_domain="firecrawl.dev",
brand_color="#EB5E28",
requires="Node.js, npx, and Firecrawl API key",
requires="Network access",
server=MCPServerConfig(
type="stdio",
command="npx",
args=["-y", "firecrawl-mcp"],
type="streamableHttp",
url="https://mcp.firecrawl.dev/v2/mcp",
tool_timeout=60,
),
fields=(
McpPresetField(
name="firecrawl_api_key",
label="Firecrawl API key",
target=("env", "FIRECRAWL_API_KEY"),
env_var="FIRECRAWL_API_KEY",
placeholder="fc-...",
),
note=(
"Uses Firecrawl Keyless through the hosted MCP endpoint. No API key is required for "
"the built-in preset; use a custom MCP server URL if you want account-specific limits."
),
),
McpPreset(
+13 -10
View File
@@ -135,26 +135,29 @@ def test_enable_no_auth_remote_presets_write_url(tmp_path, monkeypatch: pytest.M
mcp_presets_action("enable", {"name": ["microsoft-learn"]})
mcp_presets_action("enable", {"name": ["exa"]})
mcp_presets_action("enable", {"name": ["firecrawl"]})
config = load_config()
assert config.tools.mcp_servers["microsoft-learn"].url == "https://learn.microsoft.com/api/mcp"
assert config.tools.mcp_servers["exa"].url == "https://mcp.exa.ai/mcp"
assert config.tools.mcp_servers["firecrawl"].url == "https://mcp.firecrawl.dev/v2/mcp"
def test_enable_firecrawl_writes_scrubbed_env(tmp_path, monkeypatch: pytest.MonkeyPatch) -> None:
def test_firecrawl_preset_is_keyless(tmp_path, monkeypatch: pytest.MonkeyPatch) -> None:
_use_config(tmp_path, monkeypatch)
payload = mcp_presets_action(
"enable",
{
"name": ["firecrawl"],
"firecrawl_api_key": ["fc-secret"],
},
)
payload = mcp_presets_action("enable", {"name": ["firecrawl"]})
assert "fc-secret" not in str(payload)
row = next(item for item in payload["presets"] if item["name"] == "firecrawl")
assert row["transport"] == "streamableHttp"
assert row["requires"] == "Network access"
assert row["required_fields"] == []
assert row["configured"] is True
assert "Keyless" in row["note"]
config = load_config()
assert config.tools.mcp_servers["firecrawl"].env["FIRECRAWL_API_KEY"] == "fc-secret"
assert config.tools.mcp_servers["firecrawl"].type == "streamableHttp"
assert config.tools.mcp_servers["firecrawl"].url == "https://mcp.firecrawl.dev/v2/mcp"
assert config.tools.mcp_servers["firecrawl"].env == {}
def test_remove_mcp_preset_updates_config(tmp_path, monkeypatch: pytest.MonkeyPatch) -> None: