Skip to content
KitploitKITPLOIT
ツールブログ
提出
ツールブログ
提出

ハッキング、侵入テスト、サイバーセキュリティツールをあなたのセキュリティアーセナルに!

Kitploitはハッキング、サイバーセキュリティ、ペネトレーションテストのツールディレクトリです。最新のプロジェクトアップデートを見つけて、脆弱性の発見、システム分析、テストの自動化、セキュリティの強化を行いましょう。

··フィード·お問い合わせ·プライバシー·© 2026 Kitploit

ツールディレクトリ

カテゴリ

すべてのカテゴリを見る
Loading categories
mcpsnoop — MCP 向け Wireshark。AI クライアントと MCP サーバー間のすべての実際のツールコールを、ターミナル上でリアルタイムに表示する透過型プロキシ。 | Kitploit
ツール/GitHubGitHub/kerlenton/mcpsnoop
汎用ユーティリティ動的分析 (サンドボックス)ネットワークマッピングウェブプロキシと傍受スクリプトと自動化APIセキュリティテストデバッガログ分析
GitHubkerlenton/mcpsnoop

mcpsnoop

MCP 向け Wireshark。AI クライアントと MCP サーバー間のすべての実際のツールコールを、ターミナル上でリアルタイムに表示する透過型プロキシ。

リポジトリを見る
334322014日前Kitploit レビュー済み

人気

すべて見る →

コミュニティで最も使われているツールを見つけましょう。

すべてのツールを探索

ツールコレクションを閲覧

すべてのツールを見る →
共有

mcpsnoop

MCP 向け Wireshark。 AI クライアントと MCP サーバー間の実際のツール呼び出しをすべて、ターミナル上でライブ表示する透過プロキシです。

CI Go Reference MIT Marketplace

mcpsnoop demo

問題点

公式の MCP Inspector は独自のクライアントとして接続するため、あなたのクライアント(Cursor、Claude Code、Codex)がサーバーに実際に送信する内容を確認できません。また、リクエストの到着を待つだけのツールでは、モデルが呼び出さなかった呼び出しや、誤った引数で行われた呼び出しを表示できません。ツールが黙って呼び出されなかったり、機能が一致しなかったり、呼び出しがハングしたりすると、ログを調べて推測するしかなくなります。

mcpsnoop は代わりに実際のデータ経路に配置されます。 サーバーコマンドを mcpsnoop でラップすると、実際のクライアントとサーバーが通信する際に、すべての JSON-RPC フレームをライブで確認できます。

CI での利用

このページは mcpsnoop GitHub Action のリスティングも兼ねているため、その全体像をここに示します。キャプチャしたセッションを検査し、各発見事項をコードスキャニングアラートとして記録し、ゲート設定した内容に応じてジョブを失敗させます。```yaml permissions: security-events: write contents: read

steps:

  • uses: kerlenton/[email protected] with: session: artifacts/session.jsonl
root@kitploit:~
お好みのリリースを固定してください。最新版は
[リリースページ](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"] } } }

root@kitploit:~
`--` の後は、通常サーバーを起動するコマンドです。`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 はファイルを復元し、どのサーバーもラップされなくなった時点でバックアップを削除します。 どちらの操作後も Claude Desktop を再起動してください。MCP サーバーは起動時に 一度だけ起動されるためです。

その後、通常どおりクライアントを使用し、UI を開いてください。```bash mcpsnoop

root@kitploit:~
フラグも、ソケットパスも、覚えるべき起動順序もありません。シムと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実行はそれらで失敗します。

独自のサーバーをお持ちでない場合?公開されているテストサーバーに対して、実際に試してみてください。自分のクライアントで駆動します。セッション発生後に検査するには、ログから過去のセッションを確認を参照してください。

設定ファイル

プロジェクト全体で同じ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

root@kitploit:~
`redact-key`、`redact-value`、`redact-path` をそれぞれ別の行に繰り返して指定すると、それぞれを複数追加できます。

サポートされているキーはこれですべてです。

このファイルは現在の作業ディレクトリでのみ検索され、親ディレクトリでは検索されません。

明示的なコマンドラインのフラグは、設定ファイルの値を上書きします。

## コマンド

| コマンド | 機能 |
|---|---|
| `mcpsnoop -- <server>` | stdio サーバーを透過的なシムとしてラップする |
| `mcpsnoop` | ライブ TUI を開く |
| `mcpsnoop http --target <url>` | streamable-HTTP サーバーをプロキシする |
| `mcpsnoop export` | セッションを json、html、text、har、または otlp にレンダリングする |
| `mcpsnoop check` | エラー、無効なフレーム、警告、ルーティング不一致、ハングした呼び出し、遅延結果、またはレイテンシ予算で CI を失敗させる |
| `mcpsnoop baseline` | 信頼済みツール定義を検査、承認、またはリセットする |
| `mcpsnoop diff` | 2 つのキャプチャ済みセッション間でツールと呼び出しを比較する |
| `mcpsnoop open` | 保存済みセッションを TUI で開く |
| `mcpsnoop inventory` | このマシンで mcpsnoop を経由して実行されたすべてのサーバーを一覧表示する |
| `mcpsnoop stats` | 保存されたすべてのキャプチャをサーバーとツールごとに 1 行にまとめる |
| `mcpsnoop prune` | カットオフより古い保存済みセッションログを削除する |
| `mcpsnoop wrap <server>` | Claude Desktop のサーバーの 1 つを mcpsnoop 経由でルーティングする |
| `mcpsnoop unwrap <server>` | そのサーバーのエントリを元の状態に戻す |
| `mcpsnoop remote <user@host>` | SSH トンネルコマンドを表示する |
| `mcpsnoop demo` | スクリプト化されたセッションを再生する |

完全なリストは `mcpsnoop help` を、1 つのコマンドのフラグは `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 package ships no code of its own. Six platform packages each carry one build, and npm installs the single one that matches your machine, so there is nothing to download at install time and nothing to unblock in a proxy. To keep it around rather than fetching it each run, npm i -g mcpsnoop.

Go```bash

go install github.com/kerlenton/mcpsnoop/cmd/mcpsnoop@latest

root@kitploit:~
### Homebrew```bash
brew install mcpsnoop

すべてのプラットフォーム向けのプリビルドバイナリはReleasesページにあります。

シェル補完

mcpsnoopにはbash、zsh、fish、PowerShell用の補完が同梱されています。セットアップ手順(補完の有効化とOSごとのインストールパスを含む)については、mcpsnoop completion <shell> --helpを実行してください。

仕組み

mcpsnoopはAIクライアントとMCPサーバーの間のパイプに位置し、すべてのJSON-RPCフレームをライブターミナルUIにコピーします

mcpsnoopは1つのバイナリで2つの役割を担います。mcpsnoop -- <server>はクライアントが起動する透過的なシムであり、バイトをそのまま転送しながら、すべてのフレームのコピーをハブに送信します。引数なしのmcpsnoopはそのハブであり、ライブTUIでもあります。これらは既知のソケットとディスク上のログを通じてペアリングされるため、どちらが先に起動する必要はありません。

ハブはデフォルトで最新の保存済みセッション100件を読み込み、古いトレースを削除せずに起動時の処理を制限します。別の制限を選ぶにはmcpsnoop --history-limit Nを、全履歴を読み込むにはmcpsnoop --history-limit 0を使用してください。古いセッションはmcpsnoop open <session-id>とmcpsnoop export <session-id>を通じて引き続き利用できます。

履歴制限は読み込まれるセッション数を制限します。セッション内では、ライブTUIは二重に制限されます。これは、おしゃべりなサーバーを監視したまま放置されたハブが、終了されるまで肥大化し続けるためです。フレーム本体は最大64 MiBまで保持され、古いものから順に解放されます。また、フレーム数は最大200,000件までで、それを超えると古いものから完全に破棄されます。最初の制限は大きなペイロードのキャプチャで遭遇するもので、2番目の制限は小さな通知の長いストリームで発生するものです。

どちらの制限も回答を変えることはありません。本体が解放されたフレームは、その行、判定、タイムライン上の位置を維持し、インスペクタは空のフレームを表示する代わりに本体が存在しないことを示します。完全に破棄されたフレームは、まずそのツール呼び出しの統計を実行中の合計に反映させるため、ツールの概要とサーバーがコンテキストで消費するコストは、セッションが行ったすべての呼び出しを説明します(直近のものだけではありません)。ストリームのフッターは、ディスク上にある古いフレームの数のみを示し、rはパラメータを保持していないフレームを再生する代わりに拒否します。

mcpsnoop open <session-id>はログを読み取り、そのすべてを保持するため、制限はありません。TUIからのエクスポートもログを読み取るため、制限はありません。check、export、diffは意図的に無制限のストアを構築します。これは、大規模なキャプチャで過少報告するゲートが、メモリを使用するゲートよりも悪いためです。

