Python SSH MCP

Um servidor MCP SSH escrito em Python. Que se baseia em uma camada sofisticada de ferramentas e permissões. Incluindo Skills, conjunto de ferramentas Docker e Systemctl e alguns runbooks.

Documentação

Python SSH MCP

Python FastMCP License Tests

Um servidor MCP SSH construído em Python sobre o FastMCP. O objetivo: dar a um LLM acesso SSH real a muitos hosts, mantendo controle fino sobre o que ele pode e não pode fazer. A superfície de configuração é deliberadamente ampla — provavelmente exagero se você só quer uma única ferramenta ssh_exec, mas compensa assim que você começa a conectar mais de um host ou a restringir o agente a caminhos, comandos e níveis de visibilidade específicos. Se uma ferramenta que você precisa não estiver aqui, abra uma issue.

Atualmente implementado: 100 ferramentas em 10 grupos, 1649 testes unitários aprovados + 6 testes de integração com sshd dockerizado + uma suíte tests/e2e/ opcional que aciona todas as ferramentas contra o hosts.toml real do operador. known_hosts estrito por padrão, confinamento por allowlist de caminhos em toda ferramenta que lida com caminhos, log de auditoria com hash SHA-256, hooks plugáveis pelo operador. Política de redação de segredos que permite ao LLM ler arquivos de configuração sem ver os segredos (marcadores de hash HMAC-SHA256; redact_paths_globs com modos de bypass block/warn/audit_only). Cinco ferramentas de nível sudo que lidam com caminhos e respeitam a política de caminhos sob sudo (read/read_redacted/write/edit/sftp_list). Modo de streaming em disco local em upload/deploy/download/sudo_write para que arquivos grandes ignorem o canal base64 do LLM. A maioria das ferramentas retorna resultados Pydantic tipados, para que clientes MCP vejam schemas reais em tools/list (não object genéricos); as poucas que legitimamente produzem payloads mesclados ou bimodais permanecem como dict[str, Any] com a justificativa documentada na função. Alvos SSH POSIX suportados de ponta a ponta; alvos SSH Windows suportados para SFTP + operações de arquivo + ssh_file_hash via PowerShell -EncodedCommand (veja ADR-0023); CLI do Docker substituível por Podman via SSH_DOCKER_CMD / docker_cmd por host.

Conteúdo

Neste arquivo:

Início Rápido

  • Instale o python-ssh-mcp
  • Escreva sua primeira entrada de hosts.toml (Passo a passo §3)
  • Configure seu Cliente MCP (Claude Desktop, Claude Code, Cursor, ...)
  • Peça ao LLM para executar ssh_host_ping contra seu alvo — verifica agente + known_hosts + pool de ponta a ponta
  • Ative os flags de nível que você precisa (ALLOW_LOW_ACCESS_TOOLS, ALLOW_DANGEROUS_TOOLS, ALLOW_SUDO) e o LLM desbloqueia operações de arquivo, exec, sudo — veja CONFIGURATION.md → Níveis de acesso

CONFIGURATION.md — configurando mais hosts, níveis de acesso, allowlist/blocklist, grupos de ferramentas, Docker/Podman, identidade SSH por host, gerenciamento de known_hosts, sudo. ADVANCED.md — runbooks (FastMCP Skills), hooks, observabilidade, testes, rotação de chaves, arquitetura, contribuição.

