About sonirico/mcp-shell
sonirico/mcp-shell is an MCP server published by sonirico in the Developer Tools category: give hands to AI. MCP server to run shell commands securely, auditably, and on demand.
The repository has 108 stars and 20 forks, with the last commit 22 days ago. Recent commit activity is the strongest signal that reported issues will get attention.
Install
claude mcp add shell -- npx -y @kevinwatt/shell-mcpnpx -y @kevinwatt/shell-mcpThis server has no ConduID identity, so agent calls to it are not receipted. Pin the version you install and review the source before granting it credentials.
Tools (29)
deletepath*, recursive
Parameters not published.
diff_filespath_a*, path_b*
Parameters not published.
edit_filepath*, old_string*, new_string*, replace_all
Parameters not published.
git_addpaths, all
Parameters not published.
git_blamepath*, ref, line_start, line_end
Parameters not published.
git_branchesall, merged
Parameters not published.
git_commitmessage*, all
Parameters not published.
git_diffref, ref_to, staged, path, stat_only, name_only
Parameters not published.
git_logmax_count, ref, path, author, grep, since, until, oneline, follow
Parameters not published.
git_ls_filespath, untracked
Parameters not published.
Show all 29 tools
git_remotesNo description in manifest
Parameters not published.
git_restorepaths*, staged
Parameters not published.
git_rev_parseref*
Parameters not published.
git_showref, path, stat_only
Parameters not published.
git_stashaction*, message
Parameters not published.
git_stash_listNo description in manifest
Parameters not published.
git_statusNo description in manifest
Parameters not published.
git_switchbranch*, create
Parameters not published.
git_tagspattern
Parameters not published.
globpattern*, path, newer_than, max_results
Parameters not published.
greppattern*, path, glob, ignore_case, context, files_only, count, max_results
Parameters not published.
list_dirpath, depth, include_hidden
Parameters not published.
mkdirpath*
Parameters not published.
movefrom*, to*
Parameters not published.
read_filepath*, offset, limit, tail
Parameters not published.
run_scriptname*
Parameters not published.
statpath*
Parameters not published.
system_infoNo description in manifest
Parameters not published.
write_filepath*, content*, append
Parameters not published.
Ask AI
Ask AI about sonirico/mcp-shell
Powered by Claude · Grounded in docs
Security checks
Static checks derived from the repository 6 hours ago. Heuristics on the source, not an audit.
- ✓README presentThe repository ships documentation.
- ✓License declaredUsable under a stated license.
- ✓Tests presentA test suite exists in the repository.
- ✓Dependencies pinnedA lockfile pins dependency versions.
- ✓No dynamic code executionSource scan found no eval, dynamic Function, or shell execution.
- !Scoped permissionsDoesn't declare a permission scope. Assume it can do anything its process can.
Releases
README
mcp-shell
MCP server that runs shell commands. Your LLM gets a tool; you get control over what runs and how.
Built on mark3labs/mcp-go. Written in Go.
Run it
Docker (easiest):
docker run -it --rm -v /tmp/mcp-workspace:/tmp/mcp-workspace sonirico/mcp-shell:latest
From source:
git clone https://github.com/sonirico/mcp-shell && cd mcp-shell
make install
mcp-shell
Configure it
Secure mode is the default. With no config file, mcp-shell boots in secure
mode and registers only typed tools: file reads, grep/glob, git inspection,
and (opt-in) file/git writes and operator-defined scripts. There is no raw
shell command. You only need a config file to change the defaults below. To
run fully unrestricted you must opt in explicitly:
MCP_SHELL_ALLOW_UNSAFE=1 mcp-shell # disables secure mode; the only tool is shell_exec
To customize the policy, point to a YAML config:
export MCP_SHELL_SEC_CONFIG_FILE=/path/to/security.yaml
mcp-shell
Secure mode (default) — typed tools only, every path confined to working_directory:
security:
enabled: true
working_directory: /tmp/mcp-workspace
max_execution_time: 30s
max_output_size: 1048576
run_as_user: ""
audit_log: true
# Expose file and git write tools (write_file, edit_file, mkdir, move,
# delete, git_add, git_commit, git_switch, git_restore, git_stash). Off by
# default.
writes_enabled: false
# Operator-defined scripts exposed through the run_script tool. The client
# picks a name; the argv is yours and cannot be altered.
# scripts:
# test: ["go", "test", "./..."]
# lint: ["golangci-lint", "run"]
Wire it up
Claude Desktop — add to your MCP config:
{
"mcpServers": {
"shell": {
"command": "docker",
"args": ["run", "--rm", "-i", "sonirico/mcp-shell:latest"],
"env": { "MCP_SHELL_LOG_LEVEL": "info" }
}
}
}
For custom config, mount the file and set the env:
{
"command": "docker",
"args": ["run", "--rm", "-i", "-v", "/path/to/security.yaml:/etc/mcp-shell/security.yaml", "-e", "MCP_SHELL_SEC_CONFIG_FILE=/etc/mcp-shell/security.yaml", "sonirico/mcp-shell:latest"]
}
Tools
Secure mode (the default) registers these typed tools. * marks a required
parameter.
| Tool | Parameters | Available |
|---|---|---|
read_file |
path*, offset, limit, tail | always |
list_dir |
path, depth, include_hidden | always |
glob |
pattern*, path, newer_than, max_results | always |
grep |
pattern*, path, glob, ignore_case, context, files_only, count, max_results | always |
stat |
path* | always |
diff_files |
path_a*, path_b* | always |
system_info |
always | |
git_status |
always | |
git_log |
max_count, ref, path, author, grep, since, until, oneline, follow | always |
git_diff |
ref, ref_to, staged, path, stat_only, name_only | always |
git_show |
ref, path, stat_only | always |
git_blame |
path*, ref, line_start, line_end | always |
git_branches |
all, merged | always |
git_tags |
pattern | always |
git_rev_parse |
ref* | always |
git_ls_files |
path, untracked | always |
git_stash_list |
always | |
git_remotes |
always | |
write_file |
path*, content*, append | writes_enabled |
edit_file |
path*, old_string*, new_string*, replace_all | writes_enabled |
mkdir |
path* | writes_enabled |
move |
from*, to* | writes_enabled |
delete |
path*, recursive | writes_enabled |
git_add |
paths, all | writes_enabled |
git_commit |
message*, all | writes_enabled |
git_switch |
branch*, create | writes_enabled |
git_restore |
paths*, staged | writes_enabled |
git_stash |
action*, message | writes_enabled |
run_script |
name* | scripts |
Every path parameter is resolved against working_directory (symlinks
followed); anything outside it is rejected. Git paths and refs are passed
positionally and validated: a ref starting with - is rejected. There are no
network tools; push, fetch and clone are not offered.
Unrestricted mode: shell_exec exists only with MCP_SHELL_ALLOW_UNSAFE=1, runs the command through bash -c with no validation, by design, and it is the only tool registered in that mode.
Environment variables
| Variable | Description |
|---|---|
MCP_SHELL_SEC_CONFIG_FILE |
Path to security YAML (overrides built-in secure defaults) |
MCP_SHELL_ALLOW_UNSAFE |
Set 1 (or true) to disable secure mode and expose shell_exec instead of the typed tools (opt-in) |
MCP_SHELL_SERVER_NAME |
Server name (default: "mcp-shell 🐚") |
MCP_SHELL_LOG_LEVEL |
debug, info, warn, error, fatal |
MCP_SHELL_LOG_FORMAT |
json, console |
MCP_SHELL_LOG_OUTPUT |
stdout, stderr, file |
Development
make install dev-tools # deps + goimports, golines
make fmt test lint
make docker-build # build image locally
make release # binary + docker image
Security
- Default: Secure mode. The server builds every command's argv itself; the client never supplies a shell string. Only typed tools are registered.
- Path confinement: every path parameter is resolved against
working_directory, symlinks followed, and anything that resolves outside it is rejected. - Git hardening: paths are passed after
--, refs after--end-of-options, and a ref starting with-is rejected. Git runs withGIT_CONFIG_NOSYSTEM=1,GIT_CONFIG_GLOBAL=/dev/null,core.fsmonitor,core.pagerandcore.hooksPathneutralised, and--no-ext-diff --no-textconvon log/diff/show/blame. - Minimal environment: child processes get only
PATH,HOMEandLANG, never the server's own environment or.envsecrets. - Writes and scripts are opt-in:
writes_enabled: trueexposes the file/git write tools; a non-emptyscriptsmap exposesrun_script. Both are off by default. - Unrestricted: only via
MCP_SHELL_ALLOW_UNSAFE=1. The only tool registered isshell_exec, which runsbash -cwith no validation. Fine for local dev, dangerous otherwise. - Docker: Runs as non-root, Alpine-based. Use it in production. Best paired with an OS sandbox (read-only FS, dropped caps) as defense-in-depth.
Threat model, guarantees, and the scope for vulnerability reports live in SECURITY.md. Read it before opening an advisory.
Migrating from 0.x
Secure mode no longer validates a shell_exec command string; it exposes
typed tools instead. A config file's security: block no longer accepts:
| Removed key | Replacement |
|---|---|
use_shell_execution |
not needed; typed tools never shell out |
allowed_executables |
not needed; each tool runs a fixed, server-built argv |
allowed_commands |
not needed; same as above |
blocked_commands |
not needed; same as above |
blocked_patterns |
not needed; same as above |
Loading a config file that still sets one of these fails at startup with an
error naming the key. There is no more "legacy mode" and no
security-legacy.yaml example. If you need raw shell access, set
MCP_SHELL_ALLOW_UNSAFE=1 to get shell_exec back; it is no longer
constrained by the security: block at all.
Contributing
Fork, branch, make fmt test, open a PR.
README fetched from the repository 6 hours ago. The original is authoritative.