closeli-mcp-gateway
v1.0.4
Published
MCP server for handling long-running commands (codex, claude-code) with session management
Maintainers
Readme
MCP Long-Running Command Server
A TypeScript/Node.js MCP server that handles long-running commands (codex, claude-code) through session management to solve client timeout limitations.
Core Features
Three Tools
codex - Start a new codex task
- Parameters:
workspace(working directory),prompt(task prompt) - Executes:
codex exec --full-auto --skip-git-repo-check [prompt]
- Parameters:
claude-code - Start a new claude-code task
- Parameters:
workspace(working directory),prompt(task prompt) - Executes:
claude --print --dangerously-skip-permissions [prompt]
- Parameters:
resume - Continue waiting for any task result
- Parameters:
sessionId(session ID) - Universal tool, works with any task type
- Parameters:
get-session-status - Query task running status ✨
- Parameters:
sessionId(session ID) - View runtime duration, output line count, recent output, etc.
- Parameters:
Workflow
Client calls codex or claude-code
↓
Server starts process, waits 50 seconds
↓
Complete? → Yes → Return result
↓ No
Return sessionId
↓
Client calls resume + sessionId
↓
Continue waiting 50 seconds
↓
Complete? → Yes → Return result
↓ No
Return sessionId (repeat)MCP Client Configuration
To use this server with Claude Desktop or other MCP clients, add the following configuration:
Claude Desktop Configuration
Edit your Claude Desktop configuration file:
macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
Windows: %APPDATA%/Claude/claude_desktop_config.json
Add the server to your configuration:
{
"mcpServers": {
"closeli-gateway": {
"command": "npx",
"args": [
"-y",
"closeli-mcp-gateway@latest"
],
"env": {
"RESPONSE_TIMEOUT_MS": "50000",
"ORPHAN_CLEANUP_MIN": "10",
"LOG_LEVEL": "info",
"ENABLE_FILE_LOGGING": "true",
"VERBOSE": "true"
}
}
}
}Note: The @latest tag ensures you always use the most recent version. You can also specify a specific version like [email protected].
Configuration Options
The env object supports the following environment variables:
RESPONSE_TIMEOUT_MS: Response timeout in milliseconds (default: 50000)ORPHAN_CLEANUP_MIN: Orphan session cleanup threshold in minutes (default: 10)LOG_LEVEL: Log level - error, warn, info, or debug (default: info)ENABLE_FILE_LOGGING: Enable file logging to logs/ directory (default: false)VERBOSE: Enable verbose mode for detailed output (default: false)
Using a Local Development Version
If you're developing or testing locally, you can point to your local installation:
{
"mcpServers": {
"closeli-gateway": {
"command": "node",
"args": [
"/absolute/path/to/closeli-mcp-gateway/dist/index.js"
],
"env": {
"VERBOSE": "true",
"ENABLE_FILE_LOGGING": "true"
}
}
}
}Installation
# Clone or initialize project
npm install
# Copy environment configuration
cp .env.example .env
# Modify .env file as neededConfiguration
Environment variables (configure in .env file):
| Variable | Default | Description |
|----------|---------|-------------|
| RESPONSE_TIMEOUT_MS | 50000 | Response timeout (milliseconds), returns sessionId on timeout |
| ORPHAN_CLEANUP_MIN | 10 | Orphan session cleanup threshold (minutes) |
| LOG_LEVEL | info | Log level: error, warn, info, debug |
| ENABLE_FILE_LOGGING | false | Enable file logging to logs/ directory |
| VERBOSE | false | Enable verbose mode (affects claude-code output format) |
Verbose Mode 🎯
When VERBOSE=true, the claude-code tool uses --verbose --output-format stream-json:
- All 127+ line stream outputs are logged for monitoring execution
- Only the final
resultmessage (containing complete answer and statistics) is returned to the client - Significantly reduces client data transfer
# Enable verbose mode (recommended)
VERBOSE=true npm run dev
# Disable verbose mode (default)
VERBOSE=false npm run devReal-time Process Output Monitoring ⚡
The server logs process output in real-time to logs (output to stderr, doesn't affect MCP's stdio communication):
# Run server and view real-time output in console
npm run dev
# You'll see output like:
2025-12-29 10:30:15 [codex:abc12345] Analyzing project structure...
2025-12-29 10:30:16 [codex:abc12345] Found 15 files
2025-12-29 10:30:17 [codex:abc12345] ⚠️ Warning: Some files may need manual handlingEnable File Logging:
# Method 1: Set environment variable
ENABLE_FILE_LOGGING=true npm run dev
# Method 2: Set in .env file
ENABLE_FILE_LOGGING=true
# Log file locations:
# - logs/error.log - Error logs only
# - logs/combined.log - All logs (JSON format)
# - logs/process-output.log - Real-time process outputRunning
# Development environment
npm run dev
# Production environment
npm run build
npm start
# Use custom configuration
RESPONSE_TIMEOUT_MS=60000 ORPHAN_CLEANUP_MIN=15 npm startUsage Examples
Example 1: Quick Task
// Call codex tool
{
"name": "codex",
"arguments": {
"workspace": "/path/to/project",
"prompt": "List files in current directory"
}
}
// Response (task completes within 50 seconds)
{
"content": [{
"type": "text",
"text": "Standard output:\nfile1.txt\nfile2.txt\n\nExit code: 0\nStatus: completed"
}],
"_meta": {
"exitCode": 0,
"status": "completed"
}
}Example 2: Long-Running Task
// First call to codex tool
{
"name": "codex",
"arguments": {
"workspace": "/path/to/large-project",
"prompt": "Implement a complete user authentication system"
}
}
// Response (task not complete, returns sessionId)
{
"content": [{
"type": "text",
"text": "Task is still running. Use resume tool to continue waiting with sessionId=\"abc-123-def-456\""
}],
"_meta": {
"status": "running",
"sessionId": "abc-123-def-456",
"toolType": "codex"
}
}
// Use resume to continue waiting
{
"name": "resume",
"arguments": {
"sessionId": "abc-123-def-456"
}
}
// If still not complete, continues returning sessionId
// If complete, returns final result
{
"content": [{
"type": "text",
"text": "Standard output:\n[Detailed implementation output]\n\nExit code: 0\nStatus: completed"
}],
"_meta": {
"exitCode": 0,
"status": "completed"
}
}Architecture Design
Core Components
src/
├── config/
│ └── environment.ts # Environment variable configuration
├── utils/
│ ├── logger.ts # Winston logger
│ └── errors.ts # Custom error classes
├── session/
│ ├── Session.ts # Session type definitions
│ ├── ProcessExecutor.ts # Process startup and monitoring
│ └── SessionManager.ts # Session management core logic
├── tools/
│ ├── types.ts # Tool common types
│ ├── codex.ts # Codex tool
│ ├── claude-code.ts # Claude Code tool
│ └── resume.ts # Resume tool
├── server.ts # MCP server setup
└── index.ts # Entry pointKey Features
Session Management
- In-memory Map to store sessions
- Each session contains: process reference, output buffer, timestamp, status
Timeout Mechanism
- Response timeout: default 50 seconds (configurable)
- Orphan cleanup: default 10 minutes (configurable)
Process Management
- Uses
child_process.spawn() - Output buffer limit: 10,000 lines
- Graceful termination: SIGTERM → SIGKILL
- Uses
Security Considerations
shell: falseprevents injection- Path validation prevents traversal attacks
- SessionId UUID format validation
Troubleshooting
Issue: Task keeps returning sessionId but never completes
Possible Causes:
- Task is actually running and needs more time
- Process is stuck or waiting for input
Solutions:
- Check logs to view process status
- Increase
RESPONSE_TIMEOUT_MS - Ensure command doesn't require interactive input
Issue: Session not found
Possible Causes:
- Session has been cleaned up by orphan cleanup mechanism
- Incorrect SessionId
Solutions:
- Reduce interval between resume calls
- Increase
ORPHAN_CLEANUP_MIN - Verify sessionId is correct
Issue: High memory usage
Possible Causes:
- Large output buffer
- Too many concurrent sessions
Solutions:
- Output is already limited to 10,000 lines
- Regularly clean orphan sessions
- Monitor active session count
Development
# Install dependencies
npm install
# Development mode (hot reload)
npm run dev
# Build
npm run build
# Run tests
npm testLicense
MIT
