MCP Server

A remote Model Context Protocol server so agents can manage FreeRouter provider keys, FreeRouter keys, routing, usage, and account — authenticated with a management API key.

What it is

FreeRouter exposes an MCP server at https://api.freerouter.com/mcp. Point Cursor, Claude, VS Code, or any Streamable HTTP MCP client at that URL and pass a management API key (fr_mgmt_…) as a Bearer token. The tools are the same operations as the management REST API: list gateways, store provider keys, mint / update / revoke FreeRouter keys, attach routing, plus usage and account.

This is not an inference endpoint. MCP cannot run /v1/chat/completions. Use a FreeRouter key (fr_live_…) against https://api.freerouter.com/v1 for that — see the API Reference. To attach catalog MCP servers to those chat calls, see MCP Tools.

Admin-only — keep the key server-side A management key can mint FreeRouter keys that spend against your provider keys. Treat it like any server secret. Prefer a read-only management key if the client only needs reporting.

Endpoint & auth

https://api.freerouter.com/mcp
Authorization: Bearer $FREEROUTER_MANAGEMENT_KEY

Transport is Streamable HTTP: POST JSON-RPC 2.0, application/json responses. GET returns 405. Missing, invalid, revoked, or inference-shaped secrets return 401.

Protocol versions. initialize accepts 2024-11-05, 2025-03-26 and 2025-11-25 and echoes the one you sent; any other value negotiates down to 2025-03-26, the server's own version. Every response carries an MCP-Protocol-Version: 2025-03-26 header. Sessions are stateless — there is no Mcp-Session-Id to keep.

The two key types stay split:

  • fr_mgmt_… authenticates /mcp (and the management REST API on the app host). Presenting one to /v1 returns 401.
  • fr_live_… authenticates inference on /v1. Presenting one to /mcp returns 401.

IP allowlists restrict FreeRouter keys only. /mcp and management keys are not covered by them; the tools can set allowed_ips on FreeRouter keys.

Client config

Create a management key under Settings → Management API Keys, then drop it into the client. Store the secret in the client's env or secrets store — never commit it.

Cursor

{
  "mcpServers": {
    "freerouter": {
      "url": "https://api.freerouter.com/mcp",
      "headers": {
        "Authorization": "Bearer ${FREEROUTER_MANAGEMENT_KEY}"
      }
    }
  }
}

Claude / Claude Code

{
  "mcpServers": {
    "freerouter": {
      "type": "http",
      "url": "https://api.freerouter.com/mcp",
      "headers": {
        "Authorization": "Bearer ${FREEROUTER_MANAGEMENT_KEY}"
      }
    }
  }
}

curl (initialize)

curl https://api.freerouter.com/mcp \
  -H "Authorization: Bearer $FREEROUTER_MANAGEMENT_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "initialize",
    "params": {
      "protocolVersion": "2025-03-26",
      "capabilities": {},
      "clientInfo": { "name": "curl", "version": "0" }
    }
  }'

Tools

v1 mirrors the management REST API. Tool results are JSON text. Write tools are marked below.

ToolWhat it doesWrite?
list_gatewaysCatalog of gateway identifiers (openrouter, vercel, …). Use id as gateway when creating a provider key.No
list_provider_keysList BYOK provider keys (metadata, never secrets). Each id is the UUID to pass as provider_key_id. Optional gateway filter.No
get_provider_keyFetch one provider key by UUID.No
create_provider_keyStore a provider key. Secret never returned. Cloudflare needs config.account_id.Yes
update_provider_keyRename (name/label) and/or disabled: true|false. Provider notes are dashboard-only.Yes
delete_provider_keyDelete and strip the UUID from every routing rule.Yes
list_api_keysList FreeRouter keys (metadata, never secrets), including each key's routing rule. Optional offset.No
get_api_keyFetch one key by id, including routing.No
create_api_keyMint a FreeRouter key. Secret returned once as key. Optional name/label, api_shape, routing, companion_ads (Companion Ads), keyterms (Monetizable Keyterms; stored as false unless the operator has set FR_KEYTERMS_ENABLED), allowed_ips (IP allowlist), steering_message (steering), failover_ttfb_ms / upstream_timeout_ms (timeouts). The key's free-text notes are dashboard-only — not on this surface or the REST API.Yes
update_api_keyRename (name/label), revoked: true|false (idempotent: true on a revoked key and false on a live one are no-ops),companion_ads: true|false, keyterms: true|false (same FR_KEYTERMS_ENABLED gate), allowed_ips ([] clears), steering_message (null clears), and/or failover_ttfb_ms / upstream_timeout_ms (timeouts; null resets to 5s / 60s). Every field is validated first and the call applies as one transaction, so it lands whole or changes nothing; a restore applies before the other fields and a revoke after them. Any other field on a key that stays revoked is a key_revoked tool error ("Restore it first with { revoked: false }"), as is set_routing on a revoked key.Yes
revoke_api_keyRevoke by id (row retained; restore with update_api_key). Idempotent: an already-revoked key answers as it is.Yes
get_routingFetch the routing rule for a FreeRouter key.No
set_routingReplace routing. Attach stored providers by UUID (provider_key_id), not gateway slug. strategy priority or split. A target's optional ttfb_ms is its own failover timeout (omit to keep the stored one, null to clear). Optional model_remaps rewrites one incoming model to a fixed provider/model (enabled: false stages a remap without serving it). Optional decisioner: { provider_key_id, objective?, allow_model_override?, max_usd_m?, notes?, models? } is a TypeSafe, OpenRouter, Requesty, Vercel, or Ramp Router key that runs Jev as a pre-router on chat keys (objective cost / capability / efficiency); allow_model_override lets Jev pick a listed model; models is an explicit list of model ids (max 12); omit to turn it off. A call replaces the whole rule: leaving out model_remaps or decisioner clears them. Same limits as the REST API (what a rule may contain): 1–10 targets, never empty; split weights whole numbers 0–1,000,000 with one above 0; at most 20 remaps, ids up to 200 characters, enabled remaps per match totalling at most 100%; objective cost / capability / efficiency; max_usd_m above 0.Yes
get_usage_summaryTotals for range 24h|7d|30d. Optional api_key_id.No
get_usage_seriesZero-filled time buckets. Same filters.No
get_usage_breakdownTop 12 by by=model|gateway. Same filters.No
get_accountWorkspace profile + key/provider inventory. No secrets, no member emails.No
Attach routing or calls 402 A typical setup: list_gateways → create_provider_key → create_api_key with routing (or set_routing later). Pass the provider UUID as provider_key_id — not the gateway slug. Calls on an unrouted key return 402.
No cost data by design Usage tools cover requests, errors, latency, models, and gateways only. The proxy never stores tokens or per-request cost.

Read-only keys

A management key flagged read-only can call every read tool. Write tools (create_provider_key, update_provider_key, delete_provider_key, create_api_key, update_api_key, revoke_api_key, set_routing) return a tool error: This management API key is read-only. Writes are not allowed. The HTTP status stays 200 — that is MCP isError, not a JSON-RPC transport failure. Flag the key in Settings; a key cannot escalate itself.

MCP vs the management REST API

Same workspace operations, two protocols:

  • REST — https://app.freerouter.com/api/v1 (/gateways, /providers, /keys, /keys/:id/routing, /usage/*, /account). Best for backends and scripts. Documented on Management API Keys.
  • MCP — https://api.freerouter.com/mcp. Best for agents and IDEs.

Both take Authorization: Bearer $FREEROUTER_MANAGEMENT_KEY. Inference stays off this surface — use an fr_live_… key against /v1 for that.

Next Management API Keys