shell-mcp
by mhingston
README.md
# shell-mcp
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.
## Tool
### `run_shell`
| 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.
## Run
```bash
npm install
npm run build
npm start
```
The MCP endpoint defaults to:
```text
http://127.0.0.1:3000/mcp
```
For development:
```bash
npm run dev
```
## Configuration
| 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:
```bash
HOST=0.0.0.0 \
SHELL_MCP_TOKEN='use-a-long-random-secret' \
npm start
```
Configure the MCP client to send:
```text
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.
## Examples
Bash:
```json
{
"command": "uname -a && pwd",
"shell": "bash"
}
```
PowerShell:
```json
{
"command": "Get-ChildItem Env: | Select-Object -First 5",
"shell": "pwsh"
}
```
## Development
```bash
npm run check
```
## Design
- One MCP tool; no resources or prompts.
- Streamable HTTP only; no stdio transport.
- Stateless MCP handler with a fresh `McpServer` per 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.
## License
MIT
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues