---
title: "MCP Clients"
description: "Connect your agent-native app to local MCP servers (claude-in-chrome, filesystem, playwright, etc) so the agent gains their tools."
---

# MCP Clients

**This page: give your agent more tools.** Point an agent-native app at MCP servers — local or remote — so their tools show up in the agent chat. This is the _client_ direction, the mirror image of [MCP Server](/docs/mcp-protocol) (which makes your app an MCP _server_). Note the dual use of "client" here: this page is about your app acting as an MCP client of _other_ servers — a different sense from an "MCP host" like Claude or Cursor connecting to your app (see [MCP Server](/docs/mcp-protocol) for that direction).

**Looking for the provider list first?** See the [Integrations Directory](/docs/integrations)
for the self-hosted catalog wall, connection modes, setup links, and current
restricted-provider notes.

| If you want to…                                              | Read                                     |
| ------------------------------------------------------------ | ---------------------------------------- |
| Connect an external agent/host to your app                   | [External Agents](/docs/external-agents) |
| Give your agent more tools (consume other MCP servers)       | **This page** — MCP Clients              |
| Build inline UIs that render in Claude/ChatGPT               | [MCP Apps](/docs/mcp-apps)               |
| Build generated inline UI inside Agent-Native chat           | [Generative UI](/docs/generative-ui)     |
| Lower-level MCP server reference (auth, tools, custom mount) | [MCP Server](/docs/mcp-protocol)         |

With one config file, every agent-native app in your workspace gains access to tools provided by MCP servers on your machine: `claude-in-chrome` for browser automation, `@modelcontextprotocol/server-filesystem` for reading files, `@playwright/mcp` for browser testing, and anything else that speaks MCP.