履歴制限は読み込まれるものを制限します。mcpsnoop pruneは保持されるものを制限します。これは、カットオフより古い保存済みセッションログを削除し、単独で実行されることはありません。```bash mcpsnoop prune --older-than 30d --dry-run # list what would go, remove nothing mcpsnoop prune --older-than 30d # delete after confirming mcpsnoop prune --older-than 72h --yes # skip the prompt in a script

root@kitploit:~
`--older-than` は必須です(何も削除しないデフォルトは存在しません)。日数(`30d` など)または Go の期間(`72h` など)を受け付けます。ツールのベースラインは、ベースラインがセッションではなくサーバーラベルでキー付けされるため、そのまま残されます。

これは Inspector のように脇に置かれるのではなく、実際のパイプ内に位置するため、サーバーがどの言語で書かれていても、実際のクライアントとサーバーが互いにやり取りする内容を正確に確認できます。

## キーバインド

| キー | アクション | | キー | アクション |
|---|---|---|---|---|
| `enter` | 検査 / ドリルイン | | `/` | フィルタ |
| `esc` | 戻る | | `:` | コマンド |
| `j` / `k` | 移動 | | `r` / `R` | 再生 / 編集して再生 |
| `g` / `G` | 先頭 / 末尾 | | `c` | ケイパビリティ |
| `ctrl-f` / `ctrl-b` | ページ | | `s` | ツールサマリー |
| `p` | 一時停止 | | `y` | コピー |
| `shift`+`<キー>` | 列でソート | | `e` | エクスポート |
| `ctrl-d` | セッションを削除 | | `f` | フォロー |
| `?` | ヘルプ | | | |

アプリ内で `?` を押すと完全なリストが表示されます。

## ストリームのフィルタリング

セッション内で `/` を押し、スペース区切りのトークンを AND 条件で組み合わせます。プレーンテキストはメソッド、ツール、ID、ペイロードに一致します。

| トークン | フィルタ対象 | 例 |
|---|---|---|
| `tool:` | ツール名 | `tool:search` |
| `method:` | JSON-RPC メソッド | `method:tools/call` |
| `id:` | リクエスト ID、およびそれを継続する再試行 | `id:7` |
| `task:` | タスク ID | `task:01J...` |
| `dir:` | 方向(`c2s`、`s2c`) | `dir:s2c` |
| `kind:` | フレームタイプ(`req`、`resp`、`notify`、`stderr`、`invalid`) | `kind:invalid` |
| `status:` | 呼び出し結果(`ok`、`error`、`cancel`、`late`、`cancelled`、`pending`、`bad`、`warn`、`mismatch`、または `401` などの HTTP ステータス) | `status:error` |

トークンを積み重ねて特定の条件に絞り込みます。```text
tool:search status:pending        # in-flight calls to one search tool
status:cancel                     # calls the client gave up on (status:cancelled is a cancelled task)
status:late                       # results that arrived after the cancellation
method:tools/call status:error    # tool calls that failed
dir:s2c kind:req                  # server-initiated requests (servers before 2026-07-28)

The last one only finds anything on a server speaking 2025-11-25 or earlier. The 2026-07-28 revision removed server-initiated requests, and a server that needs something from the client now answers the client's own request asking for it, then the client retries. mcpsnoop links those retries back to the request they continue, so the exchange reads as one call rather than several.

Exporting sessions

Turn any captured session into a portable file.```bash mcpsnoop export -T json|html|text|har|otlp [-o file|-] [session-id|log.jsonl|-]

root@kitploit:~
| 形式 | 得られるもの |
|---|---|
| `json` | 相関付けられた呼び出し、ツールごとの件数とp50/p95/p99レイテンシ、最も遅い呼び出し、ケイパビリティ、および生のフレーム |
| `html` | 検索と折りたたみ可能なJSONを備えた自己完結型のブラウザファイル |
| `text` | 見やすいプレーンテキストのダンプ |
| `har` | 相関付けられた呼び出しごとに1エントリ。ブラウザの開発者ツールやHARを読み取るその他のツールで開くことができます |
| `otlp` | 相関付けられた呼び出しごとにスパンを持つOTLP JSON。W3Cトレースコンテキストが存在する場合は呼び出し元のトレースに結合され、それ以外の場合はセッションごとに1つのトレースになります |

MCPはHTTPではないため、HARエントリのURL、ステータスコード、およびタイミングは、ワイヤートランスクリプトではなく、各呼び出しの意図的なマッピングです。

OTLPの場合、リクエストの`_meta.traceparent`がその呼び出しのトレースと親スパンIDを提供し、`_meta.tracestate`はスパンに沿って運ばれます。traceparentが存在しないか無効な場合、mcpsnoopはセッション由来のトレースを保持し、状態を一切持ちません。mcpsnoopは参加ではなく監視を行うため、独自のベンダーエントリを追加せず、呼び出し元の状態を変更せずにそのまま渡します。```bash
mcpsnoop export -T html -o out.html                    # an HTML file to open in a browser
mcpsnoop export -T text server.py-48213-7f3a1c9e2b04   # a specific session, as text
mcpsnoop export -T json | jq                           # the newest session, piped to jq
mcpsnoop export -T har -o session.har                  # a HAR file to open in browser devtools
mcpsnoop export -T otlp -o trace.json                  # import into an OTLP-compatible tracing backend

-o を省略すると stdout に書き出され、セッションを省略すると最新のものが使用されます。または - を渡すと stdin から JSONL を読み取ります。TUI では、e を押すと選択したセッションを HTML としてエクスポートでき、コマンドモードで :export json|html|text|har|otlp [path] を実行することもできます。

リダクション

既存のキャプチャを検査または共有する前にスクラブするには、キャプチャ時に使用したものと同じリダクションフラグを export または open に渡します。```bash mcpsnoop export session.jsonl --redact-secrets --redact-key project_token -o shared.json mcpsnoop open session.jsonl --redact-path '$.params.arguments.password'

root@kitploit:~
These flags rewrite the exported file or the in-memory TUI view, never the
source JSONL. `export` refuses an output that names the same file as its input,
and writes through a temporary file that is renamed into place, so a run that
fails leaves the previous file whole.

A tool's `inputSchema` and `outputSchema`, as advertised in a `tools/list`
result, are left alone by `--redact-key` and `--redact-secrets`, for three reasons.

- A name inside a schema is a type declaration rather than a value.
- The name itself stays in the log either way.
- Scrubbing the subschema under a property called `token` would take the tool's
  own checks with it.

The exemption is that position only, so an argument that happens to be called
`inputSchema` is scrubbed like any other, and it stops at `default`, `const`,
`examples` and `enum`, which hold data rather than structure. Use
`--redact-path` to name something inside a schema, or `--redact-value`, which
matches text wherever it sits except in the two keywords mcpsnoop parses, `type`
and `x-mcp-header`.

What each flag reaches differs, so check the result rather than assuming. All
four scrub JSON-RPC payloads, and `--redact-key`, `--redact-path` and
`--redact-secrets` reach only those. Only `--redact-value` also scrubs stderr,
other non-JSON text, and the inside of a string. An `Mcp-Param-*` header is
scrubbed alongside the body value it mirrors. The other envelope metadata,
server labels, `Mcp-Name`, `Mcp-Method` and the HTTP status, is left as
captured. Redaction is best effort, so use a separate output path and read the
result before sharing it.

### Stream completed calls to an OTLP collector

Send spans while the proxy is running by pointing it at an OTLP/HTTP JSON
traces endpoint. Repeat `--otlp-header` for collector authentication or tenant
headers.```bash
mcpsnoop \
  --otlp-endpoint http://localhost:4318/v1/traces \
  --otlp-header "Authorization=Bearer $OTLP_TOKEN" \
  -- node build/index.js

mcpsnoop http \
  --target http://localhost:3000/mcp \
  --otlp-endpoint http://localhost:4318/v1/traces

配信はベストエフォート方式であり、プロキシされたMCPトラフィックをブロックすることはありません。コレクタが利用できない場合、mcpsnoopはバックグラウンドで再試行し、境界付きキューが満杯のときは新しいトレースフレームを破棄します。通常のJSONLセッションログは、永続的な記録として残ります。

セッションの比較

IDまたはJSONLパスで、保存された2つのセッションを比較します。```bash mcpsnoop diff before-session after-session mcpsnoop diff old.jsonl new.jsonl

root@kitploit:~
レポートには、追加または削除されたツール、説明と`inputSchema`の変更、ステータスが変化した一致するツール呼び出し、および顕著な所要時間の変化が表示されます。呼び出しはツール名と引数で照合されるため、順序が入れ替わった呼び出しでも正しく比較されます。デフォルトでは、所要時間の変化は少なくとも100ミリ秒かつ2倍の差が必要です。これらのしきい値を調整するには`--duration-threshold`と`--duration-ratio`を使用します。

`--exit-code`を渡すと、回帰をCIでゲートできます。afterセッションが次のいずれかに該当する場合、非ゼロで終了します:

- ツールを削除した場合
- ツールの説明、タイトル、入力スキーマ、出力スキーマ、または注釈を変更した場合
- ステータスが悪化した呼び出しがある場合
- 処理が遅くなった場合

アイコンの変更は、ツールの動作を変えずに見た目だけを変えるため、対象外です。改善、つまりツールの追加、呼び出しの修正、高速化は、依然としてゼロで終了します。

## CIでのセッションのチェック

記録されたエージェント実行を、エラー、ストリーム破損、プロトコル警告、ルーティングヘッダーの不一致、応答を受け取らなかった呼び出し、キャプチャを不完全なままにするドロップされたフレーム、ツール定義のドリフト、または非推奨のプロトコル機能の使用についてゲートします。```bash
mcpsnoop check [--format text|junit|sarif] [--fail-on error,invalid,warn,mismatch,pending,late-result,drift,deprecated,incomplete,schema] [session-id|log.jsonl|-]

error、invalid、warn は単独でチェックを失敗させます。それ以外はオプトインです。 カンマ区切りのサブセットを渡してジョブが気にするものだけをゲートし、セッションを省略すると最新のキャプチャをチェックし、- を使用してstdinからJSONLを読み取ります。

シグナル失敗条件
errorJSON-RPCエラーで応答された呼び出し、isError とマークされた結果、または失敗で終了したタスク
invalidプロトコルチャネル上のフレームが有効なJSON-RPCではない場合。通常はサーバーがstdoutにログを出力するケース
warnMCPまたはJSON-RPC仕様が設定する期待値を破るフレーム
mismatchルーティングヘッダーがボディと一致しない、バッチに乗っている、またはリビジョンが必要とする場所で欠落している
pendingキャプチャ終了時点でリクエストがまだ開いており、呼び出し元が待たされたままになった
late-resultリクエストがキャンセルされた後に到着したレスポンス
driftベースラインが承認された後に、宣伝されたツール定義が変更された
deprecated仕様が非推奨とした機能
incomplete上流でドロップされたフレーム。これにより、他のすべてのカウントが合計ではなく下限となる
schemaクライアント間でうまく伝わらない構造または方言を使用した宣伝されたスキーマ

すべてのシグナルは、ゲートするかどうかに関係なくカウントされるため、何を失敗させるべきかを決定する前に、実行結果は何が見つかったかを示します。``` session build-agent: errors=1 invalid=0 warnings=0 mismatches=0 pending=0 late_results=0 deprecated=0 missing_frames=0 schema_findings=1 schema findings: oneOf: search check failed: error

root@kitploit:~
The dropped-frame count travels with the artifacts too, so a capture that
understates itself says so wherever it is opened:

- `missing_frames` in the JSON export
- `log.comment` in HAR
- the `mcpsnoop.session.missing_frames` resource attribute in OTLP```bash
mcpsnoop check build-agent
mcpsnoop check --fail-on error,invalid artifacts/session.jsonl
mcpsnoop check --fail-on mismatch gateway-run.jsonl

終了コードは、2つのうちどちらが発生したかを示し、CIラッパーはその違いを必要とします。1はチェックが実行され、何かがゲートを失敗させたことを意味し、そのため検出結果は本物であり、公開する価値があります。2はチェックが実行されなかったことを意味します:存在しないパス、セッションログではないファイル、何も保持していない状態ディレクトリ、解析できないフラグ。2の場合、stdoutには何も書き込まれないため、パイプラインが空のレポートをあたかも判定であるかのようにアップロードすることはありません。

発生すべきことと発生してはならないことを検証する

シグナル数の他に、実行の形状を検証します。これらは互いに、また--fail-onと組み合わせて使用でき、いずれかの失敗は終了コード1(チェックが実行され、何かが見つかったことを意味するコード)で終了します。

フラグ失敗する条件
--max-duration <dur>完了したツール呼び出しの1つ以上が予算を超過し、その数と最悪の呼び出しを報告する
--expect-tool <name>指定されたツールが一度も呼び出されなかった場合(繰り返し指定可能)
--forbid-tool <name>指定されたツールが呼び出された場合(繰り返し指定可能)

a contract for the run: search must run, delete must not, nothing over 2s

mcpsnoop check --expect-tool search --forbid-tool delete --max-duration 2s run.jsonl

root@kitploit:~
### CIが既に確認している場所でレポートする

`--format junit` は、シグナルとセッションごとに1つの `<testcase>` を書き出し、その失敗はテキスト出力と同じ `--fail-on` の選択に従います。```yaml
- name: Check captured MCP session
  run: |
    mkdir -p test-results
    mcpsnoop check --format junit artifacts/session.jsonl > test-results/mcpsnoop.xml
- name: Upload mcpsnoop JUnit report
  if: always()
  uses: actions/upload-artifact@v4
  with:
    name: mcpsnoop-junit
    path: test-results/mcpsnoop.xml

--format sarif は、代わりに SARIF 2.1.0 ログを書き出します。junit がシグナルごとに1つの集約を報告するのに対し、SARIF は検出結果ごとに1つの結果を報告し、セッション、フレームの Seq、フレーム自身の警告またはドリフトテキストを保持し、フレームがデコードされたログの行を指し示します。--fail-on で指定されたシグナルはレベル error で報告され、それ以外はレベル note で報告されるため、レポートとゲートが食い違うことはありません。

結果は、検出結果の発生元であるログを指し示しますが、その方法はログが読み取られた場所によって異なります。

  • 作業ディレクトリ内のパスは相対パスになり、コードスキャンはそれをリポジトリルートに対して解決します。
  • ディスク上の別の場所にあるパス、または状態ディレクトリから解決されたセッション ID は、絶対的な file:// URI になります。
  • 標準入力からの読み取りでは、指し示すファイルがないため、結果に場所が一切含まれません。

アラートは、そのパスが分析対象のコミット内のファイルである場合にのみ周囲の行とともにレンダリングされるため、ワークフローが artifacts/ に生成したキャプチャは、メッセージ、ルール、行番号を保持するアラートを開きますが、ソースビューは含まれません。完全にレンダリングしたいキャプチャをコミットすることが、それを取得する唯一の方法です。

コードスキャンは、実行に25,000件を超える結果が含まれるファイルを拒否し、受け入れたもののうち上位5,000件のみを表示するため、レポートは5,000件に制限されています。最初にゲートが失敗した検出結果、次に、除外された件数を示す mcpsnoop/report-truncated 結果が続きます。テキスト形式と junit 形式は完全なままです。

GitHub Action

以下はすべて、このアクションが代わりに実行する内容です。mcpsnoop をインストールし、キャプチャをチェックし、検出結果を Security タブに登録し、ゲートで指定した内容でジョブを失敗させます。```yaml permissions: security-events: write contents: read

steps:

  • uses: kerlenton/[email protected] with: session: artifacts/session.jsonl
