Skip to content

Architecture ​

This guide explains the architecture of MCP Server Manager and how the gateway pattern works.

System Overview ​

MCP Server Manager uses a gateway pattern to manage multiple MCP servers across different AI clients:

┌─────────────────────────────────────────────────────────┐
│                    Your Servers                         │
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐  │
│  │ Filesystem   │  │   Database   │  │   APIs       │  │
│  └──────────────┘  └──────────────┘  └──────────────┘  │
└─────────────────────────────────────────────────────────┘
                            ▲
                            │ TCP/stdio
                            │
                    ┌───────────────────┐
                    │   mcpsm Daemon    │
                    │  (Gateway Server) │
                    └───────────────────┘
                            ▲
        ┌───────────────────┼───────────────────┐
        │                   │                   │
   ┌────────────┐   ┌──────────────┐   ┌─────────────┐
   │   Claude   │   │    Cursor    │   │  Windsurf   │
   │  Desktop   │   │              │   │             │
   └────────────┘   └──────────────┘   └─────────────┘

Core Concepts ​

Gateway Pattern ​

Instead of syncing individual servers to each client, mcpsm operates as a gateway server:

  1. Daemon: Runs a central mcpsm server that listens on localhost:{port}/mcp
  2. Client Connection: Each client connects to the daemon through a single mcpsm server entry
  3. Gateway: The mcpsm server points to the daemon (via supergateway or a direct URL, depending on the client)
  4. All Servers Accessible: All configured servers are accessible through this single gateway

Benefits ​

  • Single Point of Configuration: Add a server once, it's available in all connected clients
  • No Individual Sync: Clients don't need individual server copies
  • Easy Port Changes: Changing the port automatically updates all connected clients
  • Real-time Loading: Supported clients see changes without restart
  • Scalability: Adding new clients is as simple as running a connect command

3-State Connection Model ​

Each MCP client has three possible states:

StateMeaningHow to Reach It
ConnectedClient has mcpsm gateway; can access serversmcpsm clients connect <client>
DisconnectedClient installed but not connected to mcpsmmcpsm clients disconnect <client>
Not InstalledClient application not found on systemInstall the client

State Transitions ​

┌───────────────┐
│ Not Installed │
└───────────────┘
       │
       │ (user installs client)
       ▼
┌───────────────┐     mcpsm clients      ┌───────────────┐
│ Disconnected  │ ────────────────────→  │   Connected   │
│               │ ←──────────────────────│               │
│               │  mcpsm clients disconnect              │
└───────────────┘                        └───────────────┘

Client Service ​

The ClientService (src/services/client.service.ts) manages client detection and connections.

Client Detection ​

When you run mcpsm clients, the service:

  1. Checks for each supported client application
  2. Detects the config file location (OS-specific paths)
  3. Reads the config to check if mcpsm gateway is already connected
  4. Returns the status for each client

Client Paths ​

Config files are stored in platform-specific locations:

macOS ​

Claude Desktop:    ~/Library/Application Support/Claude/claude_desktop_config.json
Cursor:           ~/Library/Application Support/Cursor/User/globalStorage/cursor.mcp/config.json
Windsurf:         ~/Library/Application Support/Windsurf/User/globalStorage/windsurf.mcp/config.json
VS Code:          ~/Library/Application Support/Code/User/mcp.json
Zed:              ~/.config/zed/settings.json
Claude Code:      ~/.claude/claude_code_config.json
Codex CLI:        ~/.codex/config.toml
Gemini CLI:       ~/.gemini/settings.json

Windows ​

Claude Desktop:    %APPDATA%/Claude/claude_desktop_config.json
Cursor:           %APPDATA%/Cursor/User/globalStorage/cursor.mcp/config.json
Windsurf:         %APPDATA%/Windsurf/User/globalStorage/windsurf.mcp/config.json
VS Code:          %APPDATA%/Code/User/mcp.json
Zed:              %APPDATA%/Zed/settings.json
Claude Code:      %USERPROFILE%/.claude/claude_code_config.json
Codex CLI:        %USERPROFILE%/.codex/config.toml
Gemini CLI:       %USERPROFILE%/.gemini/settings.json

