Skip to main content

“OpenAI-compatible” and “SCIM 2.0” are claims, and a claim is only useful when you can check it. This page lists every external specification Rolter implements, translates, emits, parses or forwards, and every provider kind it can reach, with:

  • the official source and the revision reviewed — a dated version, a release, an RFC, or for a living document the date it was last read;
  • the conformance level: how much of the specification Rolter actually honours;
  • what is supported, what is omitted, and where Rolter deviates on purpose;
  • the tests that demonstrate the claim.

The tables below are generated from the registry crates/rolter-core/specifications.toml, the one place a reviewed version or URL is written down. The same data is in the gateway’s and the control plane’s GET /openapi.json: each operation a specification governs carries a standard externalDocs link plus three extensions, x-rolter-spec-refs (the registry ids), x-rolter-conformance and x-rolter-reviewed-at. Rolter never adds a field to a vendor’s request or response payload.

Conformance levels#

LevelMeaning
native-passthroughThe vendor’s wire format, forwarded or served unchanged. Rolter reads the fields it needs (model, stream, usage).
translation-subsetRolter rewrites between dialects. Only what the record lists is translated; a part with no equivalent fails the request.
transport-onlyBytes are relayed. Rolter neither validates the payload nor negotiates a version, so the two ends must agree between them.
extensionThe vendor’s shape plus Rolter’s own additions.
partialSome of the specification, as listed.
provider-profileA provider’s base URL, credential header and path over an OpenAI-shaped transport. Proves the profile, not full compatibility.

Versions#

  • OpenAI is recorded as REST v1. That API evolves by backward-compatible additions and gives its type system no finer version, so Rolter records a review date rather than inventing one. Rolter does not consume OpenAI’s published OpenAPI artifact, so no commit of it is pinned.
  • Anthropic is recorded with its dated anthropic-version. A request that states none is sent with [compatibility] anthropic_version, which is the recorded version when no value is stored or configured; a client’s own anthropic-version always wins. The health probes and the provider connection test send the recorded version, not your [compatibility] pin: a probe asks whether the API answers and accepts the key, which no dated version changes. See Compatibility.
  • MCP is partial: the gateway applies your organization’s tool groups to every JSON-RPC call and answers an upstream insufficient_scope with a step-up challenge, but it relays MCP-Protocol-Version without negotiating it, so the recorded version is forwarded. The MCP OAuth client is recorded against the dated revision that carries every requirement it implements.
  • OpenTelemetry GenAI attributes are pinned to the semantic-conventions release they were audited against, and the rolter-local values are listed as deviations. OTLP is recorded by its protocol version, separately from the SDK crates that implement it.

Registry#

AI APIs#

SpecificationRevisionConformanceReviewedEndpoints
OpenAI Chat Completions (openai-chat-completions)v1native-passthrough2026-10-27POST /v1/chat/completions
OpenAI Completions (legacy) (openai-completions)v1native-passthrough2026-10-27POST /v1/completions
OpenAI Responses and its lifecycle methods (openai-responses)v1partial2026-10-27POST /v1/responses
GET /v1/responses/{response_id}
DELETE /v1/responses/{response_id}
POST /v1/responses/{response_id}/cancel
GET /v1/responses/{response_id}/input_items
POST /v1/responses/{response_id}/compact
GET /v1/responses/{response_id}/input_tokens
OpenAI Embeddings (openai-embeddings)v1native-passthrough2026-10-27POST /v1/embeddings
OpenAI Models (list) (openai-models)v1extension2026-10-27GET /v1/models
OpenAI Images (generations) (openai-images)v1native-passthrough2026-10-27POST /v1/images/generations
OpenAI Audio (speech, transcriptions, translations) (openai-audio)v1native-passthrough2026-10-27POST /v1/audio/speech
POST /v1/audio/transcriptions
POST /v1/audio/translations
OpenAI Realtime (WebSocket) (openai-realtime)v1partial2026-10-27GET /v1/realtime
OpenAI error object (openai-errors)v1partial2026-10-27—
Anthropic Messages API (anthropic-messages)2023-06-01native-passthrough2026-10-27POST /v1/messages
Gemini API OpenAI compatibility (gemini-openai-compat)v1betanative-passthrough2026-10-27—
Gemini generateContent and streamGenerateContent (gemini-generate-content)v1betatranslation-subset2026-10-27—
Gemini Interactions API (gemini-interactions)v1betatranslation-subset2026-10-27—
Rerank (Cohere v1 and Jina request shape) (rerank)v1transport-only2026-10-27POST /v1/rerank
Infinity embeddings and rerank server (infinity)living (no revision)translation-subset2026-10-27—
Text Embeddings Inference (hf-tei)living (no revision)native-passthrough2026-10-27—
System One decision API (system-one)living (no revision)native-passthrough2026-10-27POST /v1/systemone

OpenAI Chat Completions#

openai-chat-completions · OpenAI · primary source

  • Supported: request and response bodies are forwarded unchanged to an OpenAI-shaped upstream; the gateway reads model, stream, messages and usage
  • Supported: chat.completion.chunk SSE frames, forwarded incrementally
  • Supported: translation to Anthropic Messages and Gemini (see the translation records)
  • Omitted: no request validation beyond model: unknown fields reach the upstream, which judges them
  • Omitted: the served OpenAPI schema names only the fields rolter reads, not the full vendor type
  • Deviations: a provider-slug/model name pins a provider and is rewritten to the upstream model before forwarding
  • Deviations: guardrails, plugins and the PII sanitizer a route configures may refuse or rewrite a request or response; with none configured the bodies pass unchanged
  • Evidence: crates/rolter-gateway/tests/integration.rs::non_streaming_request_proxies_upstream_body
    crates/rolter-gateway/tests/integration.rs::streaming_request_passes_through_sse
    crates/rolter-gateway/tests/integration.rs::output_guardrail_masks_a_non_streaming_completion
    crates/rolter-gateway/tests/integration.rs::pre_upstream_plugin_transforms_the_request_body

OpenAI Completions (legacy)#

