cmdshellmcp
Um servidor MCP de comandos e operações de arquivo restritos para agentes de IA. Limita a execução de comandos por meio de uma lista de permissões explícita, permite que cada ferramenta seja desativada individualmente e suporta tokens de autenticação gerados automaticamente. Fornece comandos Unix restritos, operações de arquivo, aplicação de patches e busca de URLs sem expor um shell irrestrito.
Documentação
cmdshellmcp
cmdshellmcp é um servidor MCP de shell de comandos restrito para agentes de IA. Ele expõe um pequeno conjunto de comandos Unix permitidos, operações de arquivo relativamente seguras, aplicação de patches e busca de URLs, para que um cliente MCP possa realizar tarefas locais limitadas sem acesso irrestrito ao shell.
O servidor é implementado em Python e executa como um servidor MCP usando o pacote fastmcp. Por padrão, ele escuta em 127.0.0.1:8003 usando o transporte HTTP streamable, a menos que --sse seja selecionado.
[!CAUTION]
Este servidor fornece execução remota de comandos (RCE), o que normalmente é considerado uma vulnerabilidade crítica de segurança. Permitir comandos poderosos—como bash, sh, python, perl, sudo, docker, ou comandos capazes de escrever arquivos—pode permitir que um atacante ou LLM não confiável contorne as restrições pretendidas e assuma o controle do sistema. Por exemplo, permitir python ou bash pode efetivamente permitir execução arbitrária de código e acesso a arquivos. Se o servidor não tiver autenticação forte, for acessível por clientes não confiáveis, ou for controlado por um LLM não confiável ou com injeção de prompt, pode causar danos graves, incluindo perda de dados, roubo de credenciais, instalação de malware ou comprometimento de outros sistemas. Execute cmdshellmcp (cmdshellmcp2.py) apenas em um sandbox protegido e descartável, com privilégios cuidadosamente limitados aos necessários para a tarefa pretendida e com acesso limitado a arquivos, credenciais, dispositivos e redes—por exemplo, um contêiner Docker efêmero ou máquina virtual que possa ser destruído com segurança após o uso.
Aviso
Este é um aplicativo experimental / de rascunho que evoluiu do uso de um servidor MCP (ferramentas) que permitem executar comandos de shell para fins de codificação. Infelizmente, para esse propósito, muitas vezes é necessário fornecer ao cliente LLM (modelo) comandos de shell bastante poderosos para "fazer seu trabalho" para um escopo / contexto / intenção específico.
Os comandos permitidos por padrão não são necessariamente seguros, ou seja, agentes LLM ou praticamente clientes que chamam
a API MCP podem "escapar" e fazer coisas fora de um contexto, por exemplo, o diretório de trabalho definido com a opção --cwd.
Também não valida se os argumentos são, afinal, seguros.
Também existem ferramentas (funções MCP expostas) que expõem operações de escrita e modificação de arquivos, incluindo execução de comandos de shell.
- A autenticação está habilitada por padrão. Mantenha o token gerado aleatoriamente, ou defina
um auth_token fixo usando o campo auth no arquivo de configuração ou
--auth. Usar--noauthpraticamente significa que você está dando execução remota de comandos (RCE) a qualquer cliente (incluindo possivelmente maliciosos ou fraudulentos) que possa alcançar o servidor. - Execute isso como um usuário sem privilégios. Executar como
rooté, na melhor das hipóteses, tolice. - Não use isso com clientes não confiáveis ou LLMs não confiáveis.
- Use em um sandbox descartável, por exemplo, um contêiner Docker autônomo ou máquina virtual que você possa descartar, incluindo o conteúdo.
- Revise a lista de permissões em
cmdshellmcp.jsone os padrões codificados, revise-os antes de usar.
Recursos
- Execução de shell com lista de permissões para um conjunto selecionado de comandos
- Operações de leitura/escrita/lista de arquivos sob um diretório de trabalho configurado
- Edição transacional de arquivos de texto com
sed, backups numerados e diffs unificados - Aplicação de patches de diff unificado via
patch - Suporte a busca HTTP com embelezamento HTML opcional
- Autenticação por token Bearer com um token seguro gerado aleatoriamente por padrão
- Registro de auditoria para stdout e/ou um arquivo
- Restrições de caminho para evitar escapar do diretório de trabalho atual
Uso de IA neste repositório
Este aplicativo e seu conteúdo, por exemplo, esta página, foi criado com auxílio de LLMs (modelos de linguagem grandes), como
- ChatGPT 5.6 sol (light), Codex
- Github Co-pilot MAI-Code-1.1-Flash
O código inicial foi escrito pelo autor e refatorado com auxílio dos LLMs, e as atualizações também são feitas parcialmente manualmente. Após a adição ou alteração de recursos, testes adicionais são frequentemente feitos executando-os manualmente, por exemplo, na Interface Web do llama-server do llama.cpp
Instalação
- Clone o repositório.
- Crie e ative um ambiente virtual, se desejado.
- Instale as dependências:
python -m venv .venv
source .venv/bin/activate
pip install fastmcp requests beautifulsoup4
Se o seu ambiente usar um requirements.txt, você também pode instalar a partir dele:
pip install -r requirements.txt
A ferramenta editFile também requer GNU sed (incluindo sua opção --sandbox)
e diff instalados no servidor. Esses programas são invocados diretamente pela
ferramenta dedicada e não precisam aparecer em allowed_commands.
Configuração
Quando --conf não é fornecido, o servidor lê o arquivo de configuração opcional cmdshellmcp.json
do diretório atual. Se o arquivo não existir, o
servidor usa valores padrão de linha de comando e embutidos.
Exemplo:
{
"host": "127.0.0.1",
"port": 8003,
"quiet": false,
"auditlog": null,
"disableTools": ["writeFile", "editFile", "applyPatch"],
"allowed_commands": [
"ls", "pwd", "date", "cat", "grep", "egrep",
"whoami", "head", "tail", "sed", "wc", "file", "du", "df",
"free", "ps", "uname", "hostname", "uptime", "w", "last",
"mkdir", "cp", "mv", "awk"
],
"auth": "_my_secret_auth_token_"
}
Chaves de configuração suportadas:
host: host de vinculação; padrão127.0.0.1port: porta de vinculação; padrão8003quiet: suprime a saída de auditoria para stdout quandotrueauditlog: caminho opcional para um arquivo de log de auditoriaallowed_commands: lista de comandos permitidos para execuçãodisableTools: lista de nomes de ferramentas MCP a serem omitidos do servidor, sensível a maiúsculas/minúsculas e é necessária correspondência exata do nomeauth: string opcional de token bearer fixo; quando omitido, um token aleatório é gerado na inicialização
Executando o servidor
Inicie o servidor com as configurações padrão:
python cmdshellmcp2.py
Quando --cwd é omitido, o servidor solicita um diretório de trabalho e mostra o
diretório atual do processo como padrão. Pressione Enter para aceitá-lo. Se a entrada
padrão não estiver disponível (por exemplo, ao executar como um serviço), o diretório
atual é selecionado automaticamente. O servidor então inicia em 127.0.0.1:8003
usando o transporte HTTP streamable.
Modo SSE
python cmdshellmcp2.py --sse
Isso executa o servidor no transporte SSE em vez de HTTP streamable.
Clientes de navegador e CORS
Ambos os transportes HTTP incluem middleware CORS para clientes MCP baseados em navegador. O
servidor aceita solicitações de qualquer origem, suporta os métodos MCP GET, POST e
DELETE e solicitações de preflight OPTIONS do navegador, e expõe o
cabeçalho de resposta mcp-session-id ao JavaScript do navegador.
Como todas as origens são permitidas, não exponha o servidor a uma rede não confiável
sem autenticação e controles de rede apropriados. Para restringir o acesso do navegador,
substitua allow_origins=["*"] em CORS_MIDDLEWARE pelas
origens confiáveis específicas.
Diretório de trabalho personalizado
python cmdshellmcp2.py --cwd /path/to/project
Isso define o diretório de trabalho usado pelas ferramentas de arquivo e shell sem solicitação.
O caminho deve existir e deve ser um diretório; ~ é expandido e o caminho
selecionado é normalizado para um caminho absoluto.
Host e porta personalizados
python cmdshellmcp2.py --host 0.0.0.0 --port 9000
Autenticação
A autenticação está habilitada por padrão. Se nem --auth nem um valor auth no
arquivo de configuração fornecerem um token fixo, o servidor gera um
token criptograficamente seguro, codificado em base64, e o exibe no log
de inicialização. O token gerado é mostrado em negrito quando o stdout suporta estilo ANSI.
Configure o cliente MCP para enviar esse valor como seu token bearer.
Para usar um token fixo:
python cmdshellmcp2.py --auth my-secret-token
Para executar explicitamente sem autenticação:
python cmdshellmcp2.py --noauth
--auth e --noauth são mutuamente exclusivos. --noauth também substitui um
valor auth no arquivo de configuração. Desabilitar a autenticação é inseguro em
qualquer rede que não seja completamente confiável.
Registro de auditoria
python cmdshellmcp2.py --quiet --auditlog /tmp/cmdshellmcp.log
--quietdesabilita o registro de auditoria para stdout.--auditloganexa eventos de auditoria ao arquivo especificado.
Opções de linha de comando
python cmdshellmcp2.py [--cwd PATH] [--host HOST] [--port PORT] \
[--allow COMMAND [COMMAND ...]] [--conf FILE] [--auth TOKEN | --noauth] \
[--disableTools TOOL[,TOOL...]] [--editdelbk] [--sse] [--quiet] \
[--auditlog FILE]
Opções:
--cwd: diretório de trabalho usado para operações de arquivo e shell; quando omitido, solicita com o diretório atual do processo como padrão--host: host de vinculação do servidor--port: porta de vinculação do servidor--allow: substitui a lista de permissões para o processo atual; pode ser repetido--disableTools: nomes de ferramentas MCP separados por vírgula a serem omitidos; substitui a listadisableToolsdo arquivo de configuração; sensível a maiúsculas/minúsculas e é necessária correspondência exata do nome--editdelbk: exclui o backup numerado apóseditFileter concluído com sucesso e composto sua resposta de diff unificado--conf: caminho do arquivo de configuração JSON; quando omitido, o padrão écmdshellmcp.jsonno diretório atual--auth: usa um token bearer fixo em vez de gerar um--noauth: desabilita explicitamente a autenticação bearer; mutuamente exclusivo com--authe inseguro em redes não confiáveis--sse: usa transporte SSE em vez de HTTP streamable--quiet: suprime a saída de auditoria no stdout--auditlog: escreve logs de auditoria em um arquivo fornecido
Substituição da lista de permissões
python cmdshellmcp2.py --allow ls pwd date whoami cat grep
Isso substitui allowed_commands do arquivo de configuração para esse processo.
Desabilitando ferramentas
python cmdshellmcp2.py --disableTools writeFile,editFile,applyPatch,fetch
Isso impede que ferramentas correspondentes sejam registradas pelo servidor. Os nomes das ferramentas
são sensíveis a maiúsculas/minúsculas e devem corresponder aos nomes das funções na seção Ferramentas MCP expostas a agentes de IA abaixo.
A opção de linha de comando substitui a lista disableTools do arquivo de configuração.
Modelo de segurança
Este servidor é intencionalmente restrito. Ele é projetado para ser relativamente seguro em um ambiente controlado, em vez de um shell geral sem restrições.
Os recursos de segurança incluem:
- Os comandos de shell devem estar explicitamente presentes na lista de permissões
- Os nomes dos comandos são verificados antes da execução
- A ferramenta
cmdshellespera um nome de comando e uma matriz de argumentos, não uma string de shell bruta - Piping não é suportado por design
- Para várias ferramentas, o servidor MCP valida caminhos para evitar acesso ou escrita fora do diretório de trabalho fornecido
https://github.com/ag88/cmdshellmcp/blob/main/cmdshellmcp2.py#L153.
No entanto, para executar comandos Unix/Linux
allow_listedreais, essa verificação não é realizada para os argumentos. Isso ocorre porque há situações em que é necessário acessar recursos compartilhados, por exemplo, um arquivo/recurso em, digamos,/usr/share,/usr/include, etc. Restrições estreitas significariam configurações de lista de permissões específicas por comando + argumentos, o que seria uma lista muito grande e detalhada, difícil de manter (manualmente) e possivelmente lenta, pois precisaria realizar a verificação a cada vez. Portanto, deve-se considerar cuidadosamente os comandos Unix/Linuxallow_listespecíficos para seu contexto/uso/intenção, ao configurá-los, por exemplo, emcmdshellmcp.json - As ferramentas de arquivo rejeitam caminhos absolutos e caminhos contendo
.. - As escritas são limitadas a locais abaixo do
cwdconfigurado editFileaceita apenas uma pequena lista de permissões de opçõessedque não selecionam arquivos, executa GNUsedem modo sandbox e não invoca um shelleditFileescreve a saída bem-sucedida em um arquivo temporário antes de substituir atomicamente o arquivo de origem; execuções desedcom falha deixam a origem inalterada- A aplicação de patches bloqueia opções perigosas de alteração de caminho
Em resumo: o shell é um sandbox estreito para operações controladas de leitura/escrita, não um terminal de host completo.
Ferramentas MCP expostas a agentes de IA
O servidor registra as seguintes ferramentas:
1. cmdshell(command, args)
Executa um comando Unix configurado com argumentos.
Parâmetros:
command: o nome do comando, que deve aparecer na lista de permissõesargs: lista de argumentos/flags a serem passados ao comando
Exemplo:
cmdshell("ls", ["-la"])
cmdshell("grep", ["-R", "needle", "."])
Observações:
- O nome do comando deve estar na lista de permissões.
- Os argumentos são passados como uma lista, reduzindo o risco de injeção de shell.
- Padrões glob podem ser expandidos automaticamente.
- Globs entre aspas podem ser passados literalmente para evitar expansão.
2. writeFile(file, text, append=False, newline=True)
Escreve texto em um arquivo abaixo do diretório de trabalho atual.
Parâmetros:
file: um caminho relativo sobcwdtext: conteúdo a ser escritoappend: setrue, anexa em vez de sobrescrevernewline: adiciona uma nova linha final quandotrue
Exemplo:
writeFile("notes.txt", "hello from the agent")
Isso é restrito a caminhos relativos abaixo do diretório de trabalho configurado.
3. readFile(file)
Lê um arquivo de texto UTF-8 abaixo do diretório de trabalho atual.
Exemplo:
readFile("README.md")
4. listFiles(path=".")
Lista as entradas em um diretório abaixo do diretório de trabalho configurado.
Exemplo:
listFiles(".")
listFiles("src")
Retorna uma lista de entradas separadas por novas linhas, com / anexado para diretórios.
5. editFile(file, script, args=None)
Edita um arquivo de texto existente abaixo do diretório de trabalho configurado usando GNU
sed. O parâmetro dedicado script é a única fonte do programa de
edição; o comando é executado com uma lista de argumentos em vez de através de um
shell.
Parâmetros:
file: caminho relativo de um arquivo regular existente abaixo decwdscript: uma expressão ou programa de ediçãosed, comos/old/new/g,/pattern/dou10,20s/old/new/gargs: opções seguras opcionais desed, como-nou-E; opções que ativam edição in-place, fornecem outra expressão ou arquivo de programa, ou selecionam arquivos adicionais de entrada/saída são rejeitadas
Exemplo:
editFile("src/example.py", "s/old_name/new_name/g")
Antes de executar sed, a ferramenta copia a origem para o próximo backup numerado
não utilizado. Por exemplo, a primeira edição acima cria src/example.py.bk1; se esse
nome existir, usa .bk2, depois .bk3, e assim por diante. Backups existentes nunca são
sobrescritos.
sed escreve seu resultado proposto na memória enquanto executa em modo sandbox, o que
bloqueia comandos GNU sed que leem arquivos, escrevem arquivos ou executam programas. A
origem é substituída a partir de um arquivo temporário no mesmo diretório somente após sed sair
com sucesso. Uma execução falha de sed deixa a origem inalterada e remove o novo backup
desnecessário. Se a substituição começou e uma etapa posterior falhar, o backup é
mantido para recuperação.
Em caso de sucesso, a resposta identifica o backup e inclui a saída de:
diff -u src/example.py.bk1 src/example.py
O backup é a versão antiga e o arquivo atual é a nova versão. Uma edição sem alteração é relatada explicitamente e ainda mantém seu backup numerado.
Inicie o servidor com --editdelbk para remover cada backup numerado após uma
edição bem-sucedida. A ferramenta primeiro executa diff e compõe a resposta completa,
para que o diff unificado retornado permaneça disponível mesmo que o backup tenha sido
excluído. A mensagem de sucesso identifica o backup excluído. Backups ainda são
mantidos quando a substituição ou geração de diff falha, então permanecem disponíveis
para recuperação. Se a exclusão do backup em si falhar, a resposta começa com Error:
e relata que a edição foi concluída, mas o backup permanece.
Nota de segurança: backups contêm o arquivo completo pré-edição, incluindo quaisquer segredos que ele continha. A menos que
--editdelbkesteja habilitado, eles permanecem no disco após edições bem-sucedidas. Proteja e remova-os de acordo com a mesma política de retenção do arquivo de origem.
6. applyPatch(file, diff, pnum=2, args=None)
Aplica um diff a um arquivo explicitamente nomeado usando GNU patch. O diff é
normalmente um diff unificado e é passado diretamente para patch via entrada padrão.
Parâmetros:
file: arquivo regular existente abaixo do diretório atual configuradodiff: texto do patch, normalmente um diff unificadopnum: número de componentes de caminho iniciais a remover, correspondendo ao patch GNU-pNUM; padrão2args: flags opcionais permitidas do GNU patch; flags que podem selecionar outro alvo, entrada, saída, diretório, destino de backup/rejeição ou valor de strip são rejeitadas
Exemplo:
applyPatch(
file="src/example.py",
pnum=2,
diff="--- a/src/example.py\n+++ b/src/example.py\n@@ -1 +1 @@\n-old\n+new\n",
)
O file explícito é autoritativo; nomes de arquivo embutidos no diff não são
usados para escolher um alvo. Caminhos absolutos e travessia de diretório pai são rejeitados, e
o alvo resolvido deve permanecer dentro do diretório atual configurado.
7. fetch(url, prettify=False)
Busca uma URL usando requests. Se prettify for true, analisa o HTML com BeautifulSoup e o imprime de forma organizada.
Exemplo:
fetch("https://example.com")
fetch("https://example.com", prettify=True)
Exemplo de inicialização
python cmdshellmcp2.py \
--cwd /workspace/project \
--host 0.0.0.0 \
--port 8003 \
--auth mytoken \
--allow ls pwd date cat grep head tail wc
Isso inicia um servidor com um diretório de trabalho fixo, host de bind, porta, autenticação e uma lista de permissões de comandos mínima.
Notas
- Transporte padrão:
streamable-http - Host padrão:
127.0.0.1 - Porta padrão:
8003 - A lista de permissões padrão é construída a partir de um pequeno conjunto de comandos relativamente seguros
Casos de uso típicos
- Inspecionar o estado do repositório e do sistema de arquivos
- Ler arquivos de origem e logs
- Escrever pequenos arquivos gerados ou alterações de configuração
- Fazer substituições de texto revisáveis com backups automáticos
- Aplicar pequenos patches
- Buscar documentação ou dados da web
- Executar um conjunto limitado de diagnósticos relativamente seguros
Este servidor é melhor usado quando um agente de IA precisa de acesso local controlado sem receber comandos de sistema irrestritos.