Linux ​

Claude Desktop:    ~/.config/Claude/claude_desktop_config.json
Cursor:           ~/.config/Cursor/User/globalStorage/cursor.mcp/config.json
Windsurf:         ~/.config/Windsurf/User/globalStorage/windsurf.mcp/config.json
VS Code:          ~/.config/Code/User/mcp.json
Zed:              ~/.config/zed/settings.json
Claude Code:      ~/.claude/claude_code_config.json
Codex CLI:        ~/.codex/config.toml
Gemini CLI:       ~/.gemini/settings.json

Real-time Config Paths ​

Some clients support real-time config loading (no restart required). These use additional config paths:

ClientReal-time Path
Cursor~/.cursor/mcp.json
Windsurf~/.codeium/windsurf/mcp_config.json
VS Code~/Library/Application Support/Code/User/mcp.json
ZedUses its primary settings.json path

When connecting a client, mcpsm writes to both the primary config path and the real-time path (if supported).

Connection Process ​

When you run mcpsm clients connect <client>:

  1. Check Installation: Verify the client application exists
  2. Read Current Config: Load the client's current MCP configuration
  3. Preserve Existing Servers: Keep all existing servers in the config
  4. Add Gateway Server: Add the mcpsm gateway server entry:
    json
    {
      "mcpsm": {
        "command": "npx",
        "args": ["-y", "supergateway", "--streamableHttp", "http://localhost:PORT/mcp"]
      }
    }
  5. Write Configs: Write to both primary and real-time paths
  6. Update Status: Client moves to "Connected" state

Disconnection Process ​

When you run mcpsm clients disconnect <client>:

  1. Read Current Config: Load the client's MCP configuration
  2. Remove Only mcpsm: Delete only the mcpsm gateway server entry
  3. Preserve Existing Servers: Keep all other servers intact
  4. Write Configs: Write updated config to both paths
  5. Update Status: Client moves to "Disconnected" state

Port Auto-Update ​

When you change the gateway port in Settings:

  1. Detect Connected Clients: Find all clients that have the mcpsm gateway
  2. Disconnect All: Remove the mcpsm gateway from all connected clients
  3. Update Port: Change the port in settings
  4. Reconnect All: Add the mcpsm gateway back with the new port
  5. Update All Configs: Write changes to both primary and real-time paths

This ensures all connected clients automatically update to use the new port without manual intervention.

Port Change Flow ​

User changes port in Settings
        ↓
Detect all connected clients
        ↓
Disconnect all clients (remove mcpsm gateway)
        ↓
Update port setting
        ↓
Reconnect all clients (add mcpsm gateway with new port)
        ↓
Write to both primary + real-time config paths
        ↓
Show success message with count of updated clients

Daemon and Gateway ​

The daemon is the background process running mcpsm:

  • Gateway Server: The daemon hosts a gateway server on localhost:{port}/mcp
  • All Servers: The daemon manages and proxies all configured MCP servers
  • Client Proxy: When a client connects through mcpsm, requests are proxied to the daemon

The gateway server in each client configuration is what connects them:

json
{
  "mcpsm": {
    "command": "npx",
    "args": ["-y", "supergateway", "--streamableHttp", "http://localhost:PORT/mcp"]
  }
}

This uses supergateway to forward all MCP protocol messages to the daemon's gateway endpoint.

Configuration Files ​

Main Configuration ​

The system stores configuration in ~/.mcp-manager/:

FilePurpose
config.jsonServer definitions (local STDIO and remote HTTP/SSE)
settings.jsonApplication settings (port, default editor, etc.)
profiles.jsonServer profiles (groupings by project/context)
tool-filters.jsonPer-server tool enable/disable settings
clients.jsonClient connection state cache (informational only)

Client Configurations ​

Each client maintains its own config file (see Client Paths above). mcpsm reads and writes to these files to manage the gateway server entry.

Real-Time vs Primary Config ​

