# Stop Copy-Pasting MCP Configs: How AgentSync Keeps All Your AI Coding Agents in Sync

> Sync MCP server configs across Claude Code, Cursor, Codex, and Gemini with one command. AgentSync CLI: single source of truth, JSON/TOML/MDC format conversion, deduplication, backups.
> Author: Roman Belov · Published: 2026-02-20 · Source: https://futurecraft.pro/blog/agentsync-mcp-config-sync/

If you work with more than one AI coding agent, you already know the friction. You add a new MCP server to Claude Code, then you have to replicate that change to Cursor, then Codex, then Gemini. Each stores its config in a different format, location, and convention. Miss one and the agent silently fails to find the server. Multiply that by every MCP server in your stack and you have a maintenance problem that scales linearly with the number of tools you use.

**agentsync** is a CLI tool that solves this. It reads your Claude Code configuration as the single source of truth and pushes it to every other agent with one command. JSON to TOML conversion, Markdown to MDC transformation, case-insensitive deduplication -- all handled automatically.

Below: the problem, the fix, and how it works internally.

## The Problem: Config Drift Across AI Agents

The Model Context Protocol (MCP) is becoming the standard way AI coding agents talk to external tools -- databases, APIs, documentation services, monitoring systems. A typical project might have 10-20 MCP servers configured: Supabase, GitHub, Linear, Notion, Sentry, Cloudflare, and so on.

The catch is that every agent has its own opinion about where and how to store this list:

- **Claude Code** uses `.mcp.json` and `~/.claude.json` (JSON), plus `CLAUDE.md` for rules.
- **Cursor** uses `~/.cursor/mcp.json` (JSON) and `.cursor/rules/project.mdc` (MDC with YAML frontmatter).
- **Codex** uses `~/.codex/config.toml` (TOML) and `AGENTS.md` (Markdown).
- **Antigravity/Gemini** uses its own JSON format and only supports stdio-based servers.

When you add a server to one agent, you need to manually replicate the change to three others. When you remove one, same story. When you rename one, or change an environment variable, you touch four files in three different formats. Forget one and you get a silent failure -- the agent just doesn't see the server.

This isn't a theoretical concern. If you have `Notion` defined in your global Claude config and `notion` (lowercase) in your project `.mcp.json`, you now have a case-sensitivity bug that causes duplicate entries in some agents and missing entries in others. These are the kinds of problems that waste 20 minutes of debugging when you could be shipping code.

## The Solution: One Source of Truth, One Command

agentsync treats your Claude Code configuration as the canonical source and generates configs for every other agent:

```
pip install agentsync-cli
agentsync init       # creates agentsync.yaml
agentsync sync       # syncs to all agents
agentsync validate   # checks everything matches
```

Here's the data flow:

```
+--------------+
|  Claude Code |  Source of Truth
|  .claude.json|  --- MCP Servers
|  .mcp.json   |  --- Rules (CLAUDE.md)
|  CLAUDE.md   |
+------+-------+
       |  agentsync sync
       +------------------+-----------------+
       v                  v                 v
+--------------+  +--------------+  +--------------+
|    Cursor    |  |    Codex     |  |  Antigravity |
|  mcp.json   |  | config.toml  |  |mcp_config.json|
| project.mdc |  |  AGENTS.md   |  |              |
+--------------+  +--------------+  +--------------+
```

We picked Claude Code as the source because it has the most complete configuration model -- three-tier MCP server merging (global, project-specific, local override) plus Markdown-based rules. Everything else can be derived from it.

## Quick Start

### Install

Pick your preferred Python package manager:

```bash
pip install agentsync-cli       # pip
pipx install agentsync-cli      # pipx (recommended for CLI tools)
uvx agentsync-cli               # uv (run without installing)
```

Requires Python 3.9 or newer. The only runtime dependencies are Click, PyYAML, and Rich -- no heavy frameworks.

### Initialize

Run `agentsync init` in your project root. This creates an `agentsync.yaml` file with sensible defaults:

```yaml
version: 1

source:
  type: claude
  global_config: ~/.claude.json
  project_mcp: .mcp.json
  rules_file: CLAUDE.md

targets:
  cursor:
    type: cursor
    mcp_path: ~/.cursor/mcp.json
    rules_path: .cursor/rules/project.mdc
    rules_format: mdc
    exclude_servers: []

  codex:
    type: codex
    config_path: ~/.codex/config.toml
    rules_path: AGENTS.md
    rules_format: md
    exclude_servers:
      - codex       # Codex can't call itself

  antigravity:
    type: antigravity
    mcp_path: ~/.gemini/antigravity/mcp_config.json
    protocols:
      - stdio       # Only stdio servers (no HTTP)
    exclude_servers: []

rules:
  exclude_sections:
    - "MCP Servers"
    - "Context Management & Agents"

sync:
  backup: true
  backup_dir: .agentsync/backups
  log_dir: .agentsync/logs
```

