A deliberately small MCP server that exposes a single tool, run_shell, for executing arbitrary shell commands over Streamable HTTP.
It uses the stable v2 Model Context Protocol TypeScript SDK (@modelcontextprotocol/server and @modelcontextprotocol/node) and runs on Node.js 20+.
Warning
run_shell has the same operating-system permissions as the shell-mcp process. Treat access to this server as equivalent to shell access. The default bind address is loopback-only. A bearer token is required if you bind to a non-loopback address.
| Input | Required | Description |
|---|---|---|
command |
yes | Command string to execute. |
shell |
no | Shell executable/path, e.g. bash, sh, zsh, pwsh, powershell.exe, or cmd.exe. Defaults to the platform shell. |
cwd |
no | Working directory. Defaults to the server process working directory. |
env |
no | Environment variables to add or override for the command. |
timeoutMs |
no | Command timeout in milliseconds. Defaults to 30 seconds. |
The result includes stdout, stderr, exit code, terminating signal, duration, timeout state, and whether the output limit was exceeded.
npm install
npm run build
npm startThe MCP endpoint defaults to:
http://127.0.0.1:3000/mcp
For development:
npm run dev| Environment variable | Default | Purpose |
|---|---|---|
HOST |
127.0.0.1 |
HTTP listen address. |
PORT |
3000 |
HTTP listen port. |
SHELL_MCP_TOKEN |
unset | Optional bearer token on loopback; required for non-loopback binds. |
SHELL_MCP_DEFAULT_TIMEOUT_MS |
30000 |
Default command timeout. |
SHELL_MCP_MAX_TIMEOUT_MS |
600000 |
Maximum timeout accepted by the tool. |
SHELL_MCP_MAX_OUTPUT_BYTES |
1048576 |
Maximum combined stdout/stderr retained before the command is terminated. |
Example network bind:
HOST=0.0.0.0 \
SHELL_MCP_TOKEN='use-a-long-random-secret' \
npm startConfigure the MCP client to send:
Authorization: Bearer use-a-long-random-secret
For anything beyond a trusted local network, put the endpoint behind TLS and an authenticated reverse proxy rather than exposing the Node process directly.
Bash:
{
"command": "uname -a && pwd",
"shell": "bash"
}PowerShell:
{
"command": "Get-ChildItem Env: | Select-Object -First 5",
"shell": "pwsh"
}npm run check- One MCP tool; no resources or prompts.
- Streamable HTTP only; no stdio transport.
- Stateless MCP handler with a fresh
McpServerper request, following the v2 SDK serving model. - Explicit shell invocation for POSIX shells, PowerShell, and
cmd.exe. - Process-tree termination on timeout or output overflow.
- Loopback binding by default, with bearer authentication required for non-loopback binds.
MIT