Activation required. AI access management must be enabled for your tenant, and private bridge connectivity must be turned on separately. To get started, contact the C1 support team.
bridge-client) next to your server; it dials out to C1 and holds a tunnel open. C1 sends incoming tool calls back down that tunnel, so nothing in your network needs to listen for inbound connections. A single bridge isn’t limited to one server: it can expose multiple MCP servers at once, each as its own named service (see Expose multiple MCP servers on one bridge). Note the distinction: multiple services run through one bridge-client, not through multiple copies of it — a credential holds only one session, so run exactly one bridge-client instance per credential. Multiple instances sharing a credential evict each other continuously (see Troubleshooting).
Setup has two halves that must match each other:
- A bridge config (YAML) that tells
bridge-clientwhere your MCP servers are and what to advertise to C1. - An MCP server registration in C1, one per advertised service, that points C1 at that service over the bridge.
Before you begin
- Your MCP server must be running and reachable from wherever you’ll run
bridge-client. Have itshost:port, endpoint path (typically/mcp), and transport (streamable-httporsse) ready. - Download
bridge-clientfrom the C1 download center. Linux and macOS binaries and container images are available there. - Creating a bridge requires the Connector Administrator or Super Administrator role.
- Registering the MCP server requires the Editor role on the destination app.
Step 1: Create a bridge in C1
Creating a bridge issues the credentials thatbridge-client uses to authenticate to C1.
1
In C1, go to Settings > Bridges.
2
Give it a display name (for example,
my-laptop or prod-vpc-east) and optionally a description, then click Create bridge. C1 navigates to the bridge’s detail page.3
On the bridge detail page, find the Credentials card and click Create credential. (On a bridge that already has an active credential, this button is labeled Rotate credential instead.)
4
Copy the Client ID and Client secret from the dialog.
Step 2: Write the bridge config
Create a file calledbridge.yaml. Set the credentials from Step 1, and add a port entry that points to your local MCP server.
Port field reference
The
service_path and transport_type you set here are what C1 uses when routing tool calls. The registration wizard in Step 4 doesn’t let you override them, so set them correctly now.Expose multiple MCP servers on one bridge
To expose more than one local service, add more entries underports:. Each entry needs its own unique name and listen_port; everything else is per-service, so different servers can use different paths and transports:
name.
Other ways to supply config
The YAML literals above aren’t the only option. Both are covered in full in the bridge setup guide:- Environment variables. Instead of a config file, set
C1_BRIDGE_CLIENT_ID,C1_BRIDGE_CLIENT_SECRET, and a single service viaC1_BRIDGE_SERVICE_LISTEN_PORTandC1_BRIDGE_SERVICE_BACKEND(plus optionalC1_BRIDGE_SERVICE_NAME,_TYPE,_PATH, and_TRANSPORT_TYPE). - HashiCorp Vault. Keep non-secret fields in YAML and pull sensitive ones (such as
client_secret) from a HashiCorp Vault backend, so no secret ever lives in the config file.
Resolve secrets from HashiCorp Vault
Add a top-levelsecret_backend: block selecting Vault, and a top-level secrets: map that points each sensitive field at a "<secret-id>:<key>" locator. At startup bridge-client fetches each value and writes it into the matching bridge: field before connecting, so a field resolved from Vault doesn’t need a literal in the YAML.
Step 3: Run the bridge
Runbridge-client inside the same network as your MCP server. Select your deployment method:
- Binary
- Docker
- Kubernetes
Start the agent. It runs continuously and holds the tunnel open:
Step 4: Register the MCP server in C1
With the bridge running, register the server in C1 so its tools are available for governance.1
Open the app you want the MCP server registered under, go to its MCP servers tab, and click Add MCP server.If you’re starting from the tenant-wide MCP servers page (Integrations > MCP servers) instead, the wizard adds a Choose app step so you can pick or create the destination app.
2
Under Choose a server, select External MCP server — “Connect to an external MCP server by URL.”
3
Under Connectivity, select Private bridge — “Route through a C1 Bridge running in your network.” Then set:
- Bridge — the bridge you created in Step 1.
- Service — the service your bridge advertised, which is the
namefield frombridge.yaml(my-mcpin the example).
4
Under Configure, enter a display name for the server. The Server URL field is read-only — it’s resolved automatically from the bridge service you selected.In the Authentication section, pick the Authentication method C1 uses to reach your server — Bearer token, Custom header, Basic auth, or OAuth2 — and enter the credentials it requires. Then click Add server.
A user can only call a tool once they’re an app user of the app the server is registered under. New external apps start with no app users. When you register from an existing app that has none, the wizard inserts a Link users step to populate them by linking an entitlement from another app. When you start from the tenant-wide MCP servers page instead, you get the Choose app step (not Link users) — populate app users afterward from the app’s settings. See Calling the tools from an AI client for the full set of ways to do this.
Step 5: Review discovered tools
After you click Add server, C1 connects to your MCP server over the bridge and pulls its tool list. The wizard’s final step shows these discovered tools. C1 records each tool’s name, description, and input schema exactly as your MCP server advertises them, and surfaces that text to AI clients during discovery. The agent relies on it to decide which tool fits a request — so clear, accurate tool descriptions and schemas on your server directly affect how reliably the right tool gets found and called. Each tool:- Becomes its own entitlement in C1 — access is requested, granted, and reviewed like any other entitlement.
- Is auto-classified in the Classification column; you can change the classification.
- Starts with State set to Unset. Flip the toggle to Enabled to allow calls to that tool, or Disabled to block it for everyone.
Setting a tool’s state to Enabled makes it callable only by users who hold a grant for it — it doesn’t grant access on its own. To grant access, add the tool to an MCP access profile and assign that profile to users. See Govern tools and toolsets.
Step 6: Verify the connection
- In Settings > Bridges, the bridge shows Connected, with your service listed.
- On the server’s Tools tab in C1, the discovered tools appear.
- On the server’s Details tab, Test credentials succeeds and reports the number of tools discovered over the bridge.
bridge-client logs. For a binary deployment, logs go to stdout/stderr. For Kubernetes:
Calling the tools from an AI client
Once the bridge is running and tools are approved, your users reach them from their AI clients (Claude Code, Claude Desktop, Cursor, VS Code) through C1’s MCP gateway — not through the bridge directly. C1 authenticates the user, enforces tool governance, and routes each call through the bridge to your local server. By default, these clients use code mode: instead of listing each tool as its own named tool, C1 exposes discovery and execution entrypoints (describe and execute), and the agent finds the tools it needs and invokes them by writing short code. Your bridged tools won’t appear one by one in the client’s tool list — that’s expected, not a discovery failure. Governance is unchanged: every underlying call still runs the same per-tool checks — the tool must be Enabled and the caller must hold a grant. Code mode is a tenant-level AI governance setting (on by default); with it off — or for Service and Ephemeral client types — C1 instead exposes each enabled tool as a directly named tool.
A call only executes when the requesting user is an app user of the server’s app and holds a grant for the tool. If the caller isn’t yet an app user, the call opens an access request instead of running. App users come from the destination app’s account sources. Populate them by linking an entitlement from another app (the Link users step during registration, or linked entitlements later in the app’s settings), by importing a CSV of app users, or — if the app is backed by a connector — by syncing them from the connector.
Troubleshooting bridge connection issues
Bridge never reaches Connected
Bridge never reaches Connected
Re-check
client_id and client_secret. The secret is shown only once — if you didn’t capture it, rotate the credential and try again. Check the bridge-client logs for an authentication error.Bridge connects, then loops with 'session torn down by server'
Bridge connects, then loops with 'session torn down by server'
If the logs repeatedly show
session torn down by server, then session lost, reconnecting and reconnected successfully, check to make sure that another instance of bridge-client is not running with the same credential. A credential holds only one session, so in this case, multiple clients will evict each other continuously and the bridge will never stay Connected. Run exactly one bridge-client per credential — check for a second instance, such as a Kubernetes Deployment with replicas greater than 1, a leftover container, or another host. If you need more than one runner, create a separate bridge and credential for each.If the reconnects instead keep failing, or you see credential reported invalid, the credential was revoked or expired — rotate it and restart.First tool call right after connecting fails with EOF or 'failed to connect to external MCP server'
First tool call right after connecting fails with EOF or 'failed to connect to external MCP server'
The connection can be slow on the very first call while the path warms up. Retry once — subsequent calls succeed.
Tool calls fail with connection refused or timeout
Tool calls fail with connection refused or timeout
The
backend host:port in your config is wrong, or the MCP server isn’t running there. Confirm the server is up and reachable from wherever bridge-client is running.Connected, but tool calls return errors
Connected, but tool calls return errors
Check
service_path and transport_type in bridge.yaml. The service_path must match the actual endpoint path your MCP server serves (for example, /mcp), and transport_type must match its transport. These values come from the config — the registration wizard doesn’t let you override them. Also confirm you selected the right service in Step 4.Rotate or revoke bridge credentials
From the bridge detail page (Settings > Bridges > your bridge > Credentials):- Rotate credential — issues a new client ID and secret. The old credential stays valid until you explicitly revoke it. Update
bridge.yamlwith the new credentials, restartbridge-client, then revoke the old credential. - Revoke credential — invalidates the credential immediately and disconnects any running agent that uses it.
Frequently asked questions about the bridge
Does one bridge cover my whole organization, or do I need several?
Does one bridge cover my whole organization, or do I need several?
One bridge can host many services, so a single deployment covers most environments. As a practical guideline, keep to a handful of active services per bridge — there is a hard limit of 32 services per bridge. If you need isolation between systems, want to reduce the blast radius of a connectivity issue, or are running a large number of services, split across multiple bridges.
Does routing through the bridge add latency compared to a cloud-hosted MCP server?
Does routing through the bridge add latency compared to a cloud-hosted MCP server?
Negligible in practice — the added latency won’t be noticeable in day-to-day use. The more important factor is network reachability: the bridge must be able to reach your MCP server from wherever it’s running. If tool calls are slow or failing, check connectivity from the bridge host to the MCP server before assuming latency is the cause.