Octelium documentation · Latest
Octelium as an MCP Gateway
Overview
Octelium provides a unified, self-hosted infrastructure for securing MCP clients and servers. The dedicated MCP Service mode understands MCP JSON-RPC messages instead of treating them as generic HTTP traffic. It provides the following:
Secure access to MCP servers running on the internet, in private networks behind NAT or as managed containers.
Standard bearer and OAuth2 authentication for MCP clients without a special Octelium SDK.
Secretless access to upstream MCP servers protected by bearer tokens, API keys, basic authentication or OAuth2 client credentials.
MCP protocol version, method, message and origin validation before a request reaches the server.
Identity-aware access control using normalized MCP methods, tool names, prompt names and resource URIs.
Protocol-aware guardrails for tool arguments, tool results, resource contents, prompt messages and tool definitions.
Dynamic routing to different MCP servers using authenticated identity and normalized MCP request context.
MCP-specific access logs for JSON-RPC requests, responses and SSE streams.
Lua, ExtProc, request rate limit, JSON Schema and direct response plugins inherited from the HTTP dataplane.
GitOps-friendly declarative management (read more here).
Unified identity for all MCP clients
JSON schema validation of tool-call params
Create an MCP Gateway
Assume that a streamable HTTP MCP server is listening at http://mcp-server.default.svc:8080/mcp. The following Service exposes it through public clientless access (read more about the BeyondCorp mode here):
Apply the configuration as follows:
endpoint is the path exposed to clients. The path in upstream.url is the path used with the server, so the two can differ. When the upstream URL has no path, Octelium preserves the downstream path.
An MCP request must use POST, carry an application/json JSON-RPC 2.0 request or notification and contain a single message. JSON-RPC batches are not supported. SSE responses are streamed and inspected event by event unless a response guardrail requires the complete response.
Upstream MCP Servers
An upstream can run anywhere an Octelium data-plane node can reach it. It can also run behind NAT and be served by a connected User (read more here):
Managed Containers
Octelium can deploy, scale and serve a containerized MCP server using the Kubernetes infrastructure of the Cluster (read more here):
The server must listen on 0.0.0.0, and container.port must match its listening port. Environment variables, custom commands, security contexts, volumes and health probes are described in the managed-container reference.
Secretless Upstream Access
If an internet-facing MCP server requires a credential, store it in an Octelium Secret:
Inject the credential into authorized upstream requests as follows:
The MCP client authenticates to Octelium, while Octelium authenticates separately to the upstream. The downstream authorization credential is never forwarded. Custom API key headers, basic authentication, OAuth2 client credentials and AWS Signature Version 4 are also supported (read more here).
MCP Clients
MCP clients can access Services privately through the octelium client (read more here) or publicly through the clientless mode. HUMAN Users can authenticate using configured IdentityProviders, while WORKLOAD Users can use authentication tokens, OpenID Connect assertions, OAuth2 client credentials or directly issued access tokens.
For public workload access, create an OAuth2 client credential as illustrated here. The MCP client obtains an Octelium access token from the Cluster's /oauth2/token endpoint and sends it as the bearer token to https://my-mcp.<DOMAIN>/mcp. The client needs no upstream MCP server credential.
An access token Credential can also be issued and used directly as a bearer token (read more here).
Protocol and Origin Validation
The protocol.versions field is an allowlist. Leaving it empty accepts any syntactically valid version, which is more forward-compatible. requireVersion rejects a request without a version in the MCP-Protocol-Version header or supported request metadata. If a version is declared in more than one location, the values must match.
Unknown but syntactically valid MCP methods are accepted by default so that protocol extensions and later revisions can reach the upstream. Set rejectUnknownMethods: true for strict validation:
Browser-based clients send an Origin header. Octelium accepts the Service's own origin, requests without an origin and origins allowed by mcp.cors. For example:
This protects MCP servers from DNS rebinding while allowing an explicit browser client. disableOriginCheck: true disables validation entirely and is not recommended for a browser-reachable endpoint.
Access Control
MCP request information is normalized under ctx.request.mcp. The following Policy allows all authenticated Users to discover tools and permits members of finance-agents to call a specific tool with a bounded argument:
ctx.request.mcp.method contains methods such as tools/call, prompts/get and resources/read. ctx.request.mcp.name contains the corresponding tool name, prompt name or resource URI. The protocol version, JSON-RPC request identifier, notification status, reported client information, capabilities and MCP transport session identifier are also available.
The MCP client information, capabilities, JSON-RPC identifier and MCP session identifier are self-reported transport data rather than authenticated identity. Use the Octelium User, Session, Device and groups for identity-based authorization.
MCP Guardrails
MCP servers can return untrusted content to an AI agent, while tool arguments can carry secrets or personal information to an external server. Protocol-aware guardrails inspect those semantic parts without hardcoding JSON paths.
The following example denies credentials in tool arguments and redacts email addresses:
A response guardrail can inspect tool results, resource contents, prompt messages and tool definitions for indirect prompt injection or tool poisoning:
Request content supports deny, redact, strip and replace actions. Response content and tool definitions can only be denied. A response guardrail buffers a complete SSE response before releasing it, which guarantees that matched content cannot reach the client but delays the first event until the stream ends.
Guardrails run after access control. They protect content; Policies continue to govern which identity may use a method, tool, prompt or resource. Read more here.
Dynamic Routing
Dynamic configuration can route a request to another MCP server using normalized MCP context and authenticated identity (read more here). The following example isolates a production deployment tool:
The endpoint, protocol validation, parsing limits, origin configuration and downstream HTTP/2 listener are global. A dynamic configuration can select the upstream, upstream credential, headers, path manipulation, plugins, upstream HTTP/2 and visibility. It can also deploy and route to different managed containers.
Other Plugins
The MCP mode supports Lua, ExtProc, direct response, request rate limit, JSON Schema and path plugins inherited from HTTP (read more here). For example, the following plugins bound the request rate per User and validate tool-call requests against a JSON Schema:
Lua and ExtProc can intentionally rewrite MCP requests and responses. If they change a method, target or protocol version that the client also supplied in a reserved MCP header, they must update the header as well. Generic plugins sit outside the MCP guardrail boundary, so a plugin that creates MCP content must inspect that content itself when necessary. The generic HTTP cache is not supported because it does not understand MCP authorization or invalidation semantics.
Visibility
The MCP mode emits identity-aware access logs that include the underlying HTTP exchange and normalized protocol version, method, target name, JSON-RPC identifier, notification status, client information and MCP session identifier. Responses can include the result type, JSON-RPC error and tool error status. SSE streams produce a start entry and a final entry with stream duration, event counts and observed protocol metadata.
Request and response bodies are recorded by default because they are useful for MCP authorization and auditing. Disable them when prompts, arguments or results must not be stored:
Body capture is bounded. Sensitive authentication and session headers remain excluded even when all headers are selected. Read more about access logs here and the complete MCP mode here.