Feature/mcp semantic state#6067
Conversation
Add MCP server support to PM2 for process management through MCP-compatible clients.
Features:
- New pm2-mcp binary that exposes PM2 process management via MCP
- 12 MCP tools for process lifecycle, logging, and monitoring:
- pm2_list_processes, pm2_describe_process
- pm2_start_process, pm2_restart_process, pm2_reload_process
- pm2_stop_process, pm2_delete_process
- pm2_flush_logs, pm2_reload_logs, pm2_tail_logs
- pm2_dump, pm2_kill_daemon
- 2 MCP resources for real-time process information:
- pm2://processes (list)
- pm2://process/{id} (detail)
- Automatic sandbox environment detection and adaptation
- Support for stdio and HTTP (Streamable) transports
- Client notifications for sandbox status and recommendations
- Compatible with Claude Code, Codex, and other MCP clients
Implementation:
- New lib/mcp/server.js with full MCP server implementation
- Uses @modelcontextprotocol/sdk for MCP protocol
- Sandbox detection checks home directory writability and environment
- Auto-selects writable PM2_HOME in sandboxed environments
- No-daemon mode by default for MCP client compatibility
- Comprehensive environment variable configuration
Documentation:
- README with MCP server quickstart and setup commands
- Environment variables table (PM2_MCP_*, PM2_HOME, etc.)
- Sandbox detection explanation
- Tool and resource documentation
- Justfile recipes for easy registration with MCP clients
Related:
- Enables pkgx packaging: pkgxdev/pantry#11219
- Development fork: https://github.com/PromptExecution/pm2-mcp
- MCP Specification: https://modelcontextprotocol.io/
Co-authored-by: Claude <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
This PR adds Model Context Protocol (MCP) server functionality to PM2, enabling process management through MCP-compatible clients like Claude Code and Codex. The implementation provides both stdio and HTTP transport options with extensive tooling for PM2 process control.
Key Changes:
- Adds comprehensive MCP server with 13 tools and 2 resource endpoints for PM2 process management
- Implements sandbox detection and adaptive PM2_HOME resolution for restricted environments
- Includes semantic state inference with log pattern analysis for enhanced process monitoring
Reviewed changes
Copilot reviewed 4 out of 5 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| package.json | Added MCP SDK dependency, increased Node.js requirement to 22.0.0, added pm2-mcp bin entry and npm script |
| lib/mcp/server.js | New MCP server implementation with tools, resources, sandbox detection, log analysis, and transport abstraction |
| bin/pm2-mcp | New CLI entry point with argument parsing for transport configuration and PM2 self-management |
| README.md | Added comprehensive MCP server documentation including setup, environment variables, and feature descriptions |
| Justfile | Added automation recipes for registering MCP server with clients and debugging sandbox detection |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| "version": "6.0.14", | ||
| "engines": { | ||
| "node": ">=16.0.0" | ||
| "node": ">=22.0.0" |
There was a problem hiding this comment.
Changing the minimum Node.js version from >=16.0.0 to >=22.0.0 is a breaking change that will prevent users on Node.js 16.x-21.x from using this version. This contradicts the PR metadata which indicates "BC breaks? no". Either update the PR metadata to indicate this is a breaking change, or reconsider this version requirement increase.
| "node": ">=22.0.0" | |
| "node": ">=16.0.0" |
| #!/usr/bin/env bash | ||
| set -euo pipefail | ||
| echo "Testing normal environment:" | ||
| node -e "const {detectSandbox} = require('./lib/mcp/server.js'); console.log(detectSandbox ? 'Available' : 'Not exported');" || echo "Normal detection test" |
There was a problem hiding this comment.
The function detectSandbox() is not exported from the module, but the Justfile at line 59 attempts to use it in a test. Either export this function or update the test to use a different approach.
| async function tailFile(filePath, lineCount) { | ||
| const fh = await fs.promises.open(filePath, 'r'); | ||
| try { | ||
| const stats = await fh.stat(); | ||
| let position = stats.size; | ||
| const chunkSize = 8192; | ||
| let buffer = ''; | ||
|
|
||
| while (position > 0 && buffer.split(/\r?\n/).length <= lineCount + 1) { | ||
| const readSize = Math.min(chunkSize, position); | ||
| position -= readSize; | ||
| const result = await fh.read({ buffer: Buffer.alloc(readSize), position }); | ||
| buffer = result.buffer.slice(0, result.bytesRead).toString('utf8') + buffer; | ||
| } | ||
|
|
||
| const lines = buffer.trimEnd().split(/\r?\n/); | ||
| return lines.slice(-lineCount); | ||
| } finally { | ||
| await fh.close(); | ||
| } | ||
| } |
There was a problem hiding this comment.
The tailFile function reads arbitrary files without path validation. If the filePath parameter comes from user-controlled process configuration, this could potentially allow reading sensitive files outside the intended log directory. Consider adding path validation to ensure the file path is within expected log directories.
| console.error('[pm2-mcp][debug] failed to send sandbox notification', err); | ||
| } | ||
| }); | ||
| }, 100); |
There was a problem hiding this comment.
[nitpick] The magic number 100 (milliseconds) for the setTimeout delay is used without explanation. Consider extracting this to a named constant like SANDBOX_NOTIFICATION_DELAY_MS to improve code clarity and maintainability.
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Here are the instructions for the pm2-mcp development agent: