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

# Govern Claude's MCP traffic

> Route every MCP server Claude Code and Claude Desktop reach through the TrueFoundry MCP Gateway: allowlists, org connectors, per-user sign-in, web search.

MCP servers connect Claude to databases, APIs, and SaaS tools. Each one a developer adds expands the attack surface: unvetted servers bring prompt-injection risk, credential sprawl, and no audit trail of which tools were called or what data was returned.

The recommended posture is to **route all MCP access through the [TrueFoundry MCP Gateway](/docs/ai-gateway/mcp/mcp-overview)** and **allowlist only the gateway URL** in Claude's managed settings. That gives you one control point regardless of how many servers you run, and it works independently of how model traffic is routed — even a Claude surface you can't point at the AI Gateway can still have its MCP servers governed this way.

* **Centralized registry** — register and manage all approved MCP servers in one place.
* **Unified authentication** — developers authenticate once; the gateway handles outbound auth (API key, OAuth2, token passthrough) to each downstream server. [Learn more](/docs/ai-gateway/mcp/mcp-gateway-auth-security)
* **Role-based access control** — control which users and teams can use which servers and tools.
* **Tool-level governance** — disable individual tools, or expose an approved subset per team via a [virtual MCP server](/docs/ai-gateway/mcp/virtual-mcp-server).
* **Guardrails** — pre/post-execution checks and approval workflows on tool calls. [Learn more](/docs/ai-gateway/guardrails-overview)
* **Full audit trail** — every tool call is traced with user attribution and payloads, exportable via OpenTelemetry. [Learn more](/docs/ai-gateway/analytics-mcp-metrics)

## How a server is exposed

An admin registers each approved server in the TrueFoundry control plane, configuring outbound auth, access policies, and guardrails. The gateway then exposes it at a tenant-scoped URL:

```text theme={"dark"}
https://<your-truefoundry-gateway-url>/<your-tenant-name>/mcp/<server-name>/server
```

Developers see the servers they have access to in the TrueFoundry UI and copy this URL into their client. Sign-in uses the gateway's OAuth flow — each user authenticates as themselves, so tool calls are attributed per user and no shared token is deployed. See [Connect an MCP server from your IDE / client](/docs/ai-gateway/mcp/connect-mcp-from-ide) for the "Sign in with TrueFoundry" flow.

Claude Code and Claude Desktop consume that URL through different config keys with different shapes. The rest of this page covers each.

| | Claude Code (CLI, VS Code) | Claude Desktop (Cowork) |
| - | - | - |
| Per-user config | `.mcp.json` / `claude mcp add` | Not available in third-party mode — connectors come only from managed config |
| Fleet config | `managed-mcp.json` (exclusive) or `managedMcpServers` in `managed-settings.json` (additive) | `managedMcpServers` managed-preference key |
| Shape | Object keyed by server name | Array of objects, each with its own `name` |
| Per-entry | `{"type": "http", "url": "…"}` | `{"transport": "http", "url": "…", "oauth": true}` |
| Sign-in | `/mcp` or `claude mcp login <server>` | **Customize → Connectors → Connect** |
| Allow user-added servers | Omit `managed-mcp.json`, or use `managedMcpServers` in `managed-settings.json` | `isLocalDevMcpEnabled` |

## Claude Code

### Add a server per user

```bash theme={"dark"}
claude mcp add --transport http github https://<gateway>/<tenant>/mcp/github/server
```

or in `.mcp.json`:

```json theme={"dark"}
{
  "mcpServers": {
    "github": {
      "type": "http",
      "url": "https://<your-truefoundry-gateway-url>/<your-tenant-name>/mcp/github/server"
    },
    "sentry": {
      "type": "http",
      "url": "https://<your-truefoundry-gateway-url>/<your-tenant-name>/mcp/sentry/server"
    }
  }
}
```

The key (`github`, `sentry`) is just the local name Claude Code shows; the server slug in the URL is what matters.

### Lock Claude Code to the gateway

Allowlist only the gateway URL and block marketplace-sourced installs in `managed-settings.json`:

```json theme={"dark"}
{
  "allowedMcpServers": [
    { "serverUrl": "https://<your-truefoundry-gateway-url>/*" }
  ],
  "strictKnownMarketplaces": []
}
```

These settings tune how much freedom developers keep (all belong in `managed-settings.json`):

| Setting | Effect |
| - | - |
| `allowedMcpServers` / `deniedMcpServers` | Allowlist / denylist by server URL, command, or name |
| `allowManagedMcpServersOnly` | Developers can use the managed servers but cannot broaden the allowlist |
| `strictPluginOnlyCustomization: ["mcp"]` | Blocks servers added through `~/.claude.json` or a project `.mcp.json` |
| `disableClaudeAiConnectors` | Turns off connectors Claude Code would otherwise pull from claude.ai |

### Push connectors fleet-wide with `managed-mcp.json`

On managed devices, pre-seed servers by deploying a `managed-mcp.json` file via MDM. When present, it takes **exclusive control** — developers cannot add MCP servers beyond what's defined:

```json theme={"dark"}
{
  "mcpServers": {
    "github": {
      "type": "http",
      "url": "https://<your-truefoundry-gateway-url>/<your-tenant-name>/mcp/github/server"
    },
    "sentry": {
      "type": "http",
      "url": "https://<your-truefoundry-gateway-url>/<your-tenant-name>/mcp/sentry/server"
    }
  }
}
```

