MCP Gateway
The MCP mode turns an Octelium Service into an identity-aware Model Context Protocol gateway. It is an HTTP-based mode that understands MCP JSON-RPC messages and makes their normalized protocol information available for access control, dynamic configuration and visibility. The underlying HTTP information is also available and the HTTP authentication, header, path and plugin configurations can be reused.
Here is a simple example for a streamable HTTP MCP server:
The optional endpoint is the exact canonical path of the MCP endpoint. When it is omitted, MCP requests are accepted on any path and forwarded to the upstream using their original path. Setting it is recommended when the MCP server exposes a single endpoint.
An MCP request must use POST, have an application/json media type and contain a single valid JSON-RPC 2.0 request or notification. JSON-RPC batch requests are not supported. A streamed SSE response is proxied without waiting for the stream to end.
Managed Containers
In addition to using an upstream that already runs in an internal network or on the internet, Octelium can deploy, scale and serve a containerized MCP server as the Service upstream. Managed containers reuse the Kubernetes infrastructure of the Octelium Cluster and are automatically scheduled over data-plane nodes (read more here).
The MCP server inside the container must listen on 0.0.0.0, and the container.port value must match its listening port. Here is an example that deploys a streamable HTTP MCP server from a private container registry:
The managed-container upstream supports environment variables and Secrets, custom commands and arguments, replica scaling, private registries, resource limits, security contexts, volumes and health probes. These options are described in detail here.
Dynamic configuration can deploy multiple managed MCP server containers and route among them based on identity or MCP request context. This can be useful for serving separate MCP server versions or isolating sensitive tools. Read more here.
Protocol Versions
You can optionally restrict the MCP protocol versions accepted by the Service using the versions allowlist. The declared version can be provided in the MCP-Protocol-Version request header or in the MCP request metadata. If both are present, they must match. An initialize request can also declare its version in params.protocolVersion.
An empty versions list accepts any syntactically valid MCP protocol version. Octelium does not keep its own hardcoded list of protocol versions, which allows a Service to accept newer MCP revisions without upgrading the Cluster. By default, requireVersion is disabled for compatibility with older revisions that did not require the version header.
The MCP protocol can add new methods over time. Therefore, unknown but otherwise valid methods are accepted by default and remain available in ctx.request.mcp.method. You can reject methods that are not recognized by the running Octelium version as follows:
Using an explicit versions allowlist and rejectUnknownMethods provides the strictest validation, while leaving them unset is more forward-compatible. Access control rules that explicitly allow the required methods usually provide a good balance between both.
Origin Validation
Browser-based MCP clients send an Origin header. By default, the MCP mode validates this header to protect MCP servers from DNS rebinding attacks. The Service's own origin is always accepted and requests without an Origin header are accepted for non-browser MCP clients.
You can allow additional origins as follows:
Origin validation can be disabled by setting disableOriginCheck to true, but this is not recommended for an MCP endpoint that can be reached by a browser.
Limits
The MCP mode limits request bodies and individual streamed response events. You can set lower limits for a particular Service as follows:
A zero value uses Octelium's default. Octelium also enforces internal upper bounds, even when these values are not explicitly configured.
Secretless Access
An MCP upstream can be protected by a bearer token, API key, basic authentication or OAuth2 client credentials without distributing the upstream credential to downstream Users (read more about secretless access here). For example, first create a Secret that contains the upstream bearer token:
You can now inject the token into every authorized upstream request as follows:
The downstream authorization credential is not forwarded to the MCP upstream. Octelium injects the configured upstream credential only after the request has been authenticated and authorized.
Access Control
MCP-specific request information is stored in ctx.request.mcp. The underlying HTTP request is available in ctx.request.mcp.http (read more about HTTP access control here). The parsed JSON request body is available in ctx.request.mcp.http.bodyMap when it is within the request-context body limit, including tool arguments that are not represented by a normalized field.
Here is an example of an inline Policy that allows a group to call a particular tool with a bounded argument and allows all authenticated Users to discover available tools:
The following normalized fields are available:
ctx.request.mcp.protocolVersionis the validated protocol version declared by the request.ctx.request.mcp.methodis the JSON-RPC method such astools/call,prompts/getorresources/read.ctx.request.mcp.nameis the tool name, prompt name or resource URI when the method has a logical target.ctx.request.mcp.requestIDis the downstream-controlled JSON-RPC request identifier normalized into a string.ctx.request.mcp.isNotificationis set when the JSON-RPC message has no request identifier.ctx.request.mcp.clientcontains the client name, version and title reported by the downstream.ctx.request.mcp.capabilitiescontains the capability identifiers reported by the downstream.ctx.request.mcp.sessionIDcontains the MCP transport session identifier, when present.
The MCP client information, capabilities, JSON-RPC request identifier and MCP session identifier are controlled by the downstream client. They are useful as request context and audit information, but must not be treated as authenticated identity. Use the Octelium User, Session, Device and group information for identity-based access control.
Dynamic Configuration
You can choose an upstream, upstream credential and other request configuration dynamically based on identity and MCP request information (read more about dynamic configuration here). Here is an example that routes a sensitive tool to a separate MCP server:
The endpoint, protocol, limits and origin options are global validation settings and must be defined in the default Service configuration. Per-request configurations can change the upstream, authentication, headers, paths, plugins and visibility options.
Plugins
The MCP mode supports the same Lua and ExtProc plugins as the HTTP mode (read more here). Plugins can inspect and intentionally mutate request and response bodies. MCP requests are parsed again after a request-body mutation so that the updated normalized context is available to the processing stages that follow the plugin.
Plugins use the POST_AUTH phase by default, so authorization in that case is based on the request that existed before the plugin ran. A PRE_AUTH plugin can be defined in the default configuration when authorization must use the mutated request. A plugin must produce a valid MCP request and remain within the configured limits.
If a plugin changes a protocol version, method or target name that was also supplied in a reserved MCP header, it should update the corresponding header. A changed MCP transport session identifier must likewise be reflected in Mcp-Session-Id. This keeps the message and headers consistent for the upstream server. The generic HTTP Cache plugin is not supported for the MCP mode because it does not understand MCP authorization scope or cache invalidation semantics.
HTTP Configuration
Since MCP is an HTTP-based mode, it also supports HTTP header manipulation, path manipulation and HTTP/2 options under config.mcp. Here is an example:
You can read more about these HTTP options here.
Visibility
The Service emits identity-aware, MCP-specific access logs in real time to the audit collector. Each log includes the underlying HTTP information together with normalized fields such as the protocol version, method, target name, request identifier, notification status, client information and MCP session identifier. Completed responses can also include the MCP result type, JSON-RPC error details and tool error status.
Streamed responses produce a STREAM_START entry and a final STREAM_END entry. The final entry can include the stream duration, event and notification counts and any protocol metadata observed during the stream. Non-streamed requests use the COMPLETE entry type.
Request and response body visibility is enabled by default for the MCP mode because inspecting JSON-RPC messages is commonly required for MCP authorization and auditing. It can be disabled and HTTP headers can be selected as follows:
Body capture is bounded by Octelium and large bodies may be omitted from an AccessLog. Disable body visibility when MCP prompts, tool arguments or results can contain sensitive information that should not be stored in the audit backend. Sensitive authentication and session headers are excluded from access logs even when all request or response headers are enabled.