A community-driven registry for the Claude Code ecosystem. Not affiliated with Anthropic.
Are you the author? Sign in to claim
Universal MCP Sync (usync) is a local-first MCP configuration manager for developers who use multiple AI clients.
Universal MCP Sync (usync) is a local-first MCP configuration manager for developers who use multiple AI clients.
Configure an MCP server once, preview every file that would change, then sync native client config files for Claude Desktop, Claude Code, Cursor, VS Code, Windsurf, Zed, Roo Code, OpenCode, Kiro, Gemini CLI, Antigravity, and Codex CLI.
[!IMPORTANT] Help grow the supported MCP list. If you maintain or rely on an MCP server, add it as a provider instead of documenting manual JSON edits. Start with Adding an MCP Provider, implement the
MCPProvidercontract, register it, and cover the client matrix with tests.Contributor baseline before a provider PR:
make fmt,make test, andmake gitignore-check. For provider/client compatibility changes, also runmake lintandmake verify.
| MCP server | Capability | Transport | Auth shape | Status |
|---|---|---|---|---|
| Exa AI Search | Web search and retrieval for agents | HTTP | API key in URL query | Stable |
| Context7 | Current library docs and code examples | Streamable HTTP | CONTEXT7_API_KEY header | Stable |
| GitHub | Repository, issue, and PR workflows | Stdio via npx | GITHUB_PERSONAL_ACCESS_TOKEN env var | Beta |
| Tavily Search | Real-time web search and data extraction | Stdio via npx | TAVILY_API_KEY env var | Stable |
| Playwright | Browser automation through accessibility snapshots | Stdio via npx | None | Stable |
| Kubernetes | Read-only Kubernetes and OpenShift runtime state | Stdio via npx | None; uses kubeconfig/RBAC | Beta |
| Terraform | Terraform Registry and HCP Terraform context | Stdio via Docker | None required; operations disabled by default | Beta |
The provider system is intentionally generic. New MCP servers are added through MCPProvider, then adapted per client through the capability matrix instead of branching the TUI or apply flow.
MCP client configuration is fragmented. Each AI client stores different JSON or TOML, uses different root keys, and handles transports differently. Manually copying credentials into those files is slow, hard to review, and easy to get wrong.
[!NOTE] Terraform-inspired:
usyncborrows Terraform's provider pattern andinit -> plan -> applyworkflow. The core setup, preview, and apply path stays generic while each MCP provider owns its credentials, validation, and generated transport config.
usync focuses on the native-config sync path:
mcpServers, servers, context_servers, httpUrl, serverUrl, TOML, and stdio bridges.macOS with Homebrew:
brew tap nawodyaishan/homebrew-tap
brew install usync
From source:
git clone https://github.com/nawodyaishan/universal-mcp-sync
cd universal-mcp-sync
make build
./bin/usync --help
Requirements for source builds:
Run usync to open the interactive dashboard:
usync
If you built from source:
./bin/usync
The first screen lets you choose between two workflows:
Doctor Mode is the recommended default for real machines because it starts from the current system state. Wizard Mode is still useful for a fast provider-first setup or test fixture flow.
Start from the dashboard and choose Doctor Mode:
usync
Doctor Mode walks through:
For a read-only terminal report without launching the TUI:
usync doctor
usync doctor --verbose
usync doctor --json
Useful filters:
usync doctor --clients cursor,vscode,codex-cli
usync doctor --workspace /path/to/project
usync doctor --no-runtimes
usync doctor exits with code 2 when it finds warnings, conflicts, missing runtimes, malformed config, or other actionable findings.
Open the guided setup wizard directly:
usync --wizard
Wizard Mode lets you choose a provider, enter credentials, select clients, assign credential profiles, preview the plan, and apply when ready. It uses the same provider architecture and apply safeguards as the rest of the app.
For automation, use the saved-plan flow. It is provider-neutral and mirrors the interactive Doctor Mode pipeline.
Create a plan for selected targets:
usync plan \
--provider exa \
--keys-file ./exa_keys.txt \
--targets cursor,vscode,codex-cli \
--out ./usync-plan.json
Or let Doctor Mode discovery select every high/medium-confidence target:
usync plan \
--provider exa \
--keys-file ./exa_keys.txt \
--all-detected \
--out ./usync-plan.json
Review the saved plan:
usync show ./usync-plan.json
Dry-run the apply preflight:
usync apply --plan ./usync-plan.json --dry-run
Apply only after the preview is correct:
usync apply --plan ./usync-plan.json
Use --auto-approve only in trusted automation after reviewing the plan:
usync apply --plan ./usync-plan.json --auto-approve
The older Exa-only compatibility path still works:
usync sync --keys-file ./exa_keys.txt --dry-run
Example redacted preview:
MCP sync plan
=============
- Claude Desktop: Claude Desktop config
credential: exa_****abcd
path: ~/Library/Application Support/Claude/claude_desktop_config.json
backup: .../claude_desktop_config.json.bak-usync-20260509-084228
Apply with the compatibility path:
usync sync --keys-file ./exa_keys.txt --apply
usync detects and updates native config files for these macOS and Linux targets:
| Client | macOS target | Linux target |
|---|---|---|
| Claude Desktop | ~/Library/Application Support/Claude/claude_desktop_config.json | ~/.config/Claude/claude_desktop_config.json |
| Claude Code | Managed through claude mcp CLI when available | Managed through claude mcp CLI when available |
| Cursor | ~/.cursor/mcp.json | ~/.cursor/mcp.json |
| VS Code | ~/.vscode/mcp.json | ~/.config/Code/User/mcp.json |
| Windsurf | ~/.codeium/windsurf/mcp_config.json | ~/.codeium/mcp_config.json, with existing ~/.codeium/windsurf/mcp_config.json preserved |
| Zed | ~/.config/zed/settings.json | ~/.config/zed/settings.json |
| Roo Code | ~/Library/Application Support/Code/User/globalStorage/saoudrizwan.claude-dev/settings/mcp_settings.json | ~/.config/Code/User/globalStorage/saoudrizwan.claude-dev/settings/mcp_settings.json |
| OpenCode | ~/.opencode.json | ~/.config/opencode/opencode.json |
| Kiro | ~/.kiro/settings/mcp.json | ~/.kiro/settings/mcp.json |
| Gemini CLI | ~/.gemini/settings.json and ~/.gemini/mcp_config.json | ~/.gemini/settings.json |
| Antigravity | ~/.gemini/config/mcp_config.json | ~/.gemini/config/mcp_config.json |
| Codex CLI | ~/.codex/config.toml | ~/.codex/config.toml |
A dry run always shows the exact path on your machine before any write.
Several MCP tools solve adjacent problems:
usync is intentionally different: it writes each AI client's native MCP configuration directly. That keeps the runtime path simple for users who want no always-on gateway, while still adding reviewability, credential redaction, backups, and rollback around local config edits.
usync doctor scan clients, runtimes, paths, and conflicts before planning writes.usync plan and usync apply --plan separate decision-making from mutation and check stale plans before apply.usync attempts to restore previous files.make coverage-check enforcing the 60% coverage gate (68.2% in the latest local run).flowchart TB
subgraph entry["Entry Points"]
cli["cmd/usync<br/>doctor / plan / apply / sync"]
tui["pkg/tui<br/>Doctor Mode dashboard / Wizard Mode"]
end
subgraph orchestration["Orchestration"]
manager["pkg/app.Manager<br/>PrepareProvider / Apply"]
plan["ExecutionPlan<br/>operations + warnings"]
result["ApplyResult<br/>backups + verification + rollback state"]
end
subgraph providerLayer["Provider Layer"]
registry["pkg/provider.Registry<br/>DefaultRegistry"]
providerAPI["MCPProvider interface<br/>credentials -> MCPConfig"]
exa["Exa provider<br/>pkg/exa helpers"]
context7["Context7 provider<br/>pkg/context7 helpers"]
github["GitHub provider<br/>stdio npx + env"]
end
subgraph clientLayer["Client Compatibility"]
matrix["pkg/client.Matrix<br/>transport support"]
adapt["pkg/client.Adapt<br/>bridges remote -> stdio when needed"]
headers["pkg/client.HeadersFor<br/>client-specific HTTP headers"]
end
subgraph configLayer["Config Persistence"]
paths["pkg/config.DetectAppConfigs<br/>target paths + file kinds"]
json["pkg/config JSON writers<br/>mcpServers / servers / context_servers"]
toml["pkg/config TOML writer<br/>Codex config"]
backup["WriteWithBackup<br/>private perms + atomic replace"]
rollback["rollback<br/>restore previous write outcomes"]
end
subgraph safety["Safety + Output"]
redact["pkg/redact<br/>keys, URLs, headers, args"]
verify["pkg/verify<br/>file and CLI verification"]
format["FormatPlan / FormatApplyResult<br/>redacted terminal output"]
end
subgraph clients["Native Client Configs"]
claude["Claude Desktop / Claude Code"]
editors["Cursor / VS Code / Windsurf / Zed / Roo Code"]
agents["OpenCode / Kiro / Gemini CLI / Antigravity / Codex CLI"]
end
cli --> manager
tui --> manager
manager --> paths
manager --> registry
registry --> providerAPI
providerAPI --> exa
providerAPI --> context7
providerAPI --> github
exa --> manager
context7 --> manager
github --> manager
manager --> matrix
matrix --> adapt
adapt --> headers
headers --> plan
plan --> format
format --> redact
plan --> manager
manager --> json
manager --> toml
manager --> backup
backup --> rollback
backup --> clients
clients --> verify
verify --> result
rollback --> result
Every MCP server integrates through this interface:
type MCPProvider interface {
ID() string
Name() string
Description() string
RequiredCredentials() []CredentialSpec
GenerateConfig(credentials map[string]string) (MCPConfig, error)
}
Typical provider work:
pkg/provider/<name>.go.DefaultRegistry() in pkg/provider/registry.go.pkg/client/.See Adding an MCP Provider for the full checklist.
The core logic is available under pkg/. The API is pre-stable and may change before v2.0.
import (
"fmt"
"github.com/nawodyaishan/universal-mcp-sync/pkg/app"
"github.com/nawodyaishan/universal-mcp-sync/pkg/config"
"github.com/nawodyaishan/universal-mcp-sync/pkg/provider"
)
func main() {
manager, err := app.NewManager("/custom/home", nil, nil)
if err != nil {
panic(err)
}
prov := provider.NewContext7Provider()
profiles := []provider.CredentialProfile{{
ProviderID: prov.ID(),
Values: map[string]string{"CONTEXT7_API_KEY": "YOUR_SECRET_KEY"},
Label: "docs",
}}
selected := map[config.AppID]bool{config.AppCursor: true}
assignments := map[config.AppID]int{config.AppCursor: 0}
plan, err := manager.PrepareProvider(prov, profiles, selected, assignments)
if err != nil {
panic(err)
}
result, err := manager.Apply(plan)
if err != nil {
fmt.Printf("apply failed: %v\n", err)
}
fmt.Printf("updated %d targets\n", len(result.UpdatedTargets))
}
Requirements:
golangci-lint for make lintCommon commands:
make tidy # sync module dependencies
make tidy-check # verify go.mod/go.sum are already tidy
make fmt # format Go sources
make vet # run go vet
make lint # run golangci-lint
make test # run all tests with repo-local caches
make test-e2e # run CLI/TUI end-to-end golden tests
make coverage-check # enforce the 60% total coverage gate
make build # build ./bin/usync
make verify # run local CI guard
make gitignore-check # verify important fixtures are tracked/ignored correctly
Install Git hooks:
brew install lefthook # or install from your OS package manager
lefthook install
Start with CONTRIBUTING.md. Useful contributor docs:
Before opening a PR, run:
make fmt
make test
make gitignore-check
Run make lint and make verify when changing shared logic, release tooling, or provider/client compatibility.
Run Claude Code as an MCP server so any agent can delegate coding tasks to it
Browser automation using accessibility snapshots instead of screenshots
Secure MCP server for MySQL database interaction, queries, and schema management
English-first Korean equity intelligence MCP — DART filings, foreign-holder 5%-rule flows, activist filings, KRX news. F