Skip to main content

Model Context Protocol (MCP) Support

Pomerium provides secure access to Model Context Protocol (MCP) servers, enabling AI agents and applications to safely interact with your internal resources through standardized interfaces. This capability allows you to expose local databases, APIs, and services to external AI clients while maintaining strict authentication and authorization controls.

On This Page

Overview

Model Context Protocol (MCP) is an open standard that allows AI agents to securely connect to external data sources and tools. Pomerium's MCP integration acts as a secure gateway between MCP clients (like Claude.ai, OpenAI APIs, or custom applications) and your internal MCP servers.

For an understanding of Pomerium's core capabilities, see Authentication and Authorization.

Experimental Feature

MCP support is currently an experimental feature only available in the main branch or Docker images built from main. To enable MCP functionality, you must set the following feature flag in your Pomerium configuration:

runtime_flags:
mcp: true

Key Benefits

  • Secure Remote Access: Expose internal MCP servers to external AI clients without compromising security
  • OAuth Integration: Seamlessly handle upstream OAuth flows for services requiring authentication
  • Centralized Authorization: Apply consistent access policies across all MCP endpoints
  • Token Management: Automatic token refresh and secure credential handling
  • Observability: Complete visibility into AI agent interactions with your resources through specialized logging

Try It Out

Explore the MCP App Demo for a hands-on example of integrating MCP with Pomerium. The demo shows a full workflow including UI, MCP server, and LLM API integration—perfect for testing and learning.

If you're new to Pomerium, start with the Quickstart Guide to set up your first Pomerium deployment.

Architecture

Pomerium supports three primary MCP integration patterns. For detailed route configuration information, see the Routes reference documentation.

1. Exposing Internal MCP Servers

This pattern allows external MCP clients to access your internal MCP servers through Pomerium's secure gateway.

  • Your MCP server does not need to implement any specific authentication or authorization logic. Works best with internal services that provide access to shared resource like databases, APIs taking API keys, or other internal tools.
  • MCP clients users must authenticate, and Pomerium enforces access policies for every request.
MCP ServerPomeriumMCP ClientMCP ServerPomeriumMCP ClientUserAdds a server URLRegisters client, initiates authSign-in URLRedirect to sign-in URLSign-inRedirect to clientObtain TokenGET https://mcp-server Authorization: Bearer TokenProxy request to MCP ServerUser

Route Configuration:

routes:
- from: https://my-mcp-server.your-domain.com
to: http://my-mcp-server.int:8080/mcp
name: My MCP Server
mcp:
server: {} # the brackets are significant, they indicate that this is an MCP server route
policy:
and:
- domain:
is: company.com
- mcp_tool:
starts_with: 'read_'

2. MCP Servers with Upstream OAuth

When your MCP server needs to access upstream services requiring OAuth authentication (GitHub, Google Drive, Notion, etc.).

  • Pomerium handles the OAuth flow and token management with the remote upstream service.
  • Your MCP server does not need to implement any of the OAuth logic, as Pomerium will manage the authentication and token refresh.
  • MCP clients only observe the External Token (TE) issued by Pomerium, which is used to access the MCP server. The Internal Token (TI) used for upstream OAuth is managed by Pomerium and is never exposed to external clients.

For more details on OAuth configuration options, see Identity Provider Settings.

MCP ServerPomeriumUpstream OAuthMCP ClientMCP ServerPomeriumUpstream OAuthMCP ClientUserAdds a server URLRegisters client, initiates authSign-in URLRedirect to sign-in URLSign-inRedirect to upstream OAuthAuthenticate with upstream OAuthReturn Internal Token (TI)Redirect to clientObtain External Token (TE)GET https://mcp-server Authorization: Bearer (TE)Refresh (TI) if necessaryProxy request to MCP Server, Bearer (TI)User

Route Configuration:

routes:
- from: https://github.your-domain
to: http://github-mcp.int:8080/mcp
name: GitHub
mcp:
server:
upstream_oauth2:
client_id: xxxxxxxxxxxx
client_secret: yyyyyyyyy
scopes: ['read:user', 'user:email']
endpoint:
auth_url: 'https://github.com/login/oauth/authorize'
token_url: 'https://github.com/login/oauth/access_token'
policy:
and:
- domain:
is: company.com
- mcp_tool:
starts_with: 'read_'

3. Building MCP-Enabled Applications

For internal applications that need to call MCP servers through AI APIs such as OpenAI or Anthropic, Pomerium provides:

  • When a route is designated as mcp: client, an External Bearer Tokens would be passed to your application backend in the Authorization: Bearer header.
  • Your application backend can list MCP servers that are available on the Pomerium backend and initiate upstream OAuth flows if necessary.
  • An External Token (TE) can be passed to LLM APIs to allow them to call MCP servers on behalf of the user.