Recursos

  • Servidor compatível com MCP expondo SSH via stdio (ou HTTP, se preferir); o transporte fala MCP diretamente, sem shim.
  • Modelo de acesso em quatro níveisread / low-access / dangerous / sudo. Cada nível é ativado com seu próprio flag de ambiente e aplicado via transformações Visibility do FastMCP. Padrão: somente leitura.
  • Dez grupos de ferramentas ortogonais aos níveis (host, session, sftp-read, file-ops, exec, sudo, shell, docker, systemctl, pkg). SSH_ENABLED_GROUPS reduz o catálogo ao que um assistente específico realmente precisa.
  • 100 ferramentas: veja TOOLS.md para a referência completa por ferramenta. Destaques:
    • Sondas somente leitura (ping, informações do host, uso de disco, processos, alertas, verificação de known-hosts, informações do usuário, notas do host, server-info)
    • Recurso mcp://ssh-mcp/server-info + ferramenta de fallback ssh_server_info — identidade do servidor + superfície de capacidades para que o LLM (ou operador) possa auto-inspecionar "qual versão é este servidor / quais níveis estão desbloqueados / quantas ferramentas estão visíveis" sem vasculhar o catálogo (v1.5.0)
    • Leituras SFTP (list, stat, download, find, file_hash) com confinamento por realpath remoto
    • ssh_read_redacted — lê configurações (.env, .yml, ...) com segredos substituídos inline por marcadores de hash HMAC-SHA256, para que o LLM obtenha informações estruturais mas nunca o texto puro (v1.4.0)
    • Operações de arquivo de baixo acesso (cp, mv, mkdir, delete, delete_folder, edit, patch, upload, deploy, link, transfer) — SFTP primeiro, gravações atômicas. upload/deploy/sftp_download suportam local_path= para transmitir arquivos grandes sem idas e voltas base64 (v1.3.0)
    • Nível exec com timeout por chamada, variante de streaming, transmissão entre hosts e uma folha de dicas ativada por padrão que captura cat/tee/sudo cat/... e redireciona para a ferramenta nativa correta
    • Nível sudo — ssh_sudo_exec mais cinco ferramentas de nível sudo que lidam com caminhos (ssh_sudo_read, _read_redacted, _write, _edit, _sftp_list) para que arquivos de propriedade do root permaneçam dentro da política de caminhos em vez de contorná-la via sudo cat bruto (v1.4.0). Senha enviada via stdin, nunca em argv; senhas em variáveis de ambiente rejeitadas na inicialização
    • 27 ferramentas Docker (ps, logs, inspect, stats, events, system_df, images, volumes, compose up/down/logs/..., ciclo de vida de contêineres, exec, run, prune)
    • 17 ferramentas systemctl (leitura + mutações de ciclo de vida) e 8 auxiliares journalctl/list
    • 9 ferramentas APT/pacotes — leitura (apt_list, apt_search, apt_show, apt_show_holds) + mutações (apt_install, apt_upgrade, apt_remove, apt_autoremove, apt_mark). Hosts não-Debian recebem um PlatformNotSupported limpo
    • Sessões de shell persistentes com rastreamento de cwd (sem PTY remoto, estado baseado em sentinela)
  • known_hosts estrito — sem aceitação automática; chaves desconhecidas ou incompatíveis falham de forma segura.
  • Confinamento de caminho em tudo — cada ferramenta que lida com caminhos canonicaliza via realpath remoto (ou realpath SFTP no Windows) e verifica a allowlist, com exceções restricted_paths para zonas sensíveis.
  • Política por host em hosts.toml — usuários, chaves, allowlists, modo sudo, plataforma, cadeias de proxy, limites de alerta, opt-out de sessão persistente.
  • Suporte a alvos SSH Windows para SFTP + operações de arquivo (veja ADR-0023); ferramentas somente POSIX recusam alvos Windows com um PlatformNotSupported limpo que nomeia a capacidade ausente.
  • Log de auditoria — uma linha JSON por chamada de ferramenta (todos os níveis), caminhos/comandos com hash SHA-256, o campo error contém apenas a classe da exceção (texto completo permanece em DEBUG localmente).
  • Hooks do operador: importe qualquer módulo via SSH_HOOKS_MODULE para eventos STARTUP / SHUTDOWN / PRE_TOOL_CALL / POST_TOOL_CALL. Timeout limitado por hook, isolamento de exceções, aviso de backlog quando tarefas pendentes se acumulam.
  • Runbooks via FastMCP Skills — arquivos SKILL.md por ferramenta dão ao LLM documentação prática e escopada sob demanda.
  • Busca de ferramentas BM25 (opcional) — substitui tools/list por search_tools + call_tool quando 50+ schemas começam a consumir contexto.
  • Visão geral do catálogo de ferramentas registrada na inicialização (contagens por nível e por grupo) para que operadores vejam exatamente o que será oferecido ao LLM.

