
MCP용 Wireshark. AI 클라이언트와 MCP 서버 간의 모든 실제 도구 호출을 터미널에서 실시간으로 보여주는 투명 프록시.
MCP용 Wireshark. AI 클라이언트와 MCP 서버 사이의 모든 실제 도구 호출을 터미널에서 실시간으로 보여주는 투명 프록시입니다.
공식 MCP Inspector는 자체 클라이언트로 연결되므로 사용자의 클라이언트(Cursor, Claude Code, Codex)가 서버에 실제로 보내는 내용을 볼 수 없습니다. 또한 요청이 도착하기를 기다리는 방식은 모델이 호출하지 않았거나 잘못된 인수로 호출한 경우를 표시할 수 없습니다. 도구가 조용히 호출되지 않거나, 기능이 일치하지 않거나, 호출이 그냥 멈추는 경우 로그를 뒤지고 추측할 수밖에 없습니다.
mcpsnoop는 대신 실제 데이터 경로에 위치합니다. 서버 명령을 mcpsnoop로 감싸면 실제 클라이언트와 서버가 통신하는 동안 모든 JSON-RPC 프레임을 실시간으로 볼 수 있습니다.
이 페이지는 mcpsnoop GitHub Action의 목록이기도 하므로 전체 내용을 여기에 담았습니다. 캡처된 세션을 검사하고, 모든 발견 사항을 코드 스캐닝 경고로 기록하며, 게이트로 설정한 조건에 따라 작업을 실패 처리합니다.```yaml permissions: security-events: write contents: read
steps:
원하는 릴리스를 고정하세요. 최신 버전은
[릴리스 페이지](https://github.com/kerlenton/mcpsnoop/releases)에 있습니다. 모든 입력,
종료 코드의 의미, 그리고 액션 없이 연결하는 방법은
아래의 [GitHub Action](#the-github-action)에 있습니다.
## 빠른 시작
설정할 것 없이 바로 확인해 보세요.```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는 디스크에서 과거 세션을 백필(backfill)합니다.
스트리밍 가능한 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 실행은 이 경우 실패한다.
자체 서버가 없다면? 직접 시도해 보기에서 공개된 테스트 서버를 대상으로 자신의 클라이언트를 구동해 볼 수 있다. 세션이 끝난 후 이를 검사하려면 로그에서 과거 세션 검토를 참조하라.
프로젝트 전반에 동일한 shim 플래그를 재사용한다면, 현재 작업 디렉터리의 .mcpsnoop.toml 파일에 이를 넣어라.```toml
label = "filesystem"
trace-file = "trace.jsonl"
redact-secrets = true
redact-key = "token,authorization"
redact-value = "sk-[A-Za-z0-9]+"
redact-path = "$.params.arguments.password"
no-trace = false
`redact-key`, `redact-value`, `redact-path`를 각각 별도의 줄에 반복해서 입력하면
각 항목을 여러 개 추가할 수 있습니다.
이것이 지원하는 키의 전부입니다.
이 파일은 현재 작업 디렉터리에서만 조회되며, 상위 디렉터리에서는 조회되지 않습니다.
명시적인 명령줄 플래그는 구성 파일의 값을 덮어씁니다.
## 명령어
| 명령어 | 기능 |
|---|---|
| `mcpsnoop -- <server>` | stdio 서버를 투명한 셔임(shim)으로 감싸기 |
| `mcpsnoop` | 실시간 TUI 열기 |
| `mcpsnoop http --target <url>` | streamable-HTTP 서버 프록시 |
| `mcpsnoop export` | 세션을 json, html, text, har 또는 otlp로 렌더링 |
| `mcpsnoop check` | 오류, 잘못된 프레임, 경고, 라우팅 불일치, 응답 없는 호출, 지연된 결과 또는 지연 시간 예산에 대해 CI 실패 처리 |
| `mcpsnoop baseline` | 신뢰할 수 있는 도구 정의 검사, 수락 또는 재설정 |
| `mcpsnoop diff` | 두 캡처 세션 간 도구 및 호출 비교 |
| `mcpsnoop open` | TUI에서 저장된 세션 열기 |
| `mcpsnoop inventory` | 이 머신에서 mcpsnoop을 통해 실행된 모든 서버 나열 |
| `mcpsnoop stats` | 저장된 모든 캡처를 서버 및 도구별로 한 행씩 접기 |
| `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 | mcpsnoop |
|---|:---:|:---:|
| 실제 클라이언트 및 서버 트래픽을 볼 수 있음 | 아니요 | 예 |
| 응답 없는 호출 및 스트림 오류 플래그 | 아니요 | 예 |
| 스트림을 손상시키는 불필요한 출력 플래그 | 아니요 | 예 |
| 잘못된 JSON-RPC 프레임 플래그 | 아니요 | 예 |
| 승인 후 도구 정의 변경 감지 | 아니요 | 예 |
| 대화형 터미널 UI | 아니요 | 예 |
| 구성 불필요, 플래그나 순서 없음 | 아니요 | 예 |
| 기능 검사기 | 부분적 | 예 |
| 캡처된 호출 재생 | 아니요 | 예, stdio 및 HTTP를 통해 |
| 세션 내보내기 (json / html / text / otlp) | 아니요 | 예 |
| 단일 바이너리, 런타임 종속성 없음 | 아니요 | 예 |
## 설치
### npm
Go 툴체인이 필요 없습니다. 대부분의 MCP 서버는 Node 또는 Python으로 작성되므로
이것이 가장 빠른 방법입니다.```bash
npx mcpsnoop -- node build/index.js
The npm 패키지에는 자체 코드가 포함되어 있지 않습니다. 6개의 플랫폼 패키지가 각각 하나의 빌드를 담고 있으며, npm은 사용자 머신과 일치하는 단일 패키지만 설치하므로 설치 시 다운로드할 항목이 없고 프록시에서 차단할 항목도 없습니다. 매번 실행할 때마다 가져오는 대신 유지하려면 npm i -g mcpsnoop을 사용하세요.
go install github.com/kerlenton/mcpsnoop/cmd/mcpsnoop@latest
### Homebrew```bash
brew install mcpsnoop
모든 플랫폼용 사전 빌드 바이너리는 Releases 페이지에 있습니다.
mcpsnoop는 bash, zsh, fish, PowerShell용 완성 기능을 제공합니다. 설정 단계는 mcpsnoop completion <shell> --help를 실행하면 확인할 수 있으며, 여기에는 완성 기능 활성화 방법과 OS별 설치 경로가 포함됩니다.
mcpsnoop는 하나의 바이너리에서 두 가지 역할을 수행합니다. mcpsnoop -- <server>는 클라이언트가 실행하는 투명한 셰임(shim)으로, 바이트를 그대로 전달하면서 모든 프레임의 사본을 허브로 보냅니다. 인수 없이 실행하는 mcpsnoop는 바로 그 허브이자 실시간 TUI입니다. 둘은 잘 알려진 소켓과 디스크의 로그를 통해 연결되므로, 어느 쪽이 먼저 시작할 필요가 없습니다.
허브는 기본적으로 가장 최근의 저장된 세션 100개를 로드하여 시작 작업을 제한된 범위로 유지하면서도 오래된 트레이스를 삭제하지 않습니다. 다른 제한을 선택하려면 mcpsnoop --history-limit N을 사용하고, 전체 기록을 로드하려면 mcpsnoop --history-limit 0을 사용하세요. 오래된 세션은 mcpsnoop open <session-id> 및 mcpsnoop export <session-id>를 통해 계속 사용할 수 있습니다.
기록 제한은 로드되는 세션 수를 제한합니다. 세션 내부에서 실시간 TUI는 두 번 제한됩니다. 대화가 많은 서버를 계속 지켜보는 허브는 그대로 두면 종료될 때까지 커지기 때문입니다. 프레임 본문은 최대 64MiB까지만 유지하며 가장 오래된 것부터 해제하고, 프레임은 최대 200,000개까지만 유지하며 그 이후로는 가장 오래된 것을 완전히 버립니다. 첫 번째 제한은 대용량 페이로드를 캡처할 때 부딪히는 한계이고, 두 번째 제한은 작은 알림이 길게 이어지는 스트림에서 발생하는 한계입니다.
어떤 제한도 답을 바꾸지 않습니다. 본문이 해제된 프레임은 행, 판정, 타임라인에서의 위치를 유지하며, 검사기(inspector)는 빈 프레임을 표시하는 대신 본문이 사라졌다고 표시합니다. 완전히 버려진 프레임은 먼저 해당 도구 호출의 통계를 실행 합계에 반영하므로, 도구 요약과 서버가 컨텍스트에서 소모하는 비용은 세션이 수행한 모든 호출을 설명하며 최근 호출만 설명하지 않습니다. 스트림 하단에는 디스크에만 있는 오래된 프레임 수가 표시되며, r은 더 이상 보유하지 않는 매개변수가 있는 프레임은 다른 것을 재생하는 대신 거부합니다.
mcpsnoop open <session-id>는 로그를 읽고 전체를 보유하며, TUI에서 내보내기도 로그를 읽으므로 둘 다 제한되지 않습니다. check, export, diff는 의도적으로 무제한 저장소를 구축합니다. 대규모 캡처에서 과소 보고하는 게이트는 메모리를 사용하는 게이트보다 더 나쁘기 때문입니다.