> ## Documentation Index
> Fetch the complete documentation index at: https://docs.getbifrost.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# v2.5.0

> v2.5.0 changelog - 2026-11-06

> [tab] NPX
>
> ```bash theme={null}
> npx -y @maximhq/bifrost --transport-version v2.5.0
> ```

> [tab] Docker
>
> ```bash theme={null}
> docker pull maximhq/bifrost:v2.5.0
> docker run -p 8080:8080 maximhq/bifrost:v2.5.0
> ```

**Bifrost(HTTP)**

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 and `ui://` resources as the server sent them, to callers that declared MCP Apps. Aggregate `/mcp` never lists app-only tools and namespaces `ui://` 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_required` result 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 by `round_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, webhook `result_url`, MCP discovery and every copyable URL in the UI carry the prefix. Helm gets `basePath`
* **SOCKS5 and TLS-Inspecting Global Proxies** - The global proxy accepts `socks5`, takes a `ca_cert_pem` to 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_identity` instead 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_ip` on, 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_sessions` and billed at the `container` rate, including under `previous_response_id` and `conversation`. OpenAI image generation tool tokens are billed at the image model's rates and show as `image_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](https://github.com/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 like `30m` alongside bare minutes

## 🐞 Fixed

* **Anthropic Prompt Caching on Chat Messages** - Message-level `cache_control` is kept on chat completion messages, and OpenAI-style `prompt_cache_breakpoint` markers become `cache_control` for Claude on Anthropic and Bedrock (thanks [@Atharva-Kanherkar](https://github.com/Atharva-Kanherkar)!)
* **Zero Token Usage** - Explicitly reported zero token counts from OpenAI-compatible providers are preserved instead of dropped (thanks [@Constantine3](https://github.com/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](https://github.com/ykakade)!)
* **Anthropic Empty Content** - Responses requests drop empty text blocks instead of failing with a 400, and text documents with empty `data` keep their source type (thanks [@david-choi-querypie](https://github.com/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](https://github.com/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_content` keep their content, and a `function_call_output` with a name and no `call_id` keeps 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_text` stream events emit Anthropic thinking deltas
* **Streamed Web Search Query** - Streamed Anthropic `web_search` blocks always carry the search query
* **DeepSeek V3.2 on Bedrock** - Leaked DSML tags are stripped, and `stopSequences` is omitted for Converse models that reject it
* **Databricks Safeguards** - The Anthropic-only `safeguards` param 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](https://github.com/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 `/api` paths return a JSON 404 instead of the dashboard shell (thanks [@pcbeingused333](https://github.com/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](https://github.com/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_url` no longer produces `//`, and every `/mcp` 401 carries `WWW-Authenticate`
* **MCP Connections** - Permanent connect errors stop retrying, invalid `ca_cert_pem` is 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, and `tls_config` is kept on per-user headers clients
* **MCP Tool Calls** - Upstream tools are called by their exact name, a tool's error flag survives on `/mcp` and in Responses, every code mode call inside agent mode is logged, code mode meta tools go through governance, `tool_execution_timeout` applies 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_configs` are checked before an update applies, deleting a client reloads its virtual keys and drops its prices, and `max_instructions_length` is 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_discovery` and the `mcp_per_user_discoveries` table with its indexes. Reversible: drops the indexes, table and column
* **add\_mcp\_client\_pending\_verification\_column** - Adds `config_mcp_clients.pending_verification` and 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_ip` and `user_email` to 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
  > [!NOTE]
  >
  > ClickHouse log stores add bloom-filter skip indexes on `id` and `parent_request_id` and backfill them once with a background `MATERIALIZE INDEX`. Startup does not wait for it.

## 🐙 Closed GitHub Issues

* [#3261](https://github.com/maximhq/bifrost/issues/3261) - Routing-rule fallbacks not invoked when primary target returns 4xx (chat completions)
* [#6764](https://github.com/maximhq/bifrost/issues/6764) - Dashboard UI full multi-language i18n (i18next, 11 locales)
* [#8037](https://github.com/maximhq/bifrost/issues/8037) - OpenAPI spec omits the 100-row clamp and default of 25 on paginated list endpoints
* [#8712](https://github.com/maximhq/bifrost/issues/8712) - Message-level cache\_control on chat messages is dropped, so Anthropic prompt caching never triggers
* [#8749](https://github.com/maximhq/bifrost/issues/8749) - Custom OpenAI-compatible provider responses drop prompt\_tokens/completion\_tokens - only total\_tokens survives
* [#8849](https://github.com/maximhq/bifrost/issues/8849) - Anthropic route: a text document with empty `data` loses `source.type`, upstream 400
* [#9150](https://github.com/maximhq/bifrost/issues/9150) - Anthropic /v1/messages overrides the client's explicit web\_search version, implicitly enabling code\_execution
* [#9316](https://github.com/maximhq/bifrost/issues/9316) - ClickHouse logs store: single-log detail scans the whole logs table, so the log drawer never loads
* [#9318](https://github.com/maximhq/bifrost/issues/9318) - Anthropic Responses converter forwards empty text blocks, upstream rejects with 400
* [#9324](https://github.com/maximhq/bifrost/issues/9324) - Persist message-type filter selection in the chat UI
* [#9490](https://github.com/maximhq/bifrost/issues/9490) - Claude Haiku 5.5 behind a custom Anthropic-base provider: reasoning effort is dropped and temperature is forwarded

**Core**

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 under `previous_response_id` and `conversation`
* feat: openai - keep `tool_usage.image_gen` on 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](https://github.com/Atharva-Kanherkar)!)
* fix: preserve explicitly reported zero token usage (thanks [@Constantine3](https://github.com/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](https://github.com/macdod)!)
* fix: anthropic - Responses requests drop empty text blocks instead of failing with a 400 (thanks [@david-choi-querypie](https://github.com/david-choi-querypie)!)
* fix: anthropic - preserve explicit web search and web fetch versions (thanks [@ykakade](https://github.com/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

**Framework**

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 `container` rate 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](https://github.com/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

**compat**

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

**governance**

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

**jsonparser**

1.6.15

* chore: upgraded core to v1.15.0 and framework to v1.12.0

**logging**

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

**maxim**

1.7.15

* chore: upgraded core to v1.15.0 and framework to v1.12.0

**mocker**

1.6.15

* chore: upgraded core to v1.15.0 and framework to v1.12.0

**modelcatalogresolver**

1.1.15

* chore: upgraded core to v1.15.0 and framework to v1.12.0

**otel**

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

**prompts**

1.1.15

* chore: upgraded core to v1.15.0 and framework to v1.12.0

**routing**

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

**semanticcache**

1.7.5

* fix: preserve explicitly reported zero token usage
* chore: upgraded core to v1.15.0 and framework to v1.12.0

**telemetry**

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


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.