Instalação

Python SSH MCP é um pacote Python padrão PEP 621 (backend de build hatchling). Use o instalador de sua preferência — uv é o caminho recomendado:

uv sync                      # create .venv + install runtime deps + dev extras
uv run ssh-mcp               # start the server on stdio

# Or without syncing a venv first — build + run in an ephemeral environment:
uvx --from . ssh-mcp

# Plain pip also works (PEP 517):
pip install -e ".[dev]"
ssh-mcp

# FastMCP shortcuts (once the package is installed):
fastmcp dev inspector        # dev UI: MCP Inspector + hot reload; auto-finds fastmcp.json
fastmcp run                  # run the server; auto-finds fastmcp.json
fastmcp run -t http -p 8000  # HTTP transport instead of stdio

Grupos de dependências opcionais:

  • .[tasks] — adiciona o cliente Redis (redis>=5.0.0) para um backend de tarefas de produção. O runtime de tarefas do FastMCP em si (docket, em memória por padrão) é uma dependência obrigatória via fastmcp[tasks] e acompanha o pacote independentemente — instale este extra apenas ao apontar FASTMCP_DOCKET_URL para um Redis real (perda de tarefas na reinicialização importa em produção com ALLOW_DANGEROUS_TOOLS=true; veja _warn_task_backend).
  • .[telemetry] — distribuição OpenTelemetry + exportador OTLP.
  • .[dev] — pytest, ruff, mypy.

Clientes MCP (Claude Desktop, Claude Code, Cursor) descobrem o servidor via fastmcp.json.

Configuração do Cliente

Todo cliente MCP importante aceita um trecho JSON que informa como iniciar o servidor. O formato é padronizado em torno de um objeto mcpServers — apenas o caminho do arquivo difere por cliente. Escolha seu cliente, cole o trecho no arquivo correto, reinicie o cliente para que o subprocesso seja reiniciado.

Atenção: o bloco deployment.env do fastmcp.json (se você mantiver um no projeto) sobrescreve as variáveis de ambiente do cliente incondicionalmente — mantenha os flags de nível fora desse bloco e deixe que venham da configuração do cliente ou do seu .env. Se o cliente parecer manter um subprocesso obsoleto após mudanças de código, veja Solução de Problemas — a maioria dos clientes inicia e é dona do subprocesso do servidor, então reiniciar apenas o terminal não é suficiente.

O trecho base (usado por Claude Desktop, Cursor, Windsurf, Kilocode — a maioria dos clientes fala esse dialeto):

{
  "mcpServers": {
    "ssh-mcp": {
      "command": "uvx",
      "args": ["--from", "git+https://github.com/Nightreaver/python-ssh-mcp", "ssh-mcp"],
      "env": {
        "LOG_LEVEL": "INFO",
        "ALLOW_LOW_ACCESS_TOOLS": "false",
        "ALLOW_DANGEROUS_TOOLS": "false",
        "ALLOW_SUDO": "false"
      }
    }
  }
}

uvx --from <path> ssh-mcp compila e executa o servidor em um ambiente efêmero gerenciado por uv; nenhum venv persistente é necessário no lado do cliente. Alternativa: substitua por "command": "fastmcp", "args": ["run", "<path-to-clone>/fastmcp.json"] se você já tiver um venv com fastmcp no PATH.

Ative os flags ALLOW_* conforme você concede capacidades ao assistente. Mantenha somente leitura como padrão e abra os níveis exec/sudo apenas onde precisar deles.

Claude Desktop

Arquivo de configuração:

  • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
  • Windows: %APPDATA%\Claude\claude_desktop_config.json
  • Linux: ~/.config/Claude/claude_desktop_config.json

Cole o trecho base. Saia completamente do Claude Desktop (ícone da bandeja → Quit) e reabra — recarregar NÃO reinicia subprocessos MCP.

Claude Code

Comando CLI, sem necessidade de editar JSON:

claude mcp add --transport stdio ssh-mcp -- uvx --from git+https://github.com/Nightreaver/python-ssh-mcp ssh-mcp

Para controle de escopo: --scope user (global), --scope project (commits .mcp.json ao repositório atual), --scope local (padrão, apenas este projeto). Variáveis de ambiente via flags --env KEY=VALUE repetidos, ou editando ~/.claude/mcp.json depois.

Cursor

Arquivo de configuração:

  • Global: ~/.cursor/mcp.json
  • Por workspace: <workspace>/.cursor/mcp.json

Mesmo formato mcpServers do trecho base. O Cursor capta mudanças de configuração na próxima sessão de chat — sem necessidade de reinicialização completa.

VS Code (GitHub Copilot Chat / Agent Mode)

O suporte MCP do VS Code (1.102+) usa uma chave ligeiramente diferente. Arquivo de configuração:

  • Por workspace: <workspace>/.vscode/mcp.json
  • Configurações globais do usuário: settings.json"mcp.servers"

.vscode/mcp.json do workspace:

{
  "servers": {
    "ssh-mcp": {
      "type": "stdio",
      "command": "uvx",
      "args": ["--from", "git+https://github.com/Nightreaver/python-ssh-mcp", "ssh-mcp"],
      "env": {
        "LOG_LEVEL": "INFO",
        "ALLOW_LOW_ACCESS_TOOLS": "false",
        "ALLOW_DANGEROUS_TOOLS": "false",
        "ALLOW_SUDO": "false"
      }
    }
  }
}

Observe que a chave de nível superior é servers (não mcpServers) e cada entrada carrega um discriminador "type": "stdio". Recarregue a janela do VS Code (Developer: Reload Window) para reiniciar.

Windsurf (Codeium)

Arquivo de configuração: ~/.codeium/windsurf/mcp_config.json. Mesmo formato mcpServers do trecho base. Reinicie o Windsurf após editar.

Kilocode

Arquivo de configuração: ~/.kilocode/mcp.json (ou o equivalente na sua instalação do Kilocode — a documentação da extensão lista o caminho exato). Mesmo formato mcpServers do trecho base. Recarregue a janela do VS Code após editar.

Continue.dev

Arquivo de configuração: ~/.continue/config.json. O Continue usa uma chave aninhada:

{
  "experimental": {
    "modelContextProtocolServers": [
      {
        "transport": {
          "type": "stdio",
          "command": "uvx",
          "args": ["--from", "git+https://github.com/Nightreaver/python-ssh-mcp", "ssh-mcp"]
        }
      }
    ]
  }
}

Observe: lista de objetos, não um mapa nomeado. Variáveis de ambiente vão dentro do bloco transport.

Zed

Configuração via Paleta de Comandos: assistant: configure context servers, ou edite ~/.config/zed/settings.json:

{
  "context_servers": {
    "ssh-mcp": {
      "source": "custom",
      "command": {
        "path": "uvx",
        "args": ["--from", "git+https://github.com/Nightreaver/python-ssh-mcp", "ssh-mcp"],
        "env": {}
      }
    }
  }
}

MCP Inspector (UI de desenvolvimento)

Para depurar o servidor antes de conectá-lo a um cliente real:

fastmcp dev inspector

Detecta automaticamente fastmcp.json, inicia a UI web com um MCP Inspector ao vivo anexado. Hot-reload em mudanças de código.


Passo a passo — seu primeiro host em 5 minutos

O caminho mais rápido: autenticação de agente + um host + nível somente leitura. Cinco etapas:

