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

# MCP proxy

> Configure Agentgateway as an MCP proxy to expose one or more MCP servers as a single aggregated endpoint.

Agentgateway acts as a transparent MCP proxy, sitting between AI agents and their upstream MCP servers. It aggregates tools, resources, and prompts from multiple backends into a single endpoint, and adds security, observability, and routing on top.

## Core concepts

Before configuring an MCP proxy, it helps to understand the four top-level objects in a gateway config:

* **`binds`** — the ports the gateway listens on
* **`listeners`** — groups of routing rules per bind
* **`routes`** — traffic matching rules and attached policies
* **`backends`** — where traffic is ultimately forwarded

For an MCP backend, a `backend` of type `mcp` holds one or more `targets`. Each target is an upstream MCP server the gateway connects to over Stdio or HTTP.

## Connecting to a stdio MCP server

The simplest setup proxies a single MCP server launched as a child process via Stdio.

```yaml config.yaml theme={null}
# yaml-language-server: $schema=https://agentgateway.dev/schema/config
binds:
- port: 3000
  listeners:
  - routes:
    - policies:
        cors:
          allowOrigins:
          - "*"
          allowHeaders:
          - mcp-protocol-version
          - content-type
          - cache-control
          exposeHeaders:
          - "Mcp-Session-Id"
      backends:
      - mcp:
          targets:
          - name: everything
            stdio:
              cmd: npx
              args: ["@modelcontextprotocol/server-everything"]
```

When a client connects to the gateway, the `cmd` is executed as a child process. The gateway handles the full MCP session lifecycle and forwards tool calls, resource reads, and prompt requests to that process.

<Tip>
  If you don't have `npx`, you can use Docker instead:

  ```yaml theme={null}
  stdio:
    cmd: docker
    args: ["run", "--rm", "-i", "mcp/everything"]
  ```
</Tip>

## Connecting to an HTTP/SSE MCP server

To proxy a remote MCP server already running over HTTP, use the `mcp` transport in the target definition:

```yaml theme={null}
targets:
- name: mcpbin
  mcp:
    host: https://mcpbin.is.solo.io/remote/mcp
```

The `host` field accepts the full base URL of the remote MCP server's streamable HTTP endpoint.

<Note>
  When proxying remote MCP servers over TLS, add `backendTLS: {}` to the route's `policies` block to enable TLS verification for the upstream connection.
</Note>

## Multiplexing multiple MCP backends

Agentgateway can multiplex multiple MCP servers into a single endpoint. Clients connect once and see all tools, resources, and prompts from every upstream server as if they came from one server.

This centralizes client configuration — when you add or remove MCP servers, only the gateway config changes, not every client.

```yaml config.yaml theme={null}
# yaml-language-server: $schema=https://agentgateway.dev/schema/config
binds:
- port: 3000
  listeners:
  - routes:
    - backends:
      - mcp:
          targets:
          - name: time
            stdio:
              cmd: uvx
              args: ["mcp-server-time"]
          - name: everything
            stdio:
              cmd: npx
              args: ["@modelcontextprotocol/server-everything"]
```

When multiple targets are configured, each tool is prefixed with `<name>_` to avoid collisions across servers. For example, the `echo` tool from the `everything` server is exposed as `everything_echo`.

<CardGroup cols={2}>
  <Card title="Tool aggregation" icon="wrench">
    Tools from all backends are merged and presented as a single tool list to clients.
  </Card>

  <Card title="Resource aggregation" icon="file">
    Resources from all backends are namespaced and aggregated into one resource list.
  </Card>

  <Card title="Prompt aggregation" icon="message">
    Prompts from all backends are collected and served from the single endpoint.
  </Card>

  <Card title="Collision prevention" icon="shield">
    Tool and resource names are prefixed with the target name to prevent conflicts.
  </Card>
</CardGroup>

## Transport: SSE vs. streamable HTTP

Agentgateway exposes two MCP transport endpoints on each bind:

| Endpoint | Transport          | Description                                 |
| -------- | ------------------ | ------------------------------------------- |
| `/sse`   | Server-Sent Events | Legacy SSE-based MCP transport              |
| `/mcp`   | Streamable HTTP    | Modern HTTP-based MCP transport (preferred) |

Both transports are served automatically — no additional configuration is required to enable them.

## Testing with MCP Inspector

<Steps>
  <Step title="Start the gateway">
    Run the gateway with your config file:

    ```bash theme={null}
    cargo run -- -f examples/basic/config.yaml
    ```
  </Step>

  <Step title="Launch MCP Inspector">
    In a separate terminal, start the inspector:

    ```bash theme={null}
    npx @modelcontextprotocol/inspector
    ```

    The inspector prints the URL it's running on. Open that URL in your browser.
  </Step>

  <Step title="Connect to the gateway">
    In the inspector UI:

    * Set **Transport** to `Streamable HTTP`
    * Set **URL** to `http://localhost:3000/mcp`

    For legacy SSE clients, use `http://localhost:3000/sse` instead.
  </Step>

  <Step title="Explore tools, resources, and prompts">
    Navigate to the **Tools** tab to see all tools aggregated from your configured backends. Select any tool and invoke it to verify the gateway is proxying requests correctly.
  </Step>
</Steps>

## Full config reference

<AccordionGroup>
  <Accordion title="Stdio target">
    ```yaml theme={null}
    targets:
    - name: <target-name>
      stdio:
        cmd: <command>
        args: [<arg1>, <arg2>]
    ```

    The `cmd` and `args` define the process that is spawned per client connection.
  </Accordion>

  <Accordion title="HTTP target">
    ```yaml theme={null}
    targets:
    - name: <target-name>
      mcp:
        host: <url>
    ```

    The `host` is the full URL to the upstream MCP server's streamable HTTP endpoint.
  </Accordion>

  <Accordion title="CORS policy">
    ```yaml theme={null}
    policies:
      cors:
        allowOrigins:
        - "*"
        allowHeaders:
        - mcp-protocol-version
        - content-type
        - cache-control
        exposeHeaders:
        - "Mcp-Session-Id"
    ```

    The `Mcp-Session-Id` response header must be exposed for stateful MCP sessions to work correctly with browser-based clients.
  </Accordion>
</AccordionGroup>