Edit this to match your setup. The key decisions are:

- **Which servers to exclude per target.** Codex shouldn't have its own MCP server in its config (it can't call itself). Some agents may not support HTTP-based servers.
- **Which rules sections to exclude.** Sections like "MCP Servers" or "Context Management & Agents" in your CLAUDE.md are Claude-specific and shouldn't leak into other agents' rules files.
- **Protocol filtering.** Antigravity/Gemini only supports stdio servers, so HTTP servers are filtered out automatically when you set `protocols: [stdio]`.

### Sync

```bash
agentsync sync                  # Full sync (MCP + rules)
agentsync sync --dry-run        # Preview changes without writing
agentsync sync --mcp-only       # Only MCP server configs
agentsync sync --rules-only     # Only rules files
agentsync sync -t cursor        # Sync specific target only
agentsync sync --no-backup      # Skip creating backup files
```

Use `--dry-run` the first time -- it shows exactly what would change without writing anything.

### Validate

After syncing, run validation to confirm everything is consistent:

```bash
agentsync validate              # Full validation
agentsync validate -v           # Verbose (show passed checks too)
agentsync validate -t codex     # Validate specific target only
```

Validation checks three things: server consistency (are all expected servers present in the target?), excluded section leaks (did any Claude-specific content slip through?), and case-insensitive duplicates (is `Notion` colliding with `notion`?).

### Status

```bash
agentsync status
```

This shows your source config health, the number of loaded servers, and whether each target is in sync or has drifted.

## How the Sync Pipeline Works

When you run `agentsync sync`, here's what happens step by step:

```
agentsync sync
  |
  +-- Load config (agentsync.yaml)
  +-- Read source (Claude Code)
  |   +-- ~/.claude.json         -> global MCP servers
  |   +-- ~/.claude.json         -> project-specific MCP servers
  |   +-- .mcp.json              -> local project override
  |   +-- CLAUDE.md              -> rules sections
  |
  +-- Deduplicate (case-insensitive)
  +-- Filter (exclude_servers, exclude_sections, protocols)
  |
  +-- Generate + Write per target
      +-- Cursor:       mcp.json + project.mdc (MDC frontmatter)
      +-- Codex:        config.toml (marker-based) + AGENTS.md
      +-- Antigravity:  mcp_config.json (stdio-only)
```

**Three-tier MCP merge.** Claude Code layers its config: global servers from `~/.claude.json` form the base, project-specific servers override those, and your local `.mcp.json` wins over both. agentsync follows the same precedence.

**Case-insensitive deduplication.** After merging, the engine normalizes all server names to lowercase and deduplicates. If your global config has `Notion` and your local `.mcp.json` has `notion`, the local one wins. The tool logs these merges so you can audit what happened.

**Per-target filtering.** Each target can exclude specific servers (via `exclude_servers`) and filter by protocol (via `protocols`). For instance, Codex excludes itself, and Antigravity only gets stdio-based servers.

**Format conversion.** Cursor gets JSON. Codex gets TOML with marker-based insertion -- existing content in `config.toml` is preserved, and agentsync only manages the block between `# === AGENTSYNC START ===` and `# === AGENTSYNC END ===` markers. Antigravity gets a simple JSON file. Rules go through Markdown section parsing and filtering, with optional MDC frontmatter generation for Cursor.

**Automatic backups.** Before every write, agentsync creates a timestamped backup of the existing file in `.agentsync/backups/`. This can be disabled with `--no-backup` or `sync.backup: false` in the config.

## Architecture: Adapters All the Way Down

agentsync is built on an adapter pattern. There's a clean separation between the sync engine (which handles orchestration, deduplication, and filtering) and the adapters (which handle format-specific reading and writing).

```
src/agentsync/
+-- adapters/           # Source and target adapters
|   +-- base.py         # Abstract base classes (SourceAdapter, TargetAdapter)
|   +-- claude.py       # Claude Code source adapter
|   +-- cursor.py       # Cursor target adapter
|   +-- codex.py        # Codex target adapter
|   +-- antigravity.py  # Antigravity/Gemini target adapter
+-- utils/              # Shared utilities
|   +-- backup.py       # File backup before writes
|   +-- dedup.py        # Case-insensitive deduplication
|   +-- diff.py         # Server diff display
|   +-- io.py           # File writing with WriteResult
|   +-- markdown.py     # Markdown section parsing and filtering
|   +-- output.py       # Rich CLI output (tables, summaries)
+-- cli.py              # Click CLI commands (sync, validate, init, status)
+-- config.py           # YAML config loading and validation
+-- sync.py             # Sync orchestrator
+-- validate.py         # Validation orchestrator
```

