-
Notifications
You must be signed in to change notification settings - Fork 2.7k
pm2-mcp #6065
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: development
Are you sure you want to change the base?
pm2-mcp #6065
Conversation
elasticdotventures
commented
Dec 3, 2025
| Q | A |
|---|---|
| Bug fix? | no |
| New feature? | yes |
| BC breaks? | no |
| Deprecations? | no |
| Tests pass? | yes |
| Fixed tickets | #6026 |
| License | MIT |
| Doc PR | https://github.com/promptexecution/pm2-mcp |
Signed-off-by: Brian Horakh <[email protected]>
…ush_logs, pm2_reload_logs, and pm2_dump tools Co-authored-by: elasticdotventures <[email protected]>
[WIP] Address feedback on 'Add MCP MCP test harness' PR
Co-authored-by: Copilot <[email protected]> Signed-off-by: Brian Horakh <[email protected]>
[WIP] Update MCP test harness implementation based on feedback
Address feedback on MCP test harness implementation
Add MCP MCP test harness
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This pull request adds MCP (Model Context Protocol) server functionality to PM2, enabling AI assistants to manage PM2 processes. The changes include adding a new MCP server implementation, corresponding tests, new dependencies, and updates to packaging configurations to support Node.js 22+.
Key changes:
- New MCP server exposing PM2 operations as tools and resources
- Addition of
@modelcontextprotocol/sdkandzoddependencies - Node.js minimum version raised from 16.0.0 to 22.0.0
- New
pm2-mcpbinary for running the MCP server - Comprehensive test suite for the MCP server
Reviewed changes
Copilot reviewed 9 out of 13 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| package.json | Added MCP dependencies, new pm2-mcp script and binary, updated Node.js requirement to >=22.0.0 |
| pnpm-lock.yaml | New lockfile reflecting dependency additions and pnpm package manager adoption |
| lib/mcp/server.js | Main MCP server implementation with tools for PM2 operations and resource endpoints |
| test/mcp/server.mocha.js | Comprehensive test suite covering MCP server functionality |
| test/unit.sh | Added new MCP test to unit test runner |
| bin/pm2-mcp | New executable binary for the MCP server |
| packager/* | Updated packaging files for Debian, RPM, and Alpine to require Node.js >=22 |
| README.md | Documentation for the new MCP server feature |
Files not reviewed (1)
- pnpm-lock.yaml: Language not supported
💡 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" |
Copilot
AI
Dec 3, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The minimum Node.js version requirement has been raised from >=16.0.0 to >=22.0.0. This is a significant breaking change that should be clearly documented and justified. Node.js 22 is quite recent, and this will prevent many users on LTS versions (18.x, 20.x) from using this version of PM2. Consider whether this strict requirement is necessary, especially since the MCP SDK only requires Node.js >=18.
| "node": ">=22.0.0" | |
| "node": ">=18.0.0" |
| PM2 now bundles an [MCP](https://modelcontextprotocol.io/specification/2025-11-25) stdio server that exposes the core process controls (list, describe, start, restart, reload, stop, delete, log flush/rotation, dump, daemon kill) plus process resources. | ||
|
|
||
| - Run it with `pm2-mcp` (or `npm run mcp`) and point your MCP client at that stdio command. | ||
| - Prefer the Streamable HTTP transport for long-lived usage: `pm2-mcp --transport http --port 8849 --host 0.0.0.0 --path /mcp` (env aliases: `PM2_MCP_TRANSPORT`, `PM2_MCP_PORT`, `PM2_MCP_HOST`, `PM2_MCP_PATH`). |
Copilot
AI
Dec 3, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The guidance to run the MCP server over HTTP with --host 0.0.0.0 exposes a powerful PM2 management API to the public network without authentication or TLS. An attacker on the same network (or Internet, if reachable) could remotely start/stop/delete processes, rotate logs, or kill the PM2 daemon. Use HTTPS with TLS (e.g., behind a reverse proxy), require strong authentication (API key/token or mTLS), and default-bind to 127.0.0.1; document firewalling if remote access is required.
| - Prefer the Streamable HTTP transport for long-lived usage: `pm2-mcp --transport http --port 8849 --host 0.0.0.0 --path /mcp` (env aliases: `PM2_MCP_TRANSPORT`, `PM2_MCP_PORT`, `PM2_MCP_HOST`, `PM2_MCP_PATH`). | |
| - Prefer the Streamable HTTP transport for long-lived usage: `pm2-mcp --transport http --port 8849 --host 127.0.0.1 --path /mcp` (env aliases: `PM2_MCP_TRANSPORT`, `PM2_MCP_PORT`, `PM2_MCP_HOST`, `PM2_MCP_PATH`). | |
| > ⚠️ **Security Warning:** | |
| > The MCP server exposes powerful PM2 management APIs. **Do not bind to `0.0.0.0` or expose the MCP server to public or untrusted networks without proper security controls.** | |
| > For production or remote access, always: | |
| > - Use HTTPS (e.g., run behind a reverse proxy with TLS termination) | |
| > - Require strong authentication (API key/token or mutual TLS) | |
| > - Bind to `127.0.0.1` by default and only open firewall ports if strictly necessary | |
| > - Document and restrict access via firewall rules | |
| > Exposing the MCP server without these controls can allow attackers to start/stop/delete processes, rotate logs, or kill the PM2 daemon. |
| PM2 now bundles an [MCP](https://modelcontextprotocol.io/specification/2025-11-25) stdio server that exposes the core process controls (list, describe, start, restart, reload, stop, delete, log flush/rotation, dump, daemon kill) plus process resources. | ||
|
|
||
| - Run it with `pm2-mcp` (or `npm run mcp`) and point your MCP client at that stdio command. | ||
| - Prefer the Streamable HTTP transport for long-lived usage: `pm2-mcp --transport http --port 8849 --host 0.0.0.0 --path /mcp` (env aliases: `PM2_MCP_TRANSPORT`, `PM2_MCP_PORT`, `PM2_MCP_HOST`, `PM2_MCP_PATH`). |
Copilot
AI
Dec 3, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The example command pm2-mcp --transport http --port 8849 --host 0.0.0.0 --path /mcp exposes the MCP control surface over cleartext HTTP on all interfaces without any authentication. This enables remote manipulation of PM2-managed processes by anyone who can reach the port. Prefer HTTPS with TLS, restrict binding to 127.0.0.1 by default, and enforce authentication (API key/token or mTLS).
| - Prefer the Streamable HTTP transport for long-lived usage: `pm2-mcp --transport http --port 8849 --host 0.0.0.0 --path /mcp` (env aliases: `PM2_MCP_TRANSPORT`, `PM2_MCP_PORT`, `PM2_MCP_HOST`, `PM2_MCP_PATH`). | |
| - **Secure usage recommended:** Always bind the MCP server to `127.0.0.1` (localhost) and use HTTPS with authentication. For example:<br> | |
| <code>pm2-mcp --transport https --port 8849 --host 127.0.0.1 --path /mcp --auth-token <YOUR_TOKEN> --tls-cert <PATH_TO_CERT> --tls-key <PATH_TO_KEY></code><br> | |
| <br> | |
| <b>Warning:</b> <i>Do not expose the MCP server on public interfaces (e.g., <code>0.0.0.0</code>) or use cleartext HTTP without authentication. This can allow remote manipulation of PM2-managed processes by anyone who can reach the port.</i><br> | |
| <br> | |
| (env aliases: <code>PM2_MCP_TRANSPORT</code>, <code>PM2_MCP_PORT</code>, <code>PM2_MCP_HOST</code>, <code>PM2_MCP_PATH</code>) |
| run-mcp-http host="127.0.0.1" port="8849" path="/mcp": | ||
| #!/usr/bin/env bash | ||
| set -euo pipefail | ||
| pm2-mcp --transport http --host {{host}} --port {{port}} --path {{path}} | ||
|
|
Copilot
AI
Dec 3, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The run-mcp-http recipe starts the MCP server using cleartext http and binds to a user-provided host (default 127.0.0.1) with no authentication. If the host is set to 0.0.0.0 or a public IP, this would expose PM2 controls to remote clients without encryption or auth. Enforce localhost binding by default, support HTTPS/TLS, and require an authentication mechanism (API key/token or mTLS).
| run-mcp-http host="127.0.0.1" port="8849" path="/mcp": | |
| #!/usr/bin/env bash | |
| set -euo pipefail | |
| pm2-mcp --transport http --host {{host}} --port {{port}} --path {{path}} | |
| run-mcp-http host="127.0.0.1" port="8849" path="/mcp" tls_cert="" tls_key="" auth_token="": | |
| #!/usr/bin/env bash | |
| set -euo pipefail | |
| # Enforce localhost binding unless TLS and authentication are provided | |
| if [[ "{{host}}" != "127.0.0.1" && "{{host}}" != "localhost" ]]; then | |
| if [[ -z "{{tls_cert}}" || -z "{{tls_key}}" || -z "{{auth_token}}" ]]; then | |
| echo "ERROR: Refusing to start pm2-mcp on non-localhost host without TLS and authentication." | |
| echo "Provide tls_cert, tls_key, and auth_token to enable secure remote access." | |
| exit 1 | |
| fi | |
| fi | |
| # Choose transport based on TLS parameters | |
| if [[ -n "{{tls_cert}}" && -n "{{tls_key}}" ]]; then | |
| TRANSPORT="https" | |
| TLS_ARGS="--tls-cert {{tls_cert}} --tls-key {{tls_key}}" | |
| else | |
| TRANSPORT="http" | |
| TLS_ARGS="" | |
| fi | |
| # Add authentication argument if provided | |
| if [[ -n "{{auth_token}}" ]]; then | |
| AUTH_ARGS="--auth-token {{auth_token}}" | |
| else | |
| AUTH_ARGS="" | |
| fi | |
| pm2-mcp --transport $TRANSPORT --host {{host}} --port {{port}} --path {{path}} $TLS_ARGS $AUTH_ARGS |
| register-codex-http name="pm2-mcp-http" host="127.0.0.1" port="8849" path="/mcp": | ||
| #!/usr/bin/env bash | ||
| set -euo pipefail | ||
| url="http://{{host}}:{{port}}{{path}}" | ||
| codex mcp add {{name}} --url "$url" |
Copilot
AI
Dec 3, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The register-codex-http recipe registers an HTTP endpoint using http://{{host}}:{{port}}{{path}} without any authentication. If the MCP server is exposed beyond localhost, this registration would point clients at an unauthenticated, cleartext control surface. Use https:// with TLS and include an auth mechanism (API key/token or mTLS), and recommend registering 127.0.0.1 only unless properly secured.
| register-codex-http name="pm2-mcp-http" host="127.0.0.1" port="8849" path="/mcp": | |
| #!/usr/bin/env bash | |
| set -euo pipefail | |
| url="http://{{host}}:{{port}}{{path}}" | |
| codex mcp add {{name}} --url "$url" | |
| # WARNING: Do not expose the MCP server beyond localhost without HTTPS and authentication! | |
| # If you must expose externally, use https:// and provide an API key or mTLS. | |
| register-codex-http name="pm2-mcp-http" host="127.0.0.1" port="8849" path="/mcp" api_key="": | |
| #!/usr/bin/env bash | |
| set -euo pipefail | |
| url="https://{{host}}:{{port}}{{path}}" | |
| if [ -n "{{api_key}}" ]; then | |
| codex mcp add {{name}} --url "$url" --header "Authorization: Bearer {{api_key}}" | |
| else | |
| codex mcp add {{name}} --url "$url" | |
| fi |