Connect an MCP client
Register an MCP client and connect it to an MCP server configured behind the P0 AI Gateway.
This guide covers the path from a configured P0 AI Gateway to a working tool call. Configure an MCP server behind the gateway, register a client so your agent can authenticate, and connect to the server from Python.
1. Overview
What this enables
Once you finish this guide, an agent you write can call the tools of an upstream MCP server through the gateway. The gateway sits in the data path. It authenticates the caller on every tool call, checks the call against the policies you set in P0, forwards it to the upstream server, and logs it. Your agent never holds upstream credentials, and no tool call reaches the upstream server unauthenticated.
Prerequisites
A P0 account at p0.app.
A deployed P0 AI Gateway. See Deploying the P0 AI Gateway.
A configured Gateway component in P0. The gateway must appear with the state Installed before an MCP server can point at it.
Python 3.10 or later, for the client example.
2. Configure the MCP server
An MCP server configured behind the gateway becomes available to P0-managed agents across your organization.
Configure in the console
Navigate to Integrations on p0.app, select Agentic gateway, then choose the MCP server component.
Click Add server.
Enter the server details, then click Next:
Server identifier: a name for this server within P0. This value also becomes the server's ID in the gateway URL, so note it. Step 4 refers to it as
SERVER_ID.Gateway: the registered gateway that hosts this server.
Set the Credential source, which selects how the gateway authenticates to the upstream:
OAuth
Set the Definition, which selects what the server actually exposes:
P0, a predefined definition. Continue to AWS MCP server or GCP MCP server for the fields specific to each.
Custom, a server you define yourself. See Custom MCP server.
For the full walkthrough of this component, including screenshots of each screen, see MCP server.
Configure with Terraform
Use the P0 Terraform provider to configure an MCP server outside the console. The p0_agentic_server resource takes the hosting gateway's id, the server's own id, a definition (p0 or custom), and a credential source (aws, gcp, or oauth), the same choices as the console fields above.
Registering the gateway itself is a separate step, covered in Gateway for the console walkthrough.
You can use Terraform to register and configure the Gateway component in P0 using the P0 Terraform provider
p0_agentic_gateway
Inspect the configured servers
Read back the configured servers, which is the fastest way to confirm what the gateway serves:
{orgId}: your P0 tenant slug, the same value that appears in console URLs atp0.app/o/{orgId}/....
These read calls accept a user token or an API key, passed as a bearer token in the Authorization header. See Authenticating with the P0 API for how to get either. This example uses an API key:
Registering a client is different: it requires a user token and rejects an API key, covered in Register the client.
What P0 creates after configuration
The server becomes reachable at
{gatewayUrl}/mcps/{serverId}, and this URL is where your client connects.GET /o/{orgId}/agentic/serversreturns the exacturlfor each server in its JSON body.The gateway periodically syncs its configuration from P0 and reconciles the set of servers it hosts, adding newly configured servers and removing ones no longer configured. When a new server is installed, the gateway performs an ad-hoc sync so the server becomes available immediately.
The server's tool catalog is synced to P0, which allows P0 to understand the tools exposed by the MCP server.
3. Register the client
A client is the identity your agent presents to the gateway. Registering one yields a client ID and a client secret.
This is the user-delegated path: the credentials identify your application, and a person still signs in through P0, so every tool call carries both the user's identity and the agent's. Use it for agents that act on behalf of a person. For an unattended workload with no human in the loop, use JWT-SVID.
Register in the console
Navigate to the Agentic page on p0.app and open the MCP clients view.

Register a new client, supplying its platform and redirect URI.
For Claude Code, the redirect URI depends on how you configure the MCP client. If you use
claude mcp add, Claude Code uses a dynamically assigned local callback port unless you configure a fixed port.For a custom agent application, provide the callback URL exposed by your application's OAuth implementation.