1. Carregue sua chave em um agente

  • Linux/macOS: ssh-add ~/.ssh/id_ed25519
  • Windows: inicie o Pageant e carregue sua .ppk (ou execute ssh-agent + ssh-add)

Verifique se o agente está acessível:

uv run python -c "import asyncio; from ssh_mcp.ssh.agent import list_agent_fingerprints; print(asyncio.run(list_agent_fingerprints()))"

Você deve ver uma ou mais linhas de SHA256:.... Copie a que pretende usar — você fará referência a ela abaixo.

2. Fixe a chave de host do alvo (verifique ANTES de confiar)

A verificação estrita de known_hosts está ativada por padrão (sem aceitação automática). A fixação é um fluxo de três etapas — nunca acrescente a saída de ssh-keyscan diretamente em known_hosts.

# 2a. Scan to a scratch file. This does NOT trust anything yet.
ssh-keyscan -t ed25519,ecdsa,rsa web01.example.com > /tmp/web01.hostkey

# 2b. Print the fingerprint and compare OUT-OF-BAND.
ssh-keygen -lf /tmp/web01.hostkey
# → 256 SHA256:abc123... web01.example.com (ED25519)

Compare essa SHA256:... com uma fonte confiável que não seja a rede que você acabou de escanear: a saída do provisionador do host, uma sessão de console, uma saída do terraform, a mensagem do sysadmin no Signal. Se não corresponderem, pare. Um erro de digitação ou um MITM fixaria uma chave hostil como confiável.

# 2c. Only after the out-of-band fingerprint matches, append and clean up.
cat /tmp/web01.hostkey >> ~/.ssh/known_hosts
rm /tmp/web01.hostkey

O servidor MCP se recusa a conectar se known_hosts estiver ausente, vazio ou não corresponder.

3. Escreva hosts.toml

Copie o modelo inicial anotado e edite:

cp hosts.toml.example hosts.toml
# Replace the SHA256:REPLACE-WITH-... fingerprints with yours from step 1.

Ou escreva do zero — o bloco mínimo viável:

[defaults]
user = "deploy"

[defaults.auth]
method = "agent"
identity_fingerprint = "SHA256:<paste-your-fingerprint-here>"
identities_only = true

[hosts.web01]
hostname = "web01.example.com"
path_allowlist = ["/opt/app", "/var/log"]

Consulte hosts.toml.example para bastion / proxy-jump, substituições de chave por host e o padrão de chave em disco + senha do keychain. Para receitas multi-host (bastions, chaves por função, hosts legados), consulte CONFIGURATION.md → Configurando mais hosts.

Herdando de ~/.ssh/config

Se você já mantém um ~/.ssh/config populado (aliases de host, ProxyJump, IdentityFile, substituições de Ciphers/MACs para equipamentos legados), aponte SSH_CONFIG_FILE para ele e evite repetir esses campos em hosts.toml:

SSH_CONFIG_FILE=~/.ssh/config

Precedência: hosts.toml sempre vence. ~/.ssh/config apenas preenche campos que você não definiu por host — a configuração do OpenSSH não pode ampliar o que path_allowlist, command_allowlist ou a lista de bloqueio de hosts permitem. Os logs de inicialização registram ssh_config: honoring <abs-path> (ou um WARNING se o arquivo estiver ausente) para que uma configuração incorreta apareça imediatamente.

4. Escreva .env

# Start locked down — only read-only tools are active.
ALLOW_LOW_ACCESS_TOOLS=false
ALLOW_DANGEROUS_TOOLS=false
ALLOW_SUDO=false

# Optional safety rail
SSH_HOSTS_BLOCKLIST=

5. Verifique de ponta a ponta

uv run ssh-mcp

De um cliente MCP (ou de um shell Python rápido), chame:

from ssh_mcp.server import mcp_server
# tools: ssh_host_ping, ssh_host_info, ssh_sftp_list, ssh_find, ...

