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

# MCP servers

> Upsert MCP server entries into agent configs without clobbering them.

An **MCP server** is a process that speaks the [Model Context Protocol](https://modelcontextprotocol.io). Coding agents that support MCP read a JSON config that lists the servers to launch and how to reach them.

gaal manages those entries declaratively: you describe each server once in `gaal.yaml` and gaal upserts it into the right JSON file for every agent that should see it. The destination path is resolved automatically from the [agent registry](/agents/overview) — you no longer have to spell it out.

## The upsert guarantee

Every agent's MCP config lives inside a larger config file. Claude Code stores MCP servers in `~/.claude.json`; VS Code-family agents use `~/.vscode/settings.json`; Codex uses `~/.codex/config.toml`. You can't safely overwrite the whole file.

gaal reads the target JSON, modifies the `mcpServers` object in place, and writes it back. Other top-level keys are preserved exactly. That's the upsert guarantee: gaal never clobbers a config it didn't author.

## Targeting agents, not paths

Each `mcps[]` entry says **which agents** to install the server in, and **which scope** to use. gaal looks up the destination JSON file in the registry.

```yaml theme={"theme":"nord"}
mcps:
  - name: filesystem
    agents: [claude-code, cursor, codex]   # explicit list
    global: true                            # write to each agent's user-global MCP config
    inline:
      command: uvx
      args: [mcp-server-filesystem, ~/projects]
```

`["*"]` is a wildcard that resolves at sync time to every registered agent that has a non-empty MCP config for the requested scope. Agents that don't expose an MCP config are skipped silently.

```yaml theme={"theme":"nord"}
mcps:
  - name: git
    agents: ["*"]
    global: true
    inline:
      command: uvx
      args: [mcp-server-git, --repository, ~/projects/gaal]
```

## Scope: `global` vs project

| `global`          | Where the entry is written                                                                                |
| ----------------- | --------------------------------------------------------------------------------------------------------- |
| `true`            | The agent's **user-global** MCP config (`global_mcp_config_file` in the registry, e.g. `~/.claude.json`). |
| `false` (default) | The agent's **project-scoped** MCP config (`project_mcp_config_file`).                                    |

In the current registry every built-in agent stores its MCP entries in a single user-global file. Project-scoped MCP configs are reserved for future agents that adopt them. **Set `global: true` for every entry today** — `global: false` is a no-op for now.

## Two ways to define a server

### Inline

The server spec lives directly in `gaal.yaml`. Stdio servers use `command` + `args` + `env`.

```yaml theme={"theme":"nord"}
mcps:
  - name: filesystem
    agents: [claude-code]
    global: true
    inline:
      command: uvx
      args: [mcp-server-filesystem, ~/projects]
      env:
        FOO: bar
```

### Remote source

For configs maintained elsewhere, point at a URL that returns an `mcpServers` document. gaal downloads the JSON and merges the entry whose key matches `name` into each target.

```yaml theme={"theme":"nord"}
mcps:
  - name: github
    source: https://raw.githubusercontent.com/github/mcp-servers/main/config.json
    agents: [claude-code, github-copilot]
    global: true
```

`source` and `inline` are mutually exclusive.

## HTTP and SSE servers

The MCP spec defines two remote transports: Streamable HTTP and the older HTTP+SSE. gaal can write native remote entries for agents that support them.

```yaml theme={"theme":"nord"}
mcps:
  - name: linear
    agents: [claude-code, cursor]
    global: true
    inline:
      type: http
      url: https://mcp.linear.app/mcp
      headers:
        Authorization:
          env: LINEAR_API_KEY

  - name: sentry
    agents: [claude-code]
    global: true
    inline:
      type: sse
      url: https://mcp.sentry.dev/sse
```

If an agent does not support native remote MCP entries yet, use a stdio bridge such as [`mcp-remote`](https://www.npmjs.com/package/mcp-remote) under `command` and `args`.

## Behaviour during sync

* The target JSON is updated in place; the named entry is added or refreshed under `mcpServers`.
* Other top-level keys in the target file are preserved.
* Other entries inside `mcpServers` that gaal didn't author are preserved.
* Removing an `mcps[]` entry from `gaal.yaml` does **not** remove it from the target file unless you pass `--prune`.
* If the target's parent directory is missing, the entry is skipped — gaal never creates an agent's config directory as a side effect.

## Behaviour with `--prune`

`gaal sync --prune` removes any `mcpServers` entries from gaal-managed targets that aren't in `gaal.yaml`. It only touches keys gaal could plausibly own; your other settings and other servers stay untouched. See [Pruning](/workflows/pruning) for the exact algorithm.

## Migrating from `target:`

Earlier versions required a `target:` path on every entry. The field is **deprecated** but still honoured for backward compatibility — gaal logs a warning when it sees one. Replace it with `agents:` + `global:` so the registry resolves the path. To install in more than one agent, list them all in the same entry instead of duplicating it.

```yaml theme={"theme":"nord"}
# Before — explicit path, one entry per agent
mcps:
  - name: filesystem
    target: ~/.claude.json
    inline:
      command: uvx
      args: [mcp-server-filesystem, ~/projects]

# After — one entry, registry-resolved, fan-out via agents:
mcps:
  - name: filesystem
    agents: [claude-code, cursor]
    global: true
    inline:
      command: uvx
      args: [mcp-server-filesystem, ~/projects]
```

## Related

<CardGroup cols={2}>
  <Card title="Configure MCP servers" icon="gear" href="/configure/mcp-servers" />

  <Card title="Agent integrations" icon="robot" href="/agents/overview" />

  <Card title="Pruning" icon="scissors" href="/workflows/pruning" />

  <Card title="Schema: mcps" icon="file-code" href="/schema/mcps" />
</CardGroup>