Copy the client ID and client secret.
The client secret is shown once, at registration. Store it securely before leaving the page. If you lose it, register a new client.
Register through the API
To register a client outside the console, POST to the clients endpoint. Set type to client_credential_post for the confidential client this guide uses. The response contains the created client, including its secret, which P0 returns only once.
Registration requires a user token: a bearer token from a session signed in as a P0 user. An API key doesn't identify a user, so P0 rejects it. The P0 CLI token method in the authentication guide prints one from your login session.
For the request and response fields, the federated-identity variant, authentication for each endpoint, and the endpoints to list and update registered clients, see the Agentic client registration API reference.
4. Connect from Python
This example uses the MCP Python SDK.
Where each value goes
SERVER_ID
The Server identifier from step 2
Path segment under /mcps/
CLIENT_ID, CLIENT_SECRET
Step 3
Client authentication
REDIRECT_URI
Step 3, and must match the registered value exactly
Where sign-in returns
Your client connects to {GATEWAY_URL}/mcps/{SERVER_ID}. The access token must use that same URL as its audience. Copy the exact URL from the url field that GET /o/{orgId}/agentic/servers returns for your server.
Where the authorization code arrives
REDIRECT_URI is where P0 sends the browser once the user signs in, with the authorization code on the query string. For an agent that runs locally, nothing is listening at that address until your process opens the port. This is the same loopback pattern Claude Code uses, and the port and path must match what you registered in step 3 exactly.
Your code is responsible for one thing: receiving that authorization code and handing it to the SDK. OAuthClientProvider does the rest, exchanging the code for an access token and attaching the token to every request, so your code never handles the token itself.
The client
This example shows how to configure an MCP client using a P0-registered client ID and client secret. Replace the example variables with your client details.
The CallbackServer below is the loopback listener for a locally run agent. If your agent runs behind a web server instead, register that server's callback route in step 3 instead of a localhost URI. Have the route pass the authorization code to callback_handler instead of running this listener.
5. Verify the connection
Confirm the session opened.
session.initialize()returns without raising.Confirm that the gateway serves the server. Call
list_tools()and confirm the server's tools come back. For a P0 predefined server you also see the access toolsaccess,check,list, andrelinquish. An empty tool list means the gateway has no definition for this server. See Troubleshooting below.Confirm P0 saw it. The
list_toolscall appears in the gateway's activity, which you can read withGET /o/{orgId}/agentic/activity. The gateway also emits anauth.verifiedaudit event recording the subject and audience of the token it accepted.
6. Troubleshooting
404 on the MCP endpoint
Wrong gateway URL, or SERVER_ID does not match a configured server
Copy the url field for your server from GET /o/{orgId}/agentic/servers. The gateway resolves the server before it authenticates, so an unknown server answers 404 and never returns a 401.
Tool list is empty, no error
The gateway has no definition for this server
Installing a server triggers an immediate sync, so this is rarely a timing problem. Confirm the server appears in GET /o/{orgId}/agentic/servers and that SERVER_ID matches its identifier exactly.
401 with WWW-Authenticate: Bearer
No token, or the token failed verification
Confirm your client obtained a token, and that its audience is {gatewayUrl}/mcps/{serverId}.
invalid_client at the token endpoint
Client ID or secret wrong, or client disabled
Check the client in GET /o/{orgId}/agentic/clients. A client's status must be active.
Sign-in returns a redirect URI mismatch
The redirectUri sent does not exactly match the registered one
They must match exactly, including port and path.
A 2xx response that is not JSON
You are talking to an SSO proxy or an app front end, not the gateway
Point at the gateway host, not the P0 console or P0 API. A proxy answers 200 with an HTML login page.
Token rejected with an audience error
The audience is the bare gateway host instead of the per-server URL
The token audience must be {gatewayUrl}/mcps/{serverId}. See the audience section in JWT-SVID.
list returns no values, no error
The project or account has no resources that both exist and that you can request.
Create at least one resource of that type and configure an access policy that allows you to request it, then call list again. This is different from an empty tool list, which means the gateway has no definition for the server.
Related
Agentic client registration API: the API reference for registering, listing, and updating clients.
JWT-SVID: connect an unattended workload instead of a user-delegated client.
MCP server: the full component walkthrough, with screenshots.
Gateway: register a gateway deployment with P0.
Use MCP servers with Claude Code: connect Claude Code instead of a client you wrote.
Agentic Access Policies: govern what agents may do.
Last updated