{"id":51503053,"url":"https://github.com/settlin/mcp-relay","last_synced_at":"2026-07-07T21:30:56.738Z","repository":{"id":354215599,"uuid":"1222312826","full_name":"settlin/mcp-relay","owner":"settlin","description":"Single source of truth for MCP server configs across AI editors","archived":false,"fork":false,"pushed_at":"2026-04-27T15:56:11.000Z","size":31,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-27T17:29:17.402Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/settlin.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-04-27T08:40:30.000Z","updated_at":"2026-04-27T15:56:16.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/settlin/mcp-relay","commit_stats":null,"previous_names":["settlin/mcp-relay"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/settlin/mcp-relay","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/settlin%2Fmcp-relay","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/settlin%2Fmcp-relay/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/settlin%2Fmcp-relay/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/settlin%2Fmcp-relay/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/settlin","download_url":"https://codeload.github.com/settlin/mcp-relay/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/settlin%2Fmcp-relay/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35243953,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-07T02:00:07.222Z","response_time":90,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-07-07T21:30:55.857Z","updated_at":"2026-07-07T21:30:56.730Z","avatar_url":"https://github.com/settlin.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# mcp-relay\n\nSingle source of truth for MCP server configurations across AI editors.\n\nOne canonical `~/.config/mcp/servers.json` propagates automatically to:\n\n| Editor | Config location | Schema key |\n|---|---|---|\n| **Zed** | `~/.config/zed/settings.json` | `context_servers` |\n| **Kilo** | `~/.config/kilo/kilo.jsonc` | `mcp` |\n| **opencode** | `~/.config/opencode/opencode.jsonc` | `mcp` |\n| **VS Code** | `~/Library/Application Support/Code/User/mcp.json` | `servers` |\n| **Claude Desktop** | `~/Library/Application Support/Claude/claude_desktop_config.json` | `mcpServers` |\n| **Cursor** | `~/.cursor/mcp.json` | `mcpServers` |\n| **custom** | any path you register | any key |\n\nA launchd agent (macOS) or systemd path unit (Linux) fires `mcp-relay sync` the moment `servers.json` is saved — zero manual steps after the first `mcp-relay install`.\n\n---\n\n## Installation\n\n### Quick (copy the script)\n\n```sh\ncurl -fsSL https://raw.githubusercontent.com/settlin/mcp-relay/main/mcp-relay \\\n  -o ~/.local/bin/mcp-relay \u0026\u0026 chmod +x ~/.local/bin/mcp-relay\nmcp-relay install\n```\n\n### From source\n\n```sh\ngit clone https://github.com/settlin/mcp-relay\ncd mcp-relay\ncp mcp-relay ~/.local/bin/mcp-relay\nchmod +x ~/.local/bin/mcp-relay\nmcp-relay install\n```\n\n### With pip / uv\n\n```sh\npip install mcp-relay          # installs `mcp-relay` entry point\n# or\nuv tool install mcp-relay\n```\n\nEnsure `~/.local/bin` is in your `PATH`:\n\n```sh\n# fish\nfish_add_path ~/.local/bin\n\n# bash / zsh\nexport PATH=\"$HOME/.local/bin:$PATH\"\n```\n\n---\n\n## Quick start\n\n```sh\n# 1. Create the canonical config (editable template)\nmcp-relay init\n\n# 2. Check what was created\nmcp-relay list\n\n# 3. Preview what sync would write to each editor\nmcp-relay diff\n\n# 4. Apply to all editors\nmcp-relay sync\n\n# 5. Install the auto-watch daemon (fire-and-forget from now on)\nmcp-relay install\n```\n\n---\n\n## Canonical config\n\n`~/.config/mcp/servers.json`\n\n```json\n{\n  \"version\": 1,\n  \"servers\": {\n    \"betterstack\": {\n      \"transport\": \"remote\",\n      \"url\": \"https://mcp.betterstack.com\"\n    },\n    \"clickup\": {\n      \"transport\": \"remote\",\n      \"url\": \"https://mcp.clickup.com/mcp\"\n    },\n    \"mongodb\": {\n      \"transport\": \"local\",\n      \"command\": [\"pnpm\", \"dlx\", \"@mongodb-js/mongodb-mcp-server\", \"--readonly\"],\n      \"env\": {\n        \"MDB_MCP_CONNECTION_STRING\": \"mongodb+srv://user:pass@host/db\"\n      }\n    }\n  }\n}\n```\n\nTwo transport types:\n\n| Field | Description |\n|---|---|\n| `transport: \"remote\"` | HTTP/SSE MCP server; only `url` needed |\n| `transport: \"local\"` | Subprocess MCP server; `command` array + optional `env` map |\n\n---\n\n## Commands\n\n### `mcp-relay init`\n\nCreate `~/.config/mcp/servers.json` from a built-in template.\n\n```sh\nmcp-relay init           # safe — won't overwrite existing\nmcp-relay init --force   # overwrite\n```\n\n---\n\n### `mcp-relay sync`\n\nPropagate canonical config to all active editor targets.\n\n```sh\nmcp-relay sync                   # all editors\nmcp-relay sync --editor zed      # only Zed\nmcp-relay sync --dry-run         # preview without writing\nmcp-relay sync -n                # shorthand for --dry-run\n```\n\nThe sync is **surgical**: only the canonical server entries are rewritten inside each editor's existing config. Other keys (model settings, keymaps, permissions, etc.) are left untouched. Comments outside the managed block are preserved.\n\n---\n\n### `mcp-relay status`\n\nShow which servers are synced (present) and which are missing in each editor.\n\n```sh\nmcp-relay status\n```\n\n```\nCanonical : /Users/you/.config/mcp/servers.json\nServers   : betterstack, clickup, mongodb\n\n  Editor          Status      Present                           Missing\n  --------------------------------------------------------------------------\n  zed             ok          betterstack, clickup, mongodb\n  kilo            ok          betterstack, clickup, mongodb\n  opencode        ok          betterstack, clickup, mongodb\n  vscode          missing     betterstack                       clickup\n  claude-desktop  not found\n```\n\n---\n\n### `mcp-relay diff`\n\nShow a unified diff of exactly what `sync` would change in each editor.\n\n```sh\nmcp-relay diff\n```\n\n---\n\n### `mcp-relay list`\n\nList all servers in the canonical config.\n\n```sh\nmcp-relay list\n```\n\n```\n  betterstack         remote  https://mcp.betterstack.com\n  clickup             remote  https://mcp.clickup.com/mcp\n  mongodb             local   pnpm dlx @mongodb-js/mongodb-mcp-server --readonly\n                              MDB_MCP_CONNECTION_STRING=mongodb+srv://...\n```\n\n---\n\n### `mcp-relay add`\n\nAdd or update a server in canonical config, then sync all editors.\n\n```sh\n# Remote server (HTTP/SSE)\nmcp-relay add betterstack --remote https://mcp.betterstack.com\nmcp-relay add clickup     --remote https://mcp.clickup.com/mcp\n\n# Local server (subprocess)\nmcp-relay add mongodb \\\n  --command \"pnpm dlx @mongodb-js/mongodb-mcp-server --readonly\" \\\n  --env MDB_MCP_CONNECTION_STRING=mongodb+srv://user:pass@host/db\n\n# Local server with separate --arg flags\nmcp-relay add myserver \\\n  --command pnpm \\\n  --arg dlx \\\n  --arg my-mcp-package \\\n  --arg --flag\n\n# Overwrite an existing entry\nmcp-relay add betterstack --remote https://mcp.betterstack.com --force\n\n# Add without syncing immediately\nmcp-relay add newserver --remote https://new.example.com --no-sync\n```\n\n---\n\n### `mcp-relay remove`\n\nRemove a server from canonical config (editor configs are not modified until the next sync).\n\n```sh\nmcp-relay remove betterstack\n```\n\n---\n\n### `mcp-relay edit`\n\nOpen the canonical config in `$EDITOR`.\n\n```sh\nmcp-relay edit          # uses $EDITOR (falls back to vi)\nEDITOR=nano mcp-relay edit\n```\n\nAfter saving, run `mcp-relay sync` — or let the daemon do it if `mcp-relay install` has been run.\n\n---\n\n### `mcp-relay targets`\n\nShow all known editor targets, whether they are active, and where their config lives.\n\n```sh\nmcp-relay targets\n```\n\n```\n  Name            On    Path\n  ----------------------------------------------------------------------\n  zed             ✓     /Users/you/.config/zed/settings.json (exists)\n  kilo            ✓     /Users/you/.config/kilo/kilo.jsonc (exists)\n  opencode        ✓     /Users/you/.config/opencode/opencode.jsonc (exists)\n  vscode          ✓     /Users/you/Library/Application Support/Code/User/mcp.json (exists)  [only: betterstack, clickup]\n  claude-desktop  ✗     /Users/you/Library/Application Support/Claude/claude_desktop_config.json (not found)\n  cursor          ✗     /Users/you/.cursor/mcp.json (not found)\n```\n\nTargets marked `✗` are auto-enabled the moment their config file appears on disk.\n\n---\n\n### `mcp-relay install`\n\nInstall `mcp-relay` to `~/.local/bin` and set up the auto-watch daemon.\n\n```sh\nmcp-relay install\n```\n\nWhat it does:\n\n1. Copies the script to `~/.local/bin/mcp-relay` (skips if already there)\n2. Creates `~/.config/mcp/servers.json` if it doesn't exist\n3. **macOS** — writes and loads a launchd `WatchPaths` agent that fires on every save of `servers.json`\n4. **Linux** — writes and enables a systemd user path unit + service\n5. Prints a `PATH` hint if `~/.local/bin` is not in `$PATH`\n\nAfter `install`, editing `servers.json` (or running `mcp-relay add/remove/edit`) automatically propagates changes — no cron, no polling.\n\nLogs are written to `~/.local/state/mcp-relay.log`.\n\n---\n\n### `mcp-relay uninstall`\n\nRemove the auto-watch daemon.\n\n```sh\nmcp-relay uninstall                  # removes daemon + binary\nmcp-relay uninstall --keep-binary    # removes daemon only\n```\n\n---\n\n### `mcp-relay logs`\n\nTail the sync log.\n\n```sh\nmcp-relay logs           # last 40 lines, then follow\nmcp-relay logs -n 100    # last 100 lines\n```\n\n---\n\n## Adding a custom editor\n\nCreate `~/.config/mcp/targets.json`:\n\n```json\n{\n  \"targets\": [\n    {\n      \"name\": \"my-editor\",\n      \"path\": \"~/.config/my-editor/config.json\",\n      \"parent_key\": \"mcpServers\",\n      \"adapter\": \"claude\"\n    }\n  ]\n}\n```\n\nAvailable adapters:\n\n| Adapter | Format | Used by |\n|---|---|---|\n| `zed` | `{enabled, command/url, args, env}` | Zed |\n| `kilo_opencode` | `{type, command/url, environment}` | Kilo, opencode |\n| `vscode` | `{transport, url}` / `{command, args, env}` | VS Code |\n| `claude` | `{url}` / `{command, args, env}` | Claude Desktop, Cursor |\n\nCustom targets take effect immediately without restarting the daemon.\n\n---\n\n## Limiting sync scope per target\n\nIf an editor manages some MCP servers itself (e.g. the VS Code MongoDB extension), you can restrict which canonical servers get written to that editor via `only_servers`:\n\n```json\n{\n  \"targets\": [\n    {\n      \"name\": \"vscode\",\n      \"path\": \"~/Library/Application Support/Code/User/mcp.json\",\n      \"parent_key\": \"servers\",\n      \"adapter\": \"vscode\",\n      \"only_servers\": [\"betterstack\", \"clickup\"]\n    }\n  ]\n}\n```\n\n---\n\n## How it works\n\n```\nservers.json  ──saved──▶  launchd / systemd\n                                │\n                          mcp-relay sync\n                                │\n              ┌─────────────────┼─────────────────┐\n              ▼                 ▼                 ▼\n    Zed settings.json   kilo.jsonc         vscode/mcp.json\n    (context_servers)    (mcp)              (servers)\n              │\n              ▼\n    opencode.jsonc  claude_desktop_config.json  cursor/mcp.json\n```\n\nThe sync is **purely additive and surgical**:\n- Each editor's file is read as raw text (JSONC-aware)\n- Only the entries for canonical servers are replaced or inserted\n- All other keys, comments, and formatting are preserved\n\n---\n\n## Development\n\n```sh\ngit clone https://github.com/settlin/mcp-relay\ncd mcp-relay\npip install -e \".[dev]\"\n# or with uv:\nuv sync --group dev\n\npytest tests/ -v\npytest tests/ -v --cov=. --cov-report=term-missing\n```\n\n---\n\n## License\n\nMIT © [Sudhanshu Raheja](https://github.com/s7dhansh)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsettlin%2Fmcp-relay","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsettlin%2Fmcp-relay","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsettlin%2Fmcp-relay/lists"}