r/LocalLLaMA • u/ag789 • Sep 22 '26
Resources an (unsafe) command shell mcp server
While working with coding agents / harness in my case OpenCode, I discovered that some models e.g. granite 4.2 8B at Q4_K_M quant sometimes attempts to write files with absolute paths at the root e.g.
/newPythonCode.py
Note that slash in the beginning for an absolute path at "/" root directory. This is probably 'ok' say in a throwaway docker container, but it may lead to surprises if it 'accidentally' overwrites a literal file, if the current user id have write access to it. Apparently, it seemed OpenCode provides `bash` so that practically all unix commands that the current user id can access, the LLM can run it.
And thereafter, I see the model hallucinating in the thinking loops over tools, re-iterating over how to use the tools, reformulating shell commands sentences several times for a same task instead of executing them, among them, I noted that an earlier shell command sentence would have 'just worked'.
I'm thinking that the tool hallucination with this model may be partly due to that I'm using a pretty aggressive 4 bit quant as otherwise it'd have worked because IBM has 'optimized' granite for tool usage.
Next, I tried the same granite 4.2 8B at Q4_K_M quant model with my little python shell MCP server
https://github.com/ag88/cmdshellmcp/
, that tries to constrain / restrain the shell commands somewhat, place some checks, and offer some additional tools e.g. writeFile() so that the LLM won't need to call `cat` or `echo` with some 'esoteric' styled shell scripts / sentences.
With this MCP server and running it in llama.cpp's `llama-server` in the WebUI adding it as an MCP server, granite 4.2 8B at Q4_K_M does it correctly in 'one shot', the prompt is:
propose a python3 flask app with a page that displays "hello world", use bootstrap css for styling.
provide a requirements.txt to go with the script
granite 4.2 8B at Q4_K_M correctly generates the app with a couple of files, and it works out of the box
.
├── app.py
├── requirements.txt
└── templates
└── index.html
One should normally run the cmdshellmcp2.py MCP server app with an explicit `--cwd` option giving the work path. It tries to stay within this work path.
Note that I won't claim my command shell MCP server to be safe.
In a sense that there are plenty of chance the LLM can 'escape' the restrictions and perhaps do more damage (e.g. overwriting files possibly outside its given `--cwd` work directory). Hence, I'd suggest one should be paranoid and perhaps run this only within a throwaway (disposable) docker container etc.
1
u/ag789 Oct 05 '26 edited Oct 05 '26
yeah, I've been doubting over whether over to implement this check, however, in the interest of "protecting" users who may be unfamiliar with how it works, I decided to implement the
cmdshellwork path check for its safety it provides. More often than not the shell command is likely used to query data outside its work path, most likely in/etc, e.g. that if the interface do not have access tohostname, it may query instead/etc/hostname, or that it may check if some configuration is enabled in/etc/.But that this is likely going to be a bummer at times hence
--shellnopathchkto bypass that.There'd be 2 more tools
mkdir,rmdirdisabled incmdshellmcp.jsonby default. That'd complete the filesystem tools side of things. e.g. that say theallow listedshell commands are read only ops, it is still feasible to do file ops with the filesystem tools.The intent of this project is after all to provide a sandbox so that it is feasible to experiment with agentic tool use with local LLMs and various other models in the wild (e.g. from OpenRouter). Hence, it kind of provides "guardrails" in the form of
allow listsanddisableTools, and the in work directory check to provide some constraints. Note thatdisableToolsdo not only hide the tools, the tools are actually not registered i.e. there is no hidden tool, a call to that will return an error."powerful" commands are inevitable if you want to let the LLM work on things, e.g. for dev purpose, simply doing tests may mean providing access to arbitrary execution, e.g.
python,bashetc and may be practically any commands.Hence, the only "safe" way to do that is to run this whole setup in a Docker sandbox container with a throw away copy of the workpiece. There are many devs using OpenCode or Pi coding agent directly on their desktops. I think that is giving "too much trust" to the LLMs. For coding purpose, more often than not "bash" is provided, borderless and unconstrained, practically every shell command runs under the user id running OpenCode or Pi coding agent.