fetchmux
FetchMux
One search endpoint for AI agents. Put a router in front of Brave, Tavily, Exa, Firecrawl, and Crossref. Every request carries a hard cost ceiling and deadline; every response comes back with a receipt that says which provider ran, why, and what it cost.
Your agents stop hard-coding a provider into prompts and app code. They send one request shape; the gateway picks an eligible provider under a policy you control, enforces the budget and deadline before the call, retries safely on failure, and returns normalized results plus a full trace. You keep your provider keys — they never leave your gateway.
The receipt
Nothing is a black box. Every /v1/search response carries the routing decision:
"route": {
"selectedProvider": "brave",
"attemptedProviders": ["brave"],
"reasonCodes": ["TASK_MATCH", "WITHIN_BUDGET", "RELIABILITY_WEIGHT"],
"attempts": [
{ "provider": "brave", "outcome": "success", "latencyMs": 640, "estimatedCostUsd": 0.005 }
],
"estimatedCostUsd": 0.005,
"latencyMs": 640,
"fallbackUsed": false,
"traceId": "rt_b400e7c8"
}Related MCP server: Argus
How it routes
agent ──▶ { query · task · maxCostUsd · maxLatencyMs }
│
▼
┌──────────────┐ your keys
│ FetchMux │ ─────▶ Brave · Tavily · Exa
│ policy │ Firecrawl · Crossref
└──────────────┘ ◀───── (bring your own)
│
▼
agent ◀── evidence[] + route receiptA provider is eligible only when its credentials, task fit, circuit state, spend, and deadline all pass. Budgets and deadlines are eligibility rules, not best-effort hints. Fallback happens only on retryable failures.
Quick start
No provider account needed — the public Crossref route runs out of the box:
git clone https://github.com/krutftw/fetchmux
cd fetchmux
npm install
npm run build
export FETCHMUX_API_KEY="a-long-random-key"
export CROSSREF_ENABLED=true
export CROSSREF_CONTACT_EMAIL="you@example.com"
npm run dev:gatewayFrom another shell:
curl http://127.0.0.1:8787/v1/search \
-H "Authorization: Bearer a-long-random-key" \
-H "Content-Type: application/json" \
-d '{ "query": "retrieval augmented generation", "task": "scholarly", "maxLatencyMs": 8000 }'To route real web search, set a provider key and use a web task instead:
export FETCHMUX_API_KEY="a-long-random-key"
export BRAVE_API_KEY="your-brave-key"
export BRAVE_COST_PER_REQUEST_USD="0.005" # from your provider plan
npm run dev:gatewayNew to Firecrawl? New accounts get 10% off the first month through this link (referral — FetchMux earns a small commission, no extra cost to you).
Use it from an agent
Point any MCP client (Claude, Cursor, and friends) at the published server:
{
"mcpServers": {
"fetchmux": {
"command": "npx",
"args": ["-y", "@fetchmux/mcp"],
"env": {
"FETCHMUX_BASE_URL": "http://127.0.0.1:8787/",
"FETCHMUX_API_KEY": "your-gateway-key"
}
}
}
}Two read-only tools: search_web and preview_search_route.
Or use the typed SDK, @fetchmux/sdk:
import { FetchMux } from "@fetchmux/sdk";
const client = new FetchMux({
baseUrl: "http://127.0.0.1:8787/",
apiKey: process.env.FETCHMUX_API_KEY,
fetch: globalThis.fetch.bind(globalThis),
});
const res = await client.search({
query: "latest stable Node.js release",
task: "fresh_facts",
maxCostUsd: 0.02,
});Providers
Bring your own key for each. Set the matching *_API_KEY, plus an optional
*_COST_PER_REQUEST_USD if you want dollar budgets enforced.
Provider | Use | Key |
Brave | web search |
|
Tavily | web search, research |
|
Exa | web search, docs |
|
Firecrawl | page content |
|
Crossref | scholarly metadata | none ( |
REST endpoints
Method | Path | Auth | Behavior |
|
| public | Process health and version |
|
| public | Provider readiness |
|
| bearer | Provider configuration status |
|
| bearer | Ranked candidates, no provider call |
|
| bearer | Routed retrieval and route receipt |
Full contract: docs/openapi.yaml.
The process does not auto-load .env in local Node development; set variables in the shell or a
process manager. Docker Compose reads the ignored .env file.
Variable | Default | Purpose |
| none | Protected-route bearer key |
| none | Comma-separated keys for rotation |
|
| Exact |
| none | Comma-separated browser origins; no CORS when empty |
|
| Bind address |
|
| TCP port |
| none | Provider credentials |
|
| Exact |
| none | Monitored contact for Crossref's polite pool |
| none | Per-provider cost estimates used by dollar budgets |
See provider configuration before enabling maxCostUsd.
Run in Docker
cp .env.example .env # add your keys, never commit it
docker compose up --build -d
curl http://127.0.0.1:8787/healthNon-root Distroless image: Linux capabilities dropped, read-only root filesystem, provider credentials passed only at container start.
Benchmark
Validate every case and provider pairing with no network calls or credits:
npm run benchmark -- --workload benchmarks/workloads/founding-v1.json --mode dry-runLive mode needs provider keys and an explicit --confirm-live. Check each provider's terms before
publishing results — see the benchmark methodology.
What it is (and isn't)
Open source, self-hosted, single-tenant, BYOK. Route events go to stdout as JSON and exclude your query text, keys, and result content by default. No database, no telemetry.
It is not a hosted service, a pooled-credit reseller, or a claim that these providers are interchangeable. Provider names are the adapters it ships with, not partnerships. A hosted version is on the roadmap — star the repo to follow.
Development
npm test # 232 tests
npm run typecheck
npm run lint
npm run build
npm run dev:gateway
npm run dev:siteMore docs: product design · local development · deployment · provider configuration · data handling · incident response
Security issues: security@fetchmux.com.
License
Apache-2.0. Free to self-host, modify, and redistribute.
This server cannot be deployed
Maintenance
Related MCP Connectors
Multi-engine search for AI agents. Trust scoring, local corpus, MCP-native. Self-hostable, BYOK.
Web search for AI agents — one tool across 6 engines, routed to the cheapest + cached.
AI routing, memory, guardrails, and governance. Routes across Claude, GPT, Gemini.
One MCP endpoint for Claude, GPT & Gemini: 100+ tools + no-code connectors + agent workers.
Related MCP Servers
- AlicenseAqualityAmaintenanceThe open retrieval layer for AI agents. Index your entire project — code, docs, legal, research, data — and serve surgical context via MCP. FTS5 full-text search, optional semantic search (FastEmbed/ONNX), 10 built-in parsers, incremental auto-sync.8906 PyPI24MIT
- AlicenseBqualityAmaintenanceOne endpoint, five search providers. Search broker for AI agents with automatic fallback, RRF ranking, and budget enforcement. The LiteLLM of web search.13148 PyPI5MIT
- AlicenseAqualityDmaintenanceWeb search for AI agents across 6 engines (Serper, Brave, Exa, Tavily, Firecrawl, Perplexity) through one search tool. Routes each query to the cheapest engine that clears a quality bar and caches repeats. Hosted, streamable-HTTP, BYOK supported.11MIT
- AlicenseNot gradedqualityCmaintenanceA self-hosted, MCP-native web-search backend for AI agents that provides meta-search, clean extraction, RAG with citations, and GitHub project selection.3MIT