
Wireshark para MCP. Um proxy transparente entre seu cliente de IA e o servidor MCP. Acompanhe cada chamada ao vivo no seu terminal, faça o CI falhar com base no que ele encontra, exporte spans do OpenTelemetry.
<p align="center"> <img src="https://assets.kitploit.com/production/public/readmes/9109/91d664ea266713affb29238906792777021b43fa6627b13f46382f48ad340a61.png" alt="mcpsnoop" width="440"> </p> **Wireshark para MCP.** O mcpsnoop fica entre o seu cliente de IA e o seu servidor MCP e registra cada frame JSON-RPC que eles trocam, sem alterar nenhum dos lados. Assista ao vivo no seu terminal, faça o CI falhar com base no que ele encontra, ou envie para o seu backend de tracing como spans OpenTelemetry. [](https://github.com/kerlenton/mcpsnoop/actions/workflows/ci.yml) [](https://pkg.go.dev/github.com/kerlenton/mcpsnoop) [](LICENSE) [](https://github.com/marketplace/actions/mcpsnoop) <p align="center"> <img src="https://assets.kitploit.com/production/public/readmes/9109/30466d77be15250e4bab6639e48a4cd5b0d44cd96e48606b60c6bacb67c15c3d.gif" alt="mcpsnoop demo"> </p> ## O problema O [MCP Inspector](https://github.com/modelcontextprotocol/inspector) oficial conecta-se como seu próprio cliente, então ele nunca vê o que *o seu* cliente (Cursor, Claude Code, Codex) realmente envia ao seu servidor. E qualquer coisa que espere uma requisição chegar não consegue mostrar a chamada que o modelo nunca fez, ou fez com os argumentos errados. Quando uma ferramenta silenciosamente não é chamada, as capacidades não se alinham, ou uma chamada simplesmente trava, você fica vasculhando logs e adivinhando. **O mcpsnoop fica no caminho real dos dados.** Envolva o comando do seu servidor com ele e assista a cada frame JSON-RPC ao vivo, enquanto seu cliente e servidor reais conversam. ## No CI Esta página também é a listagem da [GitHub Action do mcpsnoop](https://github.com/marketplace/actions/mcpsnoop), então aqui está ela por inteiro. Ela verifica uma sessão capturada, registra cada descoberta como um alerta de code scanning, e falha o job com base no que você definiu como critério. ```yaml permissions: security-events: write contents: read steps: - uses: kerlenton/[email protected] with: session: artifacts/session.jsonl ``` Sem uma captura em mãos? Grave uma sessão com seu próprio cliente uma vez, faça o commit dela e deixe a action reproduzi-la em cada build. Nenhum modelo e nenhuma chave de API são executados no CI. A reprodução é verificada como qualquer captura, e o job também falha quando o servidor ficou pior do que na gravação. Um servidor acessado via Streamable HTTP recebe `target` com seu endpoint, e uma gravação é reproduzida em qualquer um dos transportes. ```yaml steps: - uses: kerlenton/[email protected] with: replay: tests/mcp/claude-code-session.jsonl server: node dist/index.js ``` Fixe a versão que desejar. A mais recente está na [página de releases](https://github.com/kerlenton/mcpsnoop/releases). Cada entrada e saída está em [The GitHub Action](#the-github-action) mais abaixo, e cada sinal pelo qual a verificação pode falhar está em [docs/CI.md](https://github.com/kerlenton/mcpsnoop/blob/main/docs/CI.md). ## OpenTelemetry A revisão 2026-07-28 do MCP descontinua o Logging em nível de protocolo e orienta as implementações a migrar para `stderr` em stdio, ou para OpenTelemetry para observabilidade estruturada. O mcpsnoop cobre ambos sem tocar no cliente ou no servidor. As linhas de `stderr` de um servidor stdio aparecem no stream ao lado de seus frames, e cada requisição se torna um span que segue as [convenções semânticas do OpenTelemetry para MCP](https://github.com/open-telemetry/semantic-conventions-genai/tree/main/model/mcp). ```bash mcpsnoop export -T otlp -o trace.json # spans from a capture mcpsnoop --otlp-endpoint http://localhost:4318/v1/traces -- node build/index.js # spans as calls complete ``` Uma chamada de ferramenta chega como um span chamado `tools/call search`, carregando `mcp.method.name`, `gen_ai.tool.name` e `error.type`, de modo que ela aparece em um dashboard criado para MCP em vez de um criado para mcpsnoop. Métricas de ferramentas ao vivo para Prometheus estão a uma flag de distância. Ambos estão em [docs/OPENTELEMETRY.md](https://github.com/kerlenton/mcpsnoop/blob/main/docs/OPENTELEMETRY.md). ## Início rápido Veja imediatamente, sem nada para configurar. ```bash mcpsnoop demo ``` Para usá-lo de verdade, envolva seu servidor na configuração MCP do seu cliente. ```json { "mcpServers": { "my-server": { "command": "mcpsnoop", "args": ["--", "node", "build/index.js"] } } } ``` Tudo após `--` é o comando que normalmente inicia o seu servidor. Substitua pelo que você já usa, como `python server.py`, `npx -y @scope/server`, ou um binário compilado. No Claude Desktop, você não precisa fazer essa edição manualmente. ```bash mcpsnoop wrap my-server # route my-server through mcpsnoop mcpsnoop unwrap my-server # put it back ``` `wrap` encontra `claude_desktop_config.json`, copia-o para `claude_desktop_config.json.mcpsnoop.bak` na primeira vez e reescreve apenas a entrada desse servidor, de modo que a sua formatação e todos os outros servidores ficam intactos. Dentro da entrada reescrita, as chaves voltam por ordem alfabética. `unwrap` restaura o ficheiro e remove a cópia de segurança quando já não há nenhum servidor envolvido. Reinicie o Claude Desktop depois de qualquer uma das operações, uma vez que os servidores MCP são iniciados apenas uma vez no arranque. Depois, utilize o seu cliente como habitualmente e abra a interface. ```bash mcpsnoop ``` Sem flags, sem caminhos de socket, sem ordem de inicialização para lembrar. O shim e a UI se encontram sozinhos, e a UI preenche sessões passadas a partir do disco. Para um servidor streamable-HTTP, execute o mcpsnoop como um proxy reverso. ```bash mcpsnoop http --target http://localhost:3000/mcp --listen :7000 ``` O status HTTP de cada resposta aparece no stream, portanto uma resposta que não carrega nenhuma mensagem JSON-RPC própria ainda é um frame visível em vez de nada. Isso abrange o desafio 401, o 403 em uma Origin rejeitada, o 202 que confirma uma notificação e o 502 quando o alvo não pode ser alcançado de forma alguma. O cabeçalho `WWW-Authenticate` de um 401 é mantido literalmente e exibido no inspetor, pois ele nomeia o esquema de autenticação e os metadados do recurso a serem acessados em seguida. Filtre por status com `status:401` na TUI, ou por qualquer falha com `status:err`. Um 4xx ou 5xx conta como erro, então uma execução padrão de `mcpsnoop check` falha nele, e a chamada que ele respondeu é lida como falha em vez de uma ainda em espera. Não tem um servidor próprio? [Experimente de verdade](https://github.com/kerlenton/mcpsnoop/blob/main/docs/TRY_IT.md) contra um servidor de teste publicado, conduzido pelo seu próprio cliente. Para inspecionar uma sessão depois que ela aconteceu, veja [revisar sessões passadas a partir de logs](https://github.com/kerlenton/mcpsnoop/blob/main/docs/POST_MORTEM.md). ## Instalação ### npm Nenhum toolchain Go necessário. A maioria dos servidores MCP é escrita em Node ou Python, então este é o caminho mais curto. ```bash npx mcpsnoop -- node build/index.js ``` O pacote npm não inclui código próprio. Seis pacotes de plataforma carregam cada um uma build, e o npm instala apenas aquele que corresponde à sua máquina, portanto não há nada para baixar no momento da instalação nem nada para desbloquear em um proxy. Para mantê-lo disponível em vez de buscá-lo a cada execução, use `npm i -g mcpsnoop`. ### Homebrew ```bash brew install mcpsnoop ``` ### Go ```bash go install github.com/kerlenton/mcpsnoop/cmd/mcpsnoop@latest ``` Binários pré-compilados para todas as plataformas estão na página de [Releases](https://github.com/kerlenton/mcpsnoop/releases). O mcpsnoop inclui completions para bash, zsh, fish e PowerShell. Execute `mcpsnoop completion <shell> --help` para ver os passos de configuração, que abrangem a ativação do completion e o caminho de instalação para o seu sistema operacional. ## Comandos | Comando | O que faz | |---|---| | `mcpsnoop -- <server>` | envolve um servidor stdio como um shim transparente | | `mcpsnoop` | abre a TUI ao vivo | | `mcpsnoop --metrics-listen <addr>` | executa um hub headless e expõe métricas Prometheus ao vivo | | `mcpsnoop http --target <url>` | faz proxy de um servidor streamable-HTTP | | `mcpsnoop export` | renderiza uma sessão em json, html, text, har ou otlp | | `mcpsnoop check` | faz o CI falhar em erros, frames inválidos, avisos como um resultado de ferramenta que quebra seu próprio outputSchema, incompatibilidades de roteamento, chamadas travadas, resultados tardios, chamadas que podem ter sido executadas duas vezes, drift de ferramentas, anotações que afrouxaram ou não dizem nada, ou um orçamento de latência | | `mcpsnoop baseline` | inspeciona, aceita ou redefine definições de ferramentas confiáveis | | `mcpsnoop diff` | compara ferramentas e chamadas entre duas sessões capturadas | | `mcpsnoop open` | abre uma sessão salva na TUI | | `mcpsnoop mock <session>` | serve uma sessão capturada de volta como um servidor MCP stdio | | `mcpsnoop replay <session> -- <server>` | conduz um servidor, via stdio ou Streamable HTTP, com o lado cliente de uma sessão gravada, e compara o resultado com a gravação | | `mcpsnoop inventory` | lista todos os servidores que já passaram pelo mcpsnoop nesta máquina | | `mcpsnoop stats` | agrega todas as capturas armazenadas em uma linha por servidor e ferramenta | | `mcpsnoop clients` | mostra o que cada cliente MCP realmente fez no fio, por nome e versão | | `mcpsnoop prune` | exclui logs de sessão salvos mais antigos que um limite | | `mcpsnoop wrap <server>` | roteia um dos servidores do Claude Desktop através do mcpsnoop | | `mcpsnoop unwrap <server>` | restaura a entrada desse servidor ao estado anterior | | `mcpsnoop remote <user@host>` | imprime o comando do túnel SSH | | `mcpsnoop demo` | reproduz uma sessão roteirizada | Execute `mcpsnoop help` para a lista completa, ou `mcpsnoop help <command>` para as flags de um comando. ## Como se compara Cada uma destas ferramentas responde a uma pergunta diferente, e onde uma ferramenta se posiciona determina quais perguntas ela consegue responder. | Ferramenta | Onde se posiciona | Para que serve | |---|---|---| | [MCP Inspector](https://github.com/modelcontextprotocol/inspector) | seu próprio cliente, conectado ao seu servidor | testar um servidor manualmente, em um navegador ou a partir de uma CLI scriptável | | [Snyk Agent Scan](https://github.com/snyk/agent-scan) | seu próprio cliente, iniciando ou conectando-se aos servidores nas suas configurações para ler suas ferramentas | escanear agentes, servidores MCP e skills na sua máquina em busca de prompt injection e vulnerabilidades | | [MCP Observatory](https://github.com/KryptosAI/mcp-observatory) | seu próprio cliente, iniciando seu servidor para testá-lo, gravá-lo e verificá-lo | testes de segurança e regressão no CI, com simulação de ataques, drift de schema e gravação, replay e verificação | | [mcprec](https://github.com/erphq/mcprec) | no fio, entre cliente e servidor | gravar uma sessão uma vez e reproduzi-la como fixture de teste sem a rede | | mcpsnoop | no fio, entre cliente e servidor | observar o que seu cliente e servidor reais dizem, reproduzir a sessão de um cliente real contra cada build, fazer o CI falhar por isso e exportá-la como OpenTelemetry | Uma ferramenta que é seu próprio cliente vê as chamadas que ela faz, não as que seu cliente faz, portanto não consegue mostrar a chamada que seu modelo nunca fez ou fez com os argumentos errados. Um scanner lê uma definição antes de você confiar nela. O mcpsnoop observa o que acontece depois que você confia, incluindo se a definição muda mais tarde. ## Como funciona <p align="center"> <picture> <source media="(prefers-color-scheme: dark)" srcset="assets/architecture-dark.svg"> <img alt="o mcpsnoop fica no pipe entre seu cliente de IA e seus servidores MCP, copiando cada frame JSON-RPC para uma interface de terminal ao vivo" src="https://raw.githubusercontent.com/kerlenton/mcpsnoop/HEAD/assets/architecture-light.svg" width="760"> </picture> </p> O mcpsnoop é dois papéis em um único binário. `mcpsnoop -- <server>` é o shim transparente que seu cliente inicia, encaminhando bytes literalmente enquanto envia uma cópia de cada frame para o hub. `mcpsnoop` sem argumentos é esse hub e sua TUI ao vivo. Eles se emparelham através de um socket bem conhecido e de logs em disco, de modo que nenhum precisa iniciar primeiro. Como ele fica no pipe real, e não de lado como o Inspector, ele vê exatamente o que seu cliente e servidor reais dizem um ao outro, independentemente da linguagem em que o servidor foi escrito. O que limita sua memória e seu disco está em [docs/HOW_IT_WORKS.md](https://github.com/kerlenton/mcpsnoop/blob/main/docs/HOW_IT_WORKS.md). ## A GitHub Action Tudo abaixo é o que a action faz por você. Ela instala o mcpsnoop, verifica a captura, registra as descobertas na aba Security e falha o job conforme o que você definiu como condição. ```yaml permissions: security-events: write contents: read steps: - uses: kerlenton/[email protected] with: session: artifacts/session.jsonl ``` Fixe uma release, a que você quiser. A mais recente está na [página de releases](https://github.com/kerlenton/mcpsnoop/releases). Não existe uma `v1` flutuante, de propósito. A release fixada também é o binário que a action instala, então as duas nunca podem divergir e não há versão padrão para ficar desatualizada. | Entrada | | |---|---| | `session` | a captura `.jsonl` a verificar, ou um diretório delas, relativo à raiz do repositório. Informe isto ou `replay` | | `replay` | uma gravação commitada para reproduzir contra `server` ou `target`, cuja captura então é verificada e também falha o job em caso de regressão | | `server` | o comando que inicia o servidor em teste, entre aspas como em uma linha de comando. Obrigatório com `replay` para um servidor stdio. Com `target` ele inicia primeiro um servidor HTTP, e pode ser omitido quando um já está em execução | | `target` | o endpoint Streamable HTTP contra o qual reproduzir, como `http://localhost:3000/mcp`. Uma credencial vai em `replay-args` como `--header`, e o log do step mostra seu valor oculto | | `replay-args` | quaisquer outras flags de `replay`, como `--read-only`. `--out` é recusado, já que a action decide onde a captura vai | | `fail-on` | como `--fail-on`, com o padrão sendo o padrão da CLI | | `args` | quaisquer outras flags de `check`, entre aspas como em uma linha de comando. `--format` é recusado, já que a action lê o relatório | | `upload-sarif` | envia o relatório para o code scanning. `true` | | `category` | o namespace do code scanning. `mcpsnoop`. Varie por perna de uma matriz, ou as pernas sobrescrevem umas às outras | | `fail-on-findings` | falha o job em um achado. `true`. Defina `false` para registrar os alertas e deixar a verificação obrigatória do code scanning decidir | | `version` | qual mcpsnoop instalar. O padrão é a release que você fixou | | `install` | `false` quando o mcpsnoop já está no PATH, que é o caminho em uma plataforma para a qual nenhuma release é compilada | As saídas são `outcome`, `sarif`, `exit-code` e `capture`, o caminho da captura que foi verificada, que com `replay` é a que o replay gravou e vale a pena guardar como artefato. `outcome` é `passed`, `findings` ou `error`, e o terceiro vale a pena tratar separadamente. Ele significa que nada foi verificado, o que não é o mesmo que nada ter sido encontrado. **Uma execução que não conseguiu verificar falha o job independentemente do que `fail-on-findings` diga**, porque um pipeline que fica verde sem ter verificado nada é pior do que um que falha. O job precisa de `security-events: write`, ou o upload responde 403. Defina `upload-sarif: false` em um repositório sem code scanning. Executar a mesma verificação sem a action, os sinais pelos quais ela pode falhar e os códigos de saída estão em [docs/CI.md](https://github.com/kerlenton/mcpsnoop/blob/main/docs/CI.md). ## Documentação | Página | O que contém | |---|---| | [Verificando sessões em CI](https://github.com/kerlenton/mcpsnoop/blob/main/docs/CI.md) | reproduzir uma gravação contra cada build, cada sinal pelo qual `check` pode falhar, códigos de saída, asserções, relatórios JUnit e SARIF, comparar duas sessões e configurar tudo sem a action | | [OpenTelemetry e Prometheus](https://github.com/kerlenton/mcpsnoop/blob/main/docs/OPENTELEMETRY.md) | os spans e o que eles carregam, transmiti-los para um collector e métricas de ferramentas ao vivo | | [Usando o mcpsnoop](https://github.com/kerlenton/mcpsnoop/blob/main/docs/USING.md) | teclas, filtragem, formatos de exportação, replay, o que um servidor pediu ao seu usuário, custo em contexto, estatísticas entre capturas, o que cada cliente realmente envia, o inventário de servidores, máquinas remotas e o arquivo de configuração | | [Redação](https://github.com/kerlenton/mcpsnoop/blob/main/docs/REDACTION.md) | limpar segredos, durante a captura ou de uma captura que você já tem | | [Como funciona](https://github.com/kerlenton/mcpsnoop/blob/main/docs/HOW_IT_WORKS.md) | limites de memória, o limite de histórico e a poda de logs antigos | | [Experimente de verdade](https://github.com/kerlenton/mcpsnoop/blob/main/docs/TRY_IT.md) | um servidor de teste publicado, acionado pelo seu próprio cliente | | [Revisar sessões passadas](https://github.com/kerlenton/mcpsnoop/blob/main/docs/POST_MORTEM.md) | onde ficam os logs de sessão e como abrir um depois do fato | | [O formato de captura](https://github.com/kerlenton/mcpsnoop/blob/main/docs/CAPTURE_FORMAT.md) | o que cada linha de um log de sessão contém e o que nunca mudará nele, com um JSON Schema para ferramentas que leem capturas | ## Segurança O mcpsnoop executa o comando de servidor que você envolve, então só envolva servidores em que você confia, e execute os não confiáveis em um container. Ele nunca executa nada que você não colocou na configuração do seu cliente. Para fluxos de trabalho remotos, use tunelamento SSH ou transferência de arquivos via SSH para que a autenticação de transporte, criptografia, verificação de host, rotação de chaves e política de auditoria permaneçam na sua configuração SSH existente. ### O que uma captura pode fazer com o seu terminal Uma captura são dados que o outro lado escolheu. Frames e linhas de stderr podem conter sequências de escape de terminal, e um terminal age sobre tudo o que recebe, o que vai desde uma exibição embaralhada até o OSC 52 gravando na área de transferência do seu sistema. O mcpsnoop mantém apenas as sequências de cor que ele mesmo gera e descarta qualquer outro escape antes que um frame chegue ao seu terminal. As células da tabela citam caracteres de controle para que você possa ver que eles estavam lá, o inspetor os exibe por extenso, e a cópia para a área de transferência carrega a forma escapada, de modo que nada fica oculto de você e nada é executado. ### O que uma captura contém Os frames capturados podem incluir prompts, argumentos de ferramentas, credenciais e resultados de ferramentas. [docs/REDACTION.md](https://github.com/kerlenton/mcpsnoop/blob/main/docs/REDACTION.md) aborda como removê-los, durante ou após a captura. Para relatar uma vulnerabilidade, consulte [SECURITY.md](https://github.com/kerlenton/mcpsnoop/blob/main/SECURITY.md). ## Contribuindo Issues e pull requests são bem-vindos. Consulte [CONTRIBUTING.md](https://github.com/kerlenton/mcpsnoop/blob/main/CONTRIBUTING.md) para os detalhes. ## Licença [MIT](https://github.com/kerlenton/mcpsnoop/blob/main/LICENSE)