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

# MCP plane

> TrustGate's MCP plane aggregates registered Model Context Protocol servers into one endpoint — composing tools, prompts, and resources — with toolkit scoping, flexible upstream auth, and a built-in OAuth2 server for agents.

Beyond LLM traffic, TrustGate runs a dedicated **MCP plane** (`:8082`) that fronts
[Model Context Protocol](https://modelcontextprotocol.io) servers. Rather than connecting an
agent to each MCP server directly, TrustGate **aggregates** several servers into a single
MCP endpoint — composing their tools, prompts, and resources — and applies the same tenancy,
access control, auth, and observability as LLM traffic.

<Note>
  The TrustGate **data plane must reach** each MCP registry `url`. SaaS cannot call private VPC endpoints unless you expose them. Use [Hybrid](/neuraltrust/deployment/deployment-models) for internal MCPs.
</Note>

## One endpoint, many servers

An agent connects to one TrustGate MCP endpoint and sees a unified surface. TrustGate speaks
JSON-RPC over the **`streamable-http`** transport and implements the standard methods:

| Method                                                           | Returns                                         |
| ---------------------------------------------------------------- | ----------------------------------------------- |
| `tools/list` · `tools/call`                                      | The composed tool catalog, and tool invocation. |
| `resources/list` · `resources/templates/list` · `resources/read` | Composed resources and templates.               |
| `prompts/list` · `prompts/get`                                   | Composed prompts.                               |

Behind the endpoint, each upstream is an [MCP registry](/trustgate/concepts/registries)
(`type: MCP`). TrustGate fans `list` calls out to the bound registries, merges the results,
and routes each `call`/`read`/`get` to the owning server.

### Tool name composition

Because two servers can expose the same tool name, TrustGate keeps names unique on the
merged surface:

* Unique names pass through unchanged.
* On a collision, the tool is prefixed with the **registry name** (e.g. `asana_create_task`).
* If that still collides, a short registry id is added; as a last resort a numeric suffix.

So an agent always sees stable, unambiguous names regardless of how many servers are behind
the endpoint.

## Registering an MCP server

Register a server as a [registry](/trustgate/concepts/registries) of `type: MCP` with an
`mcp_target`:

| Field       | Meaning                                                                                                                                                               |
| ----------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `code`      | Catalog code (e.g. `com.asana/mcp`) — the join key the console uses to tell whether a catalog server is already connected. Empty for custom servers added by raw URL. |
| `url`       | The server's `http(s)` endpoint (required).                                                                                                                           |
| `transport` | `streamable-http` (defaults to it; the only supported transport).                                                                                                     |
| `headers`   | Static headers sent upstream.                                                                                                                                         |
| `auth`      | How TrustGate authenticates to the server (see below).                                                                                                                |

Browse pre-seeded enterprise servers via `GET /v1/mcp-servers-catalog`, validate a
connection with `test-connection`, and list a registry's live tools via
`GET /v1/gateways/{gateway_id}/registries/{id}/tools`.

## Toolkits — scoping what an agent can use

A consumer doesn't automatically get every tool on every bound server. Access is governed by
a **toolkit** — a list of grants, each scoping a registry to specific tools, prompts, or
resources:

| Entry field                    | Meaning                                                      |
| ------------------------------ | ------------------------------------------------------------ |
| `registry_id`                  | Which MCP registry the grant applies to.                     |
| `tool` / `prompt` / `resource` | The capability name to allow; `*` grants all of that kind.   |
| `expose_as`                    | Optional rename for how the capability appears to the agent. |

For [inline](/trustgate/concepts/consumers) MCP consumers, the toolkit lives on the consumer
(`mcp.toolkit`). For [role-based](/trustgate/concepts/roles) consumers, the effective view is
built from the matched roles:

* **Registries** = the union of the matched roles' MCP registries.
* **Toolkit** = the union of the roles' `mcp_policies` toolkits. A role that binds an MCP
  registry *without* an explicit toolkit grants that server **fully**.

So one MCP endpoint can present a different, identity-scoped toolkit to each caller.

### Fail mode

`fail_mode` decides what happens when an upstream server is unavailable:

* **`open`** — degrade gracefully (skip the failed server).
* **`closed`** — fail the call.

For role-based consumers, the effective mode is **open only when every contributing role
declares it open**; otherwise it is closed (and closed when no role grants access).

## Upstream authentication

`mcp_target.auth.mode` controls how TrustGate authenticates **to the MCP server**. Each mode
has its own requirements:

| Mode          | Behavior                                                            | Requires                                                                                             |
| ------------- | ------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------- |
| `none`        | No upstream auth.                                                   | —                                                                                                    |
| `static`      | A fixed header/token on every call.                                 | `header` + `value`.                                                                                  |
| `passthrough` | Forward the caller's own bearer token unchanged.                    | `expected_audience` (unconstrained passthrough is rejected); the caller's token audience must match. |
| `exchange`    | Exchange the caller's token for a downstream one (STS).             | a `pattern` (see below).                                                                             |
| `forwarded`   | Use a per-user credential the user authorized once (OAuth connect). | `provider` + registration config.                                                                    |

### Exchange patterns

The `exchange` mode implements standard token-exchange patterns:

| Pattern              | Requires                           |
| -------------------- | ---------------------------------- |
| `impersonation`      | `audience`                         |
| `delegation`         | `audience` + `actor`               |
| `obo` (on-behalf-of) | `scope` (e.g. `resource/.default`) |
| `token_exchange`     | `audience`                         |

### Forwarded (per-user OAuth)

For SaaS servers where each end-user must connect their own account (e.g. their Asana),
`forwarded` mode stores a per-user OAuth credential:

* Set `provider` and either `registration: auto` (TrustGate registers the client) or
  `registration: manual` with `client_id`, `authorize_url`, and `token_url`.
* The first call for a user with no stored credential returns a **consent-required** signal
  with a connect link; the user authorizes the provider once and the credential is vaulted.
* TrustGate refreshes expiring credentials automatically and re-prompts for consent only
  when a grant can no longer be refreshed.

## Agent authentication

The MCP plane is itself an **OAuth2 authorization server** for the agents connecting to it,
implementing the standard discovery and flow endpoints:

| Endpoint                                  | Purpose                                                                                                  |
| ----------------------------------------- | -------------------------------------------------------------------------------------------------------- |
| `/.well-known/oauth-protected-resource`   | Protected-resource metadata.                                                                             |
| `/.well-known/oauth-authorization-server` | Authorization-server metadata.                                                                           |
| `/register`                               | Dynamic Client Registration (DCR).                                                                       |
| `/authorize` · `/callback` · `/token`     | Authorization-code flow with **PKCE**.                                                                   |
| `/.well-known/jwks.json`                  | Public keys for token verification.                                                                      |
| `/connect` · `/disconnect`                | Connect/disconnect an agent's link to a downstream provider (the consent flow used by `forwarded` auth). |

Together these let an agent register, obtain a token, call the unified MCP endpoint, and —
when a downstream needs per-user authorization — complete a one-time connect without leaving
the gateway.
