shell-mcp
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@shell-mcpsearch for 'TODO' in source files"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
shell-mcp
Remote shell + file operations MCP server. Core is pure stdlib (fully unit-testable); only server.py depends on mcp / starlette / uvicorn.
Features
Streamable HTTP at
/mcp(POST). No long-lived connections, safe behind buffered reverse proxies.Bearer token auth (constant-time compare) + optional IP allowlist +
/healthendpoint.Two execution modes: restricted (command allowlist, no shell operators) / unrestricted (full shell). Windows: unrestricted mode uses
cmd.exeor PowerShell; POSIX:$SHELL -lc.Reliable process execution: stdout+stderr merged in real order; output streamed to temp file (bounded memory, no pipe deadlock); children in their own process group; timeout kills the entire process tree (POSIX
killpg/ Windowstaskkill /T).Background tasks:
run_command(background="always")for dev servers / builds;task(action="wait"|"output"|"cancel"|"list")to manage.Sync-first by default:
run_commandwaits up toSHELL_MCP_WAIT_SECONDS(30s) then auto-backgrounds. Short commands return results inline.Safe editing:
edit_fileexact replacement + atomic write + unified diff;apply_patchmulti-file atomic;expected_sha256precondition prevents stale-read conflicts (returnsFILE_CHANGEDwithout touching files).Code search:
grep(ripgrep preferred, pure-Python fallback) +glob(sort by path or modified time).Encoding consistency: auto-detect (UTF-8 / Windows code pages / GB18030), preserve original encoding on write.
Output governance: line+byte caps, tail truncation, full output spilled to OS temp dir (
shell-mcp-spool/), auto-pruned.Machine-readable errors: all failures return
code(e.g.OLD_TEXT_NOT_FOUND,FILE_NOT_FOUND) + structured fields.Audit log: JSON lines, auto-rotated.
Cross-platform: Windows / macOS / Linux. Platform-specific code gated behind
os.name == "nt".
Related MCP server: MCP Remote Code
Quick Start
pip install -r requirements.txt
cp .env.example .env # fill SHELL_MCP_TOKEN (openssl rand -hex 32)
# macOS / Linux:
./run.sh
# Windows:
run.batClient config (Streamable HTTP):
{
"url": "http://127.0.0.1:8000/mcp",
"headers": { "Authorization": "Bearer <SHELL_MCP_TOKEN>" }
}Print a ready-to-paste client snippet (with real token + auto-detected Tailscale URL):
python -m shell_mcp.server --print-client
Tools (13)
Tool | Description |
| Execute a shell command. |
| Unified background task lifecycle. |
| Regex search. Structured results: |
| File pattern matching. Sort by |
| Directory listing with optional |
| Read a text file with paging. Returns |
| Batch read up to 20 files. Partial failures don't block other files. |
| Atomic write. Optional |
| Exact string replacement with |
| Multi-file patch ( |
| Change working directory (convenience; prefer per-call |
| Extract code symbols per language (regex-based, shebang-aware). |
| One-shot audit: read file + recent commits + diff (parallel via anyio). |
Low-level tools (task_output, kill_task, list_tasks, delete_file, make_dir, rename_file) hidden by default; enable with SHELL_MCP_EXPOSE_LOWLEVEL=true.
Configuration
All via environment variables (see .env.example for full list):
Variable | Default | Description |
| (required) | Bearer token for auth |
|
| Bind address |
|
| Bind port |
|
| Working directory |
|
| Full shell vs. allowlist |
|
| Disable write/edit/patch tools |
|
| Default command timeout (seconds) |
|
| Sync-first wait before auto-background |
| (built-in) | Comma-separated command list (restricted mode) |
| (empty) | Comma-separated IP allowlist |
|
| Output/file encoding |
|
| Audit log path |
|
| Max bytes returned per call |
|
| Max lines returned per call |
|
| Hard cap on in-memory output |
|
| Max spilled output files kept |
Exposing via Tailscale
Keep SHELL_MCP_HOST=127.0.0.1 (never bind to public interfaces). Let tailscaled handle TLS:
# Tailnet-only (auto-HTTPS):
tailscale serve --bg 8000
# Public internet (Funnel; requires Funnel enabled in admin console):
tailscale funnel --bg 8000
# Check status / stop:
tailscale serve status
tailscale funnel --bg off 8000Client URL: https://<machine>.<tailnet>.ts.net/mcp
Security notes:
Funnel = anyone on the internet can reach this port. Use a long random token (
openssl rand -hex 32). KeepSHELL_MCP_UNRESTRICTED=false.Tailscale serve forwards real client IPs (
100.x.y.z). Pin them withSHELL_MCP_ALLOWED_IPSfor token+IP dual defense (tailnet only; don't use with Funnel).Funnel only supports ports 443/8443/10000 for HTTPS. TLS terminated by Tailscale.
Audit log records commands and paths. Restrict file permissions on the log.
Architecture
shell_mcp/
├── config.py # env → Config; SessionState
├── errors.py # ToolFailure → MCP isError
├── paths.py # Path resolution + sandbox enforcement
├── encoding.py # Auto-detect encoding (UTF-8 / Windows / GB18030)
├── output.py # Line+byte truncation, spool spill, pruning
├── process.py # Command parse/execute: merged output, file capture, tree kill
├── tasks.py # Background task registry
├── mutation_queue.py # Per-path serialized write queue
├── editing.py # Transactional edits: validate → atomic write → diff
├── audit.py # JSON lines audit log
├── tools/
│ ├── shell.py # run_command / task
│ ├── files.py # File tools (read/write/edit/patch)
│ ├── search.py # grep / glob
│ └── audit.py # outline / review_file
└── server.py # FastMCP + auth middleware (only third-party deps)spool:// Resources
Truncated command output and background task logs are served as spool://<name> MCP resources. Tool results include full_output_resource / log_resource fields. Files live in the OS temp directory (shell-mcp-spool/) and are auto-pruned.
Design: Stale-Read Protection
read_file(path) → {text, sha256}
write_file(path, content, expected_sha256=<from read>)
→ server re-reads file, computes sha256(disk)
→ match? write. mismatch? FILE_CHANGED (file untouched)No server-side cache. The SHA256 is computed from disk at read time and re-verified at write time. This is optimistic concurrency (ETag/If-Match pattern), not a cache.
Tests
Core is dependency-free; run directly:
python3 -m unittest discover -s tests -vLicense
MIT — see LICENSE.
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/takereshui/shell-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server