
MCP용 Wireshark. AI 클라이언트와 MCP 서버 사이의 투명 프록시입니다. 터미널에서 모든 호출을 실시간으로 확인하고, 발견된 항목을 기준으로 CI를 실패시키며, OpenTelemetry 스팬을 내보냅니다.
<p align="center"> <img src="https://assets.kitploit.com/production/public/readmes/9109/91d664ea266713affb29238906792777021b43fa6627b13f46382f48ad340a61.png" alt="mcpsnoop" width="440"> </p> **MCP를 위한 Wireshark.** mcpsnoop은 AI 클라이언트와 MCP 서버 사이에 위치하여 양측이 주고받는 모든 JSON-RPC 프레임을 기록하며, 어느 쪽도 변경할 필요가 없습니다. 터미널에서 실시간으로 지켜보거나, 발견된 항목을 기준으로 CI를 실패시키거나, 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> ## 문제점 공식 [MCP Inspector](https://github.com/modelcontextprotocol/inspector)는 자체 클라이언트로 접속하기 때문에 *당신의* 클라이언트(Cursor, Claude Code, Codex)가 실제로 서버에 보내는 내용을 결코 볼 수 없습니다. 또한 요청이 도착하기를 기다리는 방식으로는 모델이 아예 하지 않은 호출이나 잘못된 인자로 한 호출을 보여줄 수 없습니다. 도구가 조용히 호출되지 않거나, 기능이 서로 맞지 않거나, 호출이 그냥 멈춰버릴 때, 당신은 로그를 뒤지며 추측만 하게 됩니다. **대신 mcpsnoop은 실제 데이터 경로 안에 위치합니다.** 서버 명령을 mcpsnoop으로 감싸면 실제 클라이언트와 서버가 대화하는 모든 JSON-RPC 프레임을 실시간으로 지켜볼 수 있습니다. ## CI에서 이 페이지는 [mcpsnoop GitHub Action](https://github.com/marketplace/actions/mcpsnoop)의 목록 페이지이기도 하므로, 전체 내용을 여기에 담았습니다. 캡처된 세션을 검사하고, 모든 발견 사항을 코드 스캐닝 경고로 기록하며, 게이트로 지정한 항목에 따라 작업을 실패시킵니다. ```yaml permissions: security-events: write contents: read steps: - uses: kerlenton/[email protected] with: session: artifacts/session.jsonl ``` 캡처할 것이 없나요? 한 번 자신의 클라이언트로 세션 하나를 기록하고 커밋한 뒤, 액션이 모든 빌드에 대해 이를 재생하도록 하세요. CI에서는 모델도 API 키도 실행되지 않습니다. 재생은 다른 캡처와 마찬가지로 검증되며, 서버가 기록 당시보다 나빠진 경우에도 작업이 실패합니다. Streamable HTTP를 통해 접근하는 서버는 해당 엔드포인트와 함께 `target`을 받으며, 기록은 어느 전송 방식으로든 재생됩니다. ```yaml steps: - uses: kerlenton/[email protected] with: replay: tests/mcp/claude-code-session.jsonl server: node dist/index.js ``` 원하는 릴리스를 고정하세요. 최신 릴리스는 [releases 페이지](https://github.com/kerlenton/mcpsnoop/releases)에 있습니다. 모든 입력과 출력은 아래의 [The GitHub Action](#the-github-action)에 있으며, 검사가 실패할 수 있는 모든 신호는 [docs/CI.md](https://github.com/kerlenton/mcpsnoop/blob/main/docs/CI.md)에 있습니다. ## OpenTelemetry MCP 개정 2026-07-28은 프로토콜 수준의 Logging을 폐기하고, 구현체에게 stdio에서는 `stderr`로, 또는 구조화된 관측성을 위해 OpenTelemetry로 이전할 것을 권고합니다. mcpsnoop은 클라이언트나 서버를 건드리지 않고 두 가지를 모두 지원합니다. stdio 서버의 `stderr` 줄은 해당 프레임 옆의 스트림에 나타나며, 모든 요청은 [MCP용 OpenTelemetry 시맨틱 규약](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 ``` 도구 호출은 `tools/call search`라는 span으로 도착하며, `mcp.method.name`, `gen_ai.tool.name`, `error.type`을 함께 전달하므로, mcpsnoop용으로 만든 대시보드가 아니라 MCP용으로 만든 대시보드에 나타납니다. Prometheus용 실시간 도구 메트릭은 플래그 하나만 설정하면 됩니다. 둘 다 [docs/OPENTELEMETRY.md](https://github.com/kerlenton/mcpsnoop/blob/main/docs/OPENTELEMETRY.md)에 있습니다. ## 빠른 시작 아무것도 설정하지 않고 바로 확인해 보세요. ```bash mcpsnoop demo ``` 실제로 사용하려면 서버를 클라이언트의 MCP 구성으로 감싸세요. ```json { "mcpServers": { "my-server": { "command": "mcpsnoop", "args": ["--", "node", "build/index.js"] } } } ``` `--` 뒤의 모든 내용은 일반적으로 서버를 실행하는 명령입니다. 이미 사용 중인 명령으로 바꾸면 됩니다. 예를 들어 `python server.py`, `npx -y @scope/server` 또는 컴파일된 바이너리 등입니다. Claude Desktop에서는 이 편집을 직접 할 필요가 없습니다. ```bash mcpsnoop wrap my-server # route my-server through mcpsnoop mcpsnoop unwrap my-server # put it back ``` `wrap`은 `claude_desktop_config.json`을 찾아 처음 실행할 때 `claude_desktop_config.json.mcpsnoop.bak`으로 복사하고, 해당 서버의 항목만 다시 작성하므로 서식과 다른 모든 서버는 그대로 유지됩니다. 다시 작성된 항목 내부의 키는 알파벳 순서로 정렬됩니다. `unwrap`은 파일을 복원하고, 더 이상 래핑된 서버가 없으면 백업을 제거합니다. MCP 서버는 시작 시 한 번만 실행되므로 둘 중 어느 작업 후든 Claude Desktop을 재시작하세요. 그런 다음 평소처럼 클라이언트를 사용하고 UI를 여세요. ```bash mcpsnoop ``` 플래그도, 소켓 경로도, 기억해야 할 시작 순서도 없습니다. shim과 UI는 스스로 서로를 찾아내며, UI는 디스크에서 과거 세션을 백필합니다. 스트리밍 가능한 HTTP 서버의 경우, mcpsnoop을 리버스 프록시로 실행하세요. ```bash mcpsnoop http --target http://localhost:3000/mcp --listen :7000 ``` 모든 응답의 HTTP 상태가 스트림에 표시되므로, 자체적인 JSON-RPC 메시지를 담지 않은 응답도 아무것도 아닌 것이 아니라 보이는 프레임으로 나타납니다. 여기에는 401 챌린지, 거부된 Origin에 대한 403, 알림을 확인하는 202, 그리고 대상에 전혀 도달할 수 없을 때의 502가 포함됩니다. 401의 `WWW-Authenticate` 헤더는 인증 스킴과 다음에 이동할 리소스 메타데이터를 명시하므로 그대로 보존되어 검사기에 표시됩니다. TUI에서 `status:401`로 상태를 필터링하거나, `status:err`로 모든 실패를 필터링할 수 있습니다. 4xx 또는 5xx는 오류로 간주되므로 기본 `mcpsnoop check` 실행은 이 경우 실패하며, 해당 응답이 답한 호출은 여전히 대기 중인 것으로가 아니라 실패한 것으로 표시됩니다. 자체 서버가 없으신가요? 게시된 테스트 서버에 대해 자신의 클라이언트로 구동하여 [실제로 시험해 보세요](https://github.com/kerlenton/mcpsnoop/blob/main/docs/TRY_IT.md). 세션이 끝난 후 세션을 검사하려면 [로그에서 과거 세션 검토](https://github.com/kerlenton/mcpsnoop/blob/main/docs/POST_MORTEM.md)를 참조하세요. ## 설치 ### npm Go 툴체인이 필요하지 않습니다. 대부분의 MCP 서버는 Node 또는 Python으로 작성되므로, 이것이 가장 빠른 진입 방법입니다. ```bash npx mcpsnoop -- node build/index.js ``` npm 패키지 자체에는 코드가 포함되어 있지 않습니다. 여섯 개의 플랫폼 패키지가 각각 하나의 빌드를 담고 있으며, npm은 사용자의 머신과 일치하는 단 하나의 패키지만 설치하므로 설치 시점에 다운로드할 것도, 프록시에서 차단을 해제할 것도 없습니다. 매번 실행할 때마다 가져오는 대신 유지하려면 `npm i -g mcpsnoop`을 실행하세요. ### Homebrew ```bash brew install mcpsnoop ``` ### Go ```bash go install github.com/kerlenton/mcpsnoop/cmd/mcpsnoop@latest ``` 모든 플랫폼용 사전 빌드된 바이너리는 [Releases](https://github.com/kerlenton/mcpsnoop/releases) 페이지에 있습니다. mcpsnoop은 bash, zsh, fish, PowerShell용 자동 완성을 제공합니다. 설정 단계는 `mcpsnoop completion <shell> --help`를 실행하여 확인할 수 있으며, 여기에는 자동 완성 활성화와 사용 중인 OS의 설치 경로가 포함됩니다. ## 명령어 | 명령어 | 기능 | |---|---| | `mcpsnoop -- <server>` | stdio 서버를 투명한 shim으로 감싸기 | | `mcpsnoop` | 라이브 TUI 열기 | | `mcpsnoop --metrics-listen <addr>` | 헤드리스 허브를 실행하고 라이브 Prometheus 메트릭 노출 | | `mcpsnoop http --target <url>` | streamable-HTTP 서버 프록시 | | `mcpsnoop export` | 세션을 json, html, text, har 또는 otlp로 렌더링 | | `mcpsnoop check` | 오류, 잘못된 프레임, 자체 outputSchema를 위반하는 도구 결과 같은 경고, 라우팅 불일치, 멈춘 호출, 지연된 결과, 두 번 실행되었을 수 있는 호출, 도구 드리프트, 완화되었거나 아무것도 말하지 않는 어노테이션, 또는 지연 예산 초과 시 CI 실패 처리 | | `mcpsnoop baseline` | 신뢰할 수 있는 도구 정의 검사, 수락 또는 재설정 | | `mcpsnoop diff` | 두 개의 캡처된 세션 간 도구와 호출 비교 | | `mcpsnoop open` | 저장된 세션을 TUI에서 열기 | | `mcpsnoop mock <session>` | 캡처된 세션을 stdio MCP 서버로 다시 제공 | | `mcpsnoop replay <session> -- <server>` | stdio 또는 Streamable HTTP를 통해 기록된 세션의 클라이언트 측으로 서버를 구동하고 결과를 기록과 비교 | | `mcpsnoop inventory` | 이 머신에서 mcpsnoop을 통해 실행된 모든 서버 나열 | | `mcpsnoop stats` | 저장된 모든 캡처를 서버 및 도구별 한 행으로 집계 | | `mcpsnoop clients` | 각 MCP 클라이언트가 실제로 와이어에서 수행한 작업을 이름과 버전별로 표시 | | `mcpsnoop prune` | 기준 시점보다 오래된 저장된 세션 로그 삭제 | | `mcpsnoop wrap <server>` | Claude Desktop의 서버 중 하나를 mcpsnoop을 통해 라우팅 | | `mcpsnoop unwrap <server>` | 해당 서버의 항목을 원래대로 복원 | | `mcpsnoop remote <user@host>` | SSH 터널 명령 출력 | | `mcpsnoop demo` | 스크립트된 세션 재생 | 전체 목록은 `mcpsnoop help`를, 특정 명령어의 플래그는 `mcpsnoop help <command>`를 실행하여 확인하세요. ## 비교 각 도구는 서로 다른 질문에 답하며, 도구가 어디에 위치하는지가 어떤 질문에 답할 수 있는지를 결정합니다. | 도구 | 위치 | 용도 | |---|---|---| | [MCP Inspector](https://github.com/modelcontextprotocol/inspector) | 자체 클라이언트로, 사용자의 서버에 연결 | 브라우저 또는 스크립트 가능한 CLI에서 서버를 수동으로 시험 | | [Snyk Agent Scan](https://github.com/snyk/agent-scan) | 자체 클라이언트로, 설정에 있는 서버를 실행하거나 연결하여 도구를 읽음 | 머신의 에이전트, MCP 서버, 스킬을 프롬프트 인젝션 및 취약점에 대해 스캔 | | [MCP Observatory](https://github.com/KryptosAI/mcp-observatory) | 자체 클라이언트로, 서버를 실행하여 테스트, 기록 및 검증 | 공격 시뮬레이션, 스키마 드리프트, 기록·재생·검증을 포함한 CI에서의 보안 및 회귀 테스트 | | [mcprec](https://github.com/erphq/mcprec) | 와이어 상에서, 클라이언트와 서버 사이 | 세션을 한 번 기록하고 네트워크 없이 테스트 픽스처로 재생 | | mcpsnoop | 와이어 상에서, 클라이언트와 서버 사이 | 실제 클라이언트와 서버가 주고받는 내용을 관찰하고, 실제 클라이언트의 세션을 각 빌드에 대해 재생하고, 이를 기반으로 CI를 실패 처리하고, OpenTelemetry로 내보내기 | 자체 클라이언트인 도구는 자신이 만드는 호출을 보며 사용자의 클라이언트가 만드는 호출은 보지 못하므로, 모델이 만들지 않은 호출이나 잘못된 인수로 만든 호출을 보여줄 수 없습니다. 스캐너는 신뢰하기 전에 정의를 읽습니다. mcpsnoop은 신뢰한 이후에 발생하는 일을 관찰하며, 여기에는 나중에 정의가 변경되는지 여부도 포함됩니다. ## 작동 방식 <p align="center"> <picture> <source media="(prefers-color-scheme: dark)" srcset="assets/architecture-dark.svg"> <img alt="mcpsnoop은 AI 클라이언트와 MCP 서버 사이의 파이프에 위치하여 모든 JSON-RPC 프레임을 라이브 터미널 UI로 복사합니다" src="https://raw.githubusercontent.com/kerlenton/mcpsnoop/HEAD/assets/architecture-light.svg" width="760"> </picture> </p> mcpsnoop은 하나의 바이너리 안에 두 가지 역할을 담당합니다. `mcpsnoop -- <server>`는 클라이언트가 실행하는 투명한 shim으로, 바이트를 그대로 전달하면서 모든 프레임의 사본을 hub로 보냅니다. 인수 없이 실행한 `mcpsnoop`은 바로 그 hub이자 실시간 TUI입니다. 두 역할은 잘 알려진 소켓과 디스크 상의 로그를 통해 연결되므로 어느 쪽도 먼저 시작할 필요가 없습니다. Inspector처럼 옆에서 지켜보는 것이 아니라 실제 파이프 안에 자리하기 때문에, 서버가 어떤 언어로 작성되었든 실제 클라이언트와 서버가 주고받는 내용을 정확히 볼 수 있습니다. 메모리와 디스크 사용량을 무엇이 제한하는지는 [docs/HOW_IT_WORKS.md](https://github.com/kerlenton/mcpsnoop/blob/main/docs/HOW_IT_WORKS.md)에 설명되어 있습니다. ## GitHub Action 아래의 모든 내용은 이 액션이 대신 수행해 주는 작업입니다. mcpsnoop을 설치하고, 캡처를 검사하고, 발견된 사항을 Security 탭에 기록하며, 설정한 기준에 따라 작업을 실패시킵니다. ```yaml permissions: security-events: write contents: read steps: - uses: kerlenton/[email protected] with: session: artifacts/session.jsonl ``` 원하는 릴리스를 고정하세요. 최신 릴리스는 [releases 페이지](https://github.com/kerlenton/mcpsnoop/releases)에 있습니다. 의도적으로 떠다니는 `v1`은 없습니다. 고정한 릴리스는 액션이 설치하는 바이너리이기도 하므로, 둘이 서로 어긋날 수 없고 낡아버릴 버전 기본값도 없습니다. | 입력 | | |---|---| | `session` | 검사할 `.jsonl` 캡처 또는 그 캡처들이 담긴 디렉터리로, 저장소 루트 기준 상대 경로입니다. 이것 또는 `replay`를 지정하세요 | | `replay` | `server` 또는 `target`에 대해 재생할 커밋된 녹화로, 이 경우 해당 녹화의 캡처도 검사되며 회귀가 있으면 작업도 실패합니다 | | `server` | 테스트 대상 서버를 시작하는 명령으로, 명령줄에서처럼 따옴표로 감싸 지정합니다. stdio 서버의 경우 `replay`와 함께 필수입니다. `target`과 함께 쓰면 먼저 HTTP 서버를 시작하며, 이미 실행 중인 경우 생략할 수 있습니다 | | `target` | 재생 대상이 되는 Streamable HTTP 엔드포인트로, 예를 들어 `http://localhost:3000/mcp`입니다. 자격 증명은 `replay-args`에 `--header`로 넣으며, 단계 로그에는 그 값이 가려져 표시됩니다 | | `replay-args` | `--read-only` 같은 기타 `replay` 플래그입니다. `--out`은 거부되는데, 캡처를 어디에 둘지는 액션이 결정하기 때문입니다 | | `fail-on` | `--fail-on`과 같으며, 기본값은 CLI의 기본값입니다 | | `args` | 명령줄에서처럼 따옴표로 감싼 기타 `check` 플래그입니다. `--format`은 거부되는데, 액션이 보고서를 읽기 때문입니다 | | `upload-sarif` | 보고서를 코드 스캐닝으로 보냅니다. `true` | | `category` | 코드 스캐닝 네임스페이스입니다. `mcpsnoop`. 매트릭스의 각 레그마다 다르게 지정하지 않으면 레그들이 서로 덮어씁니다 | | `fail-on-findings` | 발견 사항이 있으면 작업을 실패시킵니다. `true`. `false`로 설정하면 경고를 등록하고 코드 스캐닝의 필수 검사가 판단하게 합니다 | | `version` | 설치할 mcpsnoop 버전입니다. 고정한 릴리스가 기본값입니다 | | `install` | mcpsnoop이 이미 PATH에 있을 때 `false`로, 릴리스가 빌드되지 않은 플랫폼에서 사용하는 방법입니다 | 출력은 `outcome`, `sarif`, `exit-code`, `capture`이며, `capture`는 검사한 캡처의 경로로, `replay`의 경우 재생이 기록한 캡처이므로 아티팩트로 보관할 가치가 있습니다. `outcome`은 `passed`, `findings`, `error` 중 하나이며, 세 번째는 별도로 처리할 가치가 있습니다. 이는 아무것도 검사되지 않았다는 뜻으로, 아무것도 발견되지 않은 것과는 다릅니다. **검사할 수 없었던 실행은 `fail-on-findings` 설정과 무관하게 작업을 실패시킵니다**, 아무것도 검증하지 않은 채 통과하는 파이프라인은 실패하는 파이프라인보다 나쁘기 때문입니다. 작업에는 `security-events: write`가 필요하며, 없으면 업로드가 403으로 응답합니다. 코드 스캐닝이 없는 저장소에서는 `upload-sarif: false`로 설정하세요. 액션 없이 동일한 검사를 실행하는 방법, 실패를 일으킬 수 있는 신호, 종료 코드는 [docs/CI.md](https://github.com/kerlenton/mcpsnoop/blob/main/docs/CI.md)에 있습니다. ## 문서 | 페이지 | 내용 | |---|---| | [CI에서 세션 검사하기](https://github.com/kerlenton/mcpsnoop/blob/main/docs/CI.md) | 모든 빌드에 대해 녹화를 재생하기, `check`가 실패를 일으킬 수 있는 모든 신호, 종료 코드, 어서션, JUnit 및 SARIF 보고서, 두 세션 비교하기, 액션 없이 연결하기 | | [OpenTelemetry와 Prometheus](https://github.com/kerlenton/mcpsnoop/blob/main/docs/OPENTELEMETRY.md) | 스팬과 스팬이 담는 정보, 컬렉터로 스트리밍하기, 실시간 도구 메트릭 | | [mcpsnoop 사용하기](https://github.com/kerlenton/mcpsnoop/blob/main/docs/USING.md) | 키, 필터링, 내보내기 형식, 재생, 서버가 사용자에게 요청한 것, 컨텍스트 비용, 캡처 전반의 통계, 각 클라이언트가 실제로 보내는 것, 서버 인벤토리, 원격 머신, 설정 파일 | | [마스킹](https://github.com/kerlenton/mcpsnoop/blob/main/docs/REDACTION.md) | 캡처 중 또는 이미 가진 캡처에서 비밀 정보 삭제하기 | | [작동 방식](https://github.com/kerlenton/mcpsnoop/blob/main/docs/HOW_IT_WORKS.md) | 메모리 한도, 기록 제한, 오래된 로그 정리 | | [실제로 사용해 보기](https://github.com/kerlenton/mcpsnoop/blob/main/docs/TRY_IT.md) | 직접 만든 클라이언트로 구동하는 공개 테스트 서버 | | [지난 세션 검토하기](https://github.com/kerlenton/mcpsnoop/blob/main/docs/POST_MORTEM.md) | 세션 로그가 저장되는 위치와 사후에 여는 방법 | | [캡처 형식](https://github.com/kerlenton/mcpsnoop/blob/main/docs/CAPTURE_FORMAT.md) | 세션 로그의 각 줄이 담는 내용과 절대 바뀌지 않을 부분, 캡처를 읽는 도구를 위한 JSON Schema | ## 보안 mcpsnoop은 감싼 서버 명령을 실행하므로, 신뢰하는 서버만 감싸고 신뢰할 수 없는 서버는 컨테이너에서 실행하세요. 클라이언트 설정에 넣지 않은 것은 아무것도 실행하지 않습니다. 원격 워크플로의 경우 SSH 터널링 또는 SSH 파일 전송을 사용하여 전송 인증, 암호화, 호스트 검증, 키 교체 및 감사 정책이 기존 SSH 설정에 그대로 유지되도록 하십시오. ### 캡처가 터미널에 미칠 수 있는 영향 캡처는 상대방이 선택한 데이터입니다. 프레임과 stderr 줄은 터미널 이스케이프 시퀀스를 포함할 수 있으며, 터미널은 전달받은 대로 동작하므로 화면이 깨지는 것부터 OSC 52를 통해 시스템 클립보드에 기록되는 것까지 다양합니다. mcpsnoop은 자체적으로 생성하는 색상 시퀀스만 유지하고, 프레임이 터미널에 도달하기 전에 다른 모든 이스케이프를 제거합니다. 표 셀은 제어 문자를 인용하여 해당 문자가 있었음을 확인할 수 있게 하고, 검사기는 이를 전체로 표시하며, 클립보드 복사본은 이스케이프된 형태를 담으므로 아무것도 숨겨지지 않고 아무것도 실행되지 않습니다. ### 캡처에 포함되는 내용 캡처된 프레임에는 프롬프트, 도구 인수, 자격 증명 및 도구 결과가 포함될 수 있습니다. [docs/REDACTION.md](https://github.com/kerlenton/mcpsnoop/blob/main/docs/REDACTION.md)는 캡처 중 또는 캡처 후에 이를 정리하는 방법을 다룹니다. 취약점을 보고하려면 [SECURITY.md](https://github.com/kerlenton/mcpsnoop/blob/main/SECURITY.md)를 참조하십시오. ## 기여 이슈와 풀 리퀘스트를 환영합니다. 자세한 내용은 [CONTRIBUTING.md](https://github.com/kerlenton/mcpsnoop/blob/main/CONTRIBUTING.md)를 참조하십시오. ## 라이선스 [MIT](https://github.com/kerlenton/mcpsnoop/blob/main/LICENSE)