For a complete working example, see the MCP App Demo section.

LLM APIMCP ServerYour App BackendPomeriumLLM APIMCP ServerYour App BackendPomeriumUserGET https://mcp-app-demo.your-domain.comGET http://mcp-app-demo:3000 Authorization: Bearer (TE)call tool https://mcp-server.your-domain Authorization: Bearer (TE)GET https://mcp-server.your-domain Authorization: Bearer (TE)GET https://mcp-serverUser

Route Configuration:

routes:
- from: https://mcp-app-demo.your-domain.com
to: http://mcp-app-demo:3000
mcp:
client: {}
policy: {}
- from: https://mcp-server.your-domain.com
to: http://mcp-server.int:8080/mcp
name: My MCP Server
mcp:
server: {}
policy: {}

Bearer Token Types

Understanding Pomerium's token system is crucial for MCP integration:

External Token (TE)

An externally-facing token issued by Pomerium representing the user's session. External clients use this token to authenticate requests to Pomerium-protected MCP servers.

Use cases:

  • Providing to LLM APIs for MCP server access
  • Authentication between external MCP clients and Pomerium
  • Internal applications calling external AI services

Internal Token (TI)

An internal authentication token that Pomerium obtains from upstream OAuth providers on behalf of the user. This token is never exposed to external clients and is used by Pomerium to authenticate with upstream services.

Characteristics:

  • Automatically refreshed by Pomerium
  • Securely stored and managed
  • Used for upstream API authentication
  • Invisible to external clients

Configuration Options

MCP integration can be configured through route-level settings. For general route configuration guidance, see the Routes configuration reference.

MCP Server Configuration

For routes hosting MCP servers:

mcp:
server:
# Optional: Configure upstream OAuth2 for services requiring authentication
upstream_oauth2:
client_id: 'your-oauth-client-id'
client_secret: 'your-oauth-client-secret'
endpoint:
auth_url: 'https://provider.com/oauth/authorize'
token_url: 'https://provider.com/oauth/token'
auth_style: 'header' # or "params"
scopes: ['scope1', 'scope2']

# Optional: Maximum request body size (default: 4KiB)
max_request_bytes: 1048576

** Tool Call Authorization **

When using Pomerium Policy Language (PPL) with MCP routes, you can control access to specific tools, in addition to the standard route policies. For example, to allow only certain users to call a specific MCP tool:

policy:
allow:
and:
- email:
is: analyst@company.com
- mcp_tool:
is: database_query

For more information on route-level policies, see Route Policy Configuration. For advanced policy examples, see Policy-Based Tool Access Control.

MCP Client Configuration

For applications that consume MCP servers:

mcp:
# Provides the application with external tokens for MCP server access.
# the brackets are significant, they indicate that this is an MCP client route
client: {}

For Client routes, Pomerium exposes additional endpoints to manage MCP server discovery and upstream OAuth flows. See Building MCP-Enabled Applications for architectural details.

Listing Available MCP Servers

Applications can discover available MCP servers by making a request to the /.pomerium/mcp/routes endpoint:

GET https://your-app.domain.com/.pomerium/mcp/routes
Authorization: Bearer <external-token>
Accept: application/json

Response:

{
"servers": [
{
"name": "Database Server",
"url": "https://db-mcp.your-domain.com",
"connected": true
},
{
"name": "GitHub Server",
"url": "https://github-mcp.your-domain.com",
"connected": false
}
]
}

The connected field indicates whether the user has completed all required upstream OAuth flows.

Initiating Upstream OAuth

If a server shows connected: false, redirect users to complete upstream authentication:

https://mcp-server.your-domain.com/.pomerium/mcp/connect?redirect_url=https://your-app.domain.com/callback

Requirements:

  • The redirect_url must match a configured MCP client route host
  • Users will be redirected back to the specified URL after authentication

User Identity and Claims

Both MCP client applications and servers can access authenticated user information through the X-Pomerium-Assertion HTTP header. This header contains a signed JWT with user details including email, name, and other claims.

Example JWT payload:

{
"sub": "user@example.com",
"email": "user@example.com",
"name": "John Doe",
"groups": ["engineering", "admin"],
"iss": "your-domain.com",
"aud": "your-app.domain.com"
}

JWT may be verified using standard JWT libraries or Pomerium's SDKs for Go or Python.

For detailed information about JWT verification in Pomerium, see Identity Verification with JWTs.

Security Considerations

For general security best practices with Pomerium, see the Security documentation.

Access Control

Apply appropriate policies to MCP routes:

routes:
- from: https://sensitive-mcp-server.domain.com
to: http://internal-server:8080/mcp
mcp:
server: {}
policy:
allow:
and:
- domain:
is: trusted-domain.com

Token Security