Primary Config ​

  • The main config file for each client (as listed in Client Paths)
  • Always written to when connecting/disconnecting
  • Required for all clients

Real-time Config ​

  • Additional paths for clients that support live config reloading
  • Automatically written to when connected
  • Allows changes to take effect without restart
  • Cursor, Windsurf, VS Code, and Zed support real-time loading

When mcpsm connects a client, it writes the gateway server to both locations. This ensures:

  • The primary config is always up-to-date
  • Clients that support real-time loading see changes immediately
  • Clients without real-time support still work (they'll pick up changes on restart)

Supported Clients ​

ClientIDPlatformsReal-timePrimary Config Path
Claude DesktopclaudemacOS, WindowsNoclaude_desktop_config.json
CursorcursormacOS, Windows, LinuxYescursor.mcp/config.json
WindsurfwindsurfmacOS, Windows, LinuxYeswindsurf.mcp/config.json
VS CodevscodemacOS, Windows, LinuxYesCode/User/mcp.json
ZedzedmacOS, Windows, LinuxYesZed/settings.json
Claude Codeclaude-codeCLINoclaude_code_config.json
CodexcodexmacOS, Windows, LinuxNo.codex/config.toml (TOML)
GeminigeminimacOS, Windows, LinuxNo.gemini/settings.json

Data Flow ​

Connecting a Client ​

mcpsm clients connect cursor
        ↓
ClientService.connectClient('cursor')
        ↓
1. Check if Cursor is installed
2. Read ~/.config/Cursor/User/globalStorage/cursor.mcp/config.json
3. Preserve all existing servers
4. Add mcpsm gateway server with current port
5. Write to primary config
6. Write to ~/.cursor/mcp.json (real-time)
        ↓
✓ Connected

Changing Port ​

User: mcpsm port 9000
        ↓
SettingsScreen detects port change
        ↓
1. Find all connected clients (cursor, claude, windsurf, etc.)
2. For each connected client:
   a. disconnectClient(id) - remove mcpsm entry
   b. Disconnect done, port updated
   c. connectClient(id) - add mcpsm entry with new port
   d. Write to both primary + real-time paths
3. Show: "Updated port for 3 clients"
        ↓
All clients now use new port

Client Using Servers ​

User opens Claude Desktop / Cursor / etc.
        ↓
Client loads mcpsm gateway server config
        ↓
supergateway connects to http://localhost:PORT/mcp
        ↓
User selects a tool from any server
        ↓
Tool request flows: Client → supergateway → mcpsm daemon → actual server
        ↓
Response flows back through the same path

Implementation Details ​

Key Services ​

ClientService (src/services/client.service.ts)

  • Detects installed MCP clients
  • Manages connections (connect/disconnect)
  • Handles config file reading/writing
  • Manages both primary and real-time config paths

ConfigService (src/services/config.service.ts)

  • Manages server definitions
  • Stores configuration in ~/.mcp-manager/

SettingsService (src/services/settings.service.ts)

  • Manages application settings
  • Triggers client reconnection on port changes

ProfileService (src/services/profile.service.ts)

  • Manages server profiles
  • Groups servers by context

Type Safety ​

All services are implemented in TypeScript with strict mode enabled. Key types:

  • ClientId - Union type of supported client IDs
  • ClientStatus - Union type: 'connected' | 'disconnected' | 'not-installed'
  • DetectedClient - Client with name, status, and paths
  • ClientMcpConfig - MCP server configuration structure
  • ServerDefinition - Local or remote server configuration

Error Handling ​

The system handles several error scenarios:

  • Client not installed: Returns 'not-installed' status
  • Config file missing: Creates new config with mcpsm gateway
  • File write errors: Reports error to user, doesn't partially update
  • Port in use: Caught by daemon, reported to user
  • Invalid config format: Detects and preserves valid portions

Threading and Concurrency ​

  • Client operations are synchronous (using fs and spawnSync)
  • Port updates reconnect clients in sequence to ensure consistency
  • Settings changes are atomic per client

For more information:

Released under the MIT License.