openai-completions · OpenAI · primary source

  • Supported: request and response bodies forwarded unchanged to an OpenAI-shaped upstream
  • Omitted: no translation to Anthropic or Gemini: a legacy completion reaches only an OpenAI-shaped upstream
  • Evidence: crates/rolter-gateway/tests/integration.rs::fake_llm_chat_completions_without_any_config

OpenAI Responses and its lifecycle methods#

openai-responses · OpenAI · primary source

  • Supported: create: native passthrough to an OpenAI upstream, streaming included
  • Supported: create: translated to Chat Completions, Anthropic Messages or Gemini when the route’s target speaks one of those
  • Supported: retrieve, delete, cancel and input_items: forwarded to the provider that created the response, scoped to the tenant that created it
  • Omitted: compact and input_tokens are routed but answer 501: rolter does not implement them
  • Omitted: lifecycle methods on a translated response answer 501: there is no stored upstream response to address
  • Deviations: a response id is resolved through rolter’s own registry, so another tenant’s id reads as not found (ADR-0016)
  • Evidence: crates/rolter-gateway/tests/integration.rs::responses_passthrough_preserves_body_and_sse_events
    crates/rolter-gateway/tests/integration.rs::responses_lifecycle_operations_are_uniformly_unsupported
    crates/rolter-gateway/tests/integration.rs::native_responses_lifecycle_is_tenant_scoped_and_pinned

OpenAI Embeddings#

openai-embeddings · OpenAI · primary source

  • Supported: request and response bodies forwarded unchanged to an OpenAI-shaped upstream; the gateway reads model, encoding_format and usage
  • Evidence: crates/rolter-gateway/tests/integration.rs::builtin_fake_llm_serves_embeddings
    crates/rolter-gateway/tests/tei.rs

OpenAI Models (list)#

openai-models · OpenAI · primary source

  • Supported: the OpenAI list shape (object: "list", data[].id), answered by the gateway itself rather than forwarded
  • Deviations: entries name rolter routes and provider-slug/model ids, and carry rolter’s catalogue metadata beside the OpenAI fields
  • Evidence: crates/rolter-gateway/tests/integration.rs::models_endpoint_lists_route_ids_and_provider_slug_model_ids

OpenAI Images (generations)#

openai-images · OpenAI · primary source

  • Supported: request and response bodies forwarded unchanged to an OpenAI-shaped upstream
  • Omitted: image edits and variations are not routed
  • Evidence: crates/rolter-gateway/tests/integration.rs::builtin_fake_llm_serves_images

OpenAI Audio (speech, transcriptions, translations)#

openai-audio · OpenAI · primary source

  • Supported: speech: JSON request forwarded, binary audio streamed back
  • Supported: transcriptions and translations: the multipart body is forwarded verbatim; the gateway reads only the model field
  • Evidence: crates/rolter-gateway/tests/integration.rs::builtin_fake_llm_serves_audio_speech
    crates/rolter-gateway/tests/integration.rs::builtin_fake_llm_serves_audio_transcriptions
    crates/rolter-gateway/tests/integration.rs::audio_translations_rejects_non_multipart

OpenAI Realtime (WebSocket)#

openai-realtime · OpenAI · primary source

  • Supported: the WebSocket upgrade is admitted, the model query parameter rewritten, and frames otherwise relayed both ways unchanged
  • Supported: a client’s openai-beta header is forwarded to the upstream
  • Supported: response.created and response.done server events are read for metering
  • Supported: when the route configures guardrails, webhooks or plugins, text-bearing client and server events are checked: a client event may be refused or redacted, a server delta withheld and its response cancelled
  • Omitted: no validation against the Realtime event schema: an event the content policy does not read is relayed whatever its type
  • Omitted: WebRTC and SIP session setup are not served
  • Evidence: crates/rolter-gateway/tests/integration.rs::realtime_websocket_rewrites_model_and_relays_frames_with_upstream_auth
    crates/rolter-gateway/tests/realtime_metering.rs
    crates/rolter-gateway/tests/realtime_guardrails.rs

OpenAI error object#

openai-errors · OpenAI · primary source

  • Supported: errors the gateway raises itself are {"error": {"message", "type", "code", "param"}}
  • Omitted: an upstream’s own error body is relayed unchanged
  • Deviations: code carries rolter’s own stable codes for refusals the vendor API has no name for
  • Evidence: crates/rolter-gateway/tests/integration.rs::retry_policy_distinguishes_client_and_transient_upstream_errors

Anthropic Messages API#

anthropic-messages · Anthropic · primary source

  • Supported: request and response bodies forwarded unchanged to an Anthropic upstream, streaming included
  • Supported: the client’s anthropic-version and anthropic-* headers reach an Anthropic upstream only
  • Supported: translation to OpenAI Chat Completions and Gemini (see the translation records)
  • Deviations: a request with no anthropic-version is sent with [compatibility] anthropic_version; when no value is configured or stored, that is this record’s version (a database-backed deployment reads the stored compatibility policy, whose column default is seeded by a migration)
  • Deviations: guardrails, plugins and the PII sanitizer a route configures may refuse or rewrite a request or response; with none configured the bodies pass unchanged
  • Deviations: health probes and the connection test always send this record’s version, not the operator’s [compatibility] pin: a probe asks whether the API answers and accepts the key, which no dated version changes
  • Evidence: crates/rolter-gateway/tests/integration.rs::anthropic_multimodal_content_is_forwarded_byte_for_byte
    crates/rolter-proxy/src/lib.rs::anthropic_headers_do_not_leak_to_a_non_anthropic_upstream
    crates/rolter-core/src/spec_registry.rs::the_anthropic_version_has_one_source

Gemini API OpenAI compatibility#

gemini-openai-compat · Google · primary source

  • Supported: OpenAI-shaped requests forwarded to {api_base}/chat/completions with a bearer key
  • Evidence: crates/rolter-core/src/config.rs::every_kind_resolves_by_the_documented_rule

Gemini generateContent and streamGenerateContent#