The two base classes define the contract:

```python
class SourceAdapter(ABC):
    @abstractmethod
    def load_servers(self) -> dict[str, ServerConfig]: ...
    @abstractmethod
    def load_rules(self) -> list[Section]: ...

class TargetAdapter(ABC):
    @abstractmethod
    def generate_mcp(self, servers: dict[str, ServerConfig]) -> str | dict: ...
    @abstractmethod
    def generate_rules(self, sections: list[Section]) -> str: ...
    @abstractmethod
    def write(self, dry_run: bool = False) -> list[WriteResult]: ...
    @abstractmethod
    def validate(self) -> list[ValidationResult]: ...
```

Adding a new agent means implementing `TargetAdapter` (or `SourceAdapter` if you want a different source of truth). The sync engine doesn't care about format specifics -- it works with `ServerConfig` and `Section` objects, and each adapter handles serialization.

## Adding a New Agent Adapter

Want to add support for Windsurf, Zed, Cline, or any other agent? Here's how:

1. Create `src/agentsync/adapters/youragent.py` and implement `TargetAdapter`.
2. Register it in `cli.py` (the `create_targets` function).
3. Add the type string to `KNOWN_TARGET_TYPES` in `config.py`.
4. Write tests in `tests/test_adapter_youragent.py`.
5. Update the README.

The Antigravity adapter is the simplest reference implementation at around 100 lines. It only handles MCP server config (no rules), generates JSON, and filters by protocol. A good starting point if you're adding a JSON-based agent.

The Codex adapter is more interesting if your target uses TOML or needs marker-based insertion into existing files.

## Testing and CI/CD

192 tests, 97% coverage. Tests use pytest with `tmp_path` fixtures -- they never touch real user files. Every adapter and utility has its own test module.

CI runs on GitHub Actions with a matrix across Python 3.9 through 3.13 on both Ubuntu and macOS. The pipeline runs ruff (lint + format), mypy (type checking), and the full test suite with coverage reporting.

Releases use PyPI trusted publisher flow -- push a version tag, and GitHub Actions builds the package and publishes it to PyPI without any stored API tokens. Dependabot keeps deps current.

```bash
# Run tests locally
pytest                      # All tests
pytest -v                   # Verbose
pytest --cov=agentsync      # With coverage report
```

## Exit Codes

agentsync follows Unix conventions for exit codes, so you can plug them into scripts and CI pipelines:

| Code | Meaning |
|------|---------|
| `0`  | Success |
| `1`  | Runtime error (sync failed, validation failed) |
| `2`  | Configuration error (missing config, bad YAML, unknown adapter) |

## Contributing

agentsync is MIT-licensed and open source. New agent adapters are the easiest way to contribute.

Setup takes about a minute:

```bash
git clone https://github.com/spyrae/agentsync.git
cd agentsync
python -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"
pytest
```

ruff (lint + format), mypy (type checking), and the test suite enforce code quality. All three must pass before merging.

If you have an agent you want supported, you can either open a [feature request](https://github.com/spyrae/agentsync/issues/new?template=new_adapter.yml) or submit a PR with the adapter yourself. The adapter interface is intentionally small -- four methods for a target adapter -- so most implementations are under 150 lines.

## Links

- **GitHub:** [https://github.com/spyrae/agentsync](https://github.com/spyrae/agentsync)
- **PyPI:** [https://pypi.org/project/agentsync-cli/](https://pypi.org/project/agentsync-cli/)
- **Install:** `pip install agentsync-cli`
- **License:** MIT
- **Author:** [Spyrae](https://github.com/spyrae)

---

*agentsync is built by Spyrae and released under the MIT license. If you use multiple AI coding agents and you're tired of keeping their MCP configs in sync manually, give it a try. Bug reports, feature requests, and adapter PRs are all welcome.*

## Related Reading

- [MCP in Production: From Setup to Custom Servers](/blog/mcp-production-custom-servers/) — how to build and run custom MCP servers that agentsync keeps in sync across agents
- [Multi-Agent Architecture: When One AI Isn't Enough](/blog/multi-agent-architecture/) — designing systems where multiple agents collaborate, each needing their own MCP config
- [Context Engineering Guide](/blog/context-engineering-guide/) — structuring context for LLMs, including how MCP servers feed context to agents
- [LLM Observability with Langfuse](/blog/llm-observability-langfuse/) — monitoring the LLM calls that MCP-connected agents produce

---

*Need help setting up MCP infrastructure or syncing AI agent configs across your team? I help startups build AI products and automate processes — [belov.works](https://belov.works).*
