“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#
| Level | Meaning |
|---|---|
native-passthrough | The vendor’s wire format, forwarded or served unchanged. Rolter reads the fields it needs (model, stream, usage). |
translation-subset | Rolter rewrites between dialects. Only what the record lists is translated; a part with no equivalent fails the request. |
transport-only | Bytes are relayed. Rolter neither validates the payload nor negotiates a version, so the two ends must agree between them. |
extension | The vendor’s shape plus Rolter’s own additions. |
partial | Some of the specification, as listed. |
provider-profile | A 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 ownanthropic-versionalways 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 upstreaminsufficient_scopewith a step-up challenge, but it relaysMCP-Protocol-Versionwithout negotiating it, so the recorded version isforwarded. 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#
| Specification | Revision | Conformance | Reviewed | Endpoints |
|---|---|---|---|---|
OpenAI Chat Completions (openai-chat-completions) | v1 | native-passthrough | 2026-10-27 | POST /v1/chat/completions |
OpenAI Completions (legacy) (openai-completions) | v1 | native-passthrough | 2026-10-27 | POST /v1/completions |
OpenAI Responses and its lifecycle methods (openai-responses) | v1 | partial | 2026-10-27 | POST /v1/responsesGET /v1/responses/{response_id}DELETE /v1/responses/{response_id}POST /v1/responses/{response_id}/cancelGET /v1/responses/{response_id}/input_itemsPOST /v1/responses/{response_id}/compactGET /v1/responses/{response_id}/input_tokens |
OpenAI Embeddings (openai-embeddings) | v1 | native-passthrough | 2026-10-27 | POST /v1/embeddings |
OpenAI Models (list) (openai-models) | v1 | extension | 2026-10-27 | GET /v1/models |
OpenAI Images (generations) (openai-images) | v1 | native-passthrough | 2026-10-27 | POST /v1/images/generations |
OpenAI Audio (speech, transcriptions, translations) (openai-audio) | v1 | native-passthrough | 2026-10-27 | POST /v1/audio/speechPOST /v1/audio/transcriptionsPOST /v1/audio/translations |
OpenAI Realtime (WebSocket) (openai-realtime) | v1 | partial | 2026-10-27 | GET /v1/realtime |
OpenAI error object (openai-errors) | v1 | partial | 2026-10-27 | — |
Anthropic Messages API (anthropic-messages) | 2023-06-01 | native-passthrough | 2026-10-27 | POST /v1/messages |
Gemini API OpenAI compatibility (gemini-openai-compat) | v1beta | native-passthrough | 2026-10-27 | — |
Gemini generateContent and streamGenerateContent (gemini-generate-content) | v1beta | translation-subset | 2026-10-27 | — |
Gemini Interactions API (gemini-interactions) | v1beta | translation-subset | 2026-10-27 | — |
Rerank (Cohere v1 and Jina request shape) (rerank) | v1 | transport-only | 2026-10-27 | POST /v1/rerank |
Infinity embeddings and rerank server (infinity) | living (no revision) | translation-subset | 2026-10-27 | — |
Text Embeddings Inference (hf-tei) | living (no revision) | native-passthrough | 2026-10-27 | — |
System One decision API (system-one) | living (no revision) | native-passthrough | 2026-10-27 | POST /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,messagesandusage - Supported:
chat.completion.chunkSSE 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/modelname 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_bodycrates/rolter-gateway/tests/integration.rs::streaming_request_passes_through_ssecrates/rolter-gateway/tests/integration.rs::output_guardrail_masks_a_non_streaming_completioncrates/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:
compactandinput_tokensare 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_eventscrates/rolter-gateway/tests/integration.rs::responses_lifecycle_operations_are_uniformly_unsupportedcrates/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_formatandusage - Evidence:
crates/rolter-gateway/tests/integration.rs::builtin_fake_llm_serves_embeddingscrates/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/modelids, 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
modelfield - Evidence:
crates/rolter-gateway/tests/integration.rs::builtin_fake_llm_serves_audio_speechcrates/rolter-gateway/tests/integration.rs::builtin_fake_llm_serves_audio_transcriptionscrates/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
modelquery parameter rewritten, and frames otherwise relayed both ways unchanged - Supported: a client’s
openai-betaheader is forwarded to the upstream - Supported:
response.createdandresponse.doneserver 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_authcrates/rolter-gateway/tests/realtime_metering.rscrates/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:
codecarries 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-versionandanthropic-*headers reach an Anthropic upstream only - Supported: translation to OpenAI Chat Completions and Gemini (see the translation records)
- Deviations: a request with no
anthropic-versionis 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_bytecrates/rolter-proxy/src/lib.rs::anthropic_headers_do_not_leak_to_a_non_anthropic_upstreamcrates/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/completionswith 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=sseframes 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_clientcrates/rolter-proxy/src/translation.rs::unknown_content_parts_fail_closed_on_every_gemini_paircrates/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}/interactionsand 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_endpointcrates/rolter-proxy/src/translation.rs::gemini_interactions_fails_closed_for_endpoints_it_cannot_servecrates/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-llmanswers 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_endpointbefore the upstream on a route that reaches only embedding servers - Evidence:
crates/rolter-proxy/src/infinity.rs::documents_come_back_in_the_cohere_shapecrates/rolter-gateway/tests/infinity.rscrates/rolter-gateway/tests/embedding_only.rs
Text Embeddings Inference#
hf-tei · Hugging Face · primary source
- Supported: the OpenAI-compatible
/v1/embeddingsroute, and/healthas the liveness probe - Supported: every other endpoint,
/v1/rerankincluded (TEI has no rerank mapping), refused with400 unsupported_endpointbefore the upstream on a route that reaches only embedding servers, none of them Infinity - Evidence:
crates/rolter-gateway/tests/tei.rscrates/rolter-gateway/tests/embedding_only.rs
System One decision API#
system-one · TypeSafe · primary source
- Supported: request and response forwarded unchanged; the gateway reads
modelandusage(ADR-0035) - Evidence:
crates/rolter-gateway/tests/system_one.rs
Translations#
| Specification | Revision | Conformance | Reviewed | Endpoints |
|---|---|---|---|---|
OpenAI Chat Completions ⇄ Anthropic Messages (translation-openai-anthropic) | living (no revision) | translation-subset | 2026-10-27 | — |
OpenAI Responses → Chat Completions, Anthropic Messages, Gemini (translation-responses) | living (no revision) | translation-subset | 2026-10-27 | — |
OpenAI / Anthropic / Responses → Gemini generateContent and Interactions (translation-gemini) | living (no revision) | translation-subset | 2026-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_tokensinjected from[compatibility] default_max_tokenswhen an OpenAI request sets none - Supported: Anthropic
tool_choice.disable_parallel_tool_use: truecarried as Chatparallel_tool_calls: falseon a request with tools (#3325) - Omitted: fields with no counterpart in the target dialect are dropped, never forwarded
- Deviations: an OpenAI
temperatureabove Anthropic’s maximum of 1 is sent as 1 and reported astemperature=clamped(#3324) - Evidence:
crates/rolter-proxy/src/translation.rs::openai_multimodal_and_tools_become_anthropic_blockscrates/rolter-proxy/src/translation.rs::chat_to_anthropic_clamps_a_temperature_above_onecrates/rolter-proxy/src/translation.rs::anthropic_disable_parallel_tool_use_becomes_chat_parallel_tool_callscrates/rolter-gateway/tests/integration.rs::a_chat_temperature_above_one_is_clamped_for_an_anthropic_upstreamcrates/rolter-proxy/src/translation.rs::anthropic_response_becomes_openai_responsecrates/rolter-proxy/src/translation.rs::anthropic_sse_translates_across_chunk_boundariescrates/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_inputcrates/rolter-proxy/src/translation.rs::chat_sse_becomes_responses_ssecrates/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-contentandgemini-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#
| Specification | Revision | Conformance | Reviewed | Endpoints |
|---|---|---|---|---|
Server-sent events (sse) | living (no revision) | partial | 2026-10-27 | POST /v1/chat/completionsPOST /v1/completionsPOST /v1/responsesPOST /v1/messages |
The WebSocket Protocol (websocket) | RFC 6455 | native-passthrough | 2026-10-27 | GET /v1/realtime |
Returning Values from Forms: multipart/form-data (multipart-form-data) | RFC 7578 | partial | 2026-10-27 | POST /v1/audio/transcriptionsPOST /v1/audio/translations |
Date and Time on the Internet: Timestamps (rfc3339) | RFC 3339 | partial | 2026-10-27 | — |
Uniform Resource Identifier (URI): Generic Syntax (uri) | RFC 3986 | partial | 2026-10-27 | — |
The Deprecation HTTP Response Header Field (deprecation-header) | RFC 9745 | native-passthrough | 2026-10-27 | — |
The Sunset HTTP Header Field (sunset-header) | RFC 8594 | native-passthrough | 2026-10-27 | — |
JSON-RPC 2.0 (json-rpc) | 2.0.0 | partial | 2026-10-27 | POST /mcp/{server}POST /mcp/{server}/{path} |
Server-sent events#
sse · WHATWG · primary source
- Supported:
event:anddata:fields, multi-line data and frames split across chunks, parsed when a stream is translated - Omitted:
id:andretry:are relayed but never interpreted; no reconnection - Evidence:
crates/rolter-proxy/src/translation.rs::anthropic_sse_translates_across_chunk_boundariescrates/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-timein 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:
Deprecationon every/internal/snapshotanswer served in a deprecated snapshot format (ADR-0038) - Evidence:
crates/rolter-control/src/deprecation.rs::headers_follow_rfc_9745_and_rfc_8594crates/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:
Sunsetas an IMF-fixdate on every deprecated control-plane operation - Supported:
Sunseton every/internal/snapshotanswer served in a deprecated snapshot format (ADR-0038) - Evidence:
crates/rolter-control/src/deprecation.rs::headers_follow_rfc_9745_and_rfc_8594crates/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/calloutside them is refused - Supported:
method,resultanderrorare 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_unreadableunless 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_policycrates/rolter-gateway/src/mcp_policy.rs::a_batch_is_refused_as_a_whole_naming_every_refused_callcrates/rolter-gateway/tests/integration.rs::mcp_proxy_records_a_tool_call_with_key_and_session_owner_attributioncrates/rolter-gateway/tests/integration.rs::mcp_proxy_records_a_json_rpc_error_as_a_tool_error
Transport#
| Specification | Revision | Conformance | Reviewed | Endpoints |
|---|---|---|---|---|
HTTP Semantics and HTTP/1.1 (http-semantics) | RFC 9110 | partial | 2026-10-27 | — |
MCP Streamable HTTP transport and version negotiation (mcp-transport) | forwarded | partial | 2026-10-27 | GET /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,Upgradeand 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_nominatescrates/rolter-proxy/src/hop_by_hop.rs::removes_trailer_and_the_fixed_setcrates/rolter-control/src/proxy.rs::the_relay_drops_nominated_and_trailer_headers_both_wayscrates/rolter-gateway/src/mcp_proxy.rs::the_relay_drops_nominated_and_trailer_headerscrates/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-Idrelayed 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_deniedbefore anything is forwarded (seejson-rpc) - Supported: an upstream 403 whose challenge says
insufficient_scopeis answered with 403mcp_insufficient_scopeand a rebuiltWWW-Authenticatechallenge - Omitted: no protocol-version negotiation:
MCP-Protocol-Versionis 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_bodycrates/rolter-gateway/src/mcp_policy.rs::a_governed_server_serves_only_the_tools_its_groups_listcrates/rolter-gateway/src/mcp_proxy.rs::insufficient_scope_from_an_oauth_server_is_the_step_up_answercrates/rolter-gateway/tests/integration.rs::mcp_proxy_binds_virtual_key_owner_to_server_scopes_and_bearer
Identity#
| Specification | Revision | Conformance | Reviewed | Endpoints |
|---|---|---|---|---|
MCP authorization (mcp-authorization) | 2026-07-28 | partial | 2026-10-28 | POST /api/v1/mcp-servers/{id}/oauth/authorize |
The OAuth 2.0 Authorization Framework (oauth2) | RFC 6749 | partial | 2026-10-27 | — |
OAuth 2.0 Bearer Token Usage (oauth2-bearer) | RFC 6750 | partial | 2026-10-27 | — |
Proof Key for Code Exchange (pkce) | RFC 7636 | partial | 2026-10-27 | — |
OAuth 2.0 Token Exchange (oauth2-token-exchange) | RFC 8693 | partial | 2026-10-27 | — |
OAuth 2.0 Authorization Server Metadata (oauth2-as-metadata) | RFC 8414 | partial | 2026-10-27 | — |
Resource Indicators for OAuth 2.0 (oauth2-resource-indicators) | RFC 8707 | partial | 2026-10-27 | — |
OAuth 2.0 Authorization Server Issuer Identification (oauth2-iss) | RFC 9207 | native-passthrough | 2026-10-27 | — |
OAuth 2.0 Protected Resource Metadata (oauth2-protected-resource-metadata) | RFC 9728 | partial | 2026-10-27 | — |
OpenID Connect Core 1.0 (oidc-core) | 1.0 incorporating errata set 2 | partial | 2026-10-27 | GET /auth/sso/{slug}/startGET /auth/sso/{slug}/callback |
OpenID Connect Discovery 1.0 (oidc-discovery) | 1.0 incorporating errata set 2 | partial | 2026-10-27 | — |
SCIM 2.0 core schema and protocol (scim) | RFC 7643 / RFC 7644 | partial | 2026-10-27 | GET /scim/v2/UsersPOST /scim/v2/UsersGET /scim/v2/Users/{id}PUT /scim/v2/Users/{id}PATCH /scim/v2/Users/{id}DELETE /scim/v2/Users/{id}GET /scim/v2/GroupsPOST /scim/v2/GroupsGET /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 4515 | partial | 2026-10-27 | POST /api/v1/auth/login |
TOTP: Time-Based One-Time Password Algorithm (totp) | RFC 6238 | partial | 2026-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
issvalidation, PKCE - Supported: scope selection from the challenge’s
scopeand the metadata’sscopes_supported, and step-up: a re-authorization asks for the live grant’s scopes plus the ones aninsufficient_scoperefusal 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_rowcrates/rolter-control/src/mcp_oauth_flow.rs::scopes_are_chosen_by_the_documented_precedencecrates/rolter-control/src/mcp_oauth_discovery.rs::the_challenge_parameter_is_read_off_a_www_authenticate_headercrates/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: Bearerfor virtual keys, SCIM tokens and the credential presented to an MCP server - Omitted: no
access_tokenform 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:
S256only - Omitted:
plainis 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-serverread, 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:
resourceon 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:
isschecked 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
/mcpendpoints - 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,
stateandnonce; id token signature checked against the JWKS, withiss,aud,expandnonce - Omitted: implicit and hybrid flows;
alg: noneand HMAC-signed tokens are refused - Evidence:
crates/rolter-control/src/sso.rs::authorize_url_carries_pkce_state_and_noncecrates/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-configurationread 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;
eqfilters onuserNameanddisplayName; PATCH in the shapes IdPs send - Omitted: bulk, sort,
/Me,/ServiceProviderConfigand filters beyondeq; apasswordattribute is ignored - Evidence:
crates/rolter-control/src/scim.rs::parses_the_user_name_filter_idps_sendcrates/rolter-control/src/scim.rs::rejects_filters_it_cannot_honourcrates/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_charactercrates/rolter-control/tests/control/ldap.rs::a_directory_user_signs_in_and_gets_the_grants_their_groups_map_tocrates/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_vectorscrates/rolter-auth/src/totp.rs::base32_round_trips_and_matches_rfc_4648_vectors
Telemetry#
| Specification | Revision | Conformance | Reviewed | Endpoints |
|---|---|---|---|---|
OpenTelemetry Protocol (OTLP) (otlp) | 1.10.0 (ca839c51f706) | native-passthrough | 2026-10-27 | — |
OpenTelemetry SDK environment variables (otel-sdk-env) | living (no revision) | partial | 2026-10-27 | — |
Semantic conventions for generative AI (otel-genai-semconv) | 1.41.0 (e018fe6f9186) | extension | 2026-10-27 | — |
Trace Context (w3c-trace-context) | W3C Recommendation, Level 1 | partial | 2026-10-27 | — |
B3 propagation (b3) | living (no revision) | partial | 2026-10-27 | — |
Prometheus text exposition format (prometheus-text) | 0.0.4 | native-passthrough | 2026-10-27 | GET /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.systemis still emitted besidegen_ai.provider.name, though v1.41.0 lists it as deprecated - Deviations:
rerankanddecisionare rolter-localgen_ai.operation.namevalues: the enum has no entry for either - Deviations: audio transcription and translation are
generate_contentwithgen_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_spellingscrates/rolter-gateway/src/genai.rs::the_registry_lists_every_emitted_attribute
Trace Context#
w3c-trace-context · W3C · primary source
- Supported:
traceparentparsed for the request log’s trace id;traceparentandtracestateforwarded to the upstream verbatim - Omitted: W3C Baggage is not read or forwarded
- Evidence:
crates/rolter-gateway/src/trace.rs::parses_w3c_traceparentcrates/rolter-gateway/tests/integration.rs::propagates_inbound_traceparent_to_upstream
B3 propagation#
b3 · OpenZipkin · primary source
- Supported: the single
b3header and thex-b3-*multi-header form, read and forwarded verbatim;traceparentwins when both arrive - Evidence:
crates/rolter-gateway/src/trace.rs::parses_b3_single_and_multicrates/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#
| Specification | Revision | Conformance | Reviewed | Endpoints |
|---|---|---|---|---|
OpenAPI Specification (openapi) | 3.1.0 | native-passthrough | 2026-10-27 | GET /openapi.json |
OpenAPI Specification#
openapi · OpenAPI Initiative · primary source
- Supported:
info.versionis the rolter build, never an upstream vendor’s version; provenance travels asexternalDocsandx-rolter-*extensions - Evidence:
crates/rolter-gateway/tests/integration.rs::serves_openapi_documentcrates/rolter-gateway/src/openapi.rs::every_documented_operation_carries_its_provenance
Provider kinds#
| Kind | Documentation | Auth | Primary path | Example api_base | Conformance | Reviewed | Evidence |
|---|---|---|---|---|---|---|---|
openai | OpenAI | authorization | /v1/chat/completions | https://api.openai.com | native-passthrough | 2026-10-27 | crates/rolter-gateway/tests/integration.rs::responses_passthrough_preserves_body_and_sse_events |
anthropic | Anthropic | x-api-key | /v1/messages | https://api.anthropic.com | native-passthrough | 2026-10-27 | crates/rolter-gateway/tests/integration.rs::anthropic_multimodal_content_is_forwarded_byte_for_byte |
openai_compatible | any OpenAI-compatible server (vLLM, TGI, SGLang, LM Studio) | authorization | /v1/chat/completions | — | provider-profile | 2026-10-27 | crates/rolter-gateway/tests/integration.rs::non_streaming_request_proxies_upstream_body |
ollama | Ollama | authorization | /v1/chat/completions | http://localhost:11434 | provider-profile | 2026-10-27 | crates/rolter-core/src/config.rs::every_kind_resolves_by_the_documented_rule |
ollama_cloud | Ollama | authorization | /v1/chat/completions | https://ollama.com | provider-profile | 2026-10-27 | crates/rolter-gateway/tests/ollama_cloud.rs |
llama_cpp | ggml-org/llama.cpp | authorization | /v1/chat/completions | — | provider-profile | 2026-10-27 | crates/rolter-gateway/tests/llama_cpp.rs |
openrouter | OpenRouter | authorization | /v1/chat/completions | https://openrouter.ai/api/v1 | provider-profile | 2026-10-27 | crates/rolter-gateway/tests/openrouter.rs |
tei | Hugging Face | authorization | /v1/embeddings | — | native-passthrough | 2026-10-27 | crates/rolter-gateway/tests/tei.rs |
azure_openai | Microsoft | api-key | /v1/chat/completions | https://RESOURCE.openai.azure.com/openai/v1 | provider-profile | 2026-10-27 | crates/rolter-proxy/src/lib.rs::every_kind_authenticates_with_the_header_the_probes_use |
bedrock | Amazon Web Services — a Bedrock API key as a bearer token; SigV4 signing is not implemented | authorization | /v1/chat/completions | https://bedrock-runtime.us-east-1.amazonaws.com/v1 | provider-profile | 2026-10-27 | crates/rolter-proxy/src/lib.rs::the_previewed_address_is_the_one_the_forwarder_builds |
vertex | Google Cloud — a short-lived OAuth access token as the bearer; rolter does not mint it | authorization | /v1/chat/completions | https://aiplatform.googleapis.com/v1/projects/PROJECT/locations/global/endpoints/openapi | provider-profile | 2026-10-27 | crates/rolter-proxy/src/lib.rs::the_previewed_address_is_the_one_the_forwarder_builds |
gemini | authorization | /v1/chat/completions | https://generativelanguage.googleapis.com/v1beta/openai | provider-profile | 2026-10-27 | crates/rolter-core/src/config.rs::every_kind_resolves_by_the_documented_rule | |
gemini_native | x-goog-api-key | /models/{model}:generateContent | https://generativelanguage.googleapis.com/v1beta | translation-subset | 2026-10-27 | crates/rolter-gateway/tests/integration.rs::unsupported_content_parts_never_reach_a_gemini_upstream | |
gemini_interactions | x-goog-api-key | /interactions | https://generativelanguage.googleapis.com/v1beta | translation-subset | 2026-10-27 | crates/rolter-proxy/src/lib.rs::gemini_interactions_targets_the_single_interactions_endpoint | |
mistral | Mistral AI | authorization | /v1/chat/completions | https://api.mistral.ai/v1 | provider-profile | 2026-10-27 | crates/rolter-core/src/config.rs::every_kind_resolves_by_the_documented_rule |
groq | Groq | authorization | /v1/chat/completions | https://api.groq.com/openai/v1 | provider-profile | 2026-10-27 | crates/rolter-core/src/config.rs::every_kind_resolves_by_the_documented_rule |
xai | xAI | authorization | /v1/chat/completions | https://api.x.ai/v1 | provider-profile | 2026-10-27 | crates/rolter-core/src/config.rs::every_kind_resolves_by_the_documented_rule |
meta_llama_api | Meta | authorization | /v1/chat/completions | — | provider-profile | 2026-10-27 | crates/rolter-core/src/config.rs::every_kind_resolves_by_the_documented_rule |
cohere | Cohere | authorization | /v1/chat/completions | — | provider-profile | 2026-10-27 | crates/rolter-core/src/config.rs::every_kind_resolves_by_the_documented_rule |
perplexity | Perplexity | authorization | /v1/chat/completions | — | provider-profile | 2026-10-27 | crates/rolter-core/src/config.rs::every_kind_resolves_by_the_documented_rule |
together | Together AI | authorization | /v1/chat/completions | — | provider-profile | 2026-10-27 | crates/rolter-core/src/config.rs::every_kind_resolves_by_the_documented_rule |
fireworks | Fireworks AI | authorization | /v1/chat/completions | — | provider-profile | 2026-10-27 | crates/rolter-core/src/config.rs::every_kind_resolves_by_the_documented_rule |
databricks | Databricks | authorization | /v1/chat/completions | — | provider-profile | 2026-10-27 | crates/rolter-core/src/config.rs::every_kind_resolves_by_the_documented_rule |
aleph_alpha | Aleph Alpha | authorization | /v1/chat/completions | — | provider-profile | 2026-10-27 | crates/rolter-core/src/config.rs::every_kind_resolves_by_the_documented_rule |
nebius | Nebius | authorization | /v1/chat/completions | — | provider-profile | 2026-10-27 | crates/rolter-core/src/config.rs::every_kind_resolves_by_the_documented_rule |
ovhcloud | OVHcloud | authorization | /v1/chat/completions | — | provider-profile | 2026-10-27 | crates/rolter-core/src/config.rs::every_kind_resolves_by_the_documented_rule |
scaleway | Scaleway | authorization | /v1/chat/completions | — | provider-profile | 2026-10-27 | crates/rolter-core/src/config.rs::every_kind_resolves_by_the_documented_rule |
deepseek | DeepSeek | authorization | /v1/chat/completions | — | provider-profile | 2026-10-27 | crates/rolter-core/src/config.rs::every_kind_resolves_by_the_documented_rule |
qwen | Alibaba Cloud | authorization | /v1/chat/completions | — | provider-profile | 2026-10-27 | crates/rolter-core/src/config.rs::every_kind_resolves_by_the_documented_rule |
zhipu | Zhipu AI | authorization | /v1/chat/completions | — | provider-profile | 2026-10-27 | crates/rolter-core/src/config.rs::every_kind_resolves_by_the_documented_rule |
kimi | Moonshot AI | authorization | /v1/chat/completions | — | provider-profile | 2026-10-27 | crates/rolter-core/src/config.rs::every_kind_resolves_by_the_documented_rule |
ernie | Baidu | authorization | /v1/chat/completions | — | provider-profile | 2026-10-27 | crates/rolter-core/src/config.rs::every_kind_resolves_by_the_documented_rule |
doubao | ByteDance Volcengine | authorization | /v1/chat/completions | — | provider-profile | 2026-10-27 | crates/rolter-core/src/config.rs::every_kind_resolves_by_the_documented_rule |
hunyuan | Tencent Cloud | authorization | /v1/chat/completions | — | provider-profile | 2026-10-27 | crates/rolter-core/src/config.rs::every_kind_resolves_by_the_documented_rule |
yi | 01.AI | authorization | /v1/chat/completions | — | provider-profile | 2026-10-27 | crates/rolter-core/src/config.rs::every_kind_resolves_by_the_documented_rule |
minimax | MiniMax | authorization | /v1/chat/completions | — | provider-profile | 2026-10-27 | crates/rolter-core/src/config.rs::every_kind_resolves_by_the_documented_rule |
baichuan | Baichuan AI | authorization | /v1/chat/completions | — | provider-profile | 2026-10-27 | crates/rolter-core/src/config.rs::every_kind_resolves_by_the_documented_rule |
gigachat | Sber — GigaChat issues short-lived access tokens from an OAuth endpoint; rolter sends the configured key as the bearer and does not mint one | authorization | /v1/chat/completions | — | provider-profile | 2026-10-27 | crates/rolter-core/src/config.rs::every_kind_resolves_by_the_documented_rule |
yandex_gpt | Yandex Cloud | authorization | /v1/chat/completions | — | provider-profile | 2026-10-27 | crates/rolter-core/src/config.rs::every_kind_resolves_by_the_documented_rule |
cloud_ru | Cloud.ru | authorization | /v1/chat/completions | — | provider-profile | 2026-10-27 | crates/rolter-core/src/config.rs::every_kind_resolves_by_the_documented_rule |
mts_ai | MTS AI — product page; no public API reference was found at review | authorization | /v1/chat/completions | — | provider-profile | 2026-10-27 | crates/rolter-core/src/config.rs::every_kind_resolves_by_the_documented_rule |
naver | Naver Cloud | authorization | /v1/chat/completions | — | provider-profile | 2026-10-27 | crates/rolter-core/src/config.rs::every_kind_resolves_by_the_documented_rule |
upstage | Upstage | authorization | /v1/chat/completions | — | provider-profile | 2026-10-27 | crates/rolter-core/src/config.rs::every_kind_resolves_by_the_documented_rule |
rinna | rinna — company site; no public API reference was found at review | authorization | /v1/chat/completions | — | provider-profile | 2026-10-27 | crates/rolter-core/src/config.rs::every_kind_resolves_by_the_documented_rule |
rakuten | Rakuten — product site; no public API reference was found at review | authorization | /v1/chat/completions | — | provider-profile | 2026-10-27 | crates/rolter-core/src/config.rs::every_kind_resolves_by_the_documented_rule |
sarvam | Sarvam AI | authorization | /v1/chat/completions | — | provider-profile | 2026-10-27 | crates/rolter-core/src/config.rs::every_kind_resolves_by_the_documented_rule |
krutrim | Ola Krutrim — console; no public API reference was found at review | authorization | /v1/chat/completions | — | provider-profile | 2026-10-27 | crates/rolter-core/src/config.rs::every_kind_resolves_by_the_documented_rule |
falcon | Technology Innovation Institute — product site; no public API reference was found at review | authorization | /v1/chat/completions | — | provider-profile | 2026-10-27 | crates/rolter-core/src/config.rs::every_kind_resolves_by_the_documented_rule |
system_one | TypeSafe | authorization | /v1/systemone | https://api.typesafe.ai | native-passthrough | 2026-10-27 | crates/rolter-gateway/tests/system_one.rs |
infinity | michaelfeil/infinity | authorization | /v1/embeddings | — | translation-subset | 2026-10-27 | crates/rolter-gateway/tests/infinity.rs |