main
shellmcp
An MCP server (stdio, Python stdlib only) with one tool, run: a bash command, its exit code
and its output. Gives any MCP client's model a terminal.
python3 shellmcp.py [--mode readonly|all] [--cwd DIR] [--timeout 60] [--max-output 8000] [--hide PATH]...
--mode readonly(default): every command runs in bubblewrap. The filesystem is read-only except a private /tmp; no network; no other processes visible; ~/.ssh, ~/.gnupg and each--hide PATHlook empty. Needsbwrap.--mode all: the user's full permissions (here: wheel and docker, so effectively root). Use it only with a client that asks before each tool call.
The tool description names the host, user, directory, limits and which modern tools (rg, fd, jq, ...) are installed, so the model prefers them.
Where commands run
Wherever this process runs. The client starts it (stdio), so with "command": "python3" the
commands run on the client's machine. To act on the GPU host from any machine, start it
over ssh (key login needed):
"command": "ssh", "args": ["fabian@192.168.2.169", "python3", "/home/fabian/coding/misc/shellmcp/shellmcp.py", "--mode", "readonly"]
Clients
ollmcp with gemma4 on vLLM (examples/ollmcp.json registers shell and shell-rw):
ollmcp -p openai -H http://127.0.0.1:8000/v1 -m gemma4 -j examples/ollmcp.json
Claude Code:
claude mcp add shell -- python3 /home/fabian/coding/misc/shellmcp/shellmcp.py --mode readonly
OpenAI-API apps without MCP (Open WebUI and the like): wrap it as an OpenAPI server with
uvx mcpo --port 8001 -- python3 shellmcp.py --mode readonly.
Test
python3 -m unittest -v test_shellmcp
Description
Languages
Python
100%