You can also [connect remote (HTTP) MCP servers at runtime](#remote-via-ui) — individual users or whole organizations — without editing a config file.

Every source resolves into one runtime **MCP manager**, and every tool it learns lands in the agent's tool registry under a collision-proof `mcp__<server-id>__<tool>` prefix — searchable by intent through `tool-search`.

<Diagram id="doc-block-985gtd" title="Client direction: many sources, one tool registry" summary={"Config files, env, and runtime UI all merge into the MCP manager; its tools appear prefixed and tool-searchable alongside your app's actions. This is the mirror of the server direction."}>

```html
<div class="mcp-merge">
  <div class="diagram-col sources">
    <div class="diagram-box" data-rough>
      Workspace <code>mcp.config.json</code><br /><small class="diagram-muted"
        >shared across apps</small
      >
    </div>
    <div class="diagram-box" data-rough>
      App-root <code>mcp.config.json</code><br /><small class="diagram-muted"
        >per-app override</small
      >
    </div>
    <div class="diagram-box" data-rough>
      <code>MCP_SERVERS</code> env<br /><small class="diagram-muted"
        >CI / production</small
      >
    </div>
    <div class="diagram-box" data-rough>
      Remote via settings UI<br /><small class="diagram-muted"
        >personal &amp; org scope</small
      >
    </div>
  </div>
  <div class="diagram-arrow diagram-muted" aria-hidden="true">&rarr;</div>
  <div class="diagram-panel center" data-rough>
    <span class="diagram-pill accent">MCP manager</span
    ><small class="diagram-muted">merge &middot; hot-reload</small>
  </div>
  <div class="diagram-arrow diagram-muted" aria-hidden="true">&rarr;</div>
  <div class="diagram-col out">
    <div class="diagram-node">
      Agent tool registry<br /><small class="diagram-muted"
        ><code>mcp__&lt;server-id&gt;__&lt;tool&gt;</code></small
      >
    </div>
    <div class="diagram-node">
      <code>tool-search</code><br /><small class="diagram-muted"
        >discover by intent</small
      >
    </div>
  </div>
</div>
```

```css
.mcp-merge {
  display: flex;
  align-items: center;
  gap: 14px;
  flex-wrap: wrap;
}
.mcp-merge .diagram-col {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.mcp-merge .center {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
}
.mcp-merge .diagram-arrow {
  font-size: 22px;
  line-height: 1;
}
.mcp-merge code {
  font-size: 0.85em;
}
```

</Diagram>

> The opposite direction — making _your_ app an MCP server that other hosts consume — lives in [MCP Server](/docs/mcp-protocol) and [External Agents](/docs/external-agents).

## Built-in browser and computer-use capabilities {#built-in-capabilities}

Agent-native includes local-development toggles for common stdio MCP servers.
They are off by default and can be enabled per user or per organization only
when the app is running locally. Production and hosted serverless runtimes skip
these built-ins even if old settings rows exist, and the Workspace Resources
tree does not show them as default `mcp-servers/*.json` resources.

| Capability         | Server id         | Command                                                                 |
| ------------------ | ----------------- | ----------------------------------------------------------------------- |
| Chrome DevTools    | `chrome-devtools` | `npx -y chrome-devtools-mcp@latest --autoConnect --no-usage-statistics` |
| Playwright Browser | `playwright`      | `npx -y @playwright/mcp@latest`                                         |
| Computer Use       | `computer-use`    | `npx -y computer-use-mcp@latest`                                        |

Only one browser capability can be enabled in a scope at a time. Enabling Chrome DevTools disables Playwright for that same user or org, and enabling Playwright disables Chrome DevTools.

Computer Use is macOS-only. On other platforms it is listed as unavailable and is skipped even if an old setting row contains it.

Chrome DevTools uses `--autoConnect` by default. That attaches to an eligible running Chrome instance; it does not create an isolated browser profile or sign into the user's regular profile for you. It requires Chrome 144+ with remote debugging enabled. A manual `browser-url` configuration can be added later when a deployment needs a specific debugging endpoint.

Built-ins are persisted in the framework's `settings` table under `u:<email>:mcp-builtin-capabilities` for personal toggles and `o:<orgId>:mcp-builtin-capabilities` for team toggles. When enabled, they merge into the runtime MCP manager with the same scoped visibility format as remote servers, for example `mcp__user_<emailhash>_playwright__*` or `mcp__org_<orgId>_chrome-devtools__*`.

### User-facing setup notes

Use concise, explicit setup copy for the sensitive built-ins:

- **Chrome DevTools** attaches to a running Chrome debugging target. Tell users
  it is intended for browser testing and logged-in verification, and that it
  may require enabling Chrome remote debugging before tools appear.
- **Playwright** launches an isolated browser. Recommend it for deterministic
  QA when the user's live Chrome profile is not required.
- **Computer Use** can operate local apps. Keep it off by default, explain the
  macOS Screen Recording and Accessibility prompts, and ask before taking
  sensitive actions such as purchases, financial changes, or account changes.

### Built-in endpoints

| Method | Route                        | Purpose                                                                    |
| ------ | ---------------------------- | -------------------------------------------------------------------------- |
| GET    | `/_agent-native/mcp/builtin` | List built-in capabilities, enabled scopes, merged ids, and live status.   |
| POST   | `/_agent-native/mcp/builtin` | Update a scope. Body: `{ scope, enabledIds }` or `{ scope, id, enabled }`. |

<Endpoint id="doc-block-mcpc-builtin" method="GET" path="/_agent-native/mcp/builtin" summary="List built-in capability state for the current user/org scope" responses={[
  {
    "status": "200",
    "description": "Built-in capabilities (chrome-devtools, playwright, computer-use), which scopes have them enabled, merged server ids, and live connection status.",
    "example": "{\n  \"capabilities\": [\n    { \"id\": \"playwright\", \"enabledScopes\": [\"user\"], \"connected\": true }\n  ]\n}"
  }
]}>

Reports which local-development built-ins (Chrome DevTools, Playwright, Computer Use) are enabled for the current user or organization, and whether they're currently connected. `POST` to the same path with `{ scope, enabledIds }` or `{ scope, id, enabled }` to change a scope's setting.

</Endpoint>

## Adding a local MCP server {#adding-a-server}

Create `mcp.config.json` at your workspace root (or at an individual app root — workspace root wins when both exist):

```jsonc
{
  "$schema": "https://agent-native.com/schema/mcp.config.json",
  "servers": {
    "claude-in-chrome": {
      "command": "claude-in-chrome-mcp",
      "args": [],
      "env": { "LOG_LEVEL": "info" },
    },
    "playwright": {
      "command": "npx",
      "args": ["-y", "@playwright/mcp@latest"],
    },
    "filesystem": {
      "command": "npx",
      "args": [
        "-y",
        "@modelcontextprotocol/server-filesystem@latest",
        "/Users/me/projects",
      ],
    },
  },
}
```

The shape is small: a `servers` map keyed by server id, where each entry is either a stdio launcher (`command` + `args` + optional `env`) or a remote `{ "type": "http", "url", "headers" }` entry.

<AnnotatedCode
  id="doc-block-19dkfja"
  title="mcp.config.json, annotated"
  filename="mcp.config.json"
  language="jsonc"
  code={
    '{\n  "$schema": "https://agent-native.com/schema/mcp.config.json",\n  "servers": {\n    "claude-in-chrome": {\n      "command": "claude-in-chrome-mcp",\n      "args": [],\n      "env": { "LOG_LEVEL": "info" }\n    },\n    "filesystem": {\n      "command": "npx",\n      "args": ["-y", "@modelcontextprotocol/server-filesystem@latest", "/Users/me/projects"]\n    }\n  }\n}'
  }
  annotations={[
    {
      lines: "3",
      label: "Server id",
      note: "The key becomes the tool prefix: this server's tools surface as `mcp__claude-in-chrome__*` in the agent's registry, so they can't collide with your template's actions.",
    },
    {
      lines: "4-6",
      label: "stdio launcher",
      note: "`command` + `args` spawn a local binary. Stdio servers are intended for **local development** — they are a no-op in edge runtimes.",
    },
    {
      lines: "6",
      label: "Process env",
      note: "Optional `env` is passed to the spawned process. Keep secrets out of committed config; prefer `MCP_SERVERS` or the settings UI for tokens.",
    },
  ]}
/>

On next app start you'll see:

```
[mcp-client] loaded config from /path/to/mcp.config.json (3 server(s))
[mcp-client] connected to claude-in-chrome: 12 tools
[mcp-client] connected to playwright: 9 tools
[mcp-client] connected to filesystem: 4 tools
```

The tools are registered in the agent's tool registry with the prefix `mcp__<server-id>__<tool-name>` so they can't collide with your template's actions. They are also included in `tool-search`, so agents can discover newly connected MCP capabilities by intent instead of needing the exact prefixed name up front.

## Config precedence {#precedence}

MCP configuration is resolved in this order, first match wins:

1. **Workspace root `mcp.config.json`** — detected via `agent-native.workspaceCore` in `package.json`. Shared across every app in the workspace.
2. **App-root `mcp.config.json`** — per-app override if you don't want an MCP server available in every app.
3. **`MCP_SERVERS` env var** — JSON string with the same shape, for CI/production where a file doesn't make sense.

## Production deploys: `MCP_SERVERS` {#mcp-servers-env}

For production deploys, prefer remote HTTP MCP servers and set the full config
shape (or the inner server map) as an environment variable:

```bash
MCP_SERVERS='{"servers":{"zapier":{"type":"http","url":"https://mcp.example.com/mcp","headers":{"Authorization":"Bearer paste-token-value-here"}}}}'
```

`MCP_SERVERS` is parsed as JSON, so `${...}` placeholders are not expanded
inside the string. If you store the token in another secret, expand it before
writing the final JSON value.

Stdio MCP servers spawn local binaries and are intended for local development.
MCP tools only activate in Node runtimes — Cloudflare Workers and other edge
targets silently skip MCP and continue with the rest of the app working
normally.

## Auto-detect: `claude-in-chrome` {#autodetect}

If you have **no** `mcp.config.json` and the `claude-in-chrome-mcp` binary is on `PATH` (or in the well-known install location `~/.claude-in-chrome/bin/claude-in-chrome-mcp`), agent-native auto-registers it as a default MCP server. Set `AGENT_NATIVE_DISABLE_MCP_AUTODETECT=1` to opt out.

This means users who've installed the claude-in-chrome extension get browser control across every agent-native app they open with no config changes.

## Remote MCP servers via the settings UI {#remote-via-ui}

MCP (Model Context Protocol) servers give your agent new abilities — like connecting to Zapier, Cloudflare, Composio, or your company's internal tools. Once connected, the agent can use those tools just like its built-in ones.

The chat composer `+` menu and Workspace create menu include an integration
catalog with a few remote MCP presets plus custom server setup. Product owners
can hide that surface or restrict the bundled presets from the Vite config:

```ts
import { agentNative } from "@agent-native/core/vite";

export default {
  plugins: [
    agentNative({
      // Hide the entire MCP integrations entry.
      mcpIntegrations: false,

      // Or keep custom MCP setup but hide all bundled presets.
      // mcpIntegrations: { defaults: false },

      // Or allow/block individual preset ids:
      // mcpIntegrations: { defaults: { include: ["context7", "sentry"] } },
      // mcpIntegrations: { defaults: { exclude: ["stripe", "notion"] } },
      // mcpIntegrations: { defaults: { include: ["context7"] }, custom: false },
    }),
  ],
};
```

Preset ids are `context7`, `sentry`, `notion`, `granola`, `semgrep`, `linear`,
`atlassian`, `supabase`, `neon`, `stripe`, `cloudflare`, `gitlab`, `figma`,
`canva`, `vercel`, `github`, `slack`, `asana`, `hubspot`, `intercom`, `monday`,
`webflow`, `paypal`, `box`, `netlify`, and `zapier`.

The directory distinguishes endpoints that support the framework's generic
OAuth flow from providers that require a vendor-approved client or a
pre-registered OAuth application. The latter stay visible for discovery and
link to their official setup instructions, but do not show a misleading
one-click connect button. Provider restrictions change over time, so verify
the vendor setup note before enabling one in a production catalog.

When a chat request clearly names an unconnected catalog provider, the
composer and relevant completed responses can show an inline **Connect**
suggestion. OAuth and direct connections preserve that request in the current
tab and resume it after setup completes; long or abandoned requests expire
automatically.

### Atlassian / Jira

The Atlassian preset uses Atlassian Rovo MCP's OAuth 2.1 endpoint,
`https://mcp.atlassian.com/v1/mcp/authv2`, and exposes Jira and Confluence
tools. Creating Jira tickets requires the Atlassian permissions that cover
Jira writes; the user still only sees the projects and content allowed by
their Atlassian account.

Atlassian organization admins can control whether an OAuth client is allowed
to connect. Before connecting, an admin may need to add the app's actual HTTPS
origin to the trusted-domain list under **Atlassian Administration → Rovo →
Rovo MCP server → Domains**, and enable the required **Read**, **Write**, and
**Search** permissions under **Permissions**. The domain must be the host where
the agent-native app runs; do not copy `https://builder.io/**` to another
deployment unless that is its actual origin. See Atlassian's [Rovo MCP setup
guide](https://developer.atlassian.com/cloud/rovo-mcp/guides/getting-started/)
and [admin controls](https://support.atlassian.com/security-and-access-policies/docs/control-atlassian-rovo-mcp-server-settings/).

The catalog supplies the endpoint and setup guidance. The generic settings
form stores the endpoint and optional encrypted headers; it does not replace
Atlassian's interactive OAuth consent flow. Use an OAuth-capable MCP client or
runtime when Atlassian requires interactive OAuth. If the provider or runtime
supports a static bearer token, follow its approved secret-management path and
never paste tokens into prompts or committed config.

### How to connect a remote MCP server

1. **Server name** — a short label for your own reference (e.g. "zapier", "slack-tools").
2. **URL** — the HTTPS endpoint the MCP server provider gave you (e.g. `https://mcp.zapier.com/s/abc123/mcp`). This is usually found in the provider's dashboard or integration docs.
3. **Description** (optional) — a note about what this server does.
4. **Headers** — authentication credentials the server requires, one per line. Most servers need an `Authorization` header. Example: `Authorization: Bearer sk-your-key-here`. The provider's docs will tell you what to put here.

Click **Test** to verify the connection before saving. If it succeeds, you'll see the number of tools available. Click **Connect** to add it.

### Personal vs Organization scope

Two scopes are supported:

- **Personal** — only the signed-in user gets the tools. Stored as a user-scope setting.
- **Team** — everyone in the active organization gets the tools. Owners and admins can add; members see the list read-only. Stored as an org-scope setting.

Adds and removes hot-reload into the running MCP manager — no process restart, and no server restart. The new `mcp__<scope>-<name>__*` tools appear to the agent on the next message and are searchable via `tool-search`.

HTTPS URLs are accepted everywhere; plain `http://` is only allowed for `localhost` during development. Optional auth goes in as a Bearer token that's sent via `Authorization: Bearer …` on every request. OAuth-only providers, including Atlassian Rovo MCP, require the provider's OAuth flow instead of a static header.

### Use connected MCP and OAuth provider data in extensions

Extensions run in a sandboxed iframe and never receive connector URLs, OAuth
client secrets, access tokens, or refresh tokens. They can call the same
request-scoped action surface as the host app through the injected helpers:

```html
<div
  x-data="{ tools: [] }"
  x-init="
  agentNative.mcp.listTools().then(result => tools = result)
"
>
  <template x-for="tool in tools" :key="tool.serverId + ':' + tool.name">
    <p x-text="tool.title || tool.name"></p>
  </template>
</div>
```

To invoke a tool after inspecting its contract, use
`agentNative.mcp.callTool(serverId, toolName, arguments)`. For regular OAuth
provider connectors used by Analytics, Dispatch, Mail, Content, Calendar, and
other templates, use `agentNative.providerApi.catalog(...)` and
`agentNative.providerApi.docs(...)` to discover the granted provider API. Raw
`provider-api-request` is intentionally host/agent-only: exposing arbitrary
method/path requests to shared extensions would make an extension an
authenticated write proxy. Extensions should use `agentNative.mcp.callTool(...)`
or a purpose-built app action for bounded provider operations. The discovery
helpers are also available under `agentNative.connectors.mcp` and
`agentNative.connectors.providerApi`.

Local-file extensions must explicitly allow `list-mcp-tools`,
`call-mcp-tool`, and any explicitly supported provider action they use in
`extension.json`.
Database-backed extensions use the existing extension role and action gates.
Never pass a raw bearer token or arbitrary provider URL from extension code.

Under the hood these servers are persisted in the framework's `settings` table under the key `u:<email>:mcp-servers-remote` (Personal) or `o:<orgId>:mcp-servers-remote` (Team) and merged with `mcp.config.json` on startup.

### HTTP endpoints

| Method | Route                                                 | Purpose                                                                |
| ------ | ----------------------------------------------------- | ---------------------------------------------------------------------- |
| GET    | `/_agent-native/mcp/servers`                          | List the current user's personal + org servers with live status.       |
| POST   | `/_agent-native/mcp/servers`                          | Add a server. Body: `{ scope, name, url, headers?, description? }`.    |
| DELETE | `/_agent-native/mcp/servers/:id?scope=user\|org`      | Remove a server and reconfigure the manager.                           |
| POST   | `/_agent-native/mcp/servers/:id/test?scope=user\|org` | Dry-run the existing server's connect + list-tools.                    |
| POST   | `/_agent-native/mcp/servers/test`                     | Dry-run an arbitrary URL before persisting. Body: `{ url, headers? }`. |

<Endpoint id="doc-block-mcpc-servers" method="POST" path="/_agent-native/mcp/servers" summary="Add a remote MCP server for the current user or organization" auth="Authenticated session; org-scope writes require owner or admin." request={{
  "contentType": "application/json",
  "example": "{\n  \"scope\": \"user\",\n  \"name\": \"zapier\",\n  \"url\": \"https://mcp.zapier.com/s/abc123/mcp\",\n  \"headers\": { \"Authorization\": \"Bearer sk-your-key-here\" }\n}"
}} responses={[
  {
    "status": "200",
    "description": "Server saved and hot-reloaded into the running MCP manager; its tools appear to the agent on the next message.",
    "example": "{ \"id\": \"zapier\", \"scope\": \"user\", \"toolCount\": 6 }"
  },
  {
    "status": "400",
    "description": "Invalid URL (non-HTTPS and not localhost) or malformed headers."
  }
]}>

Adds a remote MCP server for `scope: "user"` (personal) or `scope: "org"` (team, owner/admin only). The addition hot-reloads into the running MCP manager — no restart — and the new `mcp__<scope>-<name>__*` tools become searchable via `tool-search` immediately. `DELETE /_agent-native/mcp/servers/:id?scope=user|org` removes one the same way.

</Endpoint>

Stdio servers are still a no-op outside Node runtimes, but remote HTTP MCP servers work in any environment with `fetch` — including desktop production builds.

## Shared MCP servers via a hub {#hub}

If your workspace runs multiple agent-native apps (e.g. dispatch + mail + clips), share MCP servers across all of them without per-app copy-pasting of URLs and bearer tokens. See [Multi-App Workspace](/docs/multi-app-workspace) for the full deployment picture.

### Recommended: Dispatch workspace MCP resources {#hub-recommended}

For new workspace setups, prefer **Dispatch workspace MCP resources** — the
same All-app vs selected-app grant model used by workspace skills,
instructions, and reference resources. Add a workspace resource with:

```json
{
  "type": "http",
  "url": "https://example.com/mcp",
  "headers": {
    "Authorization": "Bearer ${keys.MCP_SERVER_TOKEN}"
  },
  "description": "Shared MCP tools for workspace apps"
}
```

Save it under `mcp-servers/<name>.json` with kind `mcp-server`. All-app
resources are loaded by every workspace app; selected resources load only in
apps with an active Dispatch grant. Secret placeholders resolve from the app
secret store, so put raw bearer tokens in Dispatch Vault and reference them
with `${keys.NAME}` instead of storing them in the resource body.

Apps refresh their merged MCP config about once a minute, so central resource
edits, grant changes, and removals take effect without a deploy. Set
`AGENT_NATIVE_MCP_CONFIG_REFRESH_MS=0` to disable that background refresh, or
set it to a value of at least `5000` milliseconds to tune the interval.

### Legacy: self-hosted hub mode {#hub-legacy}

The mode below remains useful for coarse "share every org-scope MCP server
from Dispatch" setups and for deployments that already use the MCP settings UI
as the source of truth. You configure **one** app as the hub and the others
pull its org-scope MCP servers automatically. Dispatch is the conventional hub
— it already coordinates across apps.

<Diagram id="doc-block-1dnioze" title="Hub model: one app serves org-scope MCP servers" summary={"Dispatch holds the org-scope MCP servers; consumer apps pull and merge them as mcp__hub_<orgId>_<name>__*. Only org-scope rows are shared — personal credentials stay put."}>

```html
<div class="mcp-hub">
  <div class="diagram-panel center" data-rough>
    <span class="diagram-pill accent">Dispatch hub</span
    ><small class="diagram-muted">org-scope MCP servers</small
    ><small class="diagram-muted"
      ><code>GET /_agent-native/mcp/hub/servers</code></small
    >
  </div>
  <div class="diagram-col arrows">
    <div class="diagram-arrow diagram-muted" aria-hidden="true">&rarr;</div>
    <div class="diagram-arrow diagram-muted" aria-hidden="true">&rarr;</div>
  </div>
  <div class="diagram-col consumers">
    <div class="diagram-box" data-rough>
      Mail<br /><small class="diagram-muted"
        ><code>mcp__hub_&lt;orgId&gt;_&lt;name&gt;__*</code></small
      >
    </div>
    <div class="diagram-box" data-rough>
      Clips<br /><small class="diagram-muted">pull + merge each ~60s</small>
    </div>
  </div>
</div>
<p class="diagram-muted note">
  Bearer-gated by <code>AGENT_NATIVE_MCP_HUB_TOKEN</code>. Personal (user-scope)
  servers are never re-exposed.
</p>
```

```css
.mcp-hub {
  display: flex;
  align-items: center;
  gap: 14px;
  flex-wrap: wrap;
}
.mcp-hub .center {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
}
.mcp-hub .diagram-col {
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.mcp-hub .arrows .diagram-arrow {
  font-size: 22px;
  line-height: 1;
}
.mcp-hub .note {
  margin: 8px 0 0;
  font-size: 0.85em;
}
.mcp-hub code {
  font-size: 0.85em;
}
```

</Diagram>

### 1. Enable hub-serve on the hub app (dispatch)

Set an env var in dispatch's deployment:

```bash
AGENT_NATIVE_MCP_HUB_TOKEN=<a-long-random-secret>
```

Dispatch now mounts `GET /_agent-native/mcp/hub/servers` which returns every org-scope MCP server stored in its `settings` table, with full URL + headers, authenticated by the token.

### 2. Point consuming apps at the hub

Set on every consumer (mail, clips, whatever):

```bash
AGENT_NATIVE_MCP_HUB_URL=https://dispatch.acme.com
AGENT_NATIVE_MCP_HUB_TOKEN=<the-same-secret>
```

At startup, each consumer pulls the hub's server list and merges it into its own MCP manager. The tools appear to the agent as `mcp__hub_<orgId>_<name>__*` — distinct from the consumer's own local `mcp__org_…` so there's no collision.

### 3. What gets shared

Only **org-scope** servers are shared. User-scope (Personal) servers stay with the user who added them — the hub never re-exposes personal credentials across apps.

Hub responses include the full auth headers (Bearer tokens etc). The transport is HTTPS, the endpoint requires the shared secret, and it only returns org-scope rows — treat the hub URL + token like a database credential.

### 4. Hot reload vs restart

Local UI adds in each app hot-reload via `McpClientManager.reconfigure()` — no restart. Hub-sourced servers are picked up by the same periodic background refresh (approximately 60 s, tunable or disableable via `AGENT_NATIVE_MCP_CONFIG_REFRESH_MS`) that the workspace resource path uses, so changes made in Dispatch propagate to all consumer apps within about a minute without a restart. Additionally, any local mutation in a consumer app immediately triggers a reconfigure for that app.

### Endpoints summary

| Method | Route                            | Purpose                                                                                                            |
| ------ | -------------------------------- | ------------------------------------------------------------------------------------------------------------------ |
| GET    | `/_agent-native/mcp/hub/servers` | Serve all org-scope servers with full creds (bearer-gated, only mounted when `AGENT_NATIVE_MCP_HUB_TOKEN` is set). |
| GET    | `/_agent-native/mcp/hub/status`  | Returns `{ serving, consuming, hubUrl }` for the settings UI card.                                                 |

## Status route {#status-route}

Every app exposes `GET /_agent-native/mcp/status` for tooling and onboarding:

<Endpoint id="doc-block-zrfvma" method="GET" path="/_agent-native/mcp/status" summary="MCP client status for tooling and onboarding" responses={[
  {
    "status": "200",
    "description": "Configured vs connected servers, tool inventory, and per-server errors.",
    "example": "{\n  \"configuredServers\": [\"claude-in-chrome\", \"playwright\"],\n  \"connectedServers\": [\"claude-in-chrome\", \"playwright\"],\n  \"totalTools\": 21,\n  \"tools\": [\n    {\n      \"source\": \"claude-in-chrome\",\n      \"name\": \"mcp__claude-in-chrome__navigate\",\n      \"description\": \"Navigate the browser to a URL\"\n    }\n  ],\n  \"errors\": {}\n}"
  }
]}>

Reports which configured servers connected, the total live tool count, the merged prefixed tool list, and any per-server connection errors. Use it to build "detected — your agent can now drive X" hints (e.g. "claude-in-chrome detected — your agent can now drive Chrome") or to debug connection problems.

</Endpoint>

## Failure modes {#failures}

Individual MCP server failures never take down the agent:

- A misconfigured `command` → the server is skipped, its error appears in `/_agent-native/mcp/status` under `errors.<server-id>`, and every other server continues to work.
- The MCP SDK is missing from `node_modules` → all MCP functionality is skipped with a warning; agent chat keeps working with zero MCP tools.
- Running in an edge runtime → MCP client is a no-op.

Agent-native will always boot; broken MCP configuration just means fewer tools.

## Security {#security}

MCP tools run on your machine with whatever permissions the spawned process has. Treat `mcp.config.json` like any other list of executables you're willing to let the agent drive. Tools from MCP servers appear in the agent's tool-use loop just like your template's own actions, so make sure you trust every server you configure.

## What's next {#whats-next}

- [**MCP Server**](/docs/mcp-protocol) — the opposite direction: making your app an MCP server other hosts consume
- [**External Agents**](/docs/external-agents) — connecting Claude, Cursor, and other hosts to your app
- [**Multi-App Workspace**](/docs/multi-app-workspace) — the shared-resource model behind Dispatch workspace MCP resources
- [**Actions**](/docs/actions) — how your own actions show up alongside MCP tools in the agent's registry
