mcp-compose 0.0.1
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/LICENSE +21 -0
- package/README.md +257 -0
- package/dist/bin/mcp-compose.d.ts +3 -0
- package/dist/bin/mcp-compose.d.ts.map +1 -0
- package/dist/bin/mcp-compose.js +210 -0
- package/dist/bin/mcp-compose.js.map +1 -0
- package/dist/src/config.d.ts +16 -0
- package/dist/src/config.d.ts.map +1 -0
- package/dist/src/config.js +175 -0
- package/dist/src/config.js.map +1 -0
- package/dist/src/index.d.ts +7 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +6 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/pm2.d.ts +21 -0
- package/dist/src/pm2.d.ts.map +1 -0
- package/dist/src/pm2.js +236 -0
- package/dist/src/pm2.js.map +1 -0
- package/dist/src/supergateway.d.ts +3 -0
- package/dist/src/supergateway.d.ts.map +1 -0
- package/dist/src/supergateway.js +38 -0
- package/dist/src/supergateway.js.map +1 -0
- package/dist/src/sync.d.ts +4 -0
- package/dist/src/sync.d.ts.map +1 -0
- package/dist/src/sync.js +79 -0
- package/dist/src/sync.js.map +1 -0
- package/dist/src/types.d.ts +91 -0
- package/dist/src/types.d.ts.map +1 -0
- package/dist/src/types.js +2 -0
- package/dist/src/types.js.map +1 -0
- package/dist/src/validation.d.ts +13 -0
- package/dist/src/validation.d.ts.map +1 -0
- package/dist/src/validation.js +197 -0
- package/dist/src/validation.js.map +1 -0
- package/package.json +57 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 unsafe9
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
# mcp-compose
|
|
2
|
+
|
|
3
|
+
Orchestrate multiple MCP servers through a unified Streamable HTTP gateway. Converts stdio-based MCP servers to Streamable HTTP endpoints and manages them with pm2.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
No installation required - use `npx`. (RECOMMENDED)
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npx -y mcp-compose status
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
You can add an alias to `~/.bashrc` or `~/.zshrc`:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
alias mcp-compose='npx -y mcp-compose'
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Or install globally:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
npm install -g mcp-compose
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Quick Start
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
# Create config file (mcp-compose.json)
|
|
29
|
+
mcp-compose up # Start servers
|
|
30
|
+
mcp-compose status # Check status
|
|
31
|
+
mcp-compose down # Stop servers
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Configuration
|
|
35
|
+
|
|
36
|
+
Create `mcp-compose.json` (or `mcp-compose.jsonc`) in:
|
|
37
|
+
- Current directory
|
|
38
|
+
- `~/.config/mcp-compose/`
|
|
39
|
+
|
|
40
|
+
### Full Configuration Reference
|
|
41
|
+
|
|
42
|
+
```json
|
|
43
|
+
{
|
|
44
|
+
"settings": {
|
|
45
|
+
"portBase": 19100,
|
|
46
|
+
"claudeConfigPath": "~/.mcp.json",
|
|
47
|
+
"logLevel": "info"
|
|
48
|
+
},
|
|
49
|
+
"mcpServers": {
|
|
50
|
+
"my-server": { ... }
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### Settings
|
|
56
|
+
|
|
57
|
+
| Property | Type | Default | Description |
|
|
58
|
+
|----------|------|---------|-------------|
|
|
59
|
+
| `portBase` | number | `19100` | Starting port for stdio servers. Ports are allocated sequentially. |
|
|
60
|
+
| `claudeConfigPath` | string | `~/.mcp.json` | Path to Claude Code's MCP config file. Supports `~` for home directory. |
|
|
61
|
+
| `logLevel` | string | `"info"` | Default log level for supergateway. Options: `"debug"`, `"info"`, `"none"` |
|
|
62
|
+
|
|
63
|
+
### Server Types
|
|
64
|
+
|
|
65
|
+
#### stdio - Local Command Server
|
|
66
|
+
|
|
67
|
+
Runs a local command and wraps it with supergateway to expose as HTTP.
|
|
68
|
+
|
|
69
|
+
```json
|
|
70
|
+
{
|
|
71
|
+
"my-server": {
|
|
72
|
+
"type": "stdio",
|
|
73
|
+
"command": "uvx",
|
|
74
|
+
"args": ["package@latest"],
|
|
75
|
+
"env": {
|
|
76
|
+
"API_KEY": "xxx"
|
|
77
|
+
},
|
|
78
|
+
"logLevel": "info",
|
|
79
|
+
"resourceLimits": {
|
|
80
|
+
"maxMemory": "512M",
|
|
81
|
+
"maxRestarts": 10,
|
|
82
|
+
"restartDelay": 1000
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
| Property | Type | Required | Description |
|
|
89
|
+
|----------|------|----------|-------------|
|
|
90
|
+
| `type` | `"stdio"` | No | Auto-detected if `command` is present |
|
|
91
|
+
| `command` | string | Yes | The command to execute |
|
|
92
|
+
| `args` | string[] | No | Command arguments |
|
|
93
|
+
| `env` | object | No | Environment variables |
|
|
94
|
+
| `disabled` | boolean | No | Skip this server when starting |
|
|
95
|
+
| `logLevel` | string | No | Override log level: `"debug"`, `"info"`, `"none"` |
|
|
96
|
+
| `resourceLimits` | object | No | Process resource limits (see below) |
|
|
97
|
+
|
|
98
|
+
#### sse/http - Remote Server
|
|
99
|
+
|
|
100
|
+
Passthrough to remote MCP servers. No local process is started.
|
|
101
|
+
|
|
102
|
+
```json
|
|
103
|
+
{
|
|
104
|
+
"remote-server": {
|
|
105
|
+
"type": "sse",
|
|
106
|
+
"url": "https://example.com/sse"
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
| Property | Type | Required | Description |
|
|
112
|
+
|----------|------|----------|-------------|
|
|
113
|
+
| `type` | `"sse"` or `"http"` | Yes | Server type |
|
|
114
|
+
| `url` | string | Yes | Remote server URL |
|
|
115
|
+
| `disabled` | boolean | No | Skip this server |
|
|
116
|
+
|
|
117
|
+
### Resource Limits
|
|
118
|
+
|
|
119
|
+
Control pm2 process management behavior for stdio servers.
|
|
120
|
+
|
|
121
|
+
```json
|
|
122
|
+
{
|
|
123
|
+
"resourceLimits": {
|
|
124
|
+
"maxMemory": "512M",
|
|
125
|
+
"maxRestarts": 10,
|
|
126
|
+
"restartDelay": 1000
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
| Property | Type | Default | Description |
|
|
132
|
+
|----------|------|---------|-------------|
|
|
133
|
+
| `maxMemory` | string or number | - | Memory limit before restart. String: `"512M"`, `"1G"`. Number: bytes. |
|
|
134
|
+
| `maxRestarts` | number | `10` | Maximum restart attempts before giving up |
|
|
135
|
+
| `restartDelay` | number | `1000` | Delay between restarts in milliseconds |
|
|
136
|
+
|
|
137
|
+
### Disabling Servers
|
|
138
|
+
|
|
139
|
+
Add `"disabled": true` to skip a server without removing its config:
|
|
140
|
+
|
|
141
|
+
```json
|
|
142
|
+
{
|
|
143
|
+
"my-server": {
|
|
144
|
+
"command": "uvx",
|
|
145
|
+
"args": ["some-package"],
|
|
146
|
+
"disabled": true
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### Example Configuration
|
|
152
|
+
|
|
153
|
+
```json
|
|
154
|
+
{
|
|
155
|
+
"settings": {
|
|
156
|
+
"portBase": 19100,
|
|
157
|
+
"claudeConfigPath": "~/.mcp.json",
|
|
158
|
+
"logLevel": "info"
|
|
159
|
+
},
|
|
160
|
+
"mcpServers": {
|
|
161
|
+
"filesystem": {
|
|
162
|
+
"command": "npx",
|
|
163
|
+
"args": ["-y", "@anthropic/mcp-server-filesystem", "/home/user/documents"],
|
|
164
|
+
"resourceLimits": {
|
|
165
|
+
"maxMemory": "256M"
|
|
166
|
+
}
|
|
167
|
+
},
|
|
168
|
+
"github": {
|
|
169
|
+
"command": "uvx",
|
|
170
|
+
"args": ["mcp-server-github"],
|
|
171
|
+
"env": {
|
|
172
|
+
"GITHUB_TOKEN": "ghp_xxx"
|
|
173
|
+
}
|
|
174
|
+
},
|
|
175
|
+
"aws-docs": {
|
|
176
|
+
"type": "http",
|
|
177
|
+
"url": "https://mcp.aws.example.com/mcp"
|
|
178
|
+
},
|
|
179
|
+
"experimental": {
|
|
180
|
+
"command": "node",
|
|
181
|
+
"args": ["./my-experimental-server.js"],
|
|
182
|
+
"disabled": true
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
## CLI Reference
|
|
189
|
+
|
|
190
|
+
```
|
|
191
|
+
mcp-compose up [servers...] Start all or specific servers
|
|
192
|
+
mcp-compose down [servers...] Stop servers
|
|
193
|
+
mcp-compose restart [servers...] Restart servers
|
|
194
|
+
mcp-compose status Show running servers
|
|
195
|
+
mcp-compose logs [server] [-f] View logs (follow with -f)
|
|
196
|
+
mcp-compose startup Enable auto-start on boot
|
|
197
|
+
mcp-compose unstartup Disable auto-start
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
### Options
|
|
201
|
+
|
|
202
|
+
| Option | Description |
|
|
203
|
+
|--------|-------------|
|
|
204
|
+
| `-c, --config <path>` | Specify config file path |
|
|
205
|
+
| `-V, --version` | Show version |
|
|
206
|
+
| `-h, --help` | Show help |
|
|
207
|
+
|
|
208
|
+
### Examples
|
|
209
|
+
|
|
210
|
+
```bash
|
|
211
|
+
# Start all servers
|
|
212
|
+
mcp-compose up
|
|
213
|
+
|
|
214
|
+
# Start specific servers
|
|
215
|
+
mcp-compose up github filesystem
|
|
216
|
+
|
|
217
|
+
# Stop specific servers
|
|
218
|
+
mcp-compose down github
|
|
219
|
+
|
|
220
|
+
# Stop all servers
|
|
221
|
+
mcp-compose down
|
|
222
|
+
|
|
223
|
+
# Use custom config file
|
|
224
|
+
mcp-compose -c ./custom-config.json up
|
|
225
|
+
|
|
226
|
+
# View logs for specific server
|
|
227
|
+
mcp-compose logs github
|
|
228
|
+
|
|
229
|
+
# Follow all logs
|
|
230
|
+
mcp-compose logs -f
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
## How It Works
|
|
234
|
+
|
|
235
|
+
1. **stdio servers**: Started via pm2 using `supergateway` to expose Streamable HTTP endpoints
|
|
236
|
+
2. **Remote servers**: Registered directly (no local process)
|
|
237
|
+
3. **Config sync**: Auto-updates `~/.mcp.json` for Claude Code integration
|
|
238
|
+
4. **Port allocation**: Automatically detects port conflicts and uses next available port
|
|
239
|
+
|
|
240
|
+
Each stdio server gets an internal port starting from `portBase` (default 19100). If a port is in use, the next available port is automatically selected.
|
|
241
|
+
|
|
242
|
+
## Features
|
|
243
|
+
|
|
244
|
+
- **Automatic port conflict detection**: Skips ports in use and allocates next available
|
|
245
|
+
- **Config validation**: Validates configuration structure with helpful error messages
|
|
246
|
+
- **Progress feedback**: Shows real-time progress during server operations
|
|
247
|
+
- **Resource limits**: Control memory usage and restart behavior per server
|
|
248
|
+
- **Process management**: Auto-restart with configurable limits via pm2
|
|
249
|
+
- **Non-destructive config sync**: Merges with existing Claude Code config
|
|
250
|
+
|
|
251
|
+
## Requirements
|
|
252
|
+
|
|
253
|
+
- Node.js 18+ (includes npx)
|
|
254
|
+
|
|
255
|
+
## License
|
|
256
|
+
|
|
257
|
+
MIT
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-compose.d.ts","sourceRoot":"","sources":["../../bin/mcp-compose.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { Command } from 'commander';
|
|
3
|
+
import { loadConfig, getStdioServers, getServerNames, allocatePorts, } from '../src/config.js';
|
|
4
|
+
import { startServers, stopServers, stopAllManagedServers, restartServers, getStatus, streamLogs, setupStartup, saveProcessList, unstartup, } from '../src/pm2.js';
|
|
5
|
+
import { syncToClaudeConfig, removeFromClaudeConfig } from '../src/sync.js';
|
|
6
|
+
function formatProgress(event) {
|
|
7
|
+
const progress = event.total ? `[${String(event.current)}/${String(event.total)}]` : '';
|
|
8
|
+
switch (event.type) {
|
|
9
|
+
case 'checking_ports':
|
|
10
|
+
return ` ⋯ Checking port availability...`;
|
|
11
|
+
case 'port_skipped':
|
|
12
|
+
return ` ⚠ Port ${String(event.originalPort)} in use, using ${String(event.port)} instead`;
|
|
13
|
+
case 'starting':
|
|
14
|
+
return ` ${progress} Starting ${event.server}...`;
|
|
15
|
+
case 'started':
|
|
16
|
+
return ` ${progress} ✓ ${event.server} → http://localhost:${String(event.port)}/mcp`;
|
|
17
|
+
case 'stopping':
|
|
18
|
+
return ` ${progress} Stopping ${event.server}...`;
|
|
19
|
+
case 'stopped':
|
|
20
|
+
return ` ${progress} ✓ ${event.server} stopped`;
|
|
21
|
+
default:
|
|
22
|
+
return '';
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
function printProgress(event) {
|
|
26
|
+
const msg = formatProgress(event);
|
|
27
|
+
if (msg)
|
|
28
|
+
console.log(msg);
|
|
29
|
+
}
|
|
30
|
+
const program = new Command();
|
|
31
|
+
function getConfigPath(cmd) {
|
|
32
|
+
return cmd.parent?.opts().config;
|
|
33
|
+
}
|
|
34
|
+
function handleError(err) {
|
|
35
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
36
|
+
console.error('Error:', message);
|
|
37
|
+
process.exit(1);
|
|
38
|
+
}
|
|
39
|
+
program
|
|
40
|
+
.name('mcp-compose')
|
|
41
|
+
.description('MCP server orchestration tool')
|
|
42
|
+
.version('0.1.0')
|
|
43
|
+
.option('-c, --config <path>', 'Path to config file');
|
|
44
|
+
program
|
|
45
|
+
.command('up')
|
|
46
|
+
.description('Start MCP servers')
|
|
47
|
+
.argument('[servers...]', 'Specific servers to start (default: all)')
|
|
48
|
+
.action(async (servers, _options, cmd) => {
|
|
49
|
+
try {
|
|
50
|
+
const config = loadConfig(getConfigPath(cmd));
|
|
51
|
+
const { processPrefix } = config.settings;
|
|
52
|
+
const stdioServers = getStdioServers(config);
|
|
53
|
+
const filteredServers = servers.length > 0
|
|
54
|
+
? stdioServers.filter((s) => servers.includes(s.name))
|
|
55
|
+
: stdioServers;
|
|
56
|
+
if (filteredServers.length === 0 && servers.length > 0) {
|
|
57
|
+
console.log('No stdio servers match the filter. Remote servers are synced directly.');
|
|
58
|
+
}
|
|
59
|
+
if (filteredServers.length > 0) {
|
|
60
|
+
console.log(`Starting ${String(filteredServers.length)} stdio server(s)...\n`);
|
|
61
|
+
// Check port availability and allocate ports
|
|
62
|
+
console.log(' ⋯ Checking port availability...');
|
|
63
|
+
const ports = await allocatePorts(filteredServers.length, config.settings.portBase, (originalPort, assignedPort) => {
|
|
64
|
+
console.log(` ⚠ Port ${String(originalPort)} in use, using ${String(assignedPort)} instead`);
|
|
65
|
+
});
|
|
66
|
+
// Update servers with allocated ports
|
|
67
|
+
const serversWithPorts = filteredServers.map((server, i) => {
|
|
68
|
+
const port = ports[i];
|
|
69
|
+
if (port === undefined) {
|
|
70
|
+
throw new Error(`Port allocation failed for server ${server.name}`);
|
|
71
|
+
}
|
|
72
|
+
return { ...server, internalPort: port };
|
|
73
|
+
});
|
|
74
|
+
console.log('');
|
|
75
|
+
await startServers(serversWithPorts, processPrefix, printProgress);
|
|
76
|
+
}
|
|
77
|
+
console.log('\nSyncing to Claude Code config...');
|
|
78
|
+
const syncResult = syncToClaudeConfig(config);
|
|
79
|
+
console.log(` ✓ Updated ${syncResult.path}`);
|
|
80
|
+
console.log(` Servers: ${syncResult.servers.join(', ')}`);
|
|
81
|
+
console.log('\nMCP servers are running via pm2.');
|
|
82
|
+
console.log('Use "mcp-compose status" to check status.');
|
|
83
|
+
console.log('Use "mcp-compose logs" to view logs.');
|
|
84
|
+
}
|
|
85
|
+
catch (err) {
|
|
86
|
+
handleError(err);
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
program
|
|
90
|
+
.command('down')
|
|
91
|
+
.description('Stop MCP servers')
|
|
92
|
+
.argument('[servers...]', 'Specific servers to stop (default: all)')
|
|
93
|
+
.action(async (servers, _options, cmd) => {
|
|
94
|
+
try {
|
|
95
|
+
const config = loadConfig(getConfigPath(cmd));
|
|
96
|
+
const { processPrefix } = config.settings;
|
|
97
|
+
if (servers.length > 0) {
|
|
98
|
+
const validServers = getServerNames(config, servers);
|
|
99
|
+
console.log(`Stopping ${String(validServers.length)} server(s)...\n`);
|
|
100
|
+
await stopServers(validServers, processPrefix, printProgress);
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
console.log('Stopping all MCP servers...');
|
|
104
|
+
const count = await stopAllManagedServers();
|
|
105
|
+
console.log(` ✓ Stopped ${String(count)} server(s)`);
|
|
106
|
+
}
|
|
107
|
+
console.log('\nRemoving from Claude Code config...');
|
|
108
|
+
const removeResult = removeFromClaudeConfig(config, servers.length > 0 ? servers : null);
|
|
109
|
+
if (removeResult.removed.length > 0) {
|
|
110
|
+
console.log(` ✓ Removed: ${removeResult.removed.join(', ')}`);
|
|
111
|
+
}
|
|
112
|
+
else {
|
|
113
|
+
console.log(' (no changes)');
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
catch (err) {
|
|
117
|
+
handleError(err);
|
|
118
|
+
}
|
|
119
|
+
});
|
|
120
|
+
program
|
|
121
|
+
.command('restart')
|
|
122
|
+
.description('Restart MCP servers')
|
|
123
|
+
.argument('[servers...]', 'Specific servers to restart (default: all)')
|
|
124
|
+
.action(async (servers, _options, cmd) => {
|
|
125
|
+
try {
|
|
126
|
+
const config = loadConfig(getConfigPath(cmd));
|
|
127
|
+
const { processPrefix } = config.settings;
|
|
128
|
+
const stdioServers = getStdioServers(config);
|
|
129
|
+
const serverNames = servers.length > 0 ? servers : stdioServers.map((s) => s.name);
|
|
130
|
+
console.log(`Restarting ${String(serverNames.length)} server(s)...`);
|
|
131
|
+
await restartServers(serverNames, processPrefix);
|
|
132
|
+
for (const name of serverNames) {
|
|
133
|
+
console.log(` ✓ ${name} restarted`);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
catch (err) {
|
|
137
|
+
handleError(err);
|
|
138
|
+
}
|
|
139
|
+
});
|
|
140
|
+
program
|
|
141
|
+
.command('status')
|
|
142
|
+
.description('Show status of MCP servers')
|
|
143
|
+
.action(async () => {
|
|
144
|
+
try {
|
|
145
|
+
const status = await getStatus();
|
|
146
|
+
if (status.length === 0) {
|
|
147
|
+
console.log('No MCP servers running.');
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
console.log('MCP Servers:\n');
|
|
151
|
+
console.log(' Name Status PID Memory Restarts');
|
|
152
|
+
console.log(' ' + '-'.repeat(65));
|
|
153
|
+
for (const s of status) {
|
|
154
|
+
const memory = s.memory
|
|
155
|
+
? `${String(Math.round(s.memory / 1024 / 1024))}MB`
|
|
156
|
+
: '-';
|
|
157
|
+
const statusColor = s.status === 'online' ? '\x1b[32m' : '\x1b[31m';
|
|
158
|
+
const reset = '\x1b[0m';
|
|
159
|
+
console.log(` ${s.name.padEnd(20)} ${statusColor}${s.status.padEnd(10)}${reset} ${String(s.pid ?? '-').padEnd(8)} ${memory.padEnd(10)} ${String(s.restarts)}`);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
catch (err) {
|
|
163
|
+
handleError(err);
|
|
164
|
+
}
|
|
165
|
+
});
|
|
166
|
+
program
|
|
167
|
+
.command('logs')
|
|
168
|
+
.description('View server logs')
|
|
169
|
+
.argument('[server]', 'Server name (default: all)')
|
|
170
|
+
.option('-f, --follow', 'Follow log output')
|
|
171
|
+
.action((server, _options, cmd) => {
|
|
172
|
+
try {
|
|
173
|
+
const config = loadConfig(getConfigPath(cmd));
|
|
174
|
+
const { processPrefix } = config.settings;
|
|
175
|
+
streamLogs(server, processPrefix);
|
|
176
|
+
}
|
|
177
|
+
catch (err) {
|
|
178
|
+
handleError(err);
|
|
179
|
+
}
|
|
180
|
+
});
|
|
181
|
+
program
|
|
182
|
+
.command('startup')
|
|
183
|
+
.description('Enable auto-start on system boot')
|
|
184
|
+
.action(async () => {
|
|
185
|
+
try {
|
|
186
|
+
console.log('Setting up pm2 startup...');
|
|
187
|
+
await setupStartup();
|
|
188
|
+
console.log('\nSaving current process list...');
|
|
189
|
+
await saveProcessList();
|
|
190
|
+
console.log('\n✓ Auto-start enabled. MCP servers will start on boot.');
|
|
191
|
+
}
|
|
192
|
+
catch (err) {
|
|
193
|
+
handleError(err);
|
|
194
|
+
}
|
|
195
|
+
});
|
|
196
|
+
program
|
|
197
|
+
.command('unstartup')
|
|
198
|
+
.description('Disable auto-start on system boot')
|
|
199
|
+
.action(async () => {
|
|
200
|
+
try {
|
|
201
|
+
console.log('Removing pm2 startup...');
|
|
202
|
+
await unstartup();
|
|
203
|
+
console.log('\n✓ Auto-start disabled.');
|
|
204
|
+
}
|
|
205
|
+
catch (err) {
|
|
206
|
+
handleError(err);
|
|
207
|
+
}
|
|
208
|
+
});
|
|
209
|
+
program.parse();
|
|
210
|
+
//# sourceMappingURL=mcp-compose.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-compose.js","sourceRoot":"","sources":["../../bin/mcp-compose.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { RawConfig, NormalizedConfig, NamedStdioServer } from './types.js';
|
|
2
|
+
export declare function expandPath(p: string): string;
|
|
3
|
+
export declare function findConfigFile(startDir?: string): string | null;
|
|
4
|
+
export declare function loadConfig(configPath?: string): NormalizedConfig;
|
|
5
|
+
/**
|
|
6
|
+
* Check if a port is available
|
|
7
|
+
*/
|
|
8
|
+
export declare function isPortAvailable(port: number): Promise<boolean>;
|
|
9
|
+
/**
|
|
10
|
+
* Allocate available ports for servers, skipping ports that are in use
|
|
11
|
+
*/
|
|
12
|
+
export declare function allocatePorts(serverCount: number, portBase: number, onPortSkipped?: (port: number, assignedPort: number) => void): Promise<number[]>;
|
|
13
|
+
export declare function normalizeConfig(config: RawConfig): NormalizedConfig;
|
|
14
|
+
export declare function getServerNames(config: NormalizedConfig, filter?: string[]): string[];
|
|
15
|
+
export declare function getStdioServers(config: NormalizedConfig): NamedStdioServer[];
|
|
16
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/config.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAEV,SAAS,EAET,gBAAgB,EAGhB,gBAAgB,EAEjB,MAAM,YAAY,CAAC;AAiBpB,wBAAgB,UAAU,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAK5C;AAED,wBAAgB,cAAc,CAAC,QAAQ,GAAE,MAAsB,GAAG,MAAM,GAAG,IAAI,CAe9E;AAED,wBAAgB,UAAU,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,gBAAgB,CA0BhE;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAa9D;AAkBD;;GAEG;AACH,wBAAsB,aAAa,CACjC,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,EAChB,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,KAAK,IAAI,GAC3D,OAAO,CAAC,MAAM,EAAE,CAAC,CAcnB;AAED,wBAAgB,eAAe,CAAC,MAAM,EAAE,SAAS,GAAG,gBAAgB,CAyBnE;AA0CD,wBAAgB,cAAc,CAC5B,MAAM,EAAE,gBAAgB,EACxB,MAAM,GAAE,MAAM,EAAO,GACpB,MAAM,EAAE,CAgBV;AAED,wBAAgB,eAAe,CAAC,MAAM,EAAE,gBAAgB,GAAG,gBAAgB,EAAE,CAI5E"}
|