gemini-generate-content · Google · primary source

  • Supported: text, image and tool parts translated from OpenAI Chat, Anthropic Messages and Responses requests
  • Supported: streamGenerateContent?alt=sse frames translated back incrementally
  • Omitted: a content part with no Gemini equivalent fails the request rather than being dropped (ADR-0014)
  • Evidence: crates/rolter-proxy/src/translation.rs::gemini_native_resolves_for_openai_client
    crates/rolter-proxy/src/translation.rs::unknown_content_parts_fail_closed_on_every_gemini_pair
    crates/rolter-gateway/tests/integration.rs::unsupported_content_parts_never_reach_a_gemini_upstream

Gemini Interactions API#

gemini-interactions · Google · primary source

  • Supported: OpenAI Chat, Anthropic Messages and Responses requests translated onto POST {api_base}/interactions and back
  • Omitted: only the create call is served; endpoints the Interactions API cannot answer fail closed
  • Evidence: crates/rolter-proxy/src/translation.rs::gemini_interactions_resolves_for_chat_dialects_and_targets_one_endpoint
    crates/rolter-proxy/src/translation.rs::gemini_interactions_fails_closed_for_endpoints_it_cannot_serve
    crates/rolter-proxy/src/translation.rs::openai_request_becomes_an_interactions_create_body

Rerank (Cohere v1 and Jina request shape)#

rerank · Cohere / Jina AI · primary source

  • Supported: the body is forwarded unchanged to the route’s upstream; the gateway reads only model
  • Supported: the built-in fake-llm answers in the Cohere v1 / Jina shape
  • Omitted: no Cohere v2 claim: a v2 body passes through to an upstream that accepts it, but no fixture covers one
  • Evidence: crates/rolter-gateway/tests/integration.rs::builtin_fake_llm_serves_rerank

Infinity embeddings and rerank server#

infinity · michaelfeil/infinity · primary source

  • Supported: embeddings: OpenAI’s own shape, forwarded unchanged
  • Supported: rerank: {"text": ...} documents flattened on the way up and bare-string documents wrapped on the way back
  • Supported: every other endpoint refused with 400 unsupported_endpoint before the upstream on a route that reaches only embedding servers
  • Evidence: crates/rolter-proxy/src/infinity.rs::documents_come_back_in_the_cohere_shape
    crates/rolter-gateway/tests/infinity.rs
    crates/rolter-gateway/tests/embedding_only.rs

Text Embeddings Inference#

hf-tei · Hugging Face · primary source

  • Supported: the OpenAI-compatible /v1/embeddings route, and /health as the liveness probe
  • Supported: every other endpoint, /v1/rerank included (TEI has no rerank mapping), refused with 400 unsupported_endpoint before the upstream on a route that reaches only embedding servers, none of them Infinity
  • Evidence: crates/rolter-gateway/tests/tei.rs
    crates/rolter-gateway/tests/embedding_only.rs

System One decision API#

system-one · TypeSafe · primary source

  • Supported: request and response forwarded unchanged; the gateway reads model and usage (ADR-0035)
  • Evidence: crates/rolter-gateway/tests/system_one.rs

Translations#

SpecificationRevisionConformanceReviewedEndpoints
OpenAI Chat Completions ⇄ Anthropic Messages (translation-openai-anthropic)living (no revision)translation-subset2026-10-27—
OpenAI Responses → Chat Completions, Anthropic Messages, Gemini (translation-responses)living (no revision)translation-subset2026-10-27—
OpenAI / Anthropic / Responses → Gemini generateContent and Interactions (translation-gemini)living (no revision)translation-subset2026-10-27—

OpenAI Chat Completions ⇄ Anthropic Messages#