For more information on Pomerium's bearer token format, see Bearer Token Format.

Observability

Pomerium provides specialized logging capabilities to monitor and audit MCP tool calling activities. By configuring authorize_log_fields, you can gain detailed insights into AI agent interactions with your MCP servers.

For general observability features, see Metrics and Tracing.

MCP-Specific Authorization Log Fields

Pomerium includes three specialized log fields for MCP monitoring:

FieldDescriptionExample Value
mcp-methodThe MCP JSON-RPC method being called"tools/call", "tools/list"
mcp-toolThe specific tool name being invoked (for tools/call requests)"database_query", "list_files"
mcp-tool-parametersThe parameters passed to the tool{"query": "SELECT * FROM users", "limit": 100}

Configuration

To enable MCP-specific logging, add the desired fields to your authorize_log_fields configuration:

authorize_log_fields:
- request-id
- user
- email
- mcp-method
- mcp-tool
- mcp-tool-parameters

Example Log Output

When an AI agent calls an MCP tool, Pomerium generates detailed authorization logs:

{
"level": "info",
"service": "authorize",
"request-id": "c9afae5a-ec5a-4242-864f-df4189f20e99",
"user": "google-oauth2|115420664726183323237",
"email": "analyst@company.com",
"mcp-method": "tools/call",
"mcp-tool": "database_query",
"mcp-tool-parameters": {
"query": "SELECT * FROM sales WHERE year = 2024",
"limit": 100,
"format": "json"
},
"allow": true,
"allow-why-true": ["domain-ok", "mcp-tool-ok"],
"deny": false,
"deny-why-false": [],
"time": "2024-06-24T10:26:33-04:00",
"message": "authorize check"
}

Understanding MCP Authorization Logs

For general information about authorization logs, see Authorize Log Fields.

Tool Call Authorization

When using Pomerium Policy Language (PPL) with MCP routes, you can control access to specific tools:

policy:
allow:
and:
- email:
is: analyst@company.com
- mcp_tool:
is: database_query

The authorization log will show:

  • allow: true and mcp-tool-ok when the tool is permitted
  • allow: false and mcp-tool-unauthorized when the tool is blocked

Method-Level Monitoring

Different MCP methods appear in logs:

Tool Listing Request:

{
"mcp-method": "tools/list",
"allow": true,
"allow-why-true": ["authenticated-user"]
}

Tool Execution Request:

{
"mcp-method": "tools/call",
"mcp-tool": "search_knowledge_base",
"mcp-tool-parameters": {
"query": "company policies",
"max_results": 10
}
}

Resource Request:

{
"mcp-method": "resources/list",
"allow": true
}

Policy-Based Tool Access Control

Pomerium provides fine-grained access control for MCP tools through a specialized mcp_tool policy criterion in Pomerium Policy Language (PPL). This allows you to control which users can access specific MCP tools, providing granular security for AI agent interactions.

For broader policy examples, see the Authorization documentation.

The mcp_tool Criterion

The mcp_tool criterion is designed specifically for MCP routes and allows policy enforcement at the individual tool level. It uses the String Matcher format and supports all standard string matching operators.

OperatorDescriptionExample
isExact match of the tool namemcp_tool: { is: "database_query" }
starts_withTool name starts with the specified prefixmcp_tool: { starts_with: "db_" }
ends_withTool name ends with the specified suffixmcp_tool: { ends_with: "_query" }
containsTool name contains the specified substringmcp_tool: { contains: "read" }
inTool name matches one of the provided valuesmcp_tool: { in: ["list_tables", "describe_table"] }

Example

Grant access to database query tools only to data analysts:

policy:
allow:
and:
- email:
ends_with: '@company.com'
- mcp_tool:
in: ['database_query', 'list_tables', 'describe_table']
- groups:
has: 'data-analysts'

For more advanced policy patterns, see the PPL documentation.

Understanding Authorization Results

The authorization logs show different reason codes based on the evaluation:

Successful Tool Access:

{
"allow": true,
"allow-why-true": ["domain-ok", "mcp-tool-ok"],
"mcp-tool": "database_query"
}

Blocked Tool Access:

{
"allow": false,
"allow-why-false": ["mcp-tool-unauthorized"],
"deny": false,
"mcp-tool": "admin_function"
}

Core Pomerium Concepts

Configuration References

Observability and Security

  • Metrics - Performance and usage metrics
  • Tracing - Request tracing and debugging
  • Security - Security best practices

Demo and Examples

For complete end-to-end examples and reference implementations:

  • MCP App Demo: Full demonstration showing custom UI frontend, MCP server integration, and remote LLM API calling through Pomerium
  • MCP Servers: Collection of example MCP server implementations with Docker and Pomerium configurations

These repositories provide practical examples of all integration patterns described in this documentation.

Feedback