**System paths:** macOS `/Library/Application Support/ClaudeCode/managed-mcp.json` · Linux `/etc/claude-code/managed-mcp.json` · Windows `C:\Program Files\ClaudeCode\managed-mcp.json`. Access decisions happen at the gateway, so this file only changes when you add or remove an entire integration — the [MDM deployment scripts](/docs/ai-gateway/claude-mdm#deployment-scripts) generate and write it for you.

Managed servers are **listed, not pre-connected**. Each developer runs `/mcp` inside Claude Code (or `claude mcp login <server>`) once and signs in through the browser as themselves.

<Note>
  **Additive instead of exclusive.** Claude Code **v2.1.259+** also reads a `managedMcpServers` key inside `managed-settings.json`, using the same object shape. That hands developers the org servers *alongside* their own rather than replacing them — useful when you want to seed connectors without locking the surface down. Older clients ignore the key.
</Note>

## Claude Desktop

In third-party inference mode the Anthropic connector directory is unavailable, so org connectors reach Claude Desktop **only** through the `managedMcpServers` managed preference (in the `com.anthropic.claudefordesktop` domain — see [Claude Desktop](/docs/ai-gateway/claude-desktop#enforce-fleet-wide-via-mdm-managed-preferences) for the full key reference). The value is a JSON-encoded **array**:

```json theme={"dark"}
[
  {
    "name": "github",
    "transport": "http",
    "url": "https://<gateway>/<tenant>/mcp/github/server",
    "oauth": true
  }
]
```

* **`oauth: true` needs no `clientId` and no pre-registered redirect URI.** Claude registers itself against the gateway's authorization server through dynamic client registration, then each user clicks **Connect** and signs in as themselves — so tool calls are attributed per user instead of sharing one fleet-wide token. The alternative is `headers` carrying the same TrueFoundry token you use for inference, or `headersHelper` pointing at a script that prints it — which keeps the token out of the config file but makes every call look like one shared identity.
* **Managed servers are listed, not connected.** They appear under **Customize → Connectors** with a **Connect** button.
* **Leave `toolPolicy` out** unless you are naming real tool names (`"create_issue": "allow"`). Its keys are individual tools, not patterns — an undocumented `{"*": "allow"}` risks the whole entry being rejected.
* **Connectors ride on the inference block.** If `inferenceProvider` is not `gateway`, the app is in first-party mode and ignores the entire managed configuration, connectors included — an empty pane with no error.
* **`isLocalDevMcpEnabled: false`** stops users adding their own local MCP servers alongside the managed ones. Defaults to `true`.

<Warning>
  **macOS ordering.** `tfy-local-ai-setup` rewrites and re-locks the whole managed-preferences plist on each run, so `managedMcpServers` has to be re-applied *after* the binary on every run — not once at provisioning time. On Windows the values are written individually under `HKLM\SOFTWARE\Policies\Claude` and survive, but write them with `New-ItemProperty`: `reg add` strips the double quotes out of a JSON value and leaves the connectors pane empty. The [MDM deployment scripts](/docs/ai-gateway/claude-mdm#deployment-scripts) handle this ordering and write both the Desktop array and Claude Code's `managed-mcp.json` from one connector list.
</Warning>

## Web search

Both Claude Code and Claude Desktop have a built-in **web search** that is an Anthropic *server-side* tool: the client emits Anthropic's `web_search_20250305` tool and asks the inference endpoint to run it. When the client points at the AI Gateway there are two ways to satisfy it, and you can use both.

**Provider-native passthrough.** The gateway forwards the server tool to whichever provider serves the model — the request tool, the `web_search_tool_result` blocks in the response, and the `num_search_queries` usage counter for billing. Nothing to configure. The catch is that it only works when the routed provider actually executes Anthropic's web-search tool (for example, the Anthropic API); a model on a provider that doesn't run it simply returns no search results.

**MCP web search (consistent across providers).** Register a web-search MCP server — for example [Tavily](/docs/ai-gateway/mcp/tavily-mcp-server) or [Exa](/docs/ai-gateway/mcp/exa-mcp-server) — on the MCP Gateway and expose it to Claude like any other connector. Search runs at the MCP server, so it behaves the same on **every** model, and the vendor key stays server-side instead of being shipped to each device.

<Tabs>
  <Tab title="Claude Code">
    ```bash theme={"dark"}
    claude mcp add --transport http web-search https://<gateway>/<tenant>/mcp/<mcp-server-name>/server
    ```

    or in `.mcp.json` / `managed-mcp.json`:

    ```json theme={"dark"}
    {
      "mcpServers": {
        "web-search": {
          "type": "http",
          "url": "https://<gateway>/<tenant>/mcp/<mcp-server-name>/server"
        }
      }
    }
    ```

    To force search through the MCP server only, deny the built-in tool in `settings.json` (or `managed-settings.json` for a fleet):

    ```json theme={"dark"}
    {
      "permissions": {
        "deny": ["WebSearch"]
      }
    }
    ```

    Add `"WebFetch"` to the same list to also block Claude Code from fetching URLs.
  </Tab>

  <Tab title="Claude Desktop">
    Add the server to `managedMcpServers`:

    ```json theme={"dark"}
    [
      {
        "name": "web-search",
        "transport": "http",
        "url": "https://<gateway>/<tenant>/mcp/<mcp-server-name>/server",
        "oauth": true
      }
    ]
    ```

    To auto-approve tools so users aren't prompted per query, add a `toolPolicy` naming the server's **real tool names** (`{"search": "allow"}`).

    To force search through the MCP server only, add `WebSearch` to `disabledBuiltinTools`:

    ```json theme={"dark"}
    {
      "disabledBuiltinTools": ["WebSearch"]
    }
    ```

    Add `"WebFetch"` to also block page fetching. In an MDM profile this value is a **JSON-encoded string**, e.g. `"[\"WebSearch\"]"`.

    <Note>
      Web Search returns links; **Web Fetch** (retrieving a page's contents) runs on the device and is gated by the `coworkEgressAllowedHosts` allowlist. If you want Claude to open the pages it finds, add those hosts to `coworkEgressAllowedHosts` (or set it to `["*"]`). See Anthropic's [Web search and web fetch](https://claude.com/docs/third-party/claude-desktop/web-tools) reference.
    </Note>
  </Tab>
</Tabs>

Replace `<mcp-server-name>` with the slug of the server you registered on the gateway (for example `tavily` or `exa`); the local name (`web-search`) is just the label the client shows.

## Next steps

<CardGroup cols={2}>
  <Card title="Enforce with MDM" icon="shield-halved" href="/docs/ai-gateway/claude-mdm">
    Deployment scripts that write both connector formats from one list and lock them.
  </Card>

  <Card title="MCP Gateway overview" icon="server" href="/docs/ai-gateway/mcp/mcp-overview">
    Registering servers, auth, RBAC, and virtual MCP servers.
  </Card>
</CardGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.