translation-openai-anthropic · rolter · primary source

  • Supported: messages, system and developer instructions, images, documents, tools and tool results, in both directions
  • Supported: SSE translated incrementally in both directions
  • Supported: max_tokens injected from [compatibility] default_max_tokens when an OpenAI request sets none
  • Supported: Anthropic tool_choice.disable_parallel_tool_use: true carried as Chat parallel_tool_calls: false on a request with tools (#3325)
  • Omitted: fields with no counterpart in the target dialect are dropped, never forwarded
  • Deviations: an OpenAI temperature above Anthropic’s maximum of 1 is sent as 1 and reported as temperature=clamped (#3324)
  • Evidence: crates/rolter-proxy/src/translation.rs::openai_multimodal_and_tools_become_anthropic_blocks
    crates/rolter-proxy/src/translation.rs::chat_to_anthropic_clamps_a_temperature_above_one
    crates/rolter-proxy/src/translation.rs::anthropic_disable_parallel_tool_use_becomes_chat_parallel_tool_calls
    crates/rolter-gateway/tests/integration.rs::a_chat_temperature_above_one_is_clamped_for_an_anthropic_upstream
    crates/rolter-proxy/src/translation.rs::anthropic_response_becomes_openai_response
    crates/rolter-proxy/src/translation.rs::anthropic_sse_translates_across_chunk_boundaries
    crates/rolter-gateway/tests/integration.rs::cross_protocol_sse_is_translated_incrementally_both_ways

OpenAI Responses → Chat Completions, Anthropic Messages, Gemini#

translation-responses · rolter · primary source

  • Supported: input items, instructions, tools and multimodal input; the response object and its SSE events rebuilt from the target’s (ADR-0015)
  • Omitted: stored-response features (previous_response_id, background mode) have no translated equivalent
  • Evidence: crates/rolter-proxy/src/translation.rs::responses_request_becomes_chat_with_tools_and_multimodal_input
    crates/rolter-proxy/src/translation.rs::chat_sse_becomes_responses_sse
    crates/rolter-gateway/tests/integration.rs::responses_translates_to_anthropic_messages

OpenAI / Anthropic / Responses → Gemini generateContent and Interactions#

translation-gemini · rolter · primary source

  • Supported: see gemini-generate-content and gemini-interactions
  • Omitted: a content part with no Gemini equivalent fails the request (ADR-0014)
  • Evidence: crates/rolter-proxy/src/translation.rs::unknown_content_parts_fail_closed_on_every_gemini_pair

Wire formats#

SpecificationRevisionConformanceReviewedEndpoints
Server-sent events (sse)living (no revision)partial2026-10-27POST /v1/chat/completions
POST /v1/completions
POST /v1/responses
POST /v1/messages
The WebSocket Protocol (websocket)RFC 6455native-passthrough2026-10-27GET /v1/realtime
Returning Values from Forms: multipart/form-data (multipart-form-data)RFC 7578partial2026-10-27POST /v1/audio/transcriptions
POST /v1/audio/translations
Date and Time on the Internet: Timestamps (rfc3339)RFC 3339partial2026-10-27—
Uniform Resource Identifier (URI): Generic Syntax (uri)RFC 3986partial2026-10-27—
The Deprecation HTTP Response Header Field (deprecation-header)RFC 9745native-passthrough2026-10-27—
The Sunset HTTP Header Field (sunset-header)RFC 8594native-passthrough2026-10-27—
JSON-RPC 2.0 (json-rpc)2.0.0partial2026-10-27POST /mcp/{server}
POST /mcp/{server}/{path}

Server-sent events#

sse · WHATWG · primary source

  • Supported: event: and data: fields, multi-line data and frames split across chunks, parsed when a stream is translated
  • Omitted: id: and retry: are relayed but never interpreted; no reconnection
  • Evidence: crates/rolter-proxy/src/translation.rs::anthropic_sse_translates_across_chunk_boundaries
    crates/rolter-gateway/tests/integration.rs::streaming_response_is_forwarded_incrementally

The WebSocket Protocol#

websocket · IETF · primary source

  • Supported: upgrade on both sides of the relay, text and binary frames, close codes
  • Evidence: crates/rolter-gateway/tests/integration.rs::realtime_websocket_rejects_missing_auth_disallowed_and_unknown_models

Returning Values from Forms: multipart/form-data#

multipart-form-data · IETF · primary source

  • Supported: quoted and unquoted boundaries; one named text field read from the buffered body
  • Omitted: the body is never re-encoded: it is forwarded byte for byte
  • Evidence: crates/rolter-gateway/src/multipart.rs::parses_boundary_variants

Date and Time on the Internet: Timestamps#

rfc3339 · IETF · primary source

  • Supported: timestamps the control-plane API accepts and returns are RFC 3339 with an offset (format: date-time in its OpenAPI document)
  • Evidence: crates/rolter-control/src/ui_events.rs::rejects_a_ts_that_is_not_rfc_3339

Uniform Resource Identifier (URI): Generic Syntax#

uri · IETF · primary source

  • Supported: percent-encoding of the unreserved set (§2.3) and scheme/host normalisation (§6.2.2) where a URI is compared
  • Evidence: crates/rolter-control/src/mcp_oauth_discovery.rs::a_resource_uri_is_canonicalised_the_way_rfc_8707_asks

The Deprecation HTTP Response Header Field#

deprecation-header · IETF · primary source

  • Supported: Deprecation: @<unix seconds> on a deprecated control-plane operation
  • Supported: Deprecation on every /internal/snapshot answer served in a deprecated snapshot format (ADR-0038)
  • Evidence: crates/rolter-control/src/deprecation.rs::headers_follow_rfc_9745_and_rfc_8594
    crates/rolter-control/src/snapshot_negotiation.rs::a_deprecated_format_carries_the_headers_and_only_it

The Sunset HTTP Header Field#

sunset-header · IETF · primary source

  • Supported: Sunset as an IMF-fixdate on every deprecated control-plane operation
  • Supported: Sunset on every /internal/snapshot answer served in a deprecated snapshot format (ADR-0038)
  • Evidence: crates/rolter-control/src/deprecation.rs::headers_follow_rfc_9745_and_rfc_8594
    crates/rolter-control/src/snapshot_negotiation.rs::a_deprecated_format_carries_the_headers_and_only_it

JSON-RPC 2.0#

json-rpc · JSON-RPC Working Group · primary source

  • Supported: every POST body is parsed as a JSON-RPC request, notification or batch to apply the organization’s tool groups; a tools/call outside them is refused
  • Supported: method, result and error are read from an MCP exchange to log tool calls
  • Omitted: an allowed message is forwarded unchanged: rolter validates no other part of it
  • Deviations: a body that cannot be read as JSON-RPC is refused with 400 mcp_request_unreadable unless the organization’s failure policy lets it through
  • Evidence: crates/rolter-gateway/src/mcp_policy.rs::an_escaped_method_name_does_not_get_around_the_policy
    crates/rolter-gateway/src/mcp_policy.rs::a_batch_is_refused_as_a_whole_naming_every_refused_call
    crates/rolter-gateway/tests/integration.rs::mcp_proxy_records_a_tool_call_with_key_and_session_owner_attribution
    crates/rolter-gateway/tests/integration.rs::mcp_proxy_records_a_json_rpc_error_as_a_tool_error

Transport#

SpecificationRevisionConformanceReviewedEndpoints
HTTP Semantics and HTTP/1.1 (http-semantics)RFC 9110partial2026-10-27—
MCP Streamable HTTP transport and version negotiation (mcp-transport)forwardedpartial2026-10-27GET /mcp/{server}
POST /mcp/{server}
DELETE /mcp/{server}
GET /mcp/{server}/{path}
POST /mcp/{server}/{path}
DELETE /mcp/{server}/{path}

HTTP Semantics and HTTP/1.1#

http-semantics · IETF · primary source

  • Supported: Connection, every field its value nominates and the fixed hop-by-hop set (Keep-Alive, Proxy-Connection, TE, Trailer, Transfer-Encoding, Upgrade and the proxy-auth fields, RFC 9110 §7.6.1) are stripped by one shared helper before a request or response is relayed
  • Evidence: crates/rolter-proxy/src/hop_by_hop.rs::removes_connection_and_the_fields_it_nominates
    crates/rolter-proxy/src/hop_by_hop.rs::removes_trailer_and_the_fixed_set
    crates/rolter-control/src/proxy.rs::the_relay_drops_nominated_and_trailer_headers_both_ways
    crates/rolter-gateway/src/mcp_proxy.rs::the_relay_drops_nominated_and_trailer_headers
    crates/rolter-gateway/src/mcp_proxy.rs::proxy_replaces_client_auth_and_preserves_path_query_and_body

MCP Streamable HTTP transport and version negotiation#

mcp-transport · Model Context Protocol · primary source

  • Supported: requests, SSE replies and Mcp-Session-Id relayed between client and server; the gateway authenticates the client and presents its own credential upstream
  • Supported: a POST naming a tool outside the organization’s enabled tool groups is refused with 403 mcp_tool_denied before anything is forwarded (see json-rpc)
  • Supported: an upstream 403 whose challenge says insufficient_scope is answered with 403 mcp_insufficient_scope and a rebuilt WWW-Authenticate challenge
  • Omitted: no protocol-version negotiation: MCP-Protocol-Version is relayed, never read
  • Omitted: no validation of what an allowed message contains, and none of the server’s replies
  • Omitted: the deprecated HTTP+SSE transport is relayed like any other request, not implemented
  • Evidence: crates/rolter-gateway/src/mcp_proxy.rs::proxy_replaces_client_auth_and_preserves_path_query_and_body
    crates/rolter-gateway/src/mcp_policy.rs::a_governed_server_serves_only_the_tools_its_groups_list
    crates/rolter-gateway/src/mcp_proxy.rs::insufficient_scope_from_an_oauth_server_is_the_step_up_answer
    crates/rolter-gateway/tests/integration.rs::mcp_proxy_binds_virtual_key_owner_to_server_scopes_and_bearer

Identity#

SpecificationRevisionConformanceReviewedEndpoints
MCP authorization (mcp-authorization)2026-07-28partial2026-10-28POST /api/v1/mcp-servers/{id}/oauth/authorize
The OAuth 2.0 Authorization Framework (oauth2)RFC 6749partial2026-10-27—
OAuth 2.0 Bearer Token Usage (oauth2-bearer)RFC 6750partial2026-10-27—
Proof Key for Code Exchange (pkce)RFC 7636partial2026-10-27—
OAuth 2.0 Token Exchange (oauth2-token-exchange)RFC 8693partial2026-10-27—
OAuth 2.0 Authorization Server Metadata (oauth2-as-metadata)RFC 8414partial2026-10-27—
Resource Indicators for OAuth 2.0 (oauth2-resource-indicators)RFC 8707partial2026-10-27—
OAuth 2.0 Authorization Server Issuer Identification (oauth2-iss)RFC 9207native-passthrough2026-10-27—
OAuth 2.0 Protected Resource Metadata (oauth2-protected-resource-metadata)RFC 9728partial2026-10-27—
OpenID Connect Core 1.0 (oidc-core)1.0 incorporating errata set 2partial2026-10-27GET /auth/sso/{slug}/start
GET /auth/sso/{slug}/callback
OpenID Connect Discovery 1.0 (oidc-discovery)1.0 incorporating errata set 2partial2026-10-27—
SCIM 2.0 core schema and protocol (scim)RFC 7643 / RFC 7644partial2026-10-27GET /scim/v2/Users
POST /scim/v2/Users
GET /scim/v2/Users/{id}
PUT /scim/v2/Users/{id}
PATCH /scim/v2/Users/{id}
DELETE /scim/v2/Users/{id}
GET /scim/v2/Groups
POST /scim/v2/Groups
GET /scim/v2/Groups/{id}
PUT /scim/v2/Groups/{id}
PATCH /scim/v2/Groups/{id}
DELETE /scim/v2/Groups/{id}
LDAP protocol and string representation of search filters (ldap)RFC 4511 / RFC 4515partial2026-10-27POST /api/v1/auth/login
TOTP: Time-Based One-Time Password Algorithm (totp)RFC 6238partial2026-10-27—

MCP authorization#

mcp-authorization · Model Context Protocol · primary source

  • Supported: the client-side MUSTs: RFC 9728 discovery, RFC 8707 resource indicators, RFC 9207 iss validation, PKCE
  • Supported: scope selection from the challenge’s scope and the metadata’s scopes_supported, and step-up: a re-authorization asks for the live grant’s scopes plus the ones an insufficient_scope refusal named (#1417)
  • Omitted: dynamic client registration and client ID metadata documents: the operator registers the client by hand
  • Evidence: crates/rolter-control/src/mcp_oauth_discovery.rs::the_rfc_9207_table_is_implemented_row_by_row
    crates/rolter-control/src/mcp_oauth_flow.rs::scopes_are_chosen_by_the_documented_precedence
    crates/rolter-control/src/mcp_oauth_discovery.rs::the_challenge_parameter_is_read_off_a_www_authenticate_header
    crates/rolter-control/src/mcp_oauth_discovery.rs::a_resource_uri_is_canonicalised_the_way_rfc_8707_asks

The OAuth 2.0 Authorization Framework#

oauth2 · IETF · primary source

  • Supported: authorization-code and refresh-token grants, as a client
  • Omitted: rolter is never an authorization server
  • Evidence: crates/rolter-control/src/mcp_oauth_flow.rs::a_refusal_and_a_missing_kek_stay_400s_with_their_own_words

OAuth 2.0 Bearer Token Usage#

oauth2-bearer · IETF · primary source

  • Supported: Authorization: Bearer for virtual keys, SCIM tokens and the credential presented to an MCP server
  • Omitted: no access_token form or query parameter
  • Evidence: crates/rolter-gateway/src/mcp_proxy.rs::proxy_replaces_client_auth_and_preserves_path_query_and_body

Proof Key for Code Exchange#

pkce · IETF · primary source

  • Supported: S256 only
  • Omitted: plain is never sent
  • Evidence: crates/rolter-control/src/sso.rs::pkce_challenge_is_the_s256_of_the_verifier

OAuth 2.0 Token Exchange#

oauth2-token-exchange · IETF · primary source

  • Supported: on-behalf-of exchange for an MCP session, as a client
  • Evidence: crates/rolter-control/src/mcp_oauth_flow.rs::a_token_endpoint_resolving_to_a_denied_address_is_never_contacted

OAuth 2.0 Authorization Server Metadata#

oauth2-as-metadata · IETF · primary source

  • Supported: /.well-known/oauth-authorization-server read, with the OIDC discovery path as the fallback
  • Evidence: crates/rolter-control/src/mcp_oauth_discovery.rs::a_metadata_host_resolving_to_a_denied_address_is_never_contacted

Resource Indicators for OAuth 2.0#

oauth2-resource-indicators · IETF · primary source

  • Supported: resource on every authorization and token request, canonicalised once
  • Evidence: crates/rolter-control/src/mcp_oauth_discovery.rs::a_resource_uri_is_canonicalised_the_way_rfc_8707_asks

OAuth 2.0 Authorization Server Issuer Identification#

oauth2-iss · IETF · primary source

  • Supported: iss checked on the authorization response against the issuer the browser was sent to
  • Evidence: crates/rolter-control/src/mcp_oauth_discovery.rs::the_rfc_9207_table_is_implemented_row_by_row

OAuth 2.0 Protected Resource Metadata#

oauth2-protected-resource-metadata · IETF · primary source

  • Supported: discovery of an MCP server’s authorization server
  • Omitted: rolter does not publish metadata for its own /mcp endpoints
  • Evidence: crates/rolter-control/src/mcp_oauth_discovery.rs::a_metadata_host_resolving_to_a_denied_address_is_never_contacted

OpenID Connect Core 1.0#

oidc-core · OpenID Foundation · primary source

  • Supported: authorization-code flow with PKCE, state and nonce; id token signature checked against the JWKS, with iss, aud, exp and nonce
  • Omitted: implicit and hybrid flows; alg: none and HMAC-signed tokens are refused
  • Evidence: crates/rolter-control/src/sso.rs::authorize_url_carries_pkce_state_and_nonce
    crates/rolter-control/src/sso.rs::symmetric_and_none_algorithms_are_not_accepted

OpenID Connect Discovery 1.0#

oidc-discovery · OpenID Foundation · primary source

  • Supported: /.well-known/openid-configuration read for the authorization, token and JWKS endpoints
  • Evidence: crates/rolter-control/src/sso.rs::a_provider_row_carries_the_uris_the_flow_uses

SCIM 2.0 core schema and protocol#

scim · IETF · primary source

  • Supported: the User and Group resources; eq filters on userName and displayName; PATCH in the shapes IdPs send
  • Omitted: bulk, sort, /Me, /ServiceProviderConfig and filters beyond eq; a password attribute is ignored
  • Evidence: crates/rolter-control/src/scim.rs::parses_the_user_name_filter_idps_send
    crates/rolter-control/src/scim.rs::rejects_filters_it_cannot_honour
    crates/rolter-control/src/scim_groups.rs::reads_members_in_every_shape_idps_send

LDAP protocol and string representation of search filters#

ldap · IETF · primary source

  • Supported: sign-in: when a local password does not verify, each enabled directory of the org is tried with a two-phase simple bind (service account search, then a bind as the user)
  • Supported: every RFC 4515 special character escaped in a filter value; ldaps:// when a directory requires TLS
  • Supported: directory groups mapped to roles through the scoped-grant model SSO and SCIM use, reconciled on every sign-in
  • Omitted: SASL binds and StartTLS upgrade of a plain ldap:// connection
  • Omitted: the directory settings API (/api/v1/ldap-directories) is rolter’s own and implements no LDAP operation
  • Evidence: crates/rolter-control/src/ldap.rs::escaping_covers_every_rfc4515_special_character
    crates/rolter-control/tests/control/ldap.rs::a_directory_user_signs_in_and_gets_the_grants_their_groups_map_to
    crates/rolter-control/tests/control/ldap.rs::a_wrong_password_and_an_unknown_login_are_the_same_refusal

TOTP: Time-Based One-Time Password Algorithm#

totp · IETF · primary source

  • Supported: HMAC-SHA1, six digits and 30-second steps; base32 (RFC 4648) secrets
  • Evidence: crates/rolter-auth/src/totp.rs::matches_the_rfc_6238_test_vectors
    crates/rolter-auth/src/totp.rs::base32_round_trips_and_matches_rfc_4648_vectors

Telemetry#

SpecificationRevisionConformanceReviewedEndpoints
OpenTelemetry Protocol (OTLP) (otlp)1.10.0 (ca839c51f706)native-passthrough2026-10-27—
OpenTelemetry SDK environment variables (otel-sdk-env)living (no revision)partial2026-10-27—
Semantic conventions for generative AI (otel-genai-semconv)1.41.0 (e018fe6f9186)extension2026-10-27—
Trace Context (w3c-trace-context)W3C Recommendation, Level 1partial2026-10-27—
B3 propagation (b3)living (no revision)partial2026-10-27—
Prometheus text exposition format (prometheus-text)0.0.4native-passthrough2026-10-27GET /metrics

OpenTelemetry Protocol (OTLP)#

otlp · OpenTelemetry · primary source

  • Supported: traces, metrics and logs over OTLP/gRPC or OTLP/HTTP
  • Evidence: crates/rolter-gateway/src/metrics.rs::otlp_labelled_export_matches_the_prometheus_text

OpenTelemetry SDK environment variables#

otel-sdk-env · OpenTelemetry · primary source

  • Supported: OTEL_EXPORTER_OTLP_*ENDPOINT, OTEL_EXPORTER_OTLP_PROTOCOL, OTEL_EXPORTER_OTLP_HEADERS, OTEL_SERVICE_NAME, OTEL_RESOURCE_ATTRIBUTES, OTEL_METRIC_EXPORT_INTERVAL
  • Evidence: crates/rolter-core/src/telemetry.rs::the_switch_beats_a_configured_endpoint

Semantic conventions for generative AI#

otel-genai-semconv · OpenTelemetry · primary source

  • Supported: gen_ai.operation.name
  • Supported: gen_ai.provider.name
  • Supported: gen_ai.request.model
  • Supported: gen_ai.response.model
  • Supported: gen_ai.response.finish_reasons
  • Supported: gen_ai.response.id
  • Supported: gen_ai.output.type
  • Supported: gen_ai.usage.input_tokens
  • Supported: gen_ai.usage.output_tokens
  • Supported: gen_ai.embeddings.dimension.count
  • Supported: gen_ai.request.encoding_formats
  • Supported: error.type
  • Omitted: prompt and completion content (gen_ai.input.messages, gen_ai.output.messages) is never emitted
  • Deviations: gen_ai.system is still emitted beside gen_ai.provider.name, though v1.41.0 lists it as deprecated
  • Deviations: rerank and decision are rolter-local gen_ai.operation.name values: the enum has no entry for either
  • Deviations: audio transcription and translation are generate_content with gen_ai.output.type=text; the audio input is not representable
  • Deviations: a Realtime session carries no GenAI operation
  • Evidence: crates/rolter-gateway/src/genai.rs::the_attribute_registry_matches_the_spec_spellings
    crates/rolter-gateway/src/genai.rs::the_registry_lists_every_emitted_attribute

Trace Context#

w3c-trace-context · W3C · primary source

  • Supported: traceparent parsed for the request log’s trace id; traceparent and tracestate forwarded to the upstream verbatim
  • Omitted: W3C Baggage is not read or forwarded
  • Evidence: crates/rolter-gateway/src/trace.rs::parses_w3c_traceparent
    crates/rolter-gateway/tests/integration.rs::propagates_inbound_traceparent_to_upstream

B3 propagation#

b3 · OpenZipkin · primary source

  • Supported: the single b3 header and the x-b3-* multi-header form, read and forwarded verbatim; traceparent wins when both arrive
  • Evidence: crates/rolter-gateway/src/trace.rs::parses_b3_single_and_multi
    crates/rolter-gateway/src/trace.rs::traceparent_wins_over_b3

Prometheus text exposition format#

prometheus-text · Prometheus · primary source

  • Supported: text/plain; version=0.0.4
  • Omitted: OpenMetrics is not served: neither its content type nor its grammar
  • Evidence: crates/rolter-gateway/tests/integration.rs::metrics_served_on_configured_path

API description#

SpecificationRevisionConformanceReviewedEndpoints
OpenAPI Specification (openapi)3.1.0native-passthrough2026-10-27GET /openapi.json

OpenAPI Specification#

openapi · OpenAPI Initiative · primary source

  • Supported: info.version is the rolter build, never an upstream vendor’s version; provenance travels as externalDocs and x-rolter-* extensions
  • Evidence: crates/rolter-gateway/tests/integration.rs::serves_openapi_document
    crates/rolter-gateway/src/openapi.rs::every_documented_operation_carries_its_provenance

Provider kinds#

KindDocumentationAuthPrimary pathExample api_baseConformanceReviewedEvidence
openaiOpenAIauthorization/v1/chat/completionshttps://api.openai.comnative-passthrough2026-10-27crates/rolter-gateway/tests/integration.rs::responses_passthrough_preserves_body_and_sse_events
anthropicAnthropicx-api-key/v1/messageshttps://api.anthropic.comnative-passthrough2026-10-27crates/rolter-gateway/tests/integration.rs::anthropic_multimodal_content_is_forwarded_byte_for_byte
openai_compatibleany OpenAI-compatible server (vLLM, TGI, SGLang, LM Studio)authorization/v1/chat/completions—provider-profile2026-10-27crates/rolter-gateway/tests/integration.rs::non_streaming_request_proxies_upstream_body
ollamaOllamaauthorization/v1/chat/completionshttp://localhost:11434provider-profile2026-10-27crates/rolter-core/src/config.rs::every_kind_resolves_by_the_documented_rule
ollama_cloudOllamaauthorization/v1/chat/completionshttps://ollama.comprovider-profile2026-10-27crates/rolter-gateway/tests/ollama_cloud.rs
llama_cppggml-org/llama.cppauthorization/v1/chat/completions—provider-profile2026-10-27crates/rolter-gateway/tests/llama_cpp.rs
openrouterOpenRouterauthorization/v1/chat/completionshttps://openrouter.ai/api/v1provider-profile2026-10-27crates/rolter-gateway/tests/openrouter.rs
teiHugging Faceauthorization/v1/embeddings—native-passthrough2026-10-27crates/rolter-gateway/tests/tei.rs
azure_openaiMicrosoftapi-key/v1/chat/completionshttps://RESOURCE.openai.azure.com/openai/v1provider-profile2026-10-27crates/rolter-proxy/src/lib.rs::every_kind_authenticates_with_the_header_the_probes_use
bedrockAmazon Web Services — a Bedrock API key as a bearer token; SigV4 signing is not implementedauthorization/v1/chat/completionshttps://bedrock-runtime.us-east-1.amazonaws.com/v1provider-profile2026-10-27crates/rolter-proxy/src/lib.rs::the_previewed_address_is_the_one_the_forwarder_builds
vertexGoogle Cloud — a short-lived OAuth access token as the bearer; rolter does not mint itauthorization/v1/chat/completionshttps://aiplatform.googleapis.com/v1/projects/PROJECT/locations/global/endpoints/openapiprovider-profile2026-10-27crates/rolter-proxy/src/lib.rs::the_previewed_address_is_the_one_the_forwarder_builds
geminiGoogleauthorization/v1/chat/completionshttps://generativelanguage.googleapis.com/v1beta/openaiprovider-profile2026-10-27crates/rolter-core/src/config.rs::every_kind_resolves_by_the_documented_rule
gemini_nativeGooglex-goog-api-key/models/{model}:generateContenthttps://generativelanguage.googleapis.com/v1betatranslation-subset2026-10-27crates/rolter-gateway/tests/integration.rs::unsupported_content_parts_never_reach_a_gemini_upstream
gemini_interactionsGooglex-goog-api-key/interactionshttps://generativelanguage.googleapis.com/v1betatranslation-subset2026-10-27crates/rolter-proxy/src/lib.rs::gemini_interactions_targets_the_single_interactions_endpoint
mistralMistral AIauthorization/v1/chat/completionshttps://api.mistral.ai/v1provider-profile2026-10-27crates/rolter-core/src/config.rs::every_kind_resolves_by_the_documented_rule
groqGroqauthorization/v1/chat/completionshttps://api.groq.com/openai/v1provider-profile2026-10-27crates/rolter-core/src/config.rs::every_kind_resolves_by_the_documented_rule
xaixAIauthorization/v1/chat/completionshttps://api.x.ai/v1provider-profile2026-10-27crates/rolter-core/src/config.rs::every_kind_resolves_by_the_documented_rule
meta_llama_apiMetaauthorization/v1/chat/completions—provider-profile2026-10-27crates/rolter-core/src/config.rs::every_kind_resolves_by_the_documented_rule
cohereCohereauthorization/v1/chat/completions—provider-profile2026-10-27crates/rolter-core/src/config.rs::every_kind_resolves_by_the_documented_rule
perplexityPerplexityauthorization/v1/chat/completions—provider-profile2026-10-27crates/rolter-core/src/config.rs::every_kind_resolves_by_the_documented_rule
togetherTogether AIauthorization/v1/chat/completions—provider-profile2026-10-27crates/rolter-core/src/config.rs::every_kind_resolves_by_the_documented_rule
fireworksFireworks AIauthorization/v1/chat/completions—provider-profile2026-10-27crates/rolter-core/src/config.rs::every_kind_resolves_by_the_documented_rule
databricksDatabricksauthorization/v1/chat/completions—provider-profile2026-10-27crates/rolter-core/src/config.rs::every_kind_resolves_by_the_documented_rule
aleph_alphaAleph Alphaauthorization/v1/chat/completions—provider-profile2026-10-27crates/rolter-core/src/config.rs::every_kind_resolves_by_the_documented_rule
nebiusNebiusauthorization/v1/chat/completions—provider-profile2026-10-27crates/rolter-core/src/config.rs::every_kind_resolves_by_the_documented_rule
ovhcloudOVHcloudauthorization/v1/chat/completions—provider-profile2026-10-27crates/rolter-core/src/config.rs::every_kind_resolves_by_the_documented_rule
scalewayScalewayauthorization/v1/chat/completions—provider-profile2026-10-27crates/rolter-core/src/config.rs::every_kind_resolves_by_the_documented_rule
deepseekDeepSeekauthorization/v1/chat/completions—provider-profile2026-10-27crates/rolter-core/src/config.rs::every_kind_resolves_by_the_documented_rule
qwenAlibaba Cloudauthorization/v1/chat/completions—provider-profile2026-10-27crates/rolter-core/src/config.rs::every_kind_resolves_by_the_documented_rule
zhipuZhipu AIauthorization/v1/chat/completions—provider-profile2026-10-27crates/rolter-core/src/config.rs::every_kind_resolves_by_the_documented_rule
kimiMoonshot AIauthorization/v1/chat/completions—provider-profile2026-10-27crates/rolter-core/src/config.rs::every_kind_resolves_by_the_documented_rule
ernieBaiduauthorization/v1/chat/completions—provider-profile2026-10-27crates/rolter-core/src/config.rs::every_kind_resolves_by_the_documented_rule
doubaoByteDance Volcengineauthorization/v1/chat/completions—provider-profile2026-10-27crates/rolter-core/src/config.rs::every_kind_resolves_by_the_documented_rule
hunyuanTencent Cloudauthorization/v1/chat/completions—provider-profile2026-10-27crates/rolter-core/src/config.rs::every_kind_resolves_by_the_documented_rule
yi01.AIauthorization/v1/chat/completions—provider-profile2026-10-27crates/rolter-core/src/config.rs::every_kind_resolves_by_the_documented_rule
minimaxMiniMaxauthorization/v1/chat/completions—provider-profile2026-10-27crates/rolter-core/src/config.rs::every_kind_resolves_by_the_documented_rule
baichuanBaichuan AIauthorization/v1/chat/completions—provider-profile2026-10-27crates/rolter-core/src/config.rs::every_kind_resolves_by_the_documented_rule
gigachatSber — GigaChat issues short-lived access tokens from an OAuth endpoint; rolter sends the configured key as the bearer and does not mint oneauthorization/v1/chat/completions—provider-profile2026-10-27crates/rolter-core/src/config.rs::every_kind_resolves_by_the_documented_rule
yandex_gptYandex Cloudauthorization/v1/chat/completions—provider-profile2026-10-27crates/rolter-core/src/config.rs::every_kind_resolves_by_the_documented_rule
cloud_ruCloud.ruauthorization/v1/chat/completions—provider-profile2026-10-27crates/rolter-core/src/config.rs::every_kind_resolves_by_the_documented_rule
mts_aiMTS AI — product page; no public API reference was found at reviewauthorization/v1/chat/completions—provider-profile2026-10-27crates/rolter-core/src/config.rs::every_kind_resolves_by_the_documented_rule
naverNaver Cloudauthorization/v1/chat/completions—provider-profile2026-10-27crates/rolter-core/src/config.rs::every_kind_resolves_by_the_documented_rule
upstageUpstageauthorization/v1/chat/completions—provider-profile2026-10-27crates/rolter-core/src/config.rs::every_kind_resolves_by_the_documented_rule
rinnarinna — company site; no public API reference was found at reviewauthorization/v1/chat/completions—provider-profile2026-10-27crates/rolter-core/src/config.rs::every_kind_resolves_by_the_documented_rule
rakutenRakuten — product site; no public API reference was found at reviewauthorization/v1/chat/completions—provider-profile2026-10-27crates/rolter-core/src/config.rs::every_kind_resolves_by_the_documented_rule
sarvamSarvam AIauthorization/v1/chat/completions—provider-profile2026-10-27crates/rolter-core/src/config.rs::every_kind_resolves_by_the_documented_rule
krutrimOla Krutrim — console; no public API reference was found at reviewauthorization/v1/chat/completions—provider-profile2026-10-27crates/rolter-core/src/config.rs::every_kind_resolves_by_the_documented_rule
falconTechnology Innovation Institute — product site; no public API reference was found at reviewauthorization/v1/chat/completions—provider-profile2026-10-27crates/rolter-core/src/config.rs::every_kind_resolves_by_the_documented_rule
system_oneTypeSafeauthorization/v1/systemonehttps://api.typesafe.ainative-passthrough2026-10-27crates/rolter-gateway/tests/system_one.rs
infinitymichaelfeil/infinityauthorization/v1/embeddings—translation-subset2026-10-27crates/rolter-gateway/tests/infinity.rs