Skip to content
中文

Installing an MCP server: per-agent format translation

Claude Code keeps your MCP servers in ~/.claude.json, as JSON under mcpServers. Codex keeps them in ~/.codex/config.toml, in TOML, with one [mcp_servers.<name>] section per server. Hermes uses YAML, and OpenCode uses its own JSON shape. The same server has to be written a different way for each agent.

  • Claude Code~/.claude.json, JSON

    "mcpServers": {
      "git": {
        "command": "uvx",
        "args": ["mcp-server-git"]
      }
    }
  • Codex~/.codex/config.toml, TOML

    [mcp_servers.git]
    command = "uvx"
    args = ["mcp-server-git"]
  • Gemini CLI~/.gemini/settings.json, JSON

    "mcpServers": {
      "git": {
        "command": "uvx",
        "args": ["mcp-server-git"]
      }
    }
  • OpenCode~/.config/opencode/opencode.json, JSONC

    "mcp": {
      "git": {
        "type": "local",
        "command": ["uvx", "mcp-server-git"]
      }
    }
  • Hermes~/.hermes/config.yaml, YAML

    mcp_servers:
      git:
        command: uvx
        args: [mcp-server-git]
The same local server in five agents' config files, in four formats. The highlights mark what differs.
  1. Read. HarnessKit finds the server in the source agent’s config file for that scope. A local server carries its command, arguments and environment variables. A remote server carries its URL and headers.
  2. Check. If the target can’t load the server’s transport, HarnessKit stops here. See Local and remote servers.
  3. Translate. HarnessKit builds the entry in the target agent’s format.
  4. Write. It adds the entry to the target’s config file. An agent that already has a server with that name in that scope is skipped. With Overwrite existing copies, most agents get the entry replaced instead. Grok Build and OpenClaw keep the old entry’s other keys, and DeepSeek Harness refuses the install.

Install to agents on the Extensions page runs these steps for several servers and agents at once, as described in Installing a skill.

Here is a local GitHub server in Claude Code:

~/.claude.json
{
"mcpServers": {
"github": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-github"],
"env": { "GITHUB_PERSONAL_ACCESS_TOKEN": "ghp_…" }
}
}
}

After you install it to Codex, Codex’s config file gains this table:

~/.codex/config.toml
[mcp_servers.github]
args = [
"-y",
"@modelcontextprotocol/server-github",
]
command = "npx"
[mcp_servers.github.env]
GITHUB_PERSONAL_ACCESS_TOKEN = "ghp_…"

Codex and DeepSeek Harness allow only letters, digits, _ and - in server names, and HarnessKit writes Grok Build’s names the same way. It replaces any other character with -, so microsoft/markitdown becomes microsoft-markitdown. DeepSeek Harness names are also cut to 32 characters. All three keep the original name in an _hk_name key, so HarnessKit still groups the server with its copies in other agents.

Antigravity and Devin Desktop are desktop apps that may not see your shell’s PATH. For them, HarnessKit replaces the command with its full path, such as /opt/homebrew/bin/npx. It also adds a PATH variable that includes that command’s folder, unless the entry already sets one.

A remote server is one the agent reaches by URL, over Streamable HTTP or the older SSE transport. Agents spell remote entries differently. Claude Code’s entries use type and url, Gemini CLI’s use httpUrl or url, and Devin Desktop’s use serverUrl. Codex’s use url, with headers under http_headers.

Some agents can’t load every remote server:

  • Codex, DeepSeek Harness and Pi accept Streamable HTTP only, so HarnessKit refuses an SSE server for them.
  • OpenClaw accepts no remote servers from HarnessKit yet.

For these agents, the Install to Agent tile is greyed out, and its tooltip names the transport the agent lacks. HarnessKit checks again before it writes.

Hermes, Kiro, Oh My Pi, DeepSeek Harness, Grok Build, OpenClaw and Pi have their own off switch for each server. HarnessKit uses it and leaves the entry in place.

The other agents have no switch that HarnessKit uses. There, disabling removes the entry from the agent’s config and stores a snapshot, an exact copy of the entry, in HarnessKit’s database. Enabling writes the copy back and deletes it from the database.

HarnessKit copies environment variables and headers as they are, tokens included. The detail panel shows each value as ****. A disabled server’s snapshot keeps its secrets. The database zeroes their bytes when the snapshot is deleted. A backup that HarnessKit made before a schema upgrade still keeps any secrets it held then.

HarnessKit 1.10.0 and earlier stored <redacted> in a snapshot in place of each secret. If you re-enable one of those servers, HarnessKit warns you and names the keys to fill in again.

  • crates/hk-core/src/adapter/mod.rs defines the config formats and the defaults that each agent’s own file in that folder overrides.
  • crates/hk-core/src/deployer.rs has one writer per format and refuses a transport the target can’t load.
  • crates/hk-core/src/service.rs finds the source entry, adds the command path for desktop agents, and masks secrets in the detail panel.
  • crates/hk-core/src/manager.rs enables and disables, natively or by remove and snapshot.
  • crates/hk-core/src/kits/install_plan.rs is the conflict check that only Kits run.