ssh_host_ping(host="web01") deve retornar {reachable: true, auth_ok: true, latency_ms: N, ...}.

Se falhar, consulte Solução de problemas.


Solução de problemas

no SSH agent reachable

A ordem de resolução do agente é: identity_agent explícito em hosts.toml → variável de ambiente SSH_AUTH_SOCK → detecção automática do Windows (Pageant / pipe OpenSSH). Verifique:

# Unix / macOS
echo $SSH_AUTH_SOCK
ssh-add -l

# Windows (PowerShell)
Get-Process Pageant -ErrorAction SilentlyContinue
uv run python -c "import asyncio; from ssh_mcp.ssh.agent import list_agent_fingerprints; print(asyncio.run(list_agent_fingerprints()))"

identity 'SHA256:...' not found in agent

A impressão digital em hosts.toml não corresponde a nenhuma chave que o agente expõe. Liste o que está realmente carregado:

uv run python -c "import asyncio; from ssh_mcp.ssh.agent import list_agent_fingerprints; [print(fp) for fp in asyncio.run(list_agent_fingerprints())]"

Copie uma das impressões digitais relatadas para identity_fingerprint.

HostKeyMismatch / UnknownHost

Ou a chave do host mudou (rotação ou MITM) ou known_hosts está sem a entrada. Não contorne isso pelo LLM e não >> uma varredura diretamente em known_hosts sem verificação. Use o fluxo de três etapas da Seção 2 do passo a passo:

ssh-keyscan -t ed25519,ecdsa <host> > /tmp/h.hostkey
ssh-keygen -lf /tmp/h.hostkey                     # compare fingerprint out-of-band
cat /tmp/h.hostkey >> ~/.ssh/known_hosts && rm /tmp/h.hostkey

HostNotAllowed

O host não está em hosts.toml e não está em SSH_HOSTS_ALLOWLIST. A resolução tenta a entrada primeiro como uma chave de hosts.<alias>, depois contra hosts.*.hostname e depois contra a lista de permissões do ambiente. Adicione uma entrada de hosts.toml ou adicione o nome de host literal a SSH_HOSTS_ALLOWLIST.

HostBlocked

A negação vence — verifique SSH_HOSTS_BLOCKLIST. Isso é intencional; remova a entrada se o bloqueio foi um erro, mas primeiro confirme com o operador que o adicionou.

PathNotAllowed

O caminho resolvido (canonicalizado) está fora de todas as raízes em path_allowlist. Verifique:

  • O caminho está correto? Ferramentas de baixo acesso resolvem symlinks antes de verificar, então um symlink apontando para fora de /opt/app será rejeitado mesmo que o link em si esteja lá.
  • O hosts.<name>.path_allowlist cobre o alvo?

command_allowlist is empty but ALLOW_DANGEROUS_TOOLS=true

O carregador avisa se você habilitar exec sem definir o escopo dos comandos permitidos. Defina SSH_COMMAND_ALLOWLIST ou um command_allowlist vazio por host (explícito = sem restrição).

Ferramentas não visíveis no cliente MCP

  • Verifique o nível: ALLOW_LOW_ACCESS_TOOLS / ALLOW_DANGEROUS_TOOLS / ALLOW_SUDO são negados por padrão.
  • Verifique o grupo: SSH_ENABLED_GROUPS (vazio = todos; explícito = filtro).
  • Reinicie o cliente MCP — as listas de ferramentas são armazenadas em cache por versão do servidor MCP.

Consultando logs de auditoria

Cada chamada de ferramenta grava uma linha JSON no logger Python ssh_mcp.audit — incluindo ferramentas de nível de leitura (desde v1.4.0, todos os níveis são auditados). Não há ferramenta em processo para consultar o log de auditoria — isso é intencional (INC-052): se o LLM pudesse ler seu próprio rastro de auditoria, um agente comprometido ou com jailbreak poderia se automonitorar quanto ao que foi pego fazendo e se ajustar em torno disso. A auditoria flui em uma única direção, para os operadores.

