closeli-mcp-gateway 1.0.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/.env.example +30 -0
- package/LICENSE +21 -0
- package/README.md +298 -0
- package/dist/config/environment.d.ts +29 -0
- package/dist/config/environment.d.ts.map +1 -0
- package/dist/config/environment.js +48 -0
- package/dist/config/environment.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +61 -0
- package/dist/index.js.map +1 -0
- package/dist/server.d.ts +14 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +201 -0
- package/dist/server.js.map +1 -0
- package/dist/session/ProcessExecutor.d.ts +20 -0
- package/dist/session/ProcessExecutor.d.ts.map +1 -0
- package/dist/session/ProcessExecutor.js +286 -0
- package/dist/session/ProcessExecutor.js.map +1 -0
- package/dist/session/Session.d.ts +60 -0
- package/dist/session/Session.d.ts.map +1 -0
- package/dist/session/Session.js +5 -0
- package/dist/session/Session.js.map +1 -0
- package/dist/session/SessionManager.d.ts +53 -0
- package/dist/session/SessionManager.d.ts.map +1 -0
- package/dist/session/SessionManager.js +228 -0
- package/dist/session/SessionManager.js.map +1 -0
- package/dist/tools/claude-code.d.ts +17 -0
- package/dist/tools/claude-code.d.ts.map +1 -0
- package/dist/tools/claude-code.js +79 -0
- package/dist/tools/claude-code.js.map +1 -0
- package/dist/tools/codex.d.ts +17 -0
- package/dist/tools/codex.d.ts.map +1 -0
- package/dist/tools/codex.js +79 -0
- package/dist/tools/codex.js.map +1 -0
- package/dist/tools/get-session-status.d.ts +16 -0
- package/dist/tools/get-session-status.d.ts.map +1 -0
- package/dist/tools/get-session-status.js +88 -0
- package/dist/tools/get-session-status.js.map +1 -0
- package/dist/tools/resume.d.ts +16 -0
- package/dist/tools/resume.d.ts.map +1 -0
- package/dist/tools/resume.js +68 -0
- package/dist/tools/resume.js.map +1 -0
- package/dist/tools/types.d.ts +28 -0
- package/dist/tools/types.d.ts.map +1 -0
- package/dist/tools/types.js +74 -0
- package/dist/tools/types.js.map +1 -0
- package/dist/utils/errors.d.ts +54 -0
- package/dist/utils/errors.d.ts.map +1 -0
- package/dist/utils/errors.js +66 -0
- package/dist/utils/errors.js.map +1 -0
- package/dist/utils/logger.d.ts +14 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +80 -0
- package/dist/utils/logger.js.map +1 -0
- package/package.json +52 -0
package/.env.example
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# MCP Long-Running Command Server Configuration
|
|
2
|
+
|
|
3
|
+
# Response timeout in milliseconds (default: 50000ms = 50 seconds)
|
|
4
|
+
# How long to wait before returning sessionId to client
|
|
5
|
+
RESPONSE_TIMEOUT_MS=50000
|
|
6
|
+
|
|
7
|
+
# Orphan cleanup threshold in minutes (default: 10 minutes)
|
|
8
|
+
# Sessions with no client check for this duration will be killed
|
|
9
|
+
ORPHAN_CLEANUP_MIN=10
|
|
10
|
+
|
|
11
|
+
# Logging level (options: error, warn, info, debug)
|
|
12
|
+
LOG_LEVEL=info
|
|
13
|
+
|
|
14
|
+
# Enable file logging (options: true, false)
|
|
15
|
+
# When enabled, logs will be written to logs/ directory:
|
|
16
|
+
# - logs/error.log - Error logs only
|
|
17
|
+
# - logs/combined.log - All logs in JSON format
|
|
18
|
+
# - logs/process-output.log - Real-time process output
|
|
19
|
+
ENABLE_FILE_LOGGING=false
|
|
20
|
+
|
|
21
|
+
# Verbose mode (options: true, false)
|
|
22
|
+
# When enabled:
|
|
23
|
+
# - claude-code: Uses --verbose and --output-format stream-json
|
|
24
|
+
# * All streaming output logged
|
|
25
|
+
# * Only final result returned to client
|
|
26
|
+
# - codex: Uses --json
|
|
27
|
+
# * All JSON output logged
|
|
28
|
+
# * Only agent_message and turn.completed returned to client
|
|
29
|
+
# - Other commands may also output more detailed information
|
|
30
|
+
VERBOSE=false
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025
|
|
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,298 @@
|
|
|
1
|
+
# MCP Long-Running Command Server
|
|
2
|
+
|
|
3
|
+
A TypeScript/Node.js MCP server that handles long-running commands (codex, claude-code) through session management to solve client timeout limitations.
|
|
4
|
+
|
|
5
|
+
## Core Features
|
|
6
|
+
|
|
7
|
+
### Three Tools
|
|
8
|
+
|
|
9
|
+
1. **codex** - Start a new codex task
|
|
10
|
+
- Parameters: `workspace` (working directory), `prompt` (task prompt)
|
|
11
|
+
- Executes: `codex exec --full-auto --skip-git-repo-check [prompt]`
|
|
12
|
+
|
|
13
|
+
2. **claude-code** - Start a new claude-code task
|
|
14
|
+
- Parameters: `workspace` (working directory), `prompt` (task prompt)
|
|
15
|
+
- Executes: `claude --print --dangerously-skip-permissions [prompt]`
|
|
16
|
+
|
|
17
|
+
3. **resume** - Continue waiting for any task result
|
|
18
|
+
- Parameters: `sessionId` (session ID)
|
|
19
|
+
- Universal tool, works with any task type
|
|
20
|
+
|
|
21
|
+
4. **get-session-status** - Query task running status ✨
|
|
22
|
+
- Parameters: `sessionId` (session ID)
|
|
23
|
+
- View runtime duration, output line count, recent output, etc.
|
|
24
|
+
|
|
25
|
+
### Workflow
|
|
26
|
+
|
|
27
|
+
```
|
|
28
|
+
Client calls codex or claude-code
|
|
29
|
+
↓
|
|
30
|
+
Server starts process, waits 50 seconds
|
|
31
|
+
↓
|
|
32
|
+
Complete? → Yes → Return result
|
|
33
|
+
↓ No
|
|
34
|
+
Return sessionId
|
|
35
|
+
↓
|
|
36
|
+
Client calls resume + sessionId
|
|
37
|
+
↓
|
|
38
|
+
Continue waiting 50 seconds
|
|
39
|
+
↓
|
|
40
|
+
Complete? → Yes → Return result
|
|
41
|
+
↓ No
|
|
42
|
+
Return sessionId (repeat)
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Installation
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
# Clone or initialize project
|
|
49
|
+
npm install
|
|
50
|
+
|
|
51
|
+
# Copy environment configuration
|
|
52
|
+
cp .env.example .env
|
|
53
|
+
|
|
54
|
+
# Modify .env file as needed
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Configuration
|
|
58
|
+
|
|
59
|
+
Environment variables (configure in `.env` file):
|
|
60
|
+
|
|
61
|
+
| Variable | Default | Description |
|
|
62
|
+
|----------|---------|-------------|
|
|
63
|
+
| `RESPONSE_TIMEOUT_MS` | 50000 | Response timeout (milliseconds), returns sessionId on timeout |
|
|
64
|
+
| `ORPHAN_CLEANUP_MIN` | 10 | Orphan session cleanup threshold (minutes) |
|
|
65
|
+
| `LOG_LEVEL` | info | Log level: error, warn, info, debug |
|
|
66
|
+
| `ENABLE_FILE_LOGGING` | false | Enable file logging to logs/ directory |
|
|
67
|
+
| `VERBOSE` | false | Enable verbose mode (affects claude-code output format) |
|
|
68
|
+
|
|
69
|
+
### Verbose Mode 🎯
|
|
70
|
+
|
|
71
|
+
When `VERBOSE=true`, the claude-code tool uses `--verbose --output-format stream-json`:
|
|
72
|
+
- All 127+ line stream outputs are logged for monitoring execution
|
|
73
|
+
- Only the final `result` message (containing complete answer and statistics) is returned to the client
|
|
74
|
+
- Significantly reduces client data transfer
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
# Enable verbose mode (recommended)
|
|
78
|
+
VERBOSE=true npm run dev
|
|
79
|
+
|
|
80
|
+
# Disable verbose mode (default)
|
|
81
|
+
VERBOSE=false npm run dev
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### Real-time Process Output Monitoring ⚡
|
|
85
|
+
|
|
86
|
+
The server logs process output in real-time to logs (output to stderr, doesn't affect MCP's stdio communication):
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
# Run server and view real-time output in console
|
|
90
|
+
npm run dev
|
|
91
|
+
|
|
92
|
+
# You'll see output like:
|
|
93
|
+
2025-12-29 10:30:15 [codex:abc12345] Analyzing project structure...
|
|
94
|
+
2025-12-29 10:30:16 [codex:abc12345] Found 15 files
|
|
95
|
+
2025-12-29 10:30:17 [codex:abc12345] ⚠️ Warning: Some files may need manual handling
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
**Enable File Logging:**
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
# Method 1: Set environment variable
|
|
102
|
+
ENABLE_FILE_LOGGING=true npm run dev
|
|
103
|
+
|
|
104
|
+
# Method 2: Set in .env file
|
|
105
|
+
ENABLE_FILE_LOGGING=true
|
|
106
|
+
|
|
107
|
+
# Log file locations:
|
|
108
|
+
# - logs/error.log - Error logs only
|
|
109
|
+
# - logs/combined.log - All logs (JSON format)
|
|
110
|
+
# - logs/process-output.log - Real-time process output
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
## Running
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
# Development environment
|
|
117
|
+
npm run dev
|
|
118
|
+
|
|
119
|
+
# Production environment
|
|
120
|
+
npm run build
|
|
121
|
+
npm start
|
|
122
|
+
|
|
123
|
+
# Use custom configuration
|
|
124
|
+
RESPONSE_TIMEOUT_MS=60000 ORPHAN_CLEANUP_MIN=15 npm start
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
## Usage Examples
|
|
128
|
+
|
|
129
|
+
### Example 1: Quick Task
|
|
130
|
+
|
|
131
|
+
```typescript
|
|
132
|
+
// Call codex tool
|
|
133
|
+
{
|
|
134
|
+
"name": "codex",
|
|
135
|
+
"arguments": {
|
|
136
|
+
"workspace": "/path/to/project",
|
|
137
|
+
"prompt": "List files in current directory"
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// Response (task completes within 50 seconds)
|
|
142
|
+
{
|
|
143
|
+
"content": [{
|
|
144
|
+
"type": "text",
|
|
145
|
+
"text": "Standard output:\nfile1.txt\nfile2.txt\n\nExit code: 0\nStatus: completed"
|
|
146
|
+
}],
|
|
147
|
+
"_meta": {
|
|
148
|
+
"exitCode": 0,
|
|
149
|
+
"status": "completed"
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### Example 2: Long-Running Task
|
|
155
|
+
|
|
156
|
+
```typescript
|
|
157
|
+
// First call to codex tool
|
|
158
|
+
{
|
|
159
|
+
"name": "codex",
|
|
160
|
+
"arguments": {
|
|
161
|
+
"workspace": "/path/to/large-project",
|
|
162
|
+
"prompt": "Implement a complete user authentication system"
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// Response (task not complete, returns sessionId)
|
|
167
|
+
{
|
|
168
|
+
"content": [{
|
|
169
|
+
"type": "text",
|
|
170
|
+
"text": "Task is still running. Use resume tool to continue waiting with sessionId=\"abc-123-def-456\""
|
|
171
|
+
}],
|
|
172
|
+
"_meta": {
|
|
173
|
+
"status": "running",
|
|
174
|
+
"sessionId": "abc-123-def-456",
|
|
175
|
+
"toolType": "codex"
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// Use resume to continue waiting
|
|
180
|
+
{
|
|
181
|
+
"name": "resume",
|
|
182
|
+
"arguments": {
|
|
183
|
+
"sessionId": "abc-123-def-456"
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// If still not complete, continues returning sessionId
|
|
188
|
+
// If complete, returns final result
|
|
189
|
+
{
|
|
190
|
+
"content": [{
|
|
191
|
+
"type": "text",
|
|
192
|
+
"text": "Standard output:\n[Detailed implementation output]\n\nExit code: 0\nStatus: completed"
|
|
193
|
+
}],
|
|
194
|
+
"_meta": {
|
|
195
|
+
"exitCode": 0,
|
|
196
|
+
"status": "completed"
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
## Architecture Design
|
|
202
|
+
|
|
203
|
+
### Core Components
|
|
204
|
+
|
|
205
|
+
```
|
|
206
|
+
src/
|
|
207
|
+
├── config/
|
|
208
|
+
│ └── environment.ts # Environment variable configuration
|
|
209
|
+
├── utils/
|
|
210
|
+
│ ├── logger.ts # Winston logger
|
|
211
|
+
│ └── errors.ts # Custom error classes
|
|
212
|
+
├── session/
|
|
213
|
+
│ ├── Session.ts # Session type definitions
|
|
214
|
+
│ ├── ProcessExecutor.ts # Process startup and monitoring
|
|
215
|
+
│ └── SessionManager.ts # Session management core logic
|
|
216
|
+
├── tools/
|
|
217
|
+
│ ├── types.ts # Tool common types
|
|
218
|
+
│ ├── codex.ts # Codex tool
|
|
219
|
+
│ ├── claude-code.ts # Claude Code tool
|
|
220
|
+
│ └── resume.ts # Resume tool
|
|
221
|
+
├── server.ts # MCP server setup
|
|
222
|
+
└── index.ts # Entry point
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
### Key Features
|
|
226
|
+
|
|
227
|
+
1. **Session Management**
|
|
228
|
+
- In-memory Map to store sessions
|
|
229
|
+
- Each session contains: process reference, output buffer, timestamp, status
|
|
230
|
+
|
|
231
|
+
2. **Timeout Mechanism**
|
|
232
|
+
- Response timeout: default 50 seconds (configurable)
|
|
233
|
+
- Orphan cleanup: default 10 minutes (configurable)
|
|
234
|
+
|
|
235
|
+
3. **Process Management**
|
|
236
|
+
- Uses `child_process.spawn()`
|
|
237
|
+
- Output buffer limit: 10,000 lines
|
|
238
|
+
- Graceful termination: SIGTERM → SIGKILL
|
|
239
|
+
|
|
240
|
+
4. **Security Considerations**
|
|
241
|
+
- `shell: false` prevents injection
|
|
242
|
+
- Path validation prevents traversal attacks
|
|
243
|
+
- SessionId UUID format validation
|
|
244
|
+
|
|
245
|
+
## Troubleshooting
|
|
246
|
+
|
|
247
|
+
### Issue: Task keeps returning sessionId but never completes
|
|
248
|
+
|
|
249
|
+
**Possible Causes**:
|
|
250
|
+
- Task is actually running and needs more time
|
|
251
|
+
- Process is stuck or waiting for input
|
|
252
|
+
|
|
253
|
+
**Solutions**:
|
|
254
|
+
- Check logs to view process status
|
|
255
|
+
- Increase `RESPONSE_TIMEOUT_MS`
|
|
256
|
+
- Ensure command doesn't require interactive input
|
|
257
|
+
|
|
258
|
+
### Issue: Session not found
|
|
259
|
+
|
|
260
|
+
**Possible Causes**:
|
|
261
|
+
- Session has been cleaned up by orphan cleanup mechanism
|
|
262
|
+
- Incorrect SessionId
|
|
263
|
+
|
|
264
|
+
**Solutions**:
|
|
265
|
+
- Reduce interval between resume calls
|
|
266
|
+
- Increase `ORPHAN_CLEANUP_MIN`
|
|
267
|
+
- Verify sessionId is correct
|
|
268
|
+
|
|
269
|
+
### Issue: High memory usage
|
|
270
|
+
|
|
271
|
+
**Possible Causes**:
|
|
272
|
+
- Large output buffer
|
|
273
|
+
- Too many concurrent sessions
|
|
274
|
+
|
|
275
|
+
**Solutions**:
|
|
276
|
+
- Output is already limited to 10,000 lines
|
|
277
|
+
- Regularly clean orphan sessions
|
|
278
|
+
- Monitor active session count
|
|
279
|
+
|
|
280
|
+
## Development
|
|
281
|
+
|
|
282
|
+
```bash
|
|
283
|
+
# Install dependencies
|
|
284
|
+
npm install
|
|
285
|
+
|
|
286
|
+
# Development mode (hot reload)
|
|
287
|
+
npm run dev
|
|
288
|
+
|
|
289
|
+
# Build
|
|
290
|
+
npm run build
|
|
291
|
+
|
|
292
|
+
# Run tests
|
|
293
|
+
npm test
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
## License
|
|
297
|
+
|
|
298
|
+
MIT
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Environment Configuration Module
|
|
3
|
+
* Parses and validates environment variables, provides default values
|
|
4
|
+
*/
|
|
5
|
+
export interface Config {
|
|
6
|
+
/** Response timeout (milliseconds), default 50 seconds */
|
|
7
|
+
RESPONSE_TIMEOUT_MS: number;
|
|
8
|
+
/** Orphan cleanup threshold (milliseconds), default 10 minutes */
|
|
9
|
+
ORPHAN_CLEANUP_MS: number;
|
|
10
|
+
/** Cleanup check interval (milliseconds), default 60 seconds */
|
|
11
|
+
CLEANUP_INTERVAL_MS: number;
|
|
12
|
+
/** Maximum output lines limit */
|
|
13
|
+
MAX_OUTPUT_LINES: number;
|
|
14
|
+
/** Process termination grace period (milliseconds) */
|
|
15
|
+
KILL_GRACE_PERIOD_MS: number;
|
|
16
|
+
/** Log level */
|
|
17
|
+
LOG_LEVEL: string;
|
|
18
|
+
/** Whether to enable verbose mode (affects claude-code output format) */
|
|
19
|
+
VERBOSE: boolean;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Load configuration from environment variables
|
|
23
|
+
*/
|
|
24
|
+
export declare const config: Config;
|
|
25
|
+
/**
|
|
26
|
+
* Validate configuration reasonableness
|
|
27
|
+
*/
|
|
28
|
+
export declare function validateConfig(): void;
|
|
29
|
+
//# sourceMappingURL=environment.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"environment.d.ts","sourceRoot":"","sources":["../../src/config/environment.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,MAAM;IACrB,0DAA0D;IAC1D,mBAAmB,EAAE,MAAM,CAAC;IAC5B,kEAAkE;IAClE,iBAAiB,EAAE,MAAM,CAAC;IAC1B,gEAAgE;IAChE,mBAAmB,EAAE,MAAM,CAAC;IAC5B,iCAAiC;IACjC,gBAAgB,EAAE,MAAM,CAAC;IACzB,sDAAsD;IACtD,oBAAoB,EAAE,MAAM,CAAC;IAC7B,gBAAgB;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,yEAAyE;IACzE,OAAO,EAAE,OAAO,CAAC;CAClB;AAmBD;;GAEG;AACH,eAAO,MAAM,MAAM,EAAE,MAQpB,CAAC;AAEF;;GAEG;AACH,wBAAgB,cAAc,IAAI,IAAI,CAUrC"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Environment Configuration Module
|
|
3
|
+
* Parses and validates environment variables, provides default values
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Parse environment variable as integer, use default value if parsing fails
|
|
7
|
+
*/
|
|
8
|
+
function parseIntOrDefault(value, defaultValue) {
|
|
9
|
+
if (!value)
|
|
10
|
+
return defaultValue;
|
|
11
|
+
const parsed = parseInt(value, 10);
|
|
12
|
+
return isNaN(parsed) ? defaultValue : parsed;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Parse boolean environment variable
|
|
16
|
+
*/
|
|
17
|
+
function parseBoolOrDefault(value, defaultValue) {
|
|
18
|
+
if (!value)
|
|
19
|
+
return defaultValue;
|
|
20
|
+
return value.toLowerCase() === 'true';
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Load configuration from environment variables
|
|
24
|
+
*/
|
|
25
|
+
export const config = {
|
|
26
|
+
RESPONSE_TIMEOUT_MS: parseIntOrDefault(process.env.RESPONSE_TIMEOUT_MS, 50000),
|
|
27
|
+
ORPHAN_CLEANUP_MS: parseIntOrDefault(process.env.ORPHAN_CLEANUP_MIN, 10) * 60 * 1000,
|
|
28
|
+
CLEANUP_INTERVAL_MS: 60 * 1000, // Fixed at 60 seconds
|
|
29
|
+
MAX_OUTPUT_LINES: 10000, // Fixed at 10,000 lines
|
|
30
|
+
KILL_GRACE_PERIOD_MS: 5000, // Fixed at 5 seconds
|
|
31
|
+
LOG_LEVEL: process.env.LOG_LEVEL || 'info',
|
|
32
|
+
VERBOSE: parseBoolOrDefault(process.env.VERBOSE, false),
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* Validate configuration reasonableness
|
|
36
|
+
*/
|
|
37
|
+
export function validateConfig() {
|
|
38
|
+
if (config.RESPONSE_TIMEOUT_MS <= 0) {
|
|
39
|
+
throw new Error('RESPONSE_TIMEOUT_MS must be greater than 0');
|
|
40
|
+
}
|
|
41
|
+
if (config.ORPHAN_CLEANUP_MS <= 0) {
|
|
42
|
+
throw new Error('ORPHAN_CLEANUP_MIN must be greater than 0');
|
|
43
|
+
}
|
|
44
|
+
if (config.RESPONSE_TIMEOUT_MS >= config.ORPHAN_CLEANUP_MS) {
|
|
45
|
+
throw new Error('RESPONSE_TIMEOUT_MS should be less than ORPHAN_CLEANUP_MS');
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=environment.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"environment.js","sourceRoot":"","sources":["../../src/config/environment.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAmBH;;GAEG;AACH,SAAS,iBAAiB,CAAC,KAAyB,EAAE,YAAoB;IACxE,IAAI,CAAC,KAAK;QAAE,OAAO,YAAY,CAAC;IAChC,MAAM,MAAM,GAAG,QAAQ,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IACnC,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,MAAM,CAAC;AAC/C,CAAC;AAED;;GAEG;AACH,SAAS,kBAAkB,CAAC,KAAyB,EAAE,YAAqB;IAC1E,IAAI,CAAC,KAAK;QAAE,OAAO,YAAY,CAAC;IAChC,OAAO,KAAK,CAAC,WAAW,EAAE,KAAK,MAAM,CAAC;AACxC,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,MAAM,MAAM,GAAW;IAC5B,mBAAmB,EAAE,iBAAiB,CAAC,OAAO,CAAC,GAAG,CAAC,mBAAmB,EAAE,KAAK,CAAC;IAC9E,iBAAiB,EAAE,iBAAiB,CAAC,OAAO,CAAC,GAAG,CAAC,kBAAkB,EAAE,EAAE,CAAC,GAAG,EAAE,GAAG,IAAI;IACpF,mBAAmB,EAAE,EAAE,GAAG,IAAI,EAAE,sBAAsB;IACtD,gBAAgB,EAAE,KAAK,EAAE,wBAAwB;IACjD,oBAAoB,EAAE,IAAI,EAAE,qBAAqB;IACjD,SAAS,EAAE,OAAO,CAAC,GAAG,CAAC,SAAS,IAAI,MAAM;IAC1C,OAAO,EAAE,kBAAkB,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,EAAE,KAAK,CAAC;CACxD,CAAC;AAEF;;GAEG;AACH,MAAM,UAAU,cAAc;IAC5B,IAAI,MAAM,CAAC,mBAAmB,IAAI,CAAC,EAAE,CAAC;QACpC,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAC;IAChE,CAAC;IACD,IAAI,MAAM,CAAC,iBAAiB,IAAI,CAAC,EAAE,CAAC;QAClC,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAC;IAC/D,CAAC;IACD,IAAI,MAAM,CAAC,mBAAmB,IAAI,MAAM,CAAC,iBAAiB,EAAE,CAAC;QAC3D,MAAM,IAAI,KAAK,CAAC,2DAA2D,CAAC,CAAC;IAC/E,CAAC;AACH,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;GAEG"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP Long-Running Command Server - Entry file
|
|
3
|
+
*/
|
|
4
|
+
import { logger, enableFileLogging } from './utils/logger.js';
|
|
5
|
+
import { config, validateConfig } from './config/environment.js';
|
|
6
|
+
import { startServer } from './server.js';
|
|
7
|
+
/**
|
|
8
|
+
* Main function
|
|
9
|
+
*/
|
|
10
|
+
async function main() {
|
|
11
|
+
try {
|
|
12
|
+
// Print startup information
|
|
13
|
+
logger.info('='.repeat(60));
|
|
14
|
+
logger.info('MCP Long-Running Command Server');
|
|
15
|
+
logger.info('='.repeat(60));
|
|
16
|
+
// Enable file logging (if environment variable is set)
|
|
17
|
+
if (process.env.ENABLE_FILE_LOGGING === 'true') {
|
|
18
|
+
enableFileLogging();
|
|
19
|
+
}
|
|
20
|
+
// Validate configuration
|
|
21
|
+
logger.info('Validating configuration...');
|
|
22
|
+
validateConfig();
|
|
23
|
+
// Print configuration information
|
|
24
|
+
logger.info('Configuration:', {
|
|
25
|
+
RESPONSE_TIMEOUT_MS: config.RESPONSE_TIMEOUT_MS,
|
|
26
|
+
ORPHAN_CLEANUP_MS: config.ORPHAN_CLEANUP_MS,
|
|
27
|
+
CLEANUP_INTERVAL_MS: config.CLEANUP_INTERVAL_MS,
|
|
28
|
+
MAX_OUTPUT_LINES: config.MAX_OUTPUT_LINES,
|
|
29
|
+
LOG_LEVEL: config.LOG_LEVEL,
|
|
30
|
+
VERBOSE: config.VERBOSE,
|
|
31
|
+
});
|
|
32
|
+
// Start server
|
|
33
|
+
await startServer();
|
|
34
|
+
}
|
|
35
|
+
catch (error) {
|
|
36
|
+
logger.error('Fatal error during startup', {
|
|
37
|
+
error: error instanceof Error ? error.message : String(error),
|
|
38
|
+
stack: error instanceof Error ? error.stack : undefined,
|
|
39
|
+
});
|
|
40
|
+
process.exit(1);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
// Handle uncaught exceptions
|
|
44
|
+
process.on('uncaughtException', (error) => {
|
|
45
|
+
logger.error('Uncaught exception', {
|
|
46
|
+
error: error.message,
|
|
47
|
+
stack: error.stack,
|
|
48
|
+
});
|
|
49
|
+
process.exit(1);
|
|
50
|
+
});
|
|
51
|
+
// Handle unhandled promise rejections
|
|
52
|
+
process.on('unhandledRejection', (reason) => {
|
|
53
|
+
logger.error('Unhandled rejection', {
|
|
54
|
+
reason: reason instanceof Error ? reason.message : String(reason),
|
|
55
|
+
stack: reason instanceof Error ? reason.stack : undefined,
|
|
56
|
+
});
|
|
57
|
+
process.exit(1);
|
|
58
|
+
});
|
|
59
|
+
// Start application
|
|
60
|
+
main();
|
|
61
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,MAAM,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAC9D,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AACjE,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1C;;GAEG;AACH,KAAK,UAAU,IAAI;IACjB,IAAI,CAAC;QACH,4BAA4B;QAC5B,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;QAC5B,MAAM,CAAC,IAAI,CAAC,iCAAiC,CAAC,CAAC;QAC/C,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;QAE5B,uDAAuD;QACvD,IAAI,OAAO,CAAC,GAAG,CAAC,mBAAmB,KAAK,MAAM,EAAE,CAAC;YAC/C,iBAAiB,EAAE,CAAC;QACtB,CAAC;QAED,yBAAyB;QACzB,MAAM,CAAC,IAAI,CAAC,6BAA6B,CAAC,CAAC;QAC3C,cAAc,EAAE,CAAC;QAEjB,kCAAkC;QAClC,MAAM,CAAC,IAAI,CAAC,gBAAgB,EAAE;YAC5B,mBAAmB,EAAE,MAAM,CAAC,mBAAmB;YAC/C,iBAAiB,EAAE,MAAM,CAAC,iBAAiB;YAC3C,mBAAmB,EAAE,MAAM,CAAC,mBAAmB;YAC/C,gBAAgB,EAAE,MAAM,CAAC,gBAAgB;YACzC,SAAS,EAAE,MAAM,CAAC,SAAS;YAC3B,OAAO,EAAE,MAAM,CAAC,OAAO;SACxB,CAAC,CAAC;QAEH,eAAe;QACf,MAAM,WAAW,EAAE,CAAC;IACtB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,KAAK,CAAC,4BAA4B,EAAE;YACzC,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;YAC7D,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS;SACxD,CAAC,CAAC;QACH,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC;AAED,6BAA6B;AAC7B,OAAO,CAAC,EAAE,CAAC,mBAAmB,EAAE,CAAC,KAAK,EAAE,EAAE;IACxC,MAAM,CAAC,KAAK,CAAC,oBAAoB,EAAE;QACjC,KAAK,EAAE,KAAK,CAAC,OAAO;QACpB,KAAK,EAAE,KAAK,CAAC,KAAK;KACnB,CAAC,CAAC;IACH,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC;AAEH,sCAAsC;AACtC,OAAO,CAAC,EAAE,CAAC,oBAAoB,EAAE,CAAC,MAAM,EAAE,EAAE;IAC1C,MAAM,CAAC,KAAK,CAAC,qBAAqB,EAAE;QAClC,MAAM,EAAE,MAAM,YAAY,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC;QACjE,KAAK,EAAE,MAAM,YAAY,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS;KAC1D,CAAC,CAAC;IACH,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC;AAEH,oBAAoB;AACpB,IAAI,EAAE,CAAC"}
|
package/dist/server.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP Server Setup
|
|
3
|
+
* Register tools and start server
|
|
4
|
+
*/
|
|
5
|
+
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
6
|
+
/**
|
|
7
|
+
* Create and configure MCP server
|
|
8
|
+
*/
|
|
9
|
+
export declare function createServer(): Server;
|
|
10
|
+
/**
|
|
11
|
+
* Start server
|
|
12
|
+
*/
|
|
13
|
+
export declare function startServer(): Promise<void>;
|
|
14
|
+
//# sourceMappingURL=server.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AAmCnE;;GAEG;AACH,wBAAgB,YAAY,IAAI,MAAM,CA2IrC;AAED;;GAEG;AACH,wBAAsB,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC,CAiBjD"}
|