Назад к MCP
🐹 GoMCP ServerCommand LineLocal

Каталог MCP

sonirico/mcp-shell

Give hands to AI. MCP server to run shell commands securely, auditably, and on demand on isolated environments like docker.

Открыть GitHub
Рейтинг
102
Звёзды GitHub
янв. 2026 г.
Добавлено
Сообщество
Статус

Описание

mcp-shell

Trust Score glama

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.

ToolParametersAvailable
read_filepath*, offset, limit, tailalways
list_dirpath, depth, include_hiddenalways
globpattern*, path, newer_than, max_resultsalways
greppattern*, path, glob, ignore_case, context, files_only, count, max_resultsalways
statpath*always
diff_filespath_a*, path_b*always
system_infoalways
git_statusalways
git_logmax_count, ref, path, author, grep, since, until, oneline, followalways
git_diffref, ref_to, staged, path, stat_only, name_onlyalways
git_showref, path, stat_onlyalways
git_blamepath*, ref, line_start, line_endalways
git_branchesall, mergedalways
git_tagspatternalways
git_rev_parseref*always
git_ls_filespath, untrackedalways
git_stash_listalways
git_remotesalways
write_filepath*, content*, appendwrites_enabled
edit_filepath*, old_string*, new_string*, replace_allwrites_enabled
mkdirpath*writes_enabled
movefrom*, to*writes_enabled
deletepath*, recursivewrites_enabled
git_addpaths, allwrites_enabled
git_commitmessage*, allwrites_enabled
git_switchbranch*, createwrites_enabled
git_restorepaths*, stagedwrites_enabled
git_stashaction*, messagewrites_enabled
run_scriptname*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

VariableDescription
MCP_SHELL_SEC_CONFIG_FILEPath to security YAML (overrides built-in secure defaults)
MCP_SHELL_ALLOW_UNSAFESet 1 (or true) to disable secure mode and expose shell_exec instead of the typed tools (opt-in)
MCP_SHELL_SERVER_NAMEServer name (default: "mcp-shell 🐚")
MCP_SHELL_LOG_LEVELdebug, info, warn, error, fatal
MCP_SHELL_LOG_FORMATjson, console
MCP_SHELL_LOG_OUTPUTstdout, 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 with GIT_CONFIG_NOSYSTEM=1, GIT_CONFIG_GLOBAL=/dev/null, core.fsmonitor, core.pager and core.hooksPath neutralised, and --no-ext-diff --no-textconv on log/diff/show/blame.
  • Minimal environment: child processes get only PATH, HOME and LANG, never the server's own environment or .env secrets.
  • Writes and scripts are opt-in: writes_enabled: true exposes the file/git write tools; a non-empty scripts map exposes run_script. Both are off by default.
  • Unrestricted: only via MCP_SHELL_ALLOW_UNSAFE=1. The only tool registered is shell_exec, which runs bash -c with 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 keyReplacement
use_shell_executionnot needed; typed tools never shell out
allowed_executablesnot needed; each tool runs a fixed, server-built argv
allowed_commandsnot needed; same as above
blocked_commandsnot needed; same as above
blocked_patternsnot 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.

Теги
GomacOSWindowsLinuxLocal