root@kitploit:~
リリースを固定してください。どれでもお好きなものを。最新版は
[リリースページ](https://github.com/kerlenton/mcpsnoop/releases)にあります。意図的に
浮動する`v1`はありません。固定したリリースは、アクションがインストールするバイナリでもあるため、
この2つが食い違うことは決してなく、古くなるデフォルトバージョンもありません。

| 入力 | |
|---|---|
| `session` | チェックする`.jsonl`キャプチャ。リポジトリルートからの相対パス。必須 |
| `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`です。`outcome`は`passed`、
`findings`、または`error`で、3つ目は個別に処理する価値があります。これは
何もチェックされなかったことを意味し、何も見つからなかったこととは異なります。**チェックできなかった実行は、
`fail-on-findings`の設定に関係なくジョブを失敗させます**。なぜなら、何も検証せずに
グリーンになるパイプラインは、失敗するものより悪いからです。

ジョブには`security-events: write`が必要です。そうしないとアップロードは403を返します。
コードスキャニングのないリポジトリでは`upload-sarif: false`を設定してください。

### または自分で配線する

このアクションは4つのステップで、魔法はありません。手動で行う場合も、同じ注意が必要です。
アップロードはレポートを持つ実行、つまり終了コード0または1で終了した実行で実行する必要があり、
終了コード2で終了した実行では実行してはいけません。また、ジョブを失敗させるステップは
その後に来る必要があります。そうしないと、検出結果が、存在する目的であるタブに到達しません。```yaml
permissions:
  # required for all workflows
  security-events: write
  # only required for workflows in private repositories
  actions: read
  contents: read

steps:
- name: Check captured MCP session
  id: check
  run: |
    code=0
    mcpsnoop check --format sarif artifacts/session.jsonl > mcpsnoop.sarif || code=$?
    echo "exit-code=$code" >> "$GITHUB_OUTPUT"
    # 2 means the check never happened, so there is no report to publish and
    # nothing was verified. Stop here rather than uploading an empty file.
    [ "$code" -le 1 ] || exit 1
- name: Upload mcpsnoop SARIF report
  if: ${{ !cancelled() }}
  uses: github/codeql-action/upload-sarif@v4
  with:
    sarif_file: mcpsnoop.sarif
    category: mcpsnoop
- name: Fail on findings
  # Separate, and after the upload, so the findings reach the Security tab on
  # exactly the runs that have some.
  if: ${{ !cancelled() && steps.check.outputs.exit-code == '1' }}
  run: exit 1

本文ボディと矛盾するルーティングヘッダーの検出

ストリーミング可能なHTTPトランスポートでは、ゲートウェイはMcp-MethodとMcp-Nameでルーティングする一方、サーバーはボディを読み取るため、ボディと矛盾するヘッダーは、両者が異なるリクエストを見ていることを意味します。mismatchシグナルは、そのようなケース、バッチ内で宛先を特定できないヘッダー、必須ヘッダーが完全に欠落しているケースをカバーします。

2026-07-28では、ルーティングヘッダーの欠落は検証エラーとなり、準拠したサーバーは400と-32020でリクエストを拒否します。mcpsnoopは、セッションがそのリビジョン以降を話すと判明した場合にのみこれを報告します。それ以前のリビジョンではこれらのヘッダーがまったく定義されておらず、そこでの省略は正しいためです。サーバー自身の-32020拒否も同じシグナルとしてカウントされます。

HTTPフィールド値に収まらない名前やリソースURIは、=?base64?…?=センチネルでBase64エンコードされて転送され、比較前にデコードされるため、正しくエンコードするクライアントが誤ってフラグ付けされることはありません。

HTTPのtools/callリクエストでは、mcpsnoopは各Mcp-Param-{Name}ヘッダーも表示し、一致するアドバタイズ済みツール定義が判明している場合は、注釈付き引数パスと比較します。ネストされたプロパティ、Base64センチネル、ブール値、数値と等価な安全な整数は、文字列比較による誤検知なしに処理されます。不明なパラメータヘッダーや、一致するツール定義がないセッションは、観察のみに留まります。キーおよび値ベースの編集は、キャプチャされたパラメータヘッダー値がシンクに到達する前に適用され、mcpsnoop自身がスクラブした値が不一致として報告されることはありません。

仕様が必須とするトランスポートヘッダーのチェック

上記のルーティングヘッダーはフレームが運ぶ唯一のものであったため、Streamable HTTPトランスポートのその他の必須ヘッダーは、それらをチェックできるものに到達しませんでした。Content-Typeが最も顕著なケースでした。レスポンス側はすでにそれを読み取ってSSEストリームとJSONボディを区別していましたが、その後破棄していました。

HTTPフレームは現在、トランスポートがルールを規定するヘッダーを運び、そのうち2つのルールがチェック可能です。

ルール報告方法
クライアントはapplication/jsonとtext/event-streamの両方を列挙したAcceptを送信しなければならない(MUST)リクエストに対するwarn
JSON-RPCリクエストに応答するサーバーはContent-Type: application/jsonまたはtext/event-streamを返さなければならない(MUST)レスポンスに対するwarn

どちらの文も2025-11-25と2026-07-28で同じ内容であるため、ドリフトチェックや拡張チェックとは異なり、リビジョンゲートは不要です。Originも記録されます。サーバーはそれを検証しなければならず(MUST)、無効な場合は403で応答しなければならない(MUST)ためですが、mcpsnoopは許可されたオリジンを把握できないため、値を判定せずに表示します。

ワイルドカードはカウントされます。*/*を送信するクライアントは両方のタイプを提供しているため、報告されることはありません。また、Content-Typeのcharsetパラメータは無視されます。mcpsnoopがこれらのヘッダーを記録する前にキャプチャされたログは、誰も書き留めていないヘッダーについてすべてのフレームを報告するのではなく、沈黙を保ちます。stdioにはそもそもこれらのヘッダーがまったくありません。

Authorizationは意図的にキャプチャされません。チャレンジをトークン事実に変換することはそれ自体が問題であり、ベアラートークンをディスクに置くことはその解決策ではありません。Mcp-Session-IdとLast-Event-IDもキャプチャされません。2026-07-28リビジョンは両方を削除し、サーバーにそれらを無視するよう指示しているため、チェックすべきルールは残っていません。

ツール定義のドリフト検出

サーバーラベルに対して観測された最初の完全なtools/listが、信頼できるベースラインになります。以降のセッションは、そのベースラインをフィールドごとに比較します:

  • 説明
  • タイトル
  • 入力および出力スキーマ
  • 注釈とアイコン

追加または削除されたツールも比較されます。これはフィールド比較ではなくセット比較です。

注釈が最も重要です。readOnlyHint付きで承認されたツールが、後で破壊的であると宣言する場合、これこそがこのチェックが存在する理由であり、仕様はクライアントに注釈を信頼できないものとして扱うよう指示しています。タイトルとアイコンはユーザーが目にするものであるため追跡され、仕様はツールのtitleをannotations.titleや名前よりも上位にランク付けします。セッションテーブルとツールサマリーは、MCPトラフィックをブロックしたり変更したりせずにドリフトをフラグ付けします。

注釈は仕様のデフォルトを通じて比較されるため、すでに依存していたヒントを明示的に書き始めたサーバーは報告されません。mcpsnoopがフィールドを追跡する前に記録されたベースラインは、記録するフィールドについては引き続き機能し、回答できないフィールドを示します。現在の定義を信頼できるようになったら、mcpsnoop baseline --acceptで再記録してください。

編集が記録するものを変更すると、ドリフトが比較するものも変更されます。--redact-valueなしで取得したベースラインを、--redact-value付きで取得したキャプチャと照合すると、スクラブされたフィールドが変更されたものとして報告されます。これは正しい動作です。記録された定義が実際に変更されたためです。編集設定を変更した後は、--acceptで再記録してください。

コマンド名やターゲットホストが衝突する可能性がある各サーバーには、安定した一意の--labelを使用してください。ベースラインは通常のmcpsnoop状態ディレクトリに保存されるため、MCPSNOOP_HOMEとXDG_STATE_HOMEが適用されます。```bash mcpsnoop check --fail-on drift session.jsonl mcpsnoop baseline session.jsonl mcpsnoop baseline --accept session.jsonl # trust a legitimate definition change mcpsnoop baseline --reset session.jsonl # trust the next complete tools/list

root@kitploit:~
In ephemeral CI では状態ディレクトリは空で始まるため、実行は比較対象がなく、検証する代わりにベースラインを記録することになります。**ドリフト時に失敗するよう要求した実行が、何も検証せずに成功することはありません**。また、どのディレクトリを永続化すべきかを示します。ベースラインの記録が失敗となるのは、このケースだけです。`--fail-on` に `drift` が指定されていない場合、ベースラインの記録は通常の処理であり、終了コードは変わりません。

したがって、ドリフトゲートが意味を持つためには、ベースラインが実行間で存続する必要があります。`--baseline` をチェックイン済みまたはキャッシュされたディレクトリに向けるか、`MCPSNOOP_HOME` を永続化されたパスに設定してください。```
recorded first-seen tool baseline (trusted, not verified)
check failed: drift

The following is a translation of the provided Markdown content into Japanese, preserving all structure and technical elements:

root@kitploit:~
このツールは、`--output` フラグを使用して出力ディレクトリを指定することをサポートしています。指定しない場合、結果は現在の作業ディレクトリに保存されます。

### 使用例

```bash
python3 tool.py --target example.com --output /path/to/results

上記のコマンドは、example.com に対するスキャンを実行し、結果を /path/to/results ディレクトリに保存します。

出力形式

結果は、以下の列を含むCSVファイルとして保存されます。

列名説明
timestampスキャンが実行された日時
targetスキャン対象のホスト名またはIPアドレス
port検出されたオープンポート番号
serviceポート上で実行されているサービス名
bannerサービスから取得されたバナー情報
statusスキャンのステータス(例:open、closed、filtered)

ログ記録

ツールは、--verbose フラグを使用して詳細なログを有効にすることができます。これにより、スキャンの進行状況と検出された問題に関する追加情報が提供されます。

root@kitploit:~
python3 tool.py --target example.com --verbose

詳細ログは、標準エラー出力(stderr)に書き込まれます。ログをファイルにリダイレクトするには、次のコマンドを使用します。

root@kitploit:~
python3 tool.py --target example.com --verbose 2> scan.log

トラブルシューティング

スキャン中に問題が発生した場合は、以下の一般的な解決策を確認してください。

  • 権限エラー: ツールが特定のポートをスキャンするために管理者権限を必要とする場合があります。sudo を使用してツールを実行してください。
  • ネットワーク接続: ターゲットに到達可能であること、およびファイアウォールがスキャンをブロックしていないことを確認してください。
  • 依存関係: ツールの要件がインストールされていることを確認してください。pip install -r requirements.txt を実行します。

ライセンス

このプロジェクトはMITライセンスの下で配布されています。詳細については、LICENSE ファイルを参照してください。

貢献

貢献は歓迎します。バグを報告するか、機能を提案するには、GitHubリポジトリでイシューを開いてください。プルリクエストも検討されます。

謝辞

このツールは、オープンソースコミュニティのサポートと、その開発に貢献したすべての開発者に感謝します。

root@kitploit:~
mcpsnoop check --fail-on drift --baseline .mcpsnoop/baselines session.jsonl
```
`drift` は `check` ではオプトインです。デフォルトの `error,invalid,warn` ゲートは変更されていません。

### どちらの側も交渉していない機能を検出する

SEP-2133 はオプション機能をコアプロトコルから拡張機能へ移し、各側のケイパビリティの `extensions` マップで告知されるようにしました。Tasks もその1つであり、2026-07-28 時点で、`tasks/get`、`notifications/tasks`、または `tools/call` がタスクハンドルで応答するのは、相手側が Tasks に対応していると表明した場合にのみ意味を持ちます。

相手側が対応していない場合、仕様は明確です。対応する側は、コアの動作にフォールバックするか、リクエストを拒否しなければなりません (MUST)。それでも実行してしまうことが、機能が配線されているように見えて、その後静かに何も動作しない理由であり、代わりにリーダーが受け取るのは、数フレーム後の `-32601` や `-32021`、あるいは進行しないタスクです。mcpsnoop は拡張機能に到達したフレームについて警告し、どちらの側がそれを告知しなかったかを明示します。```
tool "slow" answered with a task handle uses the io.modelcontextprotocol/tasks
extension, which the client never advertised
```
これは`warn`であるため、デフォルトの`check`実行では失敗します。キャプチャがネゴシエーションされた内容を示せない場合、つまりハンドシェイク後に開始されたキャプチャや、独自のリダクションが機能を削除したキャプチャ、および2026-07-28より前のリビジョンでは静かに動作します。そこでは`tasks/*`がコアプロトコルであり、それを使用することが正しいためです。

### 非推奨のプロトコル機能にフラグを付ける

2026-07-28リビジョンでは、Roots、Sampling、Loggingが非推奨になります。これらは少なくとも1年間は動作し続けるため、mcpsnoopはそれらをエラーとして扱うのではなく、マークを付けます。ストリーム、機能インスペクタ、エクスポートはすべてそれらにフラグを付け、各マーカーは置き換え先を指定します。

3つのうち2つは、現在では複数回のラウンドトリップを伴うリクエストを通じてのみ到達可能であり、メソッド名はフレーム自体ではなくサーバーの`inputRequests`マップ内にあります。これらにもフラグが付けられるため、新しいパターンに移行したサーバーが黙って報告を停止することはありません。```bash
mcpsnoop check --fail-on deprecated session.jsonl
```
`drift` と同様に、`deprecated` はオプトインです。デフォルトの実行では件数を報告してグリーンのまま維持されるため、まだ合法な非推奨機能を使用するセッションが、それだけでCIをレッドにすることはありません。

### クライアントがうまく扱えないフラグスキーマ構造

サーバーは完全に有効でありながら、エージェントにとって使いにくい場合があります。クライアントによって、JSON Schemaを実際にどこまでサポートしているかは異なり、モデルが繰り返し誤って呼び出すツールは、多くの場合、そのスキーマがクライアントの提供能力以上のものを要求しているツールです。

`s` で開くツールサマリーにはSCHEMA列があり、各公開ツールのスキーマについて最も注目すべき点が示され、複数の種類がある場合は末尾に `+` が付きます。

| 表示 | 意味 |
|---|---|
| `no root` | `inputSchema` が存在しない、JSONオブジェクトではない、またはルート型が `"object"` 以外である |
| `dialect` | リビジョンのデフォルトである2020-12以外のダイアレクトを指定する `$schema` |
| `ext ref` | ドキュメント外を指す `$ref`。仕様が実装者に盲目的に追従しないよう警告しているケースでもある |
| `oneOf`, `anyOf`, `allOf`, `not` | クライアント間で一貫性なく扱われる合成キーワード |
| `ref` | 同じドキュメント内を指す `$ref` |
| `untyped` | 型を宣言せず、受け入れる内容を他の方法でも示さないプロパティ |

最初のものを除いて、これらはすべて判定ではなく観察事項です。`oneOf` を使用するスキーマは間違っておらず、クライアントによって読み方が異なる可能性が高いだけであり、スキーマは任意のダイアレクトを宣言できます。`no root` は例外です。`Tool` 定義は `inputSchema` を必須とし、そのルート型を `"object"` に固定するため、リストを検証するクライアントはそのツールを完全に拒否し、呼び出し可能になることはなく、その理由を伝えるものはワイヤー上に何もありません。`no root` がその理由で列の先頭にあり、mcpsnoop自身の編集処理でスクラブされたスキーマは、読み取れないスキーマは間違ったスキーマではないため、決して報告されません。

この区別が、`check` がそれらに対して行う処理を決定します。`no root` は `tools/list` フレームの警告であり、フラグなしでデフォルトの `error,invalid,warn` ゲートを失敗させます。これが要点です。使用不能なツールを出荷するサーバーは、すべてのハンドシェイクに通常どおり応答し、単に `tools/call` を受け取ることはありません。観察事項は `schema_findings` としてカウントされ、`schema findings:` の下で報告され、`--fail-on` に `schema` を追加した場合のみ実行を失敗させます。どちらも `--format junit` と `--format sarif` に到達し、`export` は `summary.definitions.per_tool[].findings` の下にツールごとのリストを保持します。```bash
mcpsnoop check session.jsonl                     # a non-object root already fails this
mcpsnoop check --fail-on schema session.jsonl    # and now so do the observations
```
列は警告色を帯び、ERR列の赤になることは決してない。また、mcpsnoopは転送するトラフィックについて何も変更しない。

何も解決も取得もされない。外部の`$ref`はその形式だけで認識され、それが指し示すスキーマが読み込まれることは決してない。

### HTTP経由でキャプチャした呼び出しをリプレイする

`r`は、キャプチャした呼び出しを稼働中のサーバーに対して再発行する。stdioキャプチャの場合、コマンドはログ内にあるため、mcpsnoopは分離されたコピーを起動し、そのコピーにリクエストを送信する。HTTPキャプチャには起動するコマンドがなく、記録されたエンドポイントはユーザー情報とすべてのクエリ値が取り除かれているため、接続先アドレスではなくサーバーを指定するものとなる。

つまり、リプレイの送信先を指定するのはあなたであり、誰かがキーを押したからといってmcpsnoopが本番エンドポイントに接続することは決してない。```bash
mcpsnoop open --replay-target https://api.example.com/mcp session.jsonl
mcpsnoop open --replay-target https://api.example.com/mcp \
  --replay-header 'Authorization: Bearer sk-…' session.jsonl
```
`--replay-target` を指定しない場合、HTTP セッションは機能しないキーを提示する代わりにその旨を報告します。指定した場合、`r` はセッションの最初の送信の前に、記録されたコマンドが実行前に確認を求められるのと同じ方法で確認を求めます。

資格情報は `--replay-header` を通じてのみサーバーに到達します。mcpsnoop は `Authorization` ヘッダーを記録も再生もしないため、リプレイが漏洩させるために捕捉されたものは何もありません。

再生される POST は、トランスポートが必須とするものを運びます。これは、捕捉された生のボディだけの POST では運ばれません。`MCP-Protocol-Version`、`application/json` と `text/event-stream` の両方を列挙する `Accept`、`Mcp-Method`、仕様で要求される場合の `Mcp-Name`、そして捕捉されたすべての `Mcp-Param-*` です。これらは捕捉からそのまま再送され、base64 センチネルもすべて含まれるため、再導出が起こり得るような形でボディと矛盾することはありません。コピーされない唯一のヘッダーはプロトコルバージョンです。これは、再生されるボディが mcpsnoop が話すリビジョンを宣言しており、ヘッダーがボディと一致する必要があるためです。

`Mcp-Name` はコピーされるのではなく送信されるボディから導出されます。これは、仕様がそれを `params.name` または `params.uri` から取得し、ボディと矛盾するヘッダーをサーバーが拒否することを要求するためです。そうしないと、ツール名を変更する編集があった場合に古い名前が送信されることになります。`Mcp-Param-*` ヘッダーは捕捉された引数を反映するため、編集されたリプレイは、誰かが書き換えたボディについて何かを主張するのではなく、それらを一切送信しません。捕捉はその1つのファミリー内でのみヘッダーを設定できます。ログは人々が手渡しするファイルであり、任意のヘッダーを命名できるようにすると、必須のヘッダーを上書きしたり、誰も渡していない資格情報を追加したりできてしまいます。

リダクションルールが消去した `Mcp-Param-*` は、理由を添えてリプレイを停止します。プレースホルダーを送信すると、ユーザーが入力したかのように mcpsnoop 自身のバイトがライブサーバーに送信されることになります。

リダイレクトは追跡されるのではなく拒否されます。アドレスはあなたが指定して確認したものです。307 を追跡すると、その選択を遠端に委ね、ボディを再送信し、ポートのみを変更するホップでは資格情報も再送信することになります。mcpsnoop はサーバーが送信しようとした場所を報告し、代わりにその場所を指定するかどうかをあなたに判断させます。

単一の JSON オブジェクトとして到着する応答とイベントストリームとして到着する応答は両方とも読み取られ、失敗は番号ではなく名前で報告されます。

- 401 はサーバーが要求したスキームを報告します
- `-32020` はサーバーが拒否した内容を報告します
- 非 JSON-RPC の 400 または 404 は、そのアドレスがこのリビジョンの Streamable HTTP エンドポイントではないことを示します

### ユーザーの視点からサーバーのレイテンシーを区別する

マルチラウンドトリップリクエストでは、1回のツール呼び出しが複数のリクエストになり、人がエリシテーションに回答するのに費やした秒数がそのスパン内に含まれます。これは意図的です。その間隔は通常、最も確認したいものだからです。しかし、1つの数値で両方の質問に答えられないことを意味します。

サーバーが1.2秒処理し、ユーザーが37秒かかった `book_flight` チェーンでは、`check --max-duration 5s` はツールを38.2秒のせいにします。それでもそうなります。なぜなら、そのフラグの意味を変更すると、すでにそれを設定しているすべてのパイプラインが緩んでしまうからです。代わりに、2つの兄弟フラグが、それぞれが測定するものを名指しします。```bash
mcpsnoop check --max-server-duration 1s session.jsonl   # the server's share alone
mcpsnoop check --max-round-trips 2 session.jsonl        # how chatty a tool is
```
The `-p` option allows you to specify a custom port for the reverse shell. The `-h` option displays the help menu.```
assertion failed: 1 tool call exceeded the 1s server budget (worst: tool "book_flight" held for 1.2s)
assertion failed: 1 tool call exceeded the 2 round trip budget (worst: tool "book_flight" took 3)
```
どちらもデフォルトではオフなので、デフォルトの `check` 実行には影響せず、どちらもフレームのタイムスタンプと、mcpsnoop がすでに推測したリンクから読み取られるため、意図を推測することはありません。

TUI で `i` を押すと内訳が表示され、json、text、html のエクスポートでは `interactions` を読み取ります。各エントリは 1 つの論理操作であり、ラウンドトリップ数、合計時間、サーバーが保持していた割合、クライアントを待っていた割合が含まれ、さらに各ホップの行には各応答が何を求めたかが示されます。ツールごとのサマリーには `TRIPS` 列が追加されるため、何も開かなくても通信量の多いツールを確認できます。

`export --format har` はサーバーの保持時間を `wait` に、残りを `blocked` に格納します。これはそのフィールドの本来の用途であり、ビューアが実際には発生していない 38 秒のサーバー待機を描画し続けるのを防ぎます。

カウントと 2 つの割合は、要求時に導出されるのではなく、フレームが到着するたびに累積されます。ライブストアは予算内に収めるために古いフレームを解放するため、導出された答えは連鎖ではなく、いつの間にかウィンドウになってしまうからです。ホップごとの内訳は、まだ保持されているフレームから読み取られ、それが一部のみである場合にはその旨が示されます。`ServerTime + ClientTurnaround` は、誰かが信頼しなければならない計算ではなく、構造上合計と等しくなります。

`--max-round-trips` は、まだ実行中の連鎖を判定します。すでに行われたすべてのリクエストは数えられるため、サーバーが何度も何度も要求し続けると、誰も完了しない操作が正確に生成されるからです。`--max-server-duration` は終了を待ちます。これは `--max-duration` がすでに適用しているルールであり、まだ開いている操作には判定するレイテンシがないためです。

mcpsnoop がリンクできなかった操作は、それ自体の単一ホップのエントリとして残ります。`matchRetry` は意図的に曖昧なリンクを拒否し、このビューはそのギャップを埋めません。

1 つのリクエストで完了した操作にはホップの内訳はありません。単一のホップは上記の合計をそのまま繰り返すだけだからです。連鎖はリクエストごとに 1 ホップを報告し、ストアがすべてのフレームを保持しなくなった場合や、ホップが構成されるリクエストと応答のペアから外れて処理が確定した場合(タスクハンドルが該当)には、その旨が示されます。

### サーバーがユーザーに何を求めたかを確認する

Elicitation は、MCP において人がサーバーにデータを入力する唯一の経路であり、MRTR では質問と回答はもはや 1 つのやり取りの 2 つの半分ではありません。質問は `InputRequiredResult` に埋め込まれ、回答は別の ID での再試行時に `inputResponses` 内で返され、それらを結び付ける唯一のものは mcpsnoop がすでに推測するリンクです。

そのペアリングがなければ、拒否されたパスワード要求は単純なツールエラーとして読み取られます。```
tools/call login_legacy [form] creds: decline after 3s
  password string
```
TUIで`l`を押すか、json・text・htmlエクスポート内の`elicitations`を読んでください。各行には、質問が中断した操作、モード、メッセージ、何が求められたか、ユーザーが何をしたか、そして所要時間が記載されています。リトライが一度も応答しなかった質問は「保留中」と表示されます。これは、仕様がサーバーに対してクライアントがそもそもリトライするとは想定しないよう指示しているため、MRTRはこれをエラーではなく通常の結果として扱います。

フォーム行には、`requestedSchema`プロパティ名とその宣言された型がリストされます。リダクションルールがサブスキーマを置き換えたプロパティは、プレースホルダーではなく不明な型として表示されます。なぜなら、プレースホルダーはサーバーが宣言したものではないからです。URL行にはアドレス全体が記載され、仕様ではクライアントが同意前にこれを表示することになっており、ホスト名は単独で記載され、サブドメインスプーフィングに対して強調表示するよう指示されています。

台帳には送信された値が保持されることは決してありません。ユーザーが入力した内容は、それを必要とする人のためにキャプチャ内に残り、エクスポートして貼り付けるために作られた要約面から除外することで、このデータはリダクションの対象から完全に外れます。これは、仕様が意図的に資格情報を配置するurlモードで最も重要です。

リトライは、それが発行されたラウンドにのみ応答し、他のラウンドには応答しません。MRTRはサーバーに対し、クライアントが要求された内容の一部を省略した場合、新しいラウンドで再度尋ねるべきだと伝えます。そのため、応答済みのキーと未応答のキーを1つずつ保持する以前のラウンドは通常のトラフィックであり、未応答の半分は後のラウンドの回答を借用せずに保留中のままとなります。

記録される質問は1つに制限されています。メッセージ、URL、フィールドリストはセッションの存続期間中保持され、ボディを解放するフレーム予算の外にあります。そのため、サーバーは質問を恣意的に高コストにすることはできません。制限は実際の質問をはるかに上回り、切り詰められたメッセージには切り詰められたと表示されます。

ここで警告されるものはなく、`check`の終了コードが変更されることもありません。台帳は何が起こったかを記録します。それを判断することはありません。

### 4回に1回失敗するツールを見つける

`check`は1つのセッションを読み取り、`diff`は正確に2つを読み取るため、時々失敗するツールは、誰かが手動でキャプチャを開くまで見えないままです。`run_query`が約4分の1の確率で`isError`を返すサーバーの16件のキャプチャにわたって、`check`は最新のものを正直にクリーンとして報告します。```bash
mcpsnoop stats
mcpsnoop stats --since 7d --label prod
mcpsnoop stats --limit 20 --format json
```
# 高度な使い方

## カスタム設定

`~/.config/kitty/kitty.conf` に設定を追加することで、kitty の動作をカスタマイズできます。一般的な設定には以下が含まれます:

```conf
# フォント設定
font_family      JetBrains Mono
font_size        12.0

# カーソル設定
cursor_shape     beam
cursor_blink_interval 0.5

# スクロールバック
scrollback_lines 10000

# マウス設定
mouse_hide_wait  3.0
```

## キーボードショートカット

kitty には、生産性を向上させるための多数のキーボードショートカットが付属しています。最も便利なものには以下が含まれます:

- `ctrl+shift+t` — 新しいタブを開く
- `ctrl+shift+n` — 新しいウィンドウを開く
- `ctrl+shift+enter` — 新しいウィンドウを垂直に分割
- `ctrl+shift+alt+enter` — 新しいウィンドウを水平に分割
- `ctrl+shift+方向キー` — ウィンドウ間を移動
- `ctrl+shift+[` / `ctrl+shift+]` — タブ間を移動
- `ctrl+shift+q` — ウィンドウを閉じる

## レイアウト

kitty は、ウィンドウの配置方法を制御する複数のレイアウトをサポートしています:

- **タリング** — デフォルトのレイアウト。ウィンドウはタイル状に配置されます。
- **スタック** — ウィンドウは互いに重なり合い、一度に1つだけが表示されます。
- **スプリット** — ウィンドウは水平または垂直に分割されます。
- **グリッド** — ウィンドウはグリッドパターンで配置されます。

レイアウトを切り替えるには、`ctrl+shift+l` を押してから目的のレイアウトを選択します。

## リモート制御

kitty は、実行中のインスタンスを制御するためのリモート制御機能を提供します。これは、スクリプトや自動化に役立ちます:

```bash
# 新しいウィンドウを開く
kitty @ new-window --title "My Window"

# ウィンドウのタイトルを設定
kitty @ set-title "New Title"

# ウィンドウを一覧表示
kitty @ ls
```

## セッション

kitty はセッションをサポートしており、ウィンドウとタブのレイアウトを保存および復元できます:

```bash
# セッションを保存
kitty @ save-session ~/.config/kitty/sessions/default.json

# セッションを復元
kitty @ load-session ~/.config/kitty/sessions/default.json
```

## テーマ

kitty は、外観を変更するためのテーマをサポートしています。テーマは、[kitty-themes](https://github.com/dexpota/kitty-themes) リポジトリからインストールできます:

```bash
# テーマをインストール
kittens themes --reload-in=all

# テーマを選択
kittens themes
```

## トラブルシューティング

問題が発生した場合は、以下の一般的な解決策を確認してください:

1. **kitty が起動しない** — 設定ファイルに構文エラーがないか確認します。`kitty --debug-config` を実行して設定を検証します。
2. **フォントが正しく表示されない** — フォントがインストールされていること、および `font_family` 設定が正しいことを確認します。
3. **キーボードショートカットが機能しない** — ショートカットが他のアプリケーションと競合していないか確認します。
4. **パフォーマンスの問題** — ハードウェアアクセラレーションを無効にしてみます:`kitty --disable-ligatures`。

詳細なトラブルシューティングについては、[kitty ドキュメント](https://sw.kovidgoyal.net/kitty/) を参照してください。```
read 16 logs of 16 in ~/.local/state/mcpsnoop/sessions

SERVER       TOOL          CALLS   ERR  PROTO    FAIL%       SESS       p50      p95      p99      DEF
flaky-demo   run_query        13     3      0    23.1%       3/13     434ms    519ms    519ms     195B
docs-mirror  run_query         3     1      0    33.3%        1/3     357ms    434ms    434ms     195B
docs-mirror  search_docs      12     0      0     0.0%        0/3     377ms    386ms    386ms     200B
flaky-demo   search_docs      52     0      0     0.0%       0/13      42ms     58ms      59ms    200B
```
`ERR` と `PROTO` は仕様上別物として扱われるため、別々の列になっています。`isError` を返すツールは、モデルが対処して再試行できる何かを報告しています。JSON-RPC エラーは、リクエストまたはサーバー自体が間違っていることを示します。`SESS` は、ツールを呼び出したセッションのうち失敗を目撃したセッションの数であり、「10回に1回」という呼び出し回数ベースの割合では答えられない問いに対応します。

行はサーバーとラベルの組み合わせでキー付けされます。サーバーは、stdio では記録されたコマンドと作業ディレクトリ、HTTP ではエンドポイントであり、`inventory` が使用するのと同じ識別情報です。どちらか片方だけでは、混ぜるべきでないものをまとめてしまいます。ラベルだけだと、1つの名前を派生させる2つのサーバーが統合されます。これは、プロジェクトの2つのチェックアウトが同じエントリポイントを実行するときに常に発生します。識別情報だけだと、意図的に `prod` として実行され、その後 `staging` としても実行された1つのコマンドが統合されます。どちらの誤りも、2つのきれいな分布を、どちらも表さない1つの分布に汚染します。

2つの行が同じラベルを共有する場合、`SERVER` セルにはそれらを区別する作業ディレクトリまたはエンドポイントが入り、JSON には各行に `command`、`cwd`、`endpoint` が含まれます。曖昧さがなかった名前はそのまま残されるため、通常のテーブルは変更されません。

ログ内のすべてのセッションが折り畳まれます(最初のものだけではありません)。したがって、キャプチャを連結して作成されたファイルは、そのすべてをカウントします。

パーセンタイルは生の所要時間にわたってプールされます。中央値の中央値は、何の中央値でもありません。1回の複数ラウンドトリップ操作は、それが何回のリクエストを要したかにかかわらず、1回の呼び出しであり1つの所要時間です。また、まだ開いている呼び出しは、レイテンシに寄与しないまま `CALLS` にはカウントされます。

一度に常駐するキャプチャは1つだけです。ログは読み込まれ、実行中のカウンタに折り畳まれ、次のログが開く前に破棄されます。したがって、数百のファイルがあるディレクトリでも、その合計ではなく、最大の単一キャプチャのコストしかかかりません。

`--limit` はデフォルトで最新のログ100件に設定され、ヘッダーには何件中何件を読み取ったかが示されるため、制限付きの回答が完全な回答と誤認されることはありません。`stats` は報告するだけで、制限はかけません。何も書き込まず、ベースラインに触れず、ソケットを開かず、ウォークが成功した場合は常に終了コード0で終了します。

### ここで実際にどのサーバーが実行されているかを確認する

Shadow MCP について人々が繰り返し指摘する発見は、組織が承認された数よりも数倍多くの MCP サーバーが実行されていることを発見するというものです。なぜなら、サーバーは多くの場合、誰かが IDE プラグインに追加した単なる依存関係にすぎないからです。同じことが1台のラップトップ上でも小規模に発生しており、mcpsnoop はその答えをずっと記録してきましたが、これまで一度も表示していませんでした。```bash
mcpsnoop inventory
mcpsnoop inventory --tools          # also count what each server last advertised
mcpsnoop inventory --format json    # for something else to read
```
1行はセッションごとではなくサーバーごと。行キーは記録されたコマンドと作業ディレクトリであり、ラベルではない。ラベルはコマンドの最後のパス要素から導出され、`node ~/one/build/index.js` と `node ~/two/build/index.js` はどちらも `index.js` を導出するためである。HTTPセッションは、mcpsnoopがそこで何も起動していないため、代わりにプロキシしたエンドポイントをキーとする。

読み取りはログごとに1エンベロープであり、プロキシが最初に書き込むメタフレームであるため、大規模なキャプチャのディレクトリでもコストは低く抑えられる。`--tools` は例外で、サーバーごとに1ログ、つまり各サーバーの直近の実行を読み取るため、列ではなくフラグになっている。それでも読み取りは制限されている。ツールインベントリはセッション状態であり、ストアが進行に応じて折り込むため、100メガバイトのキャプチャは全体を保持して1つの整数を生成するのではなく、固定ウィンドウを通して読み取られる。

カウントがない場合、行は3つのうちどれが発生したかを示す。読み取れなかったログは何も宣伝しなかったサーバーではないため、両方に1つの文を使うとmcpsnoopが誤ったことを述べることになる。

`--redact` ルールが書き換えたコマンドは、実行されたコマンドとして渡されるのではなく、記録されたとおりに印刷され、マークされる。1つのサーバーの2回の実行(1回はスクラブ済み、もう1回は未スクラブ)は2行になる。mcpsnoopはプレースホルダーが何を置き換えたかを知ることができず、それらをマージすると隠れた半分が一致したと推測することになる。1つのサーバーが2つの `--label` 値で実行された場合、キーは名前ではなくコマンドであるため、両方の名前を持つ1行になる。

行内の何もmcpsnoopによって書かれない。コマンドはサーバーをインストールした人から来て、作業ディレクトリはファイルシステムから取得され、導出されたラベルはコマンドから来る。制御文字を含む値は生のまま印刷されるのではなく引用符で囲まれるため、名前に改行を含むディレクトリは、それが印刷されるフィールドを閉じて、後続の行が実行されたことのないサーバーとして読み取られるのを防ぐ。スペースを含む引数も引用符で囲まれる。`node "~/My Project/build/index.js"` は、そうでなければ2つの引数と区別がつかないためである。

ウォークが折り込めなかったものはすべて、破棄されるのではなくヘッダーに名前が付けられる。空のログは破損したログとは別にカウントされる。ゼロバイトのログは、execが失敗した実行または誰も呼ばなかったHTTPプロキシの通常の残骸であるためである。

出力は新しさではなく名前でソートされるため、1つのディレクトリに対する2回の実行は同じバイトを生成し、それが後で差分を取るためのベースラインとして使用可能にする理由である。

2つのギャップは見落としではなく構造上存在する。`--trace-file` を使用した実行はセッションディレクトリの外に書き込んだため表示されず、`prune` はログを削除するため、最初に表示されたのは常にディスク上に残っているものと同じくらい古いものにすぎない。mcpsnoopはこのマシンで何が実行されたかを報告する。ネットワークをスキャンせず、指摘されたクライアント設定も読み取らず、何も判断しない。

### 壊れたサーバーと「ノー」と言うツールを区別する

`result.isError` で応答するツールは正常に動作している。調べたが何も見つからなかったか、入力を拒否した。JSON-RPCエラーで応答するサーバーは壊れている。どちらもツールサマリーでは1つの数値であり、ドメイン障害を報告する行儀の良いツールが壊れたサーバーとまったく同じに見え、その上にソートされることを意味した。

`ERR` 列がそれらを分離する。赤はサーバー側であり、JSON-RPCエラーまたは理由を言わずに失敗で終了したタスクである。警告色はツール自身の `isError` である。両方を持つツールは結合されたカウントを表示し、赤が最初に来て、表の下の行は、説明すべき警告番号があるときはいつでも2つの合計を挙げる。エクスポートは、合計すると常に一致する `errors` 合計の横に、`protocol_errors` と `tool_errors` として同じ分割を保持する。

`check --fail-on error` は変更されておらず、どちらでも依然として発火する。一方を無視するゲートは、サーバーがもう一方を返すことでオフにできるゲートになるためである。```bash
mcpsnoop export -T json | jq '.summary.tools[] | {name, errors, protocol_errors, tool_errors}'
```
### サーバーがコンテキスト上でどれだけコストをかけているかを確認する

ツール定義は会話のたびにモデルのコンテキストに入り、ツール結果は呼び出しのたびに入ります。ツールサマリー(`s`)は、実際にキャプチャしたセッションの両方を測定します。

`definitions` 行は固定コストです。つまり、このサーバーの `tools/list` が一度も呼び出される前にどれだけの重さを持つかを示します。`DEF` 列はそれをツールごとに分解し、`RESULT` は各ツールの回答がこれまでに費やしたコストを示します。テーブルはエラーとレイテンシでソートされたままなので、`DEF` をスキャンして高コストな定義を見つけてください。エクスポートでは、それらを重い順にリストします。テーブルの下の行は、合計では隠れてしまう、最も重い単一の結果を指名します。

定義の数値は、意味のない空白を除去した JSON です。そのため、`tools/list` を整形出力するサーバーが、そうでないサーバーよりも高コストとしてカウントされることはなく、同じサーバーはキャプチャ間で同じように測定されます。`RESULT` は到着したままのバイト数です。結果は使い捨てのペイロードであり、正規化する価値のある契約ではないからです。```bash
mcpsnoop export -T json | jq '.summary.definitions'
```
エクスポートには、ツールごとに同じ数値が含まれ、説明とスキーマのバイト数に分かれているため、肥大化した説明と肥大化したスキーマは分離されたままで、それぞれをキャプチャ間で追跡できます。`mcpsnoop diff` は、2つのセッション間で説明またはスキーマが変更されたことを通知します。その変更の大きさがどこにあるかは、エクスポートに示されます。

**これらはバイト数であり、トークン数ではありません。** トークン数はモデルによって異なるため、トークンを測定するにはトークナイザーを同梱し、どのモデルのものかを選ぶ必要があります。バイト数は正確であり、独自の比率を適用できます。未完了の `tools/list` は、確認できた範囲を下限として報告し、その旨を明記します。部分的な合計を総数として偽装することはありません。

### サーバー状態を改変するクライアントを検出する

マルチラウンドトリップパターンでは、サーバーはクライアントに不透明な `requestState` を渡し、クライアントは再試行時にそれを変更せずにそのまま返す必要があります。サーバーはこれを攻撃者が制御する入力として扱うよう指示されます。なぜなら、これを改変するクライアントはサーバーの動作を変更したり、認可チェックを迂回したりしようとする可能性があるからです。

パイプの中にいる mcpsnoop は、値が送信され、戻ってくるのを確認できるため、契約が破られたタイミングを指摘できます。破られ方は3通りあり、それぞれが再試行時のプロトコル警告として報告されます。

| 報告内容 | 意味 |
|---|---|
| `MRTR retry changed requestState` | クライアントがサーバーが発行したものとは異なる値を返した |
| `MRTR retry is missing requestState` | サーバーが発行したのに、再試行でそれが省略された |
| `MRTR retry invented requestState` | 再試行がサーバーが発行したことのない値を保持していた |

これらは当社の観測ではなくクライアントによるプロトコル違反であるため、通常の警告シグナルに乗せられ、**デフォルトの `check` 実行はその1つで失敗します**。これは意図的です。サーバー状態を改変するクライアントは、ビルドを止める価値があります。

値自体は表示もログ記録もされず、デコードや解析も行われません。プリンシパルとトークンを保持する暗号化ブロブである可能性があり、不透明なバイト列の比較がチェックのすべてです。

1つのケースは対応範囲外です。サーバーが `requestState` で応答し、`inputRequests` がない場合、改変された再試行は何にも一致せず、キーも返さないため、元のリクエストに結び付けるものが残らず、違反ではなく無関係な呼び出しとして読み取られます。

放棄された交換は次の交換を妨げず、また永遠に保持されることもありません。64件の未完了の交換は、どのクライアントも同時に保持する数をはるかに超えているため、それを超えて保持するセッションは誰も完了しない交換を保持していることになり、最も古いものは、仕様がサーバーにその状態に短い有効期限を与え、その後は拒否するよう指示しているため、退役させられます。退役は黙って行われるのではなく、カウントされます。ストリームのフッターには `N unlinked` が表示され、エクスポートには `session.retired_exchanges` が含まれます。これは、退役した操作に対して再試行が到着した場合、それが独自の呼び出しとして読み取られるためであり、カウントを比較する読者にはその旨が伝えられるべきだからです。

退役により、ライブストアはその操作を解放することもできます。保留中の操作は意図的に保留されたままになるため、その期間は交換全体に及び、ストアは保留中の呼び出しを忘れることを拒否します。応答がまだ来る可能性があるからです。上限によって操作が退役すると、それに応答できるものは何もないため、保持すると、どの読者も到達できない呼び出しが存続することになります。セッションが報告する内容は変わりません。それは依然として保留中としてカウントされ、`N unlinked` にもカウントされます。これは、レコードが占有するメモリ量と、レコードが示す内容は異なる問題だからです。

放棄された交換は次の交換を妨げません。MRTR は、サーバーがクライアントに再試行を決してしないかもしれないと想定してはならないと指示するため、ユーザーが要求を辞退すると、後続のフレームが決して解決しない操作が残ります。mcpsnoop はまず、`requestState` の存在が再試行のものと一致する操作を探します。これは仕様が双方向でルールにしているため、準拠した再試行は、同じツールで放棄された交換が隣にあっても、それが継続する1つの操作を依然として見つけ出します。上記の3つの違反を報告するチェックは、何も一致しない場合にのみ実行されるため、実際に非準拠の再試行は依然として特定されます。

## 別のマシンから監視する

キャプチャはトラフィックが発生するマシンにローカルに保持し、ネットワークホップには SSH を使用します。これにより、mcpsnoop は独自のリモートトランスポートを必要としません。

### ライブビュー

ワークステーションで TUI を実行し、リモートマシンの mcpsnoop ソケットをワークステーションに転送します。ライブトンネルは SSH Unix ソケット転送を使用するため、両端が Linux または macOS で実行されている必要があります。Windows では、以下の事後ログコピーを使用してください。```bash
# on your workstation, start the TUI
mcpsnoop

# create the remote socket directory once
ssh remote-user@remote-host 'mkdir -p ~/.local/state/mcpsnoop'

# print the tunnel command, then run the printed ssh -R line
mcpsnoop remote remote-user@remote-host

# on the remote host, wrap your server as usual
mcpsnoop -- node build/index.js
```
ソケットはリモートの状態ディレクトリ配下に置かれ、`MCPSNOOP_HOME`、なければ`XDG_STATE_HOME/mcpsnoop`、それもなければ`~/.local/state/mcpsnoop`として解決されます。デフォルトでは、mcpsnoopは`user@host`からLinuxのホームディレクトリ`/home/<user>`を想定し、その推測にフォールバックするたびにstderrへリマインダーを出力します。リモートが別の場所に解決される場合は、デフォルト以外のその1つの項目を指定してください。```bash
# a non-Linux or custom home, macOS is /Users/<user> and root is /root
mcpsnoop remote --remote-home /Users/remote-user remote-user@remote-host

# an explicit MCPSNOOP_HOME on the remote
mcpsnoop remote --remote-mcpsnoop-home /srv/mcpsnoop remote-user@remote-host

# an explicit XDG_STATE_HOME on the remote
mcpsnoop remote --remote-xdg-state-home /var/lib/state remote-user@remote-host
```
### ポストモーテム

リモートセッションをSSH経由で直接TUIにストリーミングします。ローカルへのコピーは不要です。```bash
ssh remote-user@remote-host 'cat ~/.local/state/mcpsnoop/sessions/session.jsonl' | mcpsnoop open -
```
ローカルコピーを保持したい場合は、ログをセッションディレクトリにscpしてから、
通常どおりTUIを実行してください。```bash
# copy the remote logs into your local sessions directory
mkdir -p ~/.local/state/mcpsnoop/sessions
scp remote-user@remote-host:'~/.local/state/mcpsnoop/sessions/*.jsonl' \
  ~/.local/state/mcpsnoop/sessions/

# open the TUI, it backfills the copied sessions
mcpsnoop
```
## セキュリティ

mcpsnoopはラップするサーバーコマンドを実行するため、信頼できるサーバーのみをラップし、信頼できないサーバーはコンテナ内で実行してください。クライアント設定に含めていないものは一切実行しません。

リモートワークフローでは、SSHトンネリングまたはSSHファイル転送を使用して、トランスポート認証、暗号化、ホスト検証、キーローテーション、監査ポリシーを既存のSSH設定に維持してください。

### キャプチャ内容の編集

キャプチャされたフレームには、プロンプト、ツール引数、認証情報、ツール結果が含まれる場合があります。ペイロードがシークレットを運ぶ可能性がある場合は、編集をオプトインして、プロキシされたバイトが変更されずに通過する間、観測されたトレースのコピーをスクラブします。

キーベースの編集は、一致するJSONオブジェクトキーの下にある値全体を置き換え、同じキーセットはラップされたサーバーのコマンドライン引数にもベストエフォートで適用されるため、`--api-key=sk-x`や`--token sk-x`は`--redact-secrets`の下でスクラブされます。認識可能なフラグ名なしでシークレットを運ぶ引数は検出できません。

HTTPエンドポイントはその対象外です。これは送信を選択したペイロードではないためです。`--target`はプロキシを実行するために渡す必要があるフラグであるため、そのURLは編集設定に関係なくセッションログに到達します。mcpsnoopは、ユーザー情報、すべてのクエリ値、フラグメントを常に、パターンではなく構造によって削除した状態で書き留めます。クエリキーは、1つのホストの2つのエンドポイントを区別するものであるため残り、フラグメントはそもそもサーバーに到達しないため削除されます。記録されるものはサーバーを識別し、ダイヤルするアドレスではありません。

パスベースの編集は、JSONPath式で選択された値のみを置き換えます。これは、一般的なキー名がある場所では機密で、別の場所では安全な場合に役立ちます。`--redact-path`を繰り返して、複数の場所をスクラブします。

値ベースの編集は、観測された文字列値、stderrテキスト、非JSONテキストフレームに正規表現を適用します。

3つすべてベストエフォートです。正規表現はシークレットを見逃したり、無害なテキストに過剰一致したり、変換またはエンコードされた値を認識できない場合があります。

編集が非難になることはありません。観測されたものを別のものと比較するすべてのチェック(ルーティングヘッダーとボディ、ミラーリングする引数に対する`Mcp-Param`値、リビジョンがツールに要求するものに対するツールのスキーマ)は、mcpsnoopがバイトを書き換えた側であることを認識し、ユーザー自身のプライバシー設定についてサーバーを報告するのではなく、沈黙を守ります。ツール定義のドリフトは例外であり、意図的にそうなっています。編集を有効にすると記録される内容が変わり、したがってベースラインが保持する内容も変わるためです。[ツール定義ドリフトの検出](#detect-tool-definition-drift)を参照してください。```bash
# built-in preset of common secret keys
mcpsnoop --redact-secrets -- node build/index.js

# or name your own keys
mcpsnoop --redact-key token,api_key,password -- node build/index.js

# scrub one location without redacting every field named password
mcpsnoop --redact-path '$.params.arguments.password' -- node build/index.js

# wildcards scrub every matching array element
mcpsnoop --redact-path '$.params.arguments.accounts[*].password' -- node build/index.js

# scrub obvious token-shaped values outside known keys
mcpsnoop --redact-value 'sk-[A-Za-z0-9]+' -- node build/index.js

# combine the layers in http mode
mcpsnoop http --target http://localhost:3000/mcp --redact-secrets --redact-value 'Bearer\s+\S+'
```
## 貢献

問題やプルリクエストは歓迎します。詳細は [CONTRIBUTING.md](https://github.com/kerlenton/mcpsnoop/blob/main/CONTRIBUTING.md) を参照してください。

## ライセンス

[MIT](https://github.com/kerlenton/mcpsnoop/blob/main/LICENSE)
ツールをダウンロード