Files

1.6 KiB

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 PATH look empty. Needs bwrap.
  • --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