Conecte ssh_mcp.audit ao destino de sua escolha (arquivo, Loki, Splunk, Datadog, journald, ...) na sua própria configuração de logging. Para depuração local ou triagem rápida de incidentes, grave as linhas em um arquivo e consulte com jq:

# In your own bootstrap (or a custom run_server wrapper)
import logging
h = logging.FileHandler("/var/log/ssh-mcp/audit.jsonl")
h.setFormatter(logging.Formatter("%(message)s"))
logging.getLogger("ssh_mcp.audit").addHandler(h)

Cada linha é um único objeto JSON compacto. Esquema:

campotipoobservações
tsfloatsegundos Unix epoch
correlation_idstr16 caracteres hexadecimais; forma par com a linha de erro completo em nível DEBUG em ssh_mcp.audit
toolstrO nome da ferramenta MCP (ex.: ssh_exec_run, ssh_broadcast)
tierstrread / low-access / dangerous / sudo
hoststrNome de host resolvido (ou ? para ferramentas de fan-out como ssh_broadcast)
resultstrok / error
duration_msintduração em tempo real da chamada da ferramenta
path_hashstrsha256:<16hex> do caminho canônico (quando a ferramenta tocou em um)
command_hashstrsha256:<16hex> do comando com dados ocultos (quando a ferramenta executou um)
exit_codeintQuando aplicável
errorstrApenas o nome da classe de exceção — o texto completo permanece no nível DEBUG (INC-008)

Receitas úteis de jq:

# All errors in the last hour, sorted by tool
jq -r 'select(.result == "error") | "\(.ts) \(.tool) \(.host) \(.error)"' \
  /var/log/ssh-mcp/audit.jsonl | sort -k2

# Slowest dangerous-tier calls (top 20 by duration_ms)
jq 'select(.tier == "dangerous")' /var/log/ssh-mcp/audit.jsonl \
  | jq -s 'sort_by(-.duration_ms) | .[:20] | .[] | {tool, host, duration_ms}'

# Count by tool to see what the LLM is actually using
jq -r '.tool' /var/log/ssh-mcp/audit.jsonl | sort | uniq -c | sort -rn

# Trace one specific call end-to-end via correlation_id
jq 'select(.correlation_id == "a1b2c3d4e5f6abcd")' /var/log/ssh-mcp/audit.jsonl

Os campos command_hash e path_hash são auxílios de deduplicação, não controles de privacidade — prefixos curtos de SHA-256 são trivialmente vulneráveis a rainbow tables para comandos comuns e caminhos canônicos. Se a confidencialidade da auditoria for importante, aplique-a por meio de criptografia de transporte (TLS para seu backend de logs) e controle de acesso no próprio destino.

Aviso legal

Python SSH MCP é uma infraestrutura local que concede a um LLM (ou a qualquer cliente MCP) a capacidade de executar comandos em sistemas remotos via SSH. Use por sua conta e risco. As flags de nível negadas por padrão e a aplicação estrita de known_hosts protegem contra os erros óbvios, mas nenhum software pode proteger contra um operador que ativa todas as flags para true sem entender o raio de impacto.

Leia DECISIONS.md antes de habilitar o nível perigoso ou sudo em produção. Audite as linhas JSON de ssh_mcp.audit regularmente. Em caso de dúvida, deixe um nível desativado.

Este projeto não é afiliado nem endossado por nenhum provedor SSH, FastMCP ou MCP.


Suporte

Construir e manter este servidor MCP exige tempo e esforço reais, mesmo com assistência de IA. Se este SSH MCP facilitou seu fluxo de trabalho e sua vida, considere me apoiar:

Problemas, dúvidas e feedback: abra uma issue no GitHub. Se você achar Python SSH MCP útil, considere dar uma estrela no repositório — isso realmente ajuda.