> ## Documentation Index
> Fetch the complete documentation index at: https://docs.strata.io/llms.txt
> Use this file to discover all available pages before exploring further.

# MCP Proxy App

Proxy MCP (Model Context Protocol) requests to upstream MCP servers with identity injection, per-tool authorization, and delegation token exchange. The MCP Proxy app sits between AI agents and your existing MCP servers, adding enterprise identity and access control without modifying the upstream servers.

## Overview

The MCP Proxy app type is used in [AI Identity Gateway](/reference/modes/ai-identity-gateway) mode to secure MCP server traffic. It acts as an identity-aware proxy between AI agents and upstream MCP servers, applying inbound authorization policies and performing outbound token exchange so that upstream servers receive properly scoped delegation tokens. The MCP Proxy app requires an [MCP Provider](/reference/modes/ai-identity-gateway#setup) to be configured.

## How It Works

The MCP Proxy operates as an identity-aware intermediary for MCP traffic:

1. **Agent connects** -- The AI agent connects to the Orchestrator's MCP endpoint (SSE or Streamable HTTP).
2. **OAuth authentication** -- The Orchestrator validates the agent's OAuth token against the configured authorization server.
3. **Tool discovery** -- The Orchestrator proxies tool discovery to the upstream MCP server and returns the available tools (optionally namespaced with a prefix).
4. **Policy evaluation** -- When the agent invokes a tool, the Orchestrator evaluates OPA policies before forwarding the request.
5. **Token exchange** -- The Orchestrator exchanges the agent's token for a delegation token scoped to the upstream MCP server, with per-tool scopes and TTLs.
6. **Upstream forwarding** -- The tool call is forwarded to the upstream MCP server via the configured HTTP streaming transport.
7. **Response passthrough** -- The upstream server's response flows back through the Orchestrator to the agent, with audit logging capturing the interaction.

## Use Cases

* **Securing existing MCP servers** -- Add identity and authorization to upstream MCP servers without modifying them. The Orchestrator handles OAuth authentication and token exchange.
* **Per-tool authorization** -- Apply different scopes and TTLs to different tools based on the tool name. Read-only tools get read scopes; write tools get write scopes.
* **HTTP streaming transport** -- Connect to upstream MCP servers over the network via HTTP streaming.
* **Centralized token exchange** -- Exchange agent tokens for service-specific delegation tokens with per-tool granularity, preserving the user's identity through the agent-to-server chain.

## Key Concepts

### Upstream Transport

MCP Proxy connects to upstream MCP servers over HTTP streaming. Configure the upstream server URL, optional TLS profile, and connection pooling settings.

### Tool Namespacing

When multiple MCP Proxy apps connect to different upstream MCP servers, tool names can collide. The `toolNamespace` feature adds a configurable prefix to all tools from an app, enabling agents to access tools from multiple MCP servers through a single endpoint.

### Token Exchange for MCP Servers

MCP Proxy uses RFC 8693 token exchange to convert the agent's inbound OAuth token into a scoped token for the upstream MCP server. Each tool gets its own scopes and TTL, enabling least-privilege access. The delegation token carries both agent and user identity through the entire chain.

### Inbound OPA Policies

OPA Rego policies evaluate inbound MCP requests before forwarding to the upstream server. This adds a centralized authorization layer to MCP servers that may lack their own authorization. Policies can block specific tool invocations based on agent identity, user attributes, or requested tool name. See the [Authorization Policies guide](/guides/security/policies#opa-authorization-ai-identity-gateway) for the full OPA input schema, output schema, and example policies.

### Upstream Token Validation Best Practice

The upstream MCP servers receive standard MCP requests, and the Orchestrator adds identity, authorization, and audit transparently -- upgrading existing MCP servers with enterprise identity without modifying them.

While no protocol-level changes are required, it is best practice for upstream MCP servers to validate the received delegation token. Specifically, upstreams should:

* **Validate the token signature and expiry** -- Confirm the token has not been tampered with and is still valid.
* **Confirm the issuer matches the Auth Provider Orchestrator** -- The `iss` claim should match the expected authorization server.
* **Verify the audience claim matches the server's own identifier** -- The `aud` claim should contain the MCP server's registered audience.
* **Check that the token's scopes authorize the requested tool invocation** -- The `scope` claim should include the permissions required for the specific tool.

This defense-in-depth approach ensures that even if the gateway is misconfigured or compromised, the upstream server independently enforces authorization.

## Setup

<Tabs>
  <Tab title="Console UI">
    <Steps>
      <Step title="Navigate to Applications">
        Go to **Applications** in the sidebar and click **Create**. Select **MCP Proxy App** from the application type list.
      </Step>

      <Step title="Set the application name">
        Enter a **Name** to identify this MCP Proxy application.
      </Step>

      <Step title="Configure tool namespacing">
        Tool namespacing is enabled by default. Enter a **Namespace** prefix for tool names (e.g., `mission_control_`). Only alphanumeric characters, dots, dashes, and underscores are allowed. Disable the **Enable Tool Namespacing** toggle only if this is the sole MCP app.
      </Step>

      <Step title="Upload an application icon (optional)">
        Drag or click to upload an icon image (JPEG, PNG, or SVG, up to 2MB).
      </Step>

      <Step title="Configure the upstream MCP server">
        Under **Upstream MCP Server**, the **Transport Type** defaults to HTTP Streaming. Enter the **Upstream URL** of the remote MCP server (e.g., `http://mcp-server:8080/mcp`).
      </Step>

      <Step title="Configure TLS settings (optional)">
        Under **TLS Settings**, optionally set a **CA Path** for self-signed certificates on the upstream. Enable **Skip TLS Verification** only for testing. Under **mTLS**, provide the **TLS Cert** and **TLS Key** file paths or secret provider references if the upstream server requires client certificate authentication.
      </Step>

      <Step title="Configure connection authorization (optional)">
        Under **Authorization > Connection Policy**, upload an OPA policy definition (.rego file) or click **Add** to write an inline policy. This front-door admission policy is evaluated against the inbound token before a session to the upstream MCP server is established; a denial blocks the connection.
      </Step>

      <Step title="Configure inbound authorization">
        Under **Authorization > Inbound Request Policy**, upload an OPA policy definition (.rego file) or click **Add** to write an inline policy. The policy enforces fine-grained access control for incoming MCP requests based on agent identity, requested tool name, and user attributes.
      </Step>

      <Step title="Configure outbound authorization">
        Under **Outbound Request Authorization**, select the **Authorization Type** (Token Exchange or Unprotected). For Token Exchange, choose the **Exchange Type**: **Delegation** (recommended -- preserves both agent and user identity) or **Impersonation** (fully assumes user identity). Select the **OIDC Identity Provider** and enter the **Audience** for the upstream MCP server.
      </Step>

      <Step title="Add tool configurations (optional)">
        Click **Add Tool Configuration** to define per-tool authorization. Enter the **Tool Name** (exact match or regex pattern prefixed with `~ `), set an optional **Token Lifetime (TTL)**, and add **OAuth Scopes** that will be requested during token exchange for that tool.
      </Step>

      <Step title="Add operation configurations (optional)">
        Click **Add Operation Configuration** to configure authorization for MCP protocol operations. Select a **Method** (`initialize` or `tools/list`), set an optional **Token Lifetime (TTL)**, and add **OAuth Scopes** for the operation.
      </Step>

      <Step title="Save">
        Click **Save** to create the MCP Proxy application.
      </Step>
    </Steps>
  </Tab>

  <Tab title="Configuration">
    MCP Proxy apps are defined under the `apps` top-level key with `type: mcpProxy`:

    #### Configuration Reference

    | Key                                                                      | Type    | Required    | Description                                                                                             |
    | ------------------------------------------------------------------------ | ------- | ----------- | ------------------------------------------------------------------------------------------------------- |
    | `apps[].toolNamespace.disabled`                                          | Boolean | No          | Disable tool namespacing. When `false`, all tool names are prefixed with `toolNamespace.name`.          |
    | `apps[].toolNamespace.name`                                              | String  | No          | Prefix for tool names (e.g., `service_`). Characters allowed: a-z, A-Z, 0-9, `.`, `-`, `_`.             |
    | `apps[].upstream.transport`                                              | String  | Yes         | Upstream transport type: `stream` (HTTP streaming)                                                      |
    | `apps[].upstream.stream.url`                                             | String  | Yes         | Upstream MCP server URL                                                                                 |
    | `apps[].upstream.stream.tls`                                             | String  | No          | TLS profile name for the upstream connection (references a `tls` entry)                                 |
    | `apps[].upstream.stream.connection.dialTimeout`                          | String  | No          | Connection dial timeout (duration string, e.g., `10s`)                                                  |
    | `apps[].upstream.stream.connection.keepAlive.interval`                   | String  | No          | Keep-alive interval for the upstream connection (duration string)                                       |
    | `apps[].upstream.stream.connection.pool.maxIdleConns`                    | Integer | No          | Maximum number of idle connections in the pool                                                          |
    | `apps[].upstream.stream.connection.pool.maxIdleConnsPerHost`             | Integer | No          | Maximum idle connections per upstream host                                                              |
    | `apps[].authorization.connection.opa.name`                               | String  | Yes         | Name identifier for the connection (front-door admission) OPA policy. Supported on MCP Proxy apps only. |
    | `apps[].authorization.connection.opa.file`                               | String  | Conditional | Path to the Rego policy file for the connection policy. Mutually exclusive with `rego`.                 |
    | `apps[].authorization.connection.opa.rego`                               | String  | Conditional | Inline Rego connection policy. Mutually exclusive with `file`.                                          |
    | `apps[].authorization.inbound.opa.name`                                  | String  | No          | Name identifier for the OPA policy                                                                      |
    | `apps[].authorization.inbound.opa.file`                                  | String  | Conditional | Path to the Rego policy file. Mutually exclusive with `rego`.                                           |
    | `apps[].authorization.inbound.opa.rego`                                  | String  | Conditional | Inline Rego policy. Mutually exclusive with `file`.                                                     |
    | `apps[].authorization.outbound.type`                                     | String  | No          | Outbound authorization type: `tokenExchange` or `unprotected`                                           |
    | `apps[].authorization.outbound.tokenExchange.type`                       | String  | No          | Token exchange type: `delegation` (default) or `impersonation`                                          |
    | `apps[].authorization.outbound.tokenExchange.idp`                        | String  | Conditional | Identity provider connector name for token exchange. Required when using token exchange.                |
    | `apps[].authorization.outbound.tokenExchange.audience`                   | String  | Conditional | Token audience for the upstream MCP server. Required when using token exchange.                         |
    | `apps[].authorization.outbound.tokenExchange.operations[].method`        | String  | No          | MCP protocol operation method: `initialize` or `tools/list`                                             |
    | `apps[].authorization.outbound.tokenExchange.operations[].ttl`           | String  | No          | Access token lifetime for this operation (duration string, e.g., `5s`)                                  |
    | `apps[].authorization.outbound.tokenExchange.operations[].scopes[].name` | String  | No          | OAuth scope to request when exchanging tokens for this operation                                        |
    | `apps[].authorization.outbound.tokenExchange.tools[].name`               | String  | No          | Tool name (exact match) or regex pattern (`~ pattern`) for per-tool config                              |
    | `apps[].authorization.outbound.tokenExchange.tools[].ttl`                | String  | No          | Access token lifetime for this tool (duration string, e.g., `5s`)                                       |
    | `apps[].authorization.outbound.tokenExchange.tools[].scopes[].name`      | String  | No          | OAuth scope to request when exchanging tokens for this tool                                             |

    #### Upstream Transport

    MCP Proxy connects to upstream MCP servers over HTTP streaming. Configure the server URL, optional TLS profile, and connection pooling settings.

    ```yaml theme={null}
    upstream:
      transport: stream
      stream:
        url: http://mcp-server:8080/mcp
        tls: upstream-tls
        connection:
          dialTimeout: 10s
          keepAlive:
            interval: 15s
          pool:
            maxIdleConns: 100
            maxIdleConnsPerHost: 100
    ```

    #### Token Exchange

    MCP Proxy uses [RFC 8693](https://datatracker.ietf.org/doc/html/rfc8693) token exchange to obtain scoped tokens for outbound MCP server calls. Token exchange supports two modes: delegation (default) and impersonation.

    * **Delegation** (`tokenExchange.type: delegation`) -- Delegation is the default and recommended mode. The Orchestrator exchanges the agent's token for a delegation token that contains an `act` (actor) claim identifying the agent alongside the original user's identity. The upstream MCP server sees both identities -- who the user is and which agent is acting on their behalf -- which supports auditability and least-surprise behavior for downstream services.

    * **Impersonation** (`tokenExchange.type: impersonation`) -- The Orchestrator exchanges the agent's token for an impersonation token that fully assumes the user's identity, with no trace of agent involvement. The upstream MCP server receives a token that looks like it came directly from the user, meaning audit trails at the upstream server will not show agent participation. Impersonation may be required when upstream MCP servers do not support the `act` claim pattern.

    * **Token minting policies** -- When token exchange is processed by the [OIDC Provider](/reference/modes/oidc-provider), administrators can configure OPA-based token minting policies (`authorization.tokenMinting.accessToken.policies` on the OIDC Provider app) to control which tokens get issued. These policies evaluate the token exchange request context and can deny token issuance based on agent identity, requested scopes, audience, or delegating user attributes. This provides a governance layer over token exchange independent of the inbound OPA policies that control tool access.

    * **Per-tool scopes** -- Each tool can have its own OAuth scopes and token TTL. Tool names support exact matching and regex patterns for wildcarding.

    * **Per-operation scopes** -- MCP protocol operations (`initialize` and `tools/list`) can have their own scopes and TTL, separate from tool-level configuration. This allows shorter-lived tokens for connection setup and tool discovery, independent of the tokens used for actual tool invocations.

    <Tabs>
      <Tab title="Console UI">
        Configure outbound authorization from the MCP Proxy app's setup flow. See Steps 9-11 above for the Console UI walkthrough.
      </Tab>

      <Tab title="Configuration">
        ```yaml theme={null}
        authorization:
          outbound:
            type: tokenExchange
            tokenExchange:
              type: delegation
              idp: oidc-provider
              audience: https://service.example.com/
              operations:
                - method: initialize
                  ttl: 30s
                  scopes:
                    - name: items:read
                - method: tools/list
                  ttl: 30s
                  scopes:
                    - name: items:read
              tools:
                - name: listItems
                  ttl: 5s
                  scopes:
                    - name: items:read
                - name: "~ create.*"
                  ttl: 5s
                  scopes:
                    - name: items:read
                    - name: items:write
        ```
      </Tab>
    </Tabs>

    In the example above, the `operations` block configures token exchange for MCP protocol-level methods (`initialize` and `tools/list`). Operations typically carry the same base scopes required for all upstream calls -- here `items:read` -- so the upstream MCP server accepts the delegation token during connection setup and tool discovery. The per-tool configurations then include those same base scopes alongside any additional scopes needed for the specific tool. The tool named `listItems` is matched exactly, while `~ create.*` uses a regex pattern to match any tool name starting with `create` (e.g., `createItem`, `createOrder`) and adds `items:write`. This ensures each interaction -- whether protocol operation or tool invocation -- receives a properly scoped token for the upstream MCP server.

    The token exchange connects to the [OIDC Provider](/reference/modes/oidc-provider) for token issuance. The OIDC Provider must be configured with the `urn:ietf:params:oauth:grant-type:token-exchange` grant type to support token exchange requests.

    #### Connection Authorization (OPA)

    MCP Proxy supports an optional `authorization.connection` block that gates whether an upstream MCP session may be established at all. This is a front-door admission decision -- distinct from the per-tool-call inbound policy and the outbound token-exchange policy -- evaluated when the proxy would open a new upstream session for the inbound bearer token.

    Configure `authorization.connection.opa` with a `name` and either a `file` path to a Rego policy file or inline `rego` content. The policy is evaluated against the same OPA input schema as the inbound policy; the bearer token is available at `input.request.http.headers.Authorization`, and parsing its claims is the policy author's responsibility. There is no `input.request.mcp` tool context at admission time, since no tool has been invoked yet. A deny decision blocks the session and can set `external_message` to surface a meaningful error to the MCP client.

    Connection authorization is currently supported on MCP Proxy apps only. MCP Bridge apps reject the `authorization.connection` field at configuration validation time.

    <Note>
      The admission decision is evaluated when a new upstream session is established. On a permit, the decision is sticky for the lifetime of that session; on a deny, the policy is re-evaluated on subsequent requests (for example, when the client lists or calls a tool).
    </Note>

    See the [Authorization Policies guide](/guides/security/policies#opa-authorization-ai-identity-gateway) for the full OPA input schema, output schema, and example policies.

    #### Inbound Authorization (OPA)

    MCP Proxy evaluates OPA (Open Policy Agent) Rego policies on inbound MCP requests before performing outbound token exchange. This blocks unauthorized tool calls early, before any outbound MCP server call is made.

    Configure `authorization.inbound.opa` with a `name` and either a `file` path to a Rego policy file or inline `rego` content. The policy is evaluated against the MCP request context including the agent's identity and the requested tool.

    #### Example

    An MCP Proxy app securing a mission control MCP server with connection admission, inbound OPA authorization, and outbound delegation token exchange:

    ```yaml theme={null}
    apps:
      - name: mission-control-proxy
        type: mcpProxy
        toolNamespace:
          disabled: false
          name: mission_control_
        upstream:
          transport: stream
          stream:
            url: http://mission-control:8080/mcp
            connection:
              dialTimeout: 10s
              keepAlive:
                interval: 15s
              pool:
                maxIdleConns: 100
                maxIdleConnsPerHost: 100
        authorization:
          connection:
            opa:
              name: mission-control-connection-authz
              file: /etc/maverics/policies/mission-control-connection-authz.rego
          inbound:
            opa:
              name: mission-control-authz
              file: /etc/maverics/policies/mission-control-authz.rego
          outbound:
            type: tokenExchange
            tokenExchange:
              type: delegation
              idp: oidc-provider
              audience: https://mission-control.example.com/
              operations:
                - method: initialize
                  ttl: 30s
                  scopes:
                    - name: mission:List
                    - name: mission:Get
                - method: tools/list
                  ttl: 30s
                  scopes:
                    - name: mission:List
                    - name: mission:Get
              tools:
                - name: listMissions
                  ttl: 5s
                  scopes:
                    - name: mission:List
                    - name: mission:Get
                - name: getMission
                  ttl: 5s
                  scopes:
                    - name: mission:List
                    - name: mission:Get
                - name: createMission
                  ttl: 5s
                  scopes:
                    - name: mission:List
                    - name: mission:Get
                    - name: mission:Create
    ```
  </Tab>
</Tabs>

## Troubleshooting

<AccordionGroup>
  <Accordion title="Cannot connect to upstream MCP server">
    **Symptoms:** The agent connects to the proxy but tool discovery fails with a connection error. No tools are returned.

    **Causes:**

    * The `upstream.stream.url` is incorrect or unreachable from the Orchestrator.
    * TLS certificate issues when connecting to the upstream MCP server over HTTPS.
    * The upstream MCP server is not running or is not accepting connections.

    **Resolution:**

    * Verify the `upstream.stream.url` is correct and reachable from the Orchestrator host.
    * If using TLS, check the TLS profile configuration and ensure the upstream server's certificate is trusted.
    * Confirm the upstream MCP server is running and accepting connections on the expected port.
  </Accordion>

  <Accordion title="Tool namespacing conflicts">
    **Symptoms:** Tools from different upstream MCP servers have name collisions, causing unexpected behavior when agents invoke tools.

    **Causes:**

    * The `toolNamespace` feature is not configured on one or more MCP Proxy apps.
    * Namespace prefixes are not unique across apps, so tools from different servers still collide.

    **Resolution:**

    * Configure unique `toolNamespace.name` values for each MCP Proxy app to prefix tool names (e.g., `service_a_` and `service_b_`).
    * Ensure `toolNamespace.disabled` is set to `false` (the default) on all apps that share a single MCP endpoint.
  </Accordion>

  <Accordion title="Token exchange fails during tool invocation">
    **Symptoms:** The agent authenticates successfully but tool invocation fails. Orchestrator logs show a token exchange failure.

    **Causes:**

    * The Auth Provider Orchestrator's token endpoint is unreachable from the Gateway Orchestrator.
    * The `urn:ietf:params:oauth:grant-type:token-exchange` grant type is not enabled on the OIDC Provider app.
    * Audience mismatch -- the `audience` in the token exchange configuration does not match the OIDC Provider's `expectedAudiences`.

    **Resolution:**

    * Verify the Auth Provider Orchestrator's token endpoint is reachable from the Gateway Orchestrator.
    * Ensure the OIDC Provider app has `urn:ietf:params:oauth:grant-type:token-exchange` in its `grantTypes` list.
    * Check that the `audience` value in the MCP Proxy app's `tokenExchange` configuration matches the OIDC Provider app's `expectedAudiences`.
  </Accordion>

  <Accordion title="SSE transport disconnects">
    **Symptoms:** The agent connection drops during tool invocation. Logs show "connection reset" or timeout errors.

    **Causes:**

    * SSE keep-alive is not configured, so the connection appears idle to intermediate proxies or load balancers.
    * A proxy or load balancer is enforcing a timeout that kills long-lived connections.

    **Resolution:**

    * Configure `upstream.stream.connection.keepAlive.interval` with an appropriate interval (e.g., `15s`) to keep connections alive.
    * Configure any intermediate proxy or load balancer to allow long-lived connections for the MCP endpoint.
  </Accordion>

  <Accordion title="Session timeout during long operations">
    **Symptoms:** Multi-step agent interactions fail partway through. The agent loses its session between tool invocations.

    **Causes:**

    * The session timeout is too short for the expected agent workflow duration.
    * The upstream MCP server takes longer to respond than the configured timeout allows.

    **Resolution:**

    * Increase the session timeout to accommodate the expected workflow duration.
    * Review the upstream MCP server's response times and adjust connection timeouts (`upstream.stream.connection.dialTimeout`) accordingly.
  </Accordion>
</AccordionGroup>

## Related Pages

<CardGroup cols={2}>
  <Card title="Applications" icon="grid-2" href="/reference/orchestrator/applications">
    Overview of application types, route patterns, and shared configuration
  </Card>

  <Card title="AI Identity Gateway" icon="robot" href="/reference/modes/ai-identity-gateway">
    AI Identity Gateway mode configuration for MCP Proxy deployments
  </Card>

  <Card title="MCP Bridge App" icon="bridge" href="/reference/orchestrator/applications/mcp-bridge">
    Bridge REST APIs as MCP-compatible tools for AI agents
  </Card>
</CardGroup>
