Skip to main content

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.

An MCP server is a process that speaks the Model Context Protocol. 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 — 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.
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.
mcps:
  - name: git
    agents: ["*"]
    global: true
    inline:
      command: uvx
      args: [mcp-server-git, --repository, ~/projects/gaal]

Scope: global vs project

globalWhere the entry is written
trueThe 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 todayglobal: 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.
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.
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.
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 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 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.
# 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]

Configure MCP servers

Agent integrations

Pruning

Schema: mcps