> For the complete documentation index, see [llms.txt](https://docs.p0.dev/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.p0.dev/agentic-access/agentic-gateway/mcp-server/custom.md).

# Custom

Define and configure a custom MCP server behind the P0 AI Gateway when P0 does not ship a predefined server for it.

A **custom** MCP server is one you define yourself, for any MCP server P0 doesn't ship a predefined definition for. See [MCP server](/agentic-access/agentic-gateway/mcp-server.md). The gateway reaches it in one of two ways: it proxies requests to a server you host outside it, or it runs a Docker container that hosts the server for you. Once configured, it behaves like any other server behind the AI gateway, part of [P0 Runtime Access for AI](/readme/agentic-control-plane.md): agents reach it through the gateway URL, and every tool call is authenticated and checked against policy.

## Prerequisites

* A registered [Gateway](/agentic-access/agentic-gateway/gateway.md) component, with the gateway deployed in your environment.

## Configure the custom MCP server

Follow the shared steps in [MCP server](/agentic-access/agentic-gateway/mcp-server.md#add-an-mcp-server) to name the server and choose its gateway.

### Credential source

**Credential source** determines how the gateway authenticates to the upstream server. A custom server supports three sources: **OAuth** (Preview), **Native credentials**, and **GCP WIF federation**.

#### OAuth

With **OAuth**, the gateway authenticates as the user making the call, using a user-delegated token. Set **Credential source** to **OAuth** and leave **Grant type** on **Authorization code**. The upstream server must allow one of the following client authentication methods:

* [Client ID Metadata Documents (CIMD)](https://client.dev/)
* [Dynamic Client Registration (DCR)](https://oauth.net/2/dynamic-client-registration/)
* Arbitrary clients with token-authentication method equal to `none`

<figure><img src="https://3783273641-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FSQNwGQz62W737pY0FzVb%2Fuploads%2FuIpGb0oLLjDkzsExhx19%2Fimage.png?alt=media&amp;token=9e206536-4a29-4858-b6e7-6ea33f317609" alt="" width="563"><figcaption></figcaption></figure>

If the server requires scopes, add those in the "scopes" box.

To let a headless agent use an OAuth server, see [OAuth servers from a headless agent](/agentic-access/using-the-gateway/headless-oauth-credentials.md).

#### Native credentials

Choose **Native credentials** when the upstream server accepts a session token the gateway mints, rather than a user-delegated OAuth token. The gateway signs the token and sends it to the upstream on each call.

<figure><img src="https://3783273641-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FSQNwGQz62W737pY0FzVb%2Fuploads%2Fi3aTeUoaO5qI474LTQQL%2Fimage.png?alt=media&amp;token=dc917d82-1e5e-4d54-b4c3-0b4ad10ebd1c" alt="" width="563"><figcaption></figcaption></figure>

If the upstream needs extra claims in that token, add them in the optional **Claims** field.

<table><thead><tr><th width="128.06640625">Field</th><th width="545.60546875">Description</th><th>Required</th></tr></thead><tbody><tr><td><strong>Claims</strong></td><td>Extra claims to add to the minted JSON Web Token (JWT), written as a JSON object that parses to a valid JWT payload. Use <a href="https://liquidjs.com/">LiquidJS template syntax</a> to insert values from the access request.</td><td>No</td></tr></tbody></table>

For example, to set a `scopes` claim from the role in the access request:

```json
{ "scopes": {{ request.permission.role | json }} }
```

Once you've selected an access resource ([#access-control-method](#access-control-method "mention")), you may click "available variables" to view available template variables in the page sidebar:

<figure><img src="https://3783273641-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FSQNwGQz62W737pY0FzVb%2Fuploads%2F7OJXYI9RRT9ctijSqzaC%2Fimage.png?alt=media&amp;token=d792be3e-ca6a-4b03-87cd-5e27fe7f94f9" alt="" width="563"><figcaption></figcaption></figure>

{% hint style="warning" %}
Only variables listed in your gateway's NATIVE\_CREDENTIAL\_ALLOWED\_CLAIMS list may be set using **claims**. By default these are only the `scopes` and `exp` claims.
{% endhint %}

Leave **Claims** empty to send the token with its default claims.

#### GCP WIF federation

Choose **GCP WIF federation** when the upstream server accepts Google Cloud workload identity federation credentials. The gateway federates into Google Cloud as its own identity and passes a short-lived, policy-scoped credential to the upstream on each call.

This source needs an installed [GCP Workload Identity Federation](/agentic-access/credential-sources/gcp-wif.md) component. Select the one to federate through in the **Federation provider** field. If your organization has no GCP Workload Identity Federation component installed, the install fails.

<table><thead><tr><th width="181">Field</th><th width="458">Description</th><th>Required</th></tr></thead><tbody><tr><td><strong>Federation provider</strong></td><td>An installed GCP Workload Identity Federation component to federate through.</td><td>Yes</td></tr></tbody></table>

{% hint style="info" %}
Custom servers support GCP WIF federation but not **AWS IAM federation**. Choosing AWS IAM federation fails the install.
{% endhint %}

### Definition

To define a custom server, choose **Custom** here.

<figure><img src="https://3783273641-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FSQNwGQz62W737pY0FzVb%2Fuploads%2FPqjyBMt26X0HdNiGkO6h%2Fimage.png?alt=media&amp;token=ac4a54b0-8f4f-4bd0-88e5-5cd55bac1b6f" alt="" width="563"><figcaption></figcaption></figure>

#### Server type

The **Server type** determines how the gateway reaches the server. A custom server supports two types: **External** and **Container** (Preview).

**External** proxies requests to an MCP server hosted outside the gateway, reachable at a fixed URL:

<table><thead><tr><th width="176.04296875">Field</th><th width="464.51953125">Description</th><th>Required</th></tr></thead><tbody><tr><td><strong>Server URL</strong></td><td>URL of the externally hosted MCP server.</td><td>Yes</td></tr><tr><td><strong>Label</strong></td><td>Human-friendly label for this server.</td><td>Yes</td></tr></tbody></table>

**Container** (Preview) runs a Docker container that hosts the MCP server. The gateway starts the container and routes tool calls to it:

<table><thead><tr><th width="176.04296875">Field</th><th width="464.51953125">Description</th><th>Required</th></tr></thead><tbody><tr><td><strong>Label</strong></td><td>Human-friendly label for this server.</td><td>Yes</td></tr><tr><td><strong>Docker entrypoint</strong></td><td>Command the container runs on start. Use <a href="https://liquidjs.com/">LiquidJS template syntax</a> to insert request parameters and credentials.</td><td>Yes</td></tr><tr><td><strong>Docker image</strong></td><td>Image that hosts the MCP server.</td><td>Yes</td></tr><tr><td><strong>Location field name</strong></td><td>Name of the field an agent must supply to route calls to this server, for example <code>project</code> or <code>account</code>.</td><td>Yes</td></tr><tr><td><strong>Location field description</strong></td><td>Description of the value an agent passes for the location field.</td><td>Yes</td></tr></tbody></table>

{% hint style="info" %}
A custom container server starts with an empty tool list. P0 does not introspect tools from an arbitrary image, so tools appear once the container itself reports them.
{% endhint %}

### Server details

These fields apply to the server itself:

<table><thead><tr><th width="181.84765625">Field</th><th width="458.34375">Description</th><th>Required</th></tr></thead><tbody><tr><td><strong>Agent prompt</strong></td><td>Describes the argument list (<code>argv</code>) an agent should pass to request access.</td><td>Yes</td></tr></tbody></table>

<figure><img src="https://3783273641-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FSQNwGQz62W737pY0FzVb%2Fuploads%2FRyCmNncjVxcUrHDBXGgY%2Fimage.png?alt=media&amp;token=d76be2c7-e077-4ac8-9b59-fbfbf8509943" alt="" width="563"><figcaption></figcaption></figure>

### Access control method

The **Access control method** sets how the gateway decides which tool calls to allow. Pick one of three options. The default is **Annotation**.

<figure><img src="https://3783273641-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FSQNwGQz62W737pY0FzVb%2Fuploads%2FPBVFXRoKozPPOpMfJcWM%2Fimage.png?alt=media&amp;token=f2b8bbce-e6f1-47c9-b87a-811210403e7b" alt="" width="563"><figcaption></figcaption></figure>

**Annotation** (Preview) gates access by what each tool does. Tools fall into three groups: **read-only**, **write (non-destructive)**, and **destructive**. An agent asks for one or more groups, and the gateway allows any tool in a group it was granted. A tool with no label counts as destructive. There are no extra fields to set.

**Tool** (Preview) gates access by tool name. An agent asks for the exact tools it needs, and the gateway allows only those. There are no extra fields to set.

**Native** gates access in the upstream environment's own IAM, scoped to an installed access-management integration:

| Field                     | Description                                                                                                                                                                                    | Required |
| ------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- |
| **Resource**              | An installed access-management resource that gates the server. It must be an installed, requestable integration with `iam_write` capability in your organization. The install fails otherwise. | Yes      |
| **Access command prefix** | A prefix added to the request arguments when an agent requests access, for example `role MyAccessRole`.                                                                                        | Yes      |

## Next steps

* Define the [Agentic access policies](/policy-studio/policy-studio/agentic-access-policies.md) that determine which agents and users may call the custom MCP server, and what they may do.
