mcp-twin 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,306 @@
1
+ # MCP Twin
2
+
3
+ > Zero-downtime MCP server updates for **any** MCP client
4
+
5
+ **⚡ Powered by [Prax Chat](https://prax.chat)**
6
+
7
+ Works with: **Claude Desktop** · **Claude Code** · **VS Code** · **Cursor** · **Cline** · **Windsurf**
8
+
9
+ Stop restarting your AI assistant every time you change your MCP server.
10
+
11
+ <p align="center">
12
+ <img src="https://github.com/nothinginfinity/mcp-twin/raw/main/demo.gif" alt="MCP Twin Demo" width="600">
13
+ </p>
14
+
15
+ ## Demo
16
+
17
+ ```
18
+ ┌─────────────────────────────────────────────────────────────────┐
19
+ │ $ /twin start inbox-collab │
20
+ │ │
21
+ │ Started twins for inbox-collab │
22
+ │ Server A: port 8101 ● running ← ACTIVE │
23
+ │ Server B: port 8102 ● running standby │
24
+ │ │
25
+ ├─────────────────────────────────────────────────────────────────┤
26
+ │ $ vim server.py # Edit your MCP server │
27
+ │ $ /twin reload inbox-collab │
28
+ │ │
29
+ │ Reloaded inbox-collab standby │
30
+ │ Standby (B): port 8102 │
31
+ │ Health: passing ● │
32
+ │ │
33
+ ├─────────────────────────────────────────────────────────────────┤
34
+ │ $ /twin swap inbox-collab │
35
+ │ │
36
+ │ Swapped inbox-collab │
37
+ │ Previous: A (port 8101) │
38
+ │ Now active: B (port 8102) ✓ │
39
+ │ │
40
+ │ Your changes are now live! No restart needed. │
41
+ └─────────────────────────────────────────────────────────────────┘
42
+ ```
43
+
44
+ ## The Problem
45
+
46
+ Every time you edit an MCP server, you have to:
47
+ 1. Stop Claude Code
48
+ 2. Restart the MCP server
49
+ 3. Restart Claude Code
50
+ 4. Lose your conversation context
51
+
52
+ Sound familiar? **MCP Twin fixes this.**
53
+
54
+ ## The Solution
55
+
56
+ MCP Twin runs two instances of your MCP server simultaneously:
57
+ - **Server A**: Active (receiving traffic)
58
+ - **Server B**: Standby (ready to take over)
59
+
60
+ When you edit code:
61
+ 1. Reload standby with new code
62
+ 2. Swap traffic to standby
63
+ 3. Keep working - zero downtime!
64
+
65
+ ## Quick Start
66
+
67
+ ```bash
68
+ # Start twins for your MCP server
69
+ /twin start my-server
70
+
71
+ # Edit your server code...
72
+
73
+ # Reload standby with changes
74
+ /twin reload my-server
75
+
76
+ # Switch traffic to new version
77
+ /twin swap my-server
78
+
79
+ # Done! No restart needed.
80
+ ```
81
+
82
+ ## Commands
83
+
84
+ | Command | Description |
85
+ |---------|-------------|
86
+ | `/twin start [server]` | Start twin servers |
87
+ | `/twin stop [server]` | Stop twin servers |
88
+ | `/twin reload <server>` | Reload standby with new code |
89
+ | `/twin swap <server>` | Switch traffic to standby |
90
+ | `/twin status [server]` | Show twin status |
91
+ | `/twin detect` | Auto-detect MCP servers |
92
+ | `/twin help` | Show help |
93
+
94
+ ## Example Workflow
95
+
96
+ ```
97
+ $ /twin start inbox-collab
98
+
99
+ Started twins for inbox-collab
100
+
101
+ Server A: port 8101 ● running
102
+ Server B: port 8102 ● running
103
+ Active: A
104
+
105
+ Edit your code, then: /twin reload inbox-collab
106
+ ```
107
+
108
+ ```
109
+ $ /twin reload inbox-collab
110
+
111
+ Reloaded inbox-collab standby
112
+
113
+ standby (b) on port 8102
114
+ Health: passing ●
115
+ Reload count: 1
116
+
117
+ Run: /twin swap inbox-collab
118
+ ```
119
+
120
+ ```
121
+ $ /twin swap inbox-collab
122
+
123
+ Swapped inbox-collab
124
+
125
+ Previous: a (port 8101)
126
+ Now active: b (port 8102)
127
+
128
+ Your changes are now live!
129
+ ```
130
+
131
+ ## Auto-Detection
132
+
133
+ MCP Twin automatically detects servers from your Claude config:
134
+
135
+ ```
136
+ $ /twin detect
137
+
138
+ Detected 3 MCP servers:
139
+ - inbox-collab
140
+ - phi-proxy
141
+ - zti-server
142
+
143
+ 3 configured for twins.
144
+ ```
145
+
146
+ ## Installation
147
+
148
+ ### Universal CLI (any client)
149
+ ```bash
150
+ # Install globally
151
+ npm install -g mcp-twin
152
+
153
+ # Or run directly with npx
154
+ npx mcp-twin start my-server
155
+ ```
156
+
157
+ ### Claude Code Plugin
158
+ ```
159
+ /install mcp-twin
160
+ ```
161
+
162
+ ### From Source
163
+ ```bash
164
+ git clone https://github.com/nothinginfinity/mcp-twin
165
+ cd mcp-twin
166
+ npm install
167
+ npm run build
168
+ npm link # Makes 'mcp-twin' command available globally
169
+ ```
170
+
171
+ ## Supported Clients
172
+
173
+ MCP Twin auto-detects servers from all major MCP clients:
174
+
175
+ | Client | Config Location |
176
+ |--------|-----------------|
177
+ | Claude Desktop | `~/Library/Application Support/Claude/` |
178
+ | Claude Code | `~/.claude/` |
179
+ | VS Code | `.vscode/mcp.json` |
180
+ | Cursor | `~/.cursor/mcp.json` |
181
+ | Windsurf | `~/.windsurf/mcp.json` |
182
+ | Cline | VS Code settings |
183
+
184
+ ```bash
185
+ # Auto-detect all configured servers
186
+ mcp-twin detect
187
+
188
+ # Detected 3 MCP servers:
189
+ # - inbox-collab (from Claude Code)
190
+ # - my-api (from Cursor)
191
+ # - data-tools (from VS Code)
192
+ ```
193
+
194
+ ## Configuration
195
+
196
+ Config stored at `~/.mcp-twin/config.json`:
197
+
198
+ ```json
199
+ {
200
+ "servers": {
201
+ "my-server": {
202
+ "script": "/path/to/server.py",
203
+ "ports": [8101, 8102],
204
+ "python": "python3"
205
+ }
206
+ },
207
+ "settings": {
208
+ "startupWait": 2000,
209
+ "shutdownTimeout": 5000
210
+ }
211
+ }
212
+ ```
213
+
214
+ ## How It Works
215
+
216
+ ```
217
+ ┌─────────────────────────────────────────┐
218
+ │ Claude Code │
219
+ │ │ │
220
+ │ ▼ │
221
+ │ ┌─────────────────┐ │
222
+ │ │ MCP Client │ │
223
+ │ └────────┬────────┘ │
224
+ │ │ │
225
+ │ ┌─────┴─────┐ │
226
+ │ ▼ ▼ │
227
+ │ ┌───────┐ ┌───────┐ │
228
+ │ │ MCP-A │ │ MCP-B │ │
229
+ │ │:8101 │ │:8102 │ │
230
+ │ │ACTIVE │ │STANDBY│ │
231
+ │ └───────┘ └───────┘ │
232
+ │ │
233
+ └─────────────────────────────────────────┘
234
+ ```
235
+
236
+ 1. **Start**: Both A and B running, A is active
237
+ 2. **Edit**: Change your server code
238
+ 3. **Reload**: Stop B, start B with new code
239
+ 4. **Swap**: Route traffic to B, A becomes standby
240
+ 5. **Repeat**: Next edit reloads A, swap back
241
+
242
+ ## Server Requirements
243
+
244
+ Your MCP server must support HTTP mode with these flags:
245
+
246
+ ```bash
247
+ python3 server.py --http --port 8101
248
+ ```
249
+
250
+ The server should expose:
251
+ - `POST /mcp` - JSON-RPC 2.0 endpoint for MCP protocol
252
+ - `GET /health` - Health check endpoint (returns 200 OK)
253
+
254
+ ### Adding HTTP Mode to Your Server
255
+
256
+ Add this to your MCP server's main block:
257
+
258
+ ```python
259
+ if __name__ == "__main__":
260
+ import argparse
261
+
262
+ parser = argparse.ArgumentParser()
263
+ parser.add_argument("--http", action="store_true", help="Run as HTTP server")
264
+ parser.add_argument("--port", type=int, default=8101, help="HTTP port")
265
+ args = parser.parse_args()
266
+
267
+ if args.http:
268
+ run_http_server(args.port) # Your HTTP server implementation
269
+ else:
270
+ main() # Original stdio mode
271
+ ```
272
+
273
+ See the [example implementation](examples/http-server.py) for a complete template.
274
+
275
+ ## Pro Features (Coming Soon)
276
+
277
+ **[Prax Chat Pro](https://prax.chat/mcp-twin/pro)** - Enterprise MCP management
278
+
279
+ | Feature | Free | Pro |
280
+ |---------|------|-----|
281
+ | Twin servers | ✅ | ✅ |
282
+ | Manual reload/swap | ✅ | ✅ |
283
+ | Auto-reload on save | ❌ | ✅ |
284
+ | Health dashboard | ❌ | ✅ |
285
+ | Rollback history | ❌ | ✅ |
286
+ | Slack/Discord alerts | ❌ | ✅ |
287
+ | Team sharing | ❌ | ✅ |
288
+ | Priority support | ❌ | ✅ |
289
+
290
+ [Join the waitlist →](https://prax.chat/mcp-twin/pro)
291
+
292
+ ## License
293
+
294
+ MIT
295
+
296
+ ## Credits
297
+
298
+ Built with ❤️ by [Prax Chat](https://prax.chat)
299
+
300
+ ---
301
+
302
+ <p align="center">
303
+ <a href="https://prax.chat">
304
+ <img src="https://img.shields.io/badge/Powered%20by-Prax%20Chat-blue?style=for-the-badge" alt="Powered by Prax Chat">
305
+ </a>
306
+ </p>
package/dist/cli.d.ts ADDED
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * MCP Twin CLI - Universal zero-downtime MCP server management
4
+ *
5
+ * Works with ANY MCP client: Claude Desktop, VS Code, Cursor, Cline, etc.
6
+ *
7
+ * Usage:
8
+ * npx mcp-twin start my-server
9
+ * npx mcp-twin reload my-server
10
+ * npx mcp-twin swap my-server
11
+ * npx mcp-twin status
12
+ *
13
+ * Powered by Prax Chat - https://prax.chat
14
+ */
15
+ export {};
16
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;GAYG"}
package/dist/cli.js ADDED
@@ -0,0 +1,215 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ /**
4
+ * MCP Twin CLI - Universal zero-downtime MCP server management
5
+ *
6
+ * Works with ANY MCP client: Claude Desktop, VS Code, Cursor, Cline, etc.
7
+ *
8
+ * Usage:
9
+ * npx mcp-twin start my-server
10
+ * npx mcp-twin reload my-server
11
+ * npx mcp-twin swap my-server
12
+ * npx mcp-twin status
13
+ *
14
+ * Powered by Prax Chat - https://prax.chat
15
+ */
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ const twin_manager_1 = require("./twin-manager");
18
+ const config_detector_1 = require("./config-detector");
19
+ const PRAX_FOOTER = '\n─────────────────────────────────────────\n⚡ Powered by Prax Chat | prax.chat/mcp-twin';
20
+ const VERSION = '1.2.0';
21
+ async function main() {
22
+ const args = process.argv.slice(2);
23
+ const command = args[0]?.toLowerCase();
24
+ const serverName = args[1];
25
+ const manager = (0, twin_manager_1.getTwinManager)();
26
+ switch (command) {
27
+ case 'start': {
28
+ if (!serverName) {
29
+ const status = await manager.status();
30
+ console.log('Available servers:');
31
+ (status.available || []).forEach((s) => console.log(` - ${s}`));
32
+ console.log('\nUsage: mcp-twin start <server-name>');
33
+ break;
34
+ }
35
+ const result = await manager.startTwins(serverName);
36
+ if (result.ok) {
37
+ console.log(`✓ Started twins for ${serverName}`);
38
+ console.log(` Server A: port ${result.portA} (${result.statusA})`);
39
+ console.log(` Server B: port ${result.portB} (${result.statusB})`);
40
+ console.log(` Active: A`);
41
+ }
42
+ else {
43
+ console.error(`✗ Failed: ${result.error}`);
44
+ process.exit(1);
45
+ }
46
+ console.log(PRAX_FOOTER);
47
+ break;
48
+ }
49
+ case 'stop': {
50
+ if (!serverName) {
51
+ console.log('Usage: mcp-twin stop <server-name>');
52
+ console.log(' mcp-twin stop --all');
53
+ break;
54
+ }
55
+ if (serverName === '--all') {
56
+ const status = await manager.status();
57
+ for (const name of Object.keys(status.twins || {})) {
58
+ await manager.stopTwins(name);
59
+ console.log(`✓ Stopped ${name}`);
60
+ }
61
+ }
62
+ else {
63
+ const result = await manager.stopTwins(serverName);
64
+ if (result.ok) {
65
+ console.log(`✓ Stopped ${serverName} twins`);
66
+ }
67
+ else {
68
+ console.error(`✗ Failed: ${result.error}`);
69
+ process.exit(1);
70
+ }
71
+ }
72
+ break;
73
+ }
74
+ case 'reload': {
75
+ if (!serverName) {
76
+ console.log('Usage: mcp-twin reload <server-name>');
77
+ break;
78
+ }
79
+ console.log(`Reloading ${serverName} standby...`);
80
+ const result = await manager.reloadStandby(serverName);
81
+ if (result.ok) {
82
+ console.log(`✓ Reloaded ${result.reloaded}`);
83
+ console.log(` Health: ${result.healthy ? 'passing ●' : 'FAILED ○'}`);
84
+ console.log(` Reload count: ${result.reloadCount}`);
85
+ if (result.healthy) {
86
+ console.log(`\nReady to swap: mcp-twin swap ${serverName}`);
87
+ }
88
+ }
89
+ else {
90
+ console.error(`✗ Failed: ${result.error}`);
91
+ process.exit(1);
92
+ }
93
+ console.log(PRAX_FOOTER);
94
+ break;
95
+ }
96
+ case 'swap': {
97
+ if (!serverName) {
98
+ console.log('Usage: mcp-twin swap <server-name>');
99
+ break;
100
+ }
101
+ const result = await manager.swapActive(serverName);
102
+ if (result.ok) {
103
+ console.log(`✓ Swapped ${serverName}`);
104
+ console.log(` Previous: ${result.previousActive}`);
105
+ console.log(` Now active: ${result.newActive}`);
106
+ }
107
+ else {
108
+ console.error(`✗ Failed: ${result.error}`);
109
+ if (result.hint)
110
+ console.log(` Hint: ${result.hint}`);
111
+ process.exit(1);
112
+ }
113
+ console.log(PRAX_FOOTER);
114
+ break;
115
+ }
116
+ case 'status': {
117
+ const result = await manager.status(serverName);
118
+ if (serverName && result.ok) {
119
+ console.log(`${serverName} Twin Status`);
120
+ console.log('═'.repeat(40));
121
+ console.log(`\nServer A (port ${result.serverA.port})`);
122
+ console.log(` State: ${result.serverA.state}`);
123
+ console.log(` Health: ${result.serverA.healthy ? 'healthy ●' : 'unhealthy ○'}`);
124
+ console.log(` ${result.serverA.isActive ? '← ACTIVE' : ' standby'}`);
125
+ console.log(`\nServer B (port ${result.serverB.port})`);
126
+ console.log(` State: ${result.serverB.state}`);
127
+ console.log(` Health: ${result.serverB.healthy ? 'healthy ●' : 'unhealthy ○'}`);
128
+ console.log(` ${result.serverB.isActive ? '← ACTIVE' : ' standby'}`);
129
+ console.log(`\nReloads: ${result.reloadCount}`);
130
+ }
131
+ else if (result.ok) {
132
+ console.log('MCP Twin Status');
133
+ console.log('═'.repeat(40));
134
+ const twins = result.twins || {};
135
+ if (Object.keys(twins).length === 0) {
136
+ console.log('\nNo twins running.');
137
+ console.log('\nAvailable servers:');
138
+ (result.available || []).forEach((s) => console.log(` - ${s}`));
139
+ }
140
+ else {
141
+ for (const [name, info] of Object.entries(twins)) {
142
+ const activePort = info.ports[info.active === 'a' ? 0 : 1];
143
+ console.log(`\n${name}`);
144
+ console.log(` Active: ${info.active.toUpperCase()} (port ${activePort}) ${info.healthy[info.active === 'a' ? 0 : 1] ? '●' : '○'}`);
145
+ console.log(` Reloads: ${info.reloadCount}`);
146
+ }
147
+ }
148
+ }
149
+ break;
150
+ }
151
+ case 'detect': {
152
+ console.log('Detecting MCP servers...');
153
+ const result = (0, config_detector_1.autoConfigureTwins)();
154
+ if (result.detected === 0) {
155
+ console.log('No MCP servers found.');
156
+ console.log('\nSearched:');
157
+ console.log(' - Claude Desktop: ~/Library/Application Support/Claude/');
158
+ console.log(' - Claude Code: ~/.claude/');
159
+ console.log(' - VS Code: .vscode/mcp.json');
160
+ console.log(' - Cursor: ~/.cursor/mcp.json');
161
+ }
162
+ else {
163
+ console.log(`✓ Detected ${result.detected} MCP servers:`);
164
+ result.servers.forEach((s) => console.log(` - ${s}`));
165
+ console.log(`\n${result.configured} configured for twins.`);
166
+ }
167
+ break;
168
+ }
169
+ case 'version':
170
+ case '-v':
171
+ case '--version': {
172
+ console.log(`MCP Twin v${VERSION}`);
173
+ console.log('Powered by Prax Chat - https://prax.chat');
174
+ break;
175
+ }
176
+ case 'help':
177
+ case '-h':
178
+ case '--help':
179
+ default: {
180
+ console.log(`
181
+ MCP Twin v${VERSION} - Zero-Downtime MCP Server Updates
182
+ ${'═'.repeat(50)}
183
+
184
+ Works with: Claude Desktop, VS Code, Cursor, Cline, Windsurf
185
+
186
+ Commands:
187
+ mcp-twin start <server> Start twin servers
188
+ mcp-twin stop <server> Stop twin servers (--all for all)
189
+ mcp-twin reload <server> Reload standby with new code
190
+ mcp-twin swap <server> Switch traffic to standby
191
+ mcp-twin status [server] Show twin status
192
+ mcp-twin detect Auto-detect MCP servers
193
+ mcp-twin help Show this help
194
+
195
+ Workflow:
196
+ 1. mcp-twin start my-server → Start A (active) + B (standby)
197
+ 2. Edit your server code
198
+ 3. mcp-twin reload my-server → Update standby B
199
+ 4. mcp-twin swap my-server → Switch to B (zero downtime!)
200
+
201
+ Config: ~/.mcp-twin/config.json
202
+ Logs: ~/.mcp-twin/logs/
203
+ ${PRAX_FOOTER}
204
+
205
+ Pro features: prax.chat/mcp-twin/pro
206
+ `);
207
+ break;
208
+ }
209
+ }
210
+ }
211
+ main().catch(err => {
212
+ console.error('Error:', err.message);
213
+ process.exit(1);
214
+ });
215
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Config Detector - Auto-detect MCP servers from multiple MCP clients
3
+ *
4
+ * Supports:
5
+ * - Claude Desktop
6
+ * - Claude Code
7
+ * - VS Code (GitHub Copilot)
8
+ * - Cursor
9
+ * - Cline
10
+ * - Windsurf
11
+ *
12
+ * Powered by Prax Chat - https://prax.chat
13
+ */
14
+ export interface DetectedServer {
15
+ name: string;
16
+ command: string;
17
+ args: string[];
18
+ scriptPath: string | null;
19
+ language: 'python' | 'node' | 'unknown';
20
+ source: string;
21
+ }
22
+ /**
23
+ * Assign deterministic ports based on server name
24
+ */
25
+ export declare function assignPorts(serverName: string): [number, number];
26
+ /**
27
+ * Detect MCP servers from all supported MCP clients
28
+ */
29
+ export declare function detectMCPServers(): DetectedServer[];
30
+ /**
31
+ * Detect MCP servers from Claude config only (legacy)
32
+ */
33
+ export declare function detectMCPServersFromClaude(): DetectedServer[];
34
+ /**
35
+ * Generate twin config from detected servers
36
+ */
37
+ export declare function generateTwinConfig(servers: DetectedServer[]): Record<string, any>;
38
+ /**
39
+ * Auto-detect and update twin config
40
+ */
41
+ export declare function autoConfigureTwins(): {
42
+ detected: number;
43
+ configured: number;
44
+ servers: string[];
45
+ };
46
+ declare const _default: {
47
+ detectMCPServers: typeof detectMCPServers;
48
+ generateTwinConfig: typeof generateTwinConfig;
49
+ autoConfigureTwins: typeof autoConfigureTwins;
50
+ assignPorts: typeof assignPorts;
51
+ };
52
+ export default _default;
53
+ //# sourceMappingURL=config-detector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-detector.d.ts","sourceRoot":"","sources":["../src/config-detector.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAiBH,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,QAAQ,EAAE,QAAQ,GAAG,MAAM,GAAG,SAAS,CAAC;IACxC,MAAM,EAAE,MAAM,CAAC;CAChB;AAsID;;GAEG;AACH,wBAAgB,WAAW,CAAC,UAAU,EAAE,MAAM,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAYhE;AAED;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,cAAc,EAAE,CAyCnD;AAED;;GAEG;AACH,wBAAgB,0BAA0B,IAAI,cAAc,EAAE,CAkC7D;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,cAAc,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAqBjF;AAED;;GAEG;AACH,wBAAgB,kBAAkB,IAAI;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,EAAE,CAAA;CAAE,CAShG;;;;;;;AAwBD,wBAKE"}