- NPX
- Docker
2.5.0
✨ Features
- MCP Per-User Tool Discovery - Per-user OAuth and per-user headers clients can set
per_user_discovery, so each caller sees the tools, prompts and resources their own credential unlocks on the MCP gateway. Discovery is stored at sign-in, shared across callers with identical results, and removed with the credential. A per-caller connect tool, caller counts in the sessions table and registry, and a Refresh tools action on the sessions page come with it. Turning it off sends a per-user OAuth server back to pending verification - MCP Apps on the Gateway -
/mcp/<slug>serves MCP Apps tools andui://resources as the server sent them, to callers that declared MCP Apps. Aggregate/mcpnever lists app-only tools and namespacesui://URIs per client. App-only tools never reach models, tools are accepted by the names their own server gave them, and MCP logs record Apps use - MCP Multi Round-Trip - Bifrost passes an upstream server’s
input_requiredresult through to a gateway caller that can answer it, and forwards callers’ declared capabilities upstream. MCP logs record each round and link a call’s rounds byround_trip_id - Faster Boot with MCP Clients - MCP clients from config.json connect in the background, so an unreachable client no longer delays the HTTP listener
- Serve Under a Base Path -
server.base_path(or-base-path/BIFROST_BASE_PATH) serves the API and UI under a URL prefix. Redirects, OAuth bootstrap URLs, webhookresult_url, MCP discovery and every copyable URL in the UI carry the prefix. Helm getsbasePath - SOCKS5 and TLS-Inspecting Global Proxies - The global proxy accepts
socks5, takes aca_cert_pemto trust a TLS-inspecting proxy, and always verifies targets through the proxy. The Inference and API toggles now take effect - Anthropic Workload Identity Federation - Anthropic keys (and custom providers with an Anthropic base) can carry
anthropic_key_config.workload_identityinstead of a static key. Bifrost exchanges the workload’s OIDC token for a short-lived access token and refreshes it before expiry. The key form gets an API Key / Workload Identity tab - Caller Identity on Logs - LLM, MCP and relay logs record the caller’s user email and, with
logs_store.capture_client_ipon, their client IP. Both show on log pages and in CSV exports, and export to object storage - Relay Logs Match LLM Logs - The relay log store, API and UI reach parity with LLM logs: session and correlation ids, large payload previews, filters and capture behaviour. The relay detail header is redesigned and OpenAPI import moves to a side sheet
- Multi-Value Metadata Filters - Log metadata filters accept several values per key
- Gemini Interactions Billing - On
/genai_passthrough, the Interactions agent is recorded as the model, poll records name it, and each run is billed and counted as one request - Container and Image Tool Billing - Containers started through OpenAI and Azure code interpreter and hosted shell, and Anthropic code execution, are counted on
usage.tool_usage.container_sessionsand billed at thecontainerrate, including underprevious_response_idandconversation. OpenAI image generation tool tokens are billed at the image model’s rates and show asimage_cost - OpenAI 12h Prompt Cache - Prompt cache breakpoints accept a TTL, and 12h cache writes are priced from new datasheet columns
- Complexity Router Confidence Thresholds - Decision model routers take confidence thresholds before they act on a classification
- Optional Routing Rule IDs - config.json routing rules no longer need an
id. A rule without one matches the stored rule by name and scope, and a priority collision with an undeclared stored rule logs a warning instead of stopping startup - Dashboard Languages - The dashboard is fully translated with i18next across 11 locales. Numbers and dates follow the selected language, non-English catalogs lazy-load, and the language toggle lives in client settings (thanks @occcat!)
- Command Palette - Press ⌘K to jump anywhere in the workspace
- MCP Server UI - The MCP server sheet splits into a read-only view and a settings editor, tool parameters toggle between table and JSON, extra access grants have their own registry, and code mode settings collapse into an accordion
- Sticky Log Message Filter - The log detail messages filter persists across reloads
- Duration Strings for
tool_sync_interval- Accepts values like30malongside bare minutes
🐞 Fixed
- Anthropic Prompt Caching on Chat Messages - Message-level
cache_controlis kept on chat completion messages, and OpenAI-styleprompt_cache_breakpointmarkers becomecache_controlfor Claude on Anthropic and Bedrock (thanks @Atharva-Kanherkar!) - Zero Token Usage - Explicitly reported zero token counts from OpenAI-compatible providers are preserved instead of dropped (thanks @Constantine3!)
- Anthropic Web Tool Versions - Explicit web search and web fetch versions are kept instead of upgraded, and web search and code execution are dropped for Claude on Bedrock (thanks @ykakade!)
- Anthropic Empty Content - Responses requests drop empty text blocks instead of failing with a 400, and text documents with empty
datakeep their source type (thanks @david-choi-querypie!) - Claude Haiku 5.x Parameters - Haiku 5.x takes reasoning effort like Sonnet 5.x, sampling params are dropped, and custom Anthropic-based providers read their base provider’s capabilities (thanks @macdod!)
- Codex on Claude - Codex’s client-side tool search runs as the caller’s own, a tool re-declared mid-session no longer fails as a duplicate after namespace flattening, and invalid tool arguments in history replay as
{}instead of a 500 - Codex on OpenAI Responses - Assistant messages carrying
encrypted_contentkeep their content, and afunction_call_outputwith a name and nocall_idkeeps its name - Gemini Item IDs - Non-streamed Gemini item ids stay under 64 characters, reasoning items get ids, and Bedrock Mantle replay keeps them
- vLLM and SGLang Reasoning - Unsigned thinking blocks and replayed reasoning content are kept, and raw
reasoning_textstream events emit Anthropic thinking deltas - Streamed Web Search Query - Streamed Anthropic
web_searchblocks always carry the search query - DeepSeek V3.2 on Bedrock - Leaked DSML tags are stripped, and
stopSequencesis omitted for Converse models that reject it - Databricks Safeguards - The Anthropic-only
safeguardsparam is stripped from Databricks chat and Responses requests - GitHub Copilot Tool Search - Tool search works without the beta header Copilot rejects
- Chat to Responses Conversion - Assistant text next to tool calls is kept
- Runware Async Output - Bifrost polls the task when a sync request turns async
- Multi-Key Stored Objects - Follow-up calls on a stored response, container or video find the key that created it instead of returning 404
- Routing Rule Fallbacks on 4xx - Routing-rule fallbacks run when the primary target returns a 4xx
- Pricing Model Names - Pricing lookups match model names case-insensitively, and Azure Model Router deployments bill the served model’s tokens
- Dropped Requests Skipped Post-Hooks - Requests rejected before reaching a provider worker (full queue, shutdown, cancelled wait) run their post-hooks, and telemetry no longer counts them as upstream traffic
- ClickHouse Log Detail at Scale - Opening a single log no longer scans the whole logs table (thanks @17jmumford!)
- Log Retention Lag - Postgres retention runs hourly, keeps draining past a short batch, and lets one replica drain each table. ClickHouse dedupes deletes per cutoff
- Fallback Chain Banner - The banner shows only for real fallback attempts, not for session rows sharing a parent id
- Realtime and Live Logging Headers - Setup-request headers reach realtime and Live log rows
- Config-File-Only Mode Logs - The dashboard and MCP logs show in config-file-only mode
- Unmatched API Paths - Unknown
/apipaths return a JSON 404 instead of the dashboard shell (thanks @pcbeingused333!) - Config Sync - Unchanged framework URLs skip the URL accessibility check, and a config.json MCP client keeps its stored id
- Relay Passthrough - Relays match passthrough for headers and streams
- Drop-Params Key Aliases - Supported-param lookups resolve key aliases
- Complexity Router Subagents - Complexity session state is scoped per subagent
- MCP OAuth Server - ChatGPT and other CIMD clients sign in, including documents that list grants the server does not offer (thanks @camferguson!). A replayed authorization code revokes its grant, an expired virtual key cannot consent or refresh, a grant bound before an issuer change cannot refresh, a trailing slash in
issuer_urlno longer produces//, and every/mcp401 carriesWWW-Authenticate - MCP Connections - Permanent connect errors stop retrying, invalid
ca_cert_pemis refused, a failed enable stays unstable with its checker retrying, TLS and SSE header edits apply to the live client, a per-call credential refreshes once on a 401, a tool’s own 401 is no longer treated as an upstream auth failure, andtls_configis kept on per-user headers clients - MCP Tool Calls - Upstream tools are called by their exact name, a tool’s error flag survives on
/mcpand in Responses, every code mode call inside agent mode is logged, code mode meta tools go through governance,tool_execution_timeoutapplies to code mode and in-process clients, and timeout errors report the caller’s deadline - MCP Admin API - Client create, rename, reconnect, OAuth and virtual key mistakes return 400, 404 or 409 instead of 500. Unknown auth types and per-user auth on SSE and STDIO are refused,
vk_configsare checked before an update applies, deleting a client reloads its virtual keys and drops its prices, andmax_instructions_lengthis returned in the client list - MCP Per-User Auth - A revoke is not undone by a sign-in finishing during it, pending OAuth flows can be revoked from the sessions list, per-user headers keep their sample values as the admin credential, a stored OpenAPI credential cannot fill a caller-supplied header, and sign-in prompts no longer create MCP log rows
- MCP Library - Invalid catalog entries are skipped, permanent fetch errors stop retrying, and a custom entry can reuse a deleted entry’s name
🗄️ Database Migrations
- add_anthropic_workload_identity_column - Adds
config_keys.anthropic_workload_identity_json. Non-reversible: dropping it would delete every Anthropic key’s workload identity config. Additive, so older binaries ignore it - add_mcp_per_user_discoveries - Adds
config_mcp_clients.per_user_discoveryand themcp_per_user_discoveriestable with its indexes. Reversible: drops the indexes, table and column - add_mcp_client_pending_verification_column - Adds
config_mcp_clients.pending_verificationand backfills it to true for OAuth and per-user clients still awaiting verification. Reversible: drops the column - add_cache_creation_above_12hr_pricing_columns - Adds eight 12h cache write pricing columns. Reversible: drops them
- mcp_tool_logs_add_round_trip_id_column, logs_add_client_ip_column, logs_add_user_email_column - Add
round_trip_id,client_ipanduser_emailto the log tables. Reversible only while the columns are empty: rollback is refused once any row holds a value - relay_logs_add_session_id, relay_logs_add_correlation_columns, relay_logs_add_large_payload_response - Add session, correlation and preview columns to relay logs. Non-reversible: dropping them would lose recorded relay data
ClickHouse log stores add bloom-filter skip indexes on
idandparent_request_idand backfill them once with a backgroundMATERIALIZE INDEX. Startup does not wait for it.
🐙 Closed GitHub Issues
- #3261 - Routing-rule fallbacks not invoked when primary target returns 4xx (chat completions)
- #6764 - Dashboard UI full multi-language i18n (i18next, 11 locales)
- #8037 - OpenAPI spec omits the 100-row clamp and default of 25 on paginated list endpoints
- #8712 - Message-level cache_control on chat messages is dropped, so Anthropic prompt caching never triggers
- #8749 - Custom OpenAI-compatible provider responses drop prompt_tokens/completion_tokens - only total_tokens survives
- #8849 - Anthropic route: a text document with empty
datalosessource.type, upstream 400 - #9150 - Anthropic /v1/messages overrides the client’s explicit web_search version, implicitly enabling code_execution
- #9316 - ClickHouse logs store: single-log detail scans the whole logs table, so the log drawer never loads
- #9318 - Anthropic Responses converter forwards empty text blocks, upstream rejects with 400
- #9324 - Persist message-type filter selection in the chat UI
- #9490 - Claude Haiku 5.5 behind a custom Anthropic-base provider: reasoning effort is dropped and temperature is forwarded
1.15.0
- feat: mcp - per-user tool discovery: pluggable discovery store, per-caller tools, prompts and resources on the gateway, per-caller connect tool, Refresh tools, and an explicit pending_verification flag
- feat: mcp - serve MCP Apps tools and ui:// resources on the gateway, keep app-only tools away from models, and accept tools by their upstream names
- feat: mcp - relay input_required to gateway callers, forward callers’ declared capabilities upstream, and log rounds by round_trip_id and MCP Apps use
- feat: mcp - dial boot MCP clients in the background
- feat: anthropic - workload identity federation for Anthropic and Anthropic-based keys
- feat: accept SOCKS5 global proxies, trust the global proxy’s CA, and always verify targets through a proxy
- feat: record caller IP and user email on LLM, MCP and relay logs; bring relay logging to LLM log parity
- feat: count containers started by OpenAI and Azure code interpreter and hosted shell and by Anthropic code execution on
usage.tool_usage.container_sessions, including underprevious_response_idandconversation - feat: openai - keep
tool_usage.image_genon Responses output with the image tool’s model, and support prompt cache breakpoint TTL - feat: gemini - treat the Interactions agent as the model on /genai_passthrough and name it on poll records
- feat: schemas - raw response formats and raw request/response text rewriters so plugins can edit streamed and passthrough payloads
- fix: anthropic - keep message-level cache_control on chat messages, and map prompt cache breakpoints to cache_control for Anthropic and Bedrock (thanks @Atharva-Kanherkar!)
- fix: preserve explicitly reported zero token usage (thanks @Constantine3!)
- fix: anthropic - Claude Haiku 5.x takes reasoning effort as adaptive thinking plus output_config.effort, drops sampling params, and Anthropic-based custom providers read their base provider’s capabilities (thanks @macdod!)
- fix: anthropic - Responses requests drop empty text blocks instead of failing with a 400 (thanks @david-choi-querypie!)
- fix: anthropic - preserve explicit web search and web fetch versions (thanks @ykakade!)
- fix: anthropic - keep source type on text documents with empty data; drop web_search and code_execution for Claude on Bedrock; run Codex’s client tool search as the caller’s own; replay invalid tool arguments as
{} - fix: responses - merge re-declared additional tools instead of duplicating them after namespace flattening
- fix: openai - keep content on Codex assistant messages with encrypted_content; keep the name on a function_call_output without call_id
- fix: gemini - keep minted item ids under 64 characters and add ids to non-streamed reasoning items; bedrock mantle replay keeps them
- fix: vllm and sglang - keep unsigned thinking blocks and replayed reasoning content; emit thinking deltas for raw reasoning_text events
- fix: anthropic - streamed web_search blocks always carry the query
- fix: bedrock - strip leaked DSML tags from DeepSeek V3.2; omit stopSequences for models that reject it
- fix: databricks - strip the Anthropic-only safeguards param
- fix: github copilot - serve tool search without the rejected beta header
- fix: keep assistant text alongside tool calls when converting chat to Responses messages
- fix: runware - poll the task when a sync request turns async
- fix: multi-key providers - follow-up calls on a stored response, container or video find the key that created it; video list pages across every key
- fix: routing rules fall back when the primary target returns 4xx
- fix: run post-hooks for requests rejected before enqueue
- fix: relays - match passthrough for headers and streams
- fix: mcp - call upstream tools by exact name, keep tool error flags, log every code mode call in agent mode, apply tool_execution_timeout to code mode and in-process clients, and report the caller’s deadline in timeout errors
- fix: mcp - stop retrying permanent connect errors, refresh per-call credentials once on 401, keep failed enables unstable with the checker retrying, apply TLS/SSE/ping edits live, and check sooner after a failed reconnect
- fix: mcp - return 400, 404 and 409 instead of 500 for client create, rename and reconnect mistakes
1.12.0
- feat: configstore - per-user MCP discovery stores, pending_verification flag, Anthropic workload identity column, and 12h cache write pricing columns
- feat: logstore - client_ip (opt-in via
logs_store.capture_client_ip) and user_email columns, exported to object storage - feat: logstore - relay log store parity with LLM logs: session and correlation ids, large payload previews
- feat: logstore - multiple values per metadata filter key
- feat: logstore - MCP round_trip_id column and MCP Apps use
- feat: bill containers started through server tools at the
containerrate and OpenAI image generation tool tokens at image rates, including on stored logs - feat: bill each Gemini Interactions run once and count it as one request
- feat: support OpenAI prompt cache breakpoint TTL and 12h cache write pricing
- feat: config.json routing rule id is optional
- feat: complexity router confidence thresholds
- fix: ClickHouse log store looks single logs up by id without scanning the whole table, using bloom-filter skip indexes backfilled once in the background (thanks @17jmumford!)
- fix: Postgres retention runs hourly, keeps draining past a short batch, and lets one replica drain each table; ClickHouse dedupes deletes per cutoff
- fix: model catalog matches pricing model names case-insensitively
- fix: azure - bill the served model’s tokens for a Model Router deployment behind a key alias
- fix: mcp - OAuth server revokes a replayed authorization code’s grant, checks client names and slugs at create, and returns 400 when endpoint discovery fails
- fix: mcp - skip invalid library catalog entries and let a custom entry reuse a deleted entry’s name
- fix: mcp - a revoke is not undone by a concurrent per-user sign-in
- fix: show dashboard and MCP logs in config-file-only mode
- fix: OAuth bootstrap URLs, webhook result_url and discovery carry server.base_path
- chore: upgraded core to v1.15.0
0.5.4
- fix: drop-params resolves key aliases when looking up supported params
- chore: upgraded core to v1.15.0 and framework to v1.12.0
1.12.0
- feat: per-caller connect tool for MCP clients with per-user discovery
- feat: treat the Gemini Interactions agent as the model and count a run as one request
- fix: evaluate code mode meta tools like any tool call
- fix: relays match passthrough for headers and streams
- chore: upgraded core to v1.15.0 and framework to v1.12.0
1.6.15
- chore: upgraded core to v1.15.0 and framework to v1.12.0
1.12.0
- feat: record caller IP (opt-in) and user email on LLM, MCP and relay logs
- feat: record MCP input_required rounds linked by round_trip_id and MCP Apps use
- feat: relay logging matches LLM logs for capture, status and stale-row eviction
- feat: bill each Gemini Interactions run once and name the agent on poll records
- feat: multiple values per metadata filter key
- fix: skip MCP log entries for sign-in prompts
- fix: relays match passthrough for headers and streams
- chore: upgraded core to v1.15.0 and framework to v1.12.0
1.7.15
- chore: upgraded core to v1.15.0 and framework to v1.12.0
1.6.15
- chore: upgraded core to v1.15.0 and framework to v1.12.0
1.1.15
- chore: upgraded core to v1.15.0 and framework to v1.12.0
1.6.5
- fix: relay metrics match passthrough for headers and streams
- chore: upgraded core to v1.15.0 and framework to v1.12.0
1.1.15
- chore: upgraded core to v1.15.0 and framework to v1.12.0
1.3.0
- feat: confidence thresholds for decision model routers
- fix: routing rules fall back when the primary target returns 4xx
- fix: scope complexity session state per subagent
- chore: upgraded core to v1.15.0 and framework to v1.12.0
1.7.5
- fix: preserve explicitly reported zero token usage
- chore: upgraded core to v1.15.0 and framework to v1.12.0
1.9.5
- fix: requests dropped before enqueue no longer count as upstream traffic
- fix: relay metrics match passthrough for headers and streams
- chore: upgraded core to v1.15.0 and framework to v1.12.0

