A CLI tool for managing MCP (Model Context Protocol) servers across Claude Desktop, Cursor, and Windsurf.
axis keeps a local registry of your MCP servers and syncs them into the config files that each client reads. You add a server once and enable it wherever you need it.
npm install -g axis
After installation, run axis init to create the config directory:
axis init
# Search the community index for available servers
axis search filesystem
# Add a server to your local registry
axis add npm:@modelcontextprotocol/server-filesystem --name filesystem --command npx --args -y @modelcontextprotocol/server-filesystem /home/user
# Enable it in Claude Desktop
axis enable filesystem --target claude
# Check what is synced where
axis status
| Command | Description |
|---|---|
axis add <source> |
Add an MCP server to the local registry |
axis remove <name> |
Remove a server from the registry |
axis enable <name> |
Enable a server in client config files |
axis disable <name> |
Disable a server from client config files |
axis list |
List all servers in the registry |
axis favorite <name> |
Mark a server as a favorite |
axis unfavorite <name> |
Remove a server from favorites |
axis sync |
Sync all enabled servers to client configs |
axis search <query> |
Search the community index |
axis export |
Export the registry to JSON |
axis import <file> |
Import servers from a JSON file |
axis init |
Interactive setup |
axis status |
Show which servers are synced to which clients |
axis add <source> [options]
Source formats:
npm:<package> npm package (e.g. npm:@modelcontextprotocol/server-filesystem)
github:<user>/<repo> GitHub repository
local:<path> Local path
Options:
-n, --name <alias> Alias for the server (derived from source if omitted)
-c, --command <cmd> Command to run the server
-a, --args <args...> Arguments passed to the command
-d, --description <desc> Description
-t, --tags <tags...> Tags
--overwrite Replace an existing server with the same name
axis enable <name> [options]
Options:
-t, --target <target> claude, cursor, windsurf, or all (default: all)
-p, --project <path> Enable only for a specific project path
--dry-run Show what would change without writing files
--no-backup Skip backing up the config file before modifying
axis disable <name> [options]
Options:
-t, --target <target> claude, cursor, windsurf, or all (default: all)
--dry-run Show what would change without writing files
--no-backup Skip backing up the config file before modifying
axis sync [options]
Writes all globally enabled servers from the registry into the target client config(s).
Servers present in the client config that are not in the registry are preserved.
Options:
-t, --target <target> claude, cursor, windsurf, or all (default: all)
--dry-run Show what would change without writing files
--no-backup Skip backing up config files before modifying
axis list [options]
Options:
-e, --enabled Show only globally enabled servers
-f, --favorites Show only favorited servers
--json Output as JSON
# Export registry to stdout
axis export
# Export to a file
axis export --output registry-backup.json
# Import from a file
axis import registry-backup.json
# Import and overwrite conflicts
axis import registry-backup.json --overwrite
| Client | macOS | Linux | Windows |
|---|---|---|---|
| Claude Desktop | ~/Library/Application Support/Claude/claude_desktop_config.json |
~/.config/Claude/claude_desktop_config.json |
%APPDATA%\Claude\claude_desktop_config.json |
| Cursor | ~/.cursor/mcp.json |
~/.cursor/mcp.json |
~/.cursor/mcp.json |
| Windsurf | ~/.codeium/windsurf/mcp_config.json |
~/.codeium/windsurf/mcp_config.json |
~/.codeium/windsurf/mcp_config.json |
axis registry: ~/.axis/registry.json
All config writes are atomic (write to .tmp, then rename) and the original file is backed up before any modification.
~/.axis/registry.json:
{
"version": "1",
"servers": {
"<name>": {
"name": "string",
"source": "npm:pkg | github:user/repo | local:./path",
"command": "string",
"args": ["string"],
"env": { "KEY": "VALUE" },
"enabled": { "global": true, "projects": ["./path/to/project"] },
"favorite": false,
"installedAt": "ISO date",
"description": "string",
"tags": ["string"]
}
}
}- Fork the repository
- Create a feature branch:
git checkout -b feat/my-feature - Write your changes and add tests (Vitest, required for all new code)
- Run
npm testto verify all tests pass - Run
npx tsc --noEmitto verify type correctness - Open a pull request
npm install
npm run build # compile TypeScript
npm test # run Vitest
npm run test:watch # watch mode
- Create
src/commands/<name>.ts - Export a
register<Name>(program: Command): voidfunction - Import and call it in
src/index.ts - Add integration tests in
tests/integration/cli.test.ts
MIT