Overview
With the MCP gateway, MCP clients reach remote MCP servers through a instead of connecting to them directly.The gateway works with remote MCP servers that clients reach over HTTPS. It doesn’t cover local servers that clients start as a subprocess over stdio.
Upstream authentication
When you add a server, you choose which credential Formal sends to it. The admin Catalog offers three options:Linked accounts (OAuth)
Each user links their own account for the server once. Formal stores the token encrypted in its control plane and refreshes it when the server supports refresh. The Connector adds the token to each request after policies allow it. Users never see the token. Users link accounts on the server’s page in the Catalog. They can also link during OAuth sign-in from an MCP client. Formal needs an OAuth client to sign users in to the server. Choose one under OAuth app:Formal's app (Client ID Metadata Document)
Formal's app (Client ID Metadata Document)
Formal identifies itself with a Client ID Metadata Document (CIMD). Its client ID is a URL where Formal hosts its name and redirect URI. You don’t register anything with the server.The server’s authorization server must:
- Advertise
client_id_metadata_document_supported: true. - Support the authorization code flow with PKCE
S256. - Accept public clients, with token endpoint auth method
none.
Your OAuth app (pre-registered)
Your OAuth app (pre-registered)
Use this for servers without CIMD support, such as GitHub and Slack.
- Register an OAuth app with the server’s provider.
- Copy the Redirect URI from the Catalog into the app’s allowed redirect URIs.
- Enter the app’s Client ID and, if it has one, its Client secret.
Shared credentials
Formal adds one credential that you provide, such as an API key or a service account token. Users never see it. You store the credential as a native user on the server’s resource, and Formal sends the default one. To send different credentials to different people, add selection rules on the resource page. Use shared credentials for servers that accept API keys, or when everyone should act as one account.Pass through
Clients send their own sign-in or API key, and Formal forwards it unchanged. Formal stores nothing. With pass through, the client’s own credential goes to the server, and nothing in the request identifies the Formal user. Formal can only attribute these requests when they come through the Formal Endpoint, which adds the user’s identity. For that reason, pass-through servers have no Connector address in the Catalog.Downstream authentication
Clients identify the user to the Connector in one of two ways. Formal uses that identity for policies, logs, and choosing the upstream credential.Formal OAuth
When upstream authentication isn’t pass through, the Connector acts as an OAuth protected resource:- The Connector answers a request without a token with
401 Unauthorized. ItsWWW-Authenticateheader points to/.well-known/oauth-protected-resource. - Formal is listed in that document as the authorization server.
- The client starts an authorization code flow with Formal. It identifies itself with its own CIMD URL.
- The user signs in to Formal and approves the client on a Catalog consent screen. If the server uses linked accounts, the user links their account here too.
- Formal issues a short-lived access token bound to this server’s address, plus a refresh token.
S256. It doesn’t support Dynamic Client Registration (DCR). Clients that only support DCR can’t sign in this way. On a device, route them through the Endpoint with identity headers.
Users can review and revoke approved clients on the server’s page in the Catalog. After a revoke, Formal stops refreshing that client’s tokens, but access tokens already issued stay valid until they expire.
Identity headers
The Connector also accepts a Formal identity in two headers:X-Formal-User-Username: the Formal username, such asidp:formal:human:alice@example.comX-Formal-User-Password: a Formal-signed token for that user
https://mcp.linear.app/mcp. They don’t sign in again, because the Endpoint already knows who they are.
To route Endpoint traffic to the gateway, create a network rule that forwards MCP traffic from AI agents to the Connector:
pre_tls keeps Formal from terminating TLS on the agents’ other traffic. Servers you add later are covered without editing the rule. To cover other applications, widen the process conditions.
Deploy the Connector
Before you add servers, set up the following on the Connector:- A listener that routes MCP traffic.
- A hostname.
- DNS and TLS that cover every subdomain of that hostname (i.e.,
*.<connector-hostname>), to enable smart routing. A request tolinear.acme.connectors.joinformal.comroutes to the server namedlinear.
1. Add an MCP listener
Create a listener with a Technology rule set to MCP. Use port443 so client URLs don’t need a port.
- Control Plane
- Terraform
- Go to Connectors and open your Connector.
- Add a listener on port
443. - Add a rule with type Technology and technology MCP.
2. Add a hostname with wildcard DNS and TLS
Clients reach each server at a subdomain of the Connector hostname, so both DNS and the TLS certificate must cover*.<connector-hostname>.
- Formal-managed
- Customer-managed
Use a hostname ending in
.<your-org>.connectors.joinformal.com. Formal creates both the hostname and wildcard DNS records. It also issues a wildcard certificate.Grant access to the Catalog
Users finish setup in the employee Catalog at catalog.formal.ai. There, they approve MCP clients during OAuth sign-in and link their upstream accounts. In Permissions, you control these calls through the Catalog application. If a permission usesdefault allow := false, add a rule for the Catalog to that same permission:
- Only active human users can approve an MCP client. Machine users authenticate with identity headers instead.
- Administrators who add servers need the Mcp and Resource applications. To edit Access Controls on a server, they also need Policies.
Add an MCP server
- Go to Catalog and click Add MCP.
- Pick a template, or click Add Custom and enter the server’s URL.
- Enter a Name. Formal uses it as the server’s subdomain on the Connector.
- Under Authentication, choose how Formal authenticates to the server. See Upstream authentication.
- Save the server.
Use a valid DNS label for the name: lowercase letters, digits, and hyphens, up to 63 characters. Formal can’t give a server with any other name a Connector address.
mcp-endpoint tag to the server’s MCP path:
- Open the server in the Catalog.
- On the Configuration tab, under Authentication, choose an option for How does Formal authenticate to this server?
- For Linked accounts, choose an OAuth app. For Shared credentials, click Add credential.
- Click Save authentication.
- Open the server in the Catalog. On its Configuration tab, you’ll see a Connector address, such as
https://linear.gateway.<your-org>.connectors.joinformal.com/mcp. If the address is missing, the reason appears in its place. - If you chose linked accounts or shared credentials, confirm that Formal is listed as the authorization server:
Connect MCP clients
Pick the URL based on where the client runs:
Users can find the right URL and setup steps for over 40 clients on each server’s page in the Catalog. The steps account for whether their device runs the Endpoint.
In the examples below, the server is named
linear, and the Connector hostname is gateway.acme.connectors.joinformal.com.
Claude and ChatGPT
Claude and ChatGPT call MCP servers from Anthropic’s and OpenAI’s clouds, so they always use the Connector address. A workspace owner adds the server once for the organization. Each member then connects with their own Formal account. The Add to Claude and Add to ChatGPT buttons appear under Add to your organization’s AI apps in the server’s Authentication section. You’ll see them once the server uses linked accounts or shared credentials and has a Connector address.- Claude
- ChatGPT
To add the server for your organization:
- In the Catalog, open the server and go to the Configuration tab.
- Under Add to your organization’s AI apps, click Add to Claude. Claude opens its organization connector settings with the server’s name and Connector address filled in.
- As a Claude Owner, confirm the connector.
- In Claude, open Settings → Connectors, find the server, and click Connect.
- Sign in to Formal and approve Claude on the Catalog consent screen.
- In a new conversation, enable the connector from the tools menu.
Claude Code
- With the Formal Endpoint
- Without the Formal Endpoint
Use the server’s original URL. The Endpoint routes it through the gateway and adds your identity.If the server uses linked accounts, link your account in the Catalog first.
Codex
- With the Formal Endpoint
- Without the Formal Endpoint
Use the server’s original URL:If the server uses linked accounts, link your account in the Catalog first.
Governance
Every request through the gateway carries a Formal identity, so you can control who uses each server and which tools they can call.Restrict access and tools
- Go to Catalog and open the server.
- Open the Access Controls tab.
- Under Who can use this MCP?, choose Everyone, Specific users, or No one. With Specific users, add users and groups.
- Under Which tools can they use?, choose All tools or Specific tools. With Specific tools, select the allowed tools. Use the Read-only and Destructive filters to find tools by the hints each server publishes.
- Optionally, edit Message shown when access is denied.
- Click Save changes.
MCP access controls: <server-name>. The Connector blocks requests from anyone outside the allowed users and groups. It also blocks tools/call requests for tools outside the list. Clients may still list those tools, but calls to them fail with the block message.
The Access Controls tab shows only the policy it created. Other policies can also restrict the server.
Write custom policies
For rules the tab doesn’t cover, write a policy on MCP traffic. Policies can read each call’s tool name and parameters. See MCP resources for an example and MCP policy inputs for every field.Review usage
Tool calls appear in Logs with the user, server, and tool name. In the Catalog, a server’s Usage tab breaks down its requests by tool and by user.Troubleshooting
No Connector address in the Catalog
No Connector address in the Catalog
Possible causes:
- The Connector has no hostname, or no listener routes MCP
- The Connector is in a different Space from the server
- The server name isn’t a valid DNS label
TLS or certificate errors in the client
TLS or certificate errors in the client
Possible causes:
- The certificate covers only the bare hostname, not
*.<connector-hostname> - No wildcard DNS record exists
dig and openssl checks in Deploy the Connector.Invalid client error during sign-in
Invalid client error during sign-in
Possible causes:
- The client doesn’t support Client ID Metadata Documents
- The client’s redirect URI isn’t in its metadata document
403 Forbidden on the consent screen
403 Forbidden on the consent screen
Cause: A permission denies the Catalog application for this user.Fix: Allow
input.app.name == "Catalog" in every permission that uses default allow := false. See Grant access to the Catalog.Account linking fails
Account linking fails
Possible causes:
- The server doesn’t support CIMD with public clients
- A pre-registered app is missing Formal’s redirect URI
Tool calls fail with a message to link an account
Tool calls fail with a message to link an account
Cause: The server uses linked accounts, and the user hasn’t linked one, or the link expired.Fix: Link or re-link the account on the server’s page in the Catalog.
Next Steps
MCP Resources
Write policies on MCP tool calls
Native Users
Manage shared credentials
Network Rules
Route Endpoint traffic to the Connector
Permissions
Control who can use the Catalog