endpoint-probe について
endpoint-probe は、API の連携や評価に先立ち、公開されている機能を調べるコマンドラインスキルです。HTTP または stdio で MCP サーバーも調査し、ツール、リソース、プロンプトと入力スキーマを一覧表示します。
主な機能
- 01API パスと OpenAPI 仕様の検出
- 02認証、CORS、レート制限の確認
- 03HTTP または stdio による MCP の調査
- 04MCP のツール、リソース、プロンプトの一覧
- 05MCP 入力スキーマの表示
活用シーン
- 01連携前に未文書化 API を調査
- 02API の認証要件を確認
- 03設定前に MCP サーバーを調査
MCP 対応
StreamableHTTP または stdio 経由で MCP サーバーを調査するクライアントとして動作します。ハンドシェイクを行い、ツール、リソース、プロンプト、入力スキーマを一覧表示します。
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ moonlight-lupin/ agent-skills --skill endpoint-probeインストール後、Claude Code で/endpoint-probeを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/code-review-history.mdcode-review-v1.2.1.mdinterpretation-guide.mdscripts/probe_api.pytests/conftest.pytest_redaction.py詳細
エンドポイントのプローブ
ベース URL をプローブして、API の概要(種類、認証、エンドポイント、レート制限、CORS、サーバーのフィンガープリント)を調べます。
使用する場面
- ユーザーからベース URL を渡され、「どのような API が利用できますか?」や「どんなエンドポイントがありますか?」と尋ねられた場合
- 統合を構築する前に、ドキュメントのない API やドキュメントが一部しかない API の仕様を把握する必要がある場合
- ユーザーから「この API の認証方法は?」や「このエンドポイントにはどの認証が必要ですか?」と尋ねられた場合
- サードパーティーサービスを評価し、その API の概要を把握する必要がある場合
- ユーザーから API エンドポイントの「検出」、「プローブ」、「調査」、「偵察」を依頼された場合
- ユーザーが設定前に MCP サーバーが提供するツールを知りたい場合
- ユーザーから「この MCP サーバーでは何ができますか?」や「MCP サーバー X にはどんなツールがありますか?」と尋ねられた場合
次の用途には使用しないでください:
- HTML ページの内容のスクレイピング(
website-scrapingを使用してください) - 既知の機能の QA テスト(QA/テスト用のスキルを使用してください)
- MCP サーバーの設定(MCP 設定用のスキルを使用してください)。このスキルは MCP サーバーの概要を検出するものであり、設定は行いません
- API の継続的な監視(このツールは一度限りの検出用です)
ワークフロー
1. プローブスクリプトを実行する
python scripts/probe_api.py <base_url> [options]
オプション:
| フラグ | 説明 | デフォルト |
|---|---|---|
--auth TOKEN | 認証トークン/認証情報 | なし |
--auth-type | bearer、basic、または apikey | bearer |
--header "Key: Value" | カスタムヘッダー(複数回指定可能) | なし |
--timeout N | リクエストのタイムアウト(秒) | 10 |
--json | 整形済みレポートではなく、生の JSON を出力します | 無効 |
--no-guess | REST リソースの推測をスキップします | 無効 |
--api-version v1 | リソースのプローブに使う API バージョンのプレフィックス | なし |
--mcp | HTTP(StreamableHTTP)経由で MCP サーバーとしてプローブします | 無効 |
--mcp-stdio | stdio 経由で MCP サーバーとしてプローブします(サブプロセスを起動) | 無効 |
--mcp-env "KEY=value" | stdio MCP サーバー用の環境変数(複数回指定可能) | なし |
--allow-private | プライベート/内部 IP アドレスへのプローブを許可します | 無効 |
例:
# Basic probe — no auth
python scripts/probe_api.py https://api.example.com
# With Bearer token
python scripts/probe_api.py https://api.example.com --auth "tok_abc123"
# With API key (sends X-API-Key header)
python scripts/probe_api.py https://api.example.com --auth "key_xyz" --auth-type apikey
# Skip resource guessing (faster, less noisy)
python scripts/probe_api.py https://api.example.com --no-guess
# JSON output for programmatic use
python scripts/probe_api.py https://api.example.com --json
2. レポートを解釈する
プローブでは、次の 7 つのフェーズを順番に実行します。
- サーバーのフィンガープリント —
ServerおよびX-Powered-Byヘッダーから、フレームワーク(Express、FastAPI、Django、Rails、Spring など)を特定します - 既知のパス —
/openapi.json、/swagger.json、/docs、/graphql、/.well-known/、/health、/versionなど、約 40 の検出用パスを確認します - GraphQL イントロスペクション —
/graphql、/api/graphql、/queryにイントロスペクションクエリを POST し、成功した場合は型を抽出します - OPTIONS/CORS —
/、/api、/api/v1に OPTIONS リクエストを送信し、許可されたメソッドと CORS ポリシーを調べます - 認証の検出 — 認証情報なしで認証が必要と思われるエンドポイントにアクセスし、401/403 応答と
WWW-Authenticateヘッダーを調べます - レート制限 —
X-RateLimit-*、RateLimit-*、Retry-Afterヘッダーを確認します - REST リソースの推測 — 約 50 の一般的なリソースパス(
/api/users、/api/ordersなど)をプローブし、404 以外の応答を報告します
3. 調査結果を活用する
- OpenAPI が見つかった場合 → 仕様を解析して、エンドポイントの全一覧、リクエスト/レスポンスのスキーマ、認証方式を確認します。プローブでは仕様からエンドポイントをすでに抽出しています。
- GraphQL イントロスペクションが成功した場合 → 型システム全体を取得できています。検出した型を使ってクエリを作成します。
- REST リソースのみが見つかった場合 → API にはドキュメントがありません。検出したリソースパスを出発点として、GET/POST/PUT/DELETE で個々のエンドポイントをプローブします。
- 認証が検出された場合 → 以降のすべてのリクエストで、特定された方式を使用します。
- 何も見つからない場合 → API はログインの背後にあるか、標準外のパスを使用しているか、その URL には存在しない可能性があります。認証情報を使って試すか、ベース URL が正しいか確認してください。
MCP サーバーのプローブ
このプローブでは、MCP(Model Context Protocol)サーバーの概要(ツール、リソース、プロンプト、および完全な入力スキーマ)の検出にも対応しています。これにより、Hermes で設定する前に MCP サーバーを評価できます。
HTTP 経由の MCP(StreamableHTTP トランスポート)
# Probe a remote MCP server
python scripts/probe_api.py "https://mcp.example.com/mcp" --mcp
# With auth headers
python scripts/probe_api.py "https://mcp.example.com/mcp" --mcp --auth "tok_abc123"
# With custom headers
python scripts/probe_api.py "https://mcp.example.com/mcp" --mcp --header "X-API-Key: mykey"
stdio 経由の MCP(ローカルサブプロセス)
# Probe a local MCP server (npx-based)
python scripts/probe_api.py "npx -y @modelcontextprotocol/server-time" --mcp-stdio
# Probe a Python-based MCP server
python scripts/probe_api.py "python3 /path/to/mcp_server.py" --mcp-stdio
# With environment variables
python scripts/probe_api.py "npx -y @modelcontextprotocol/server-github" --mcp-stdio \
--mcp-env "GITHUB_PERSONAL_ACCESS_TOKEN=ghp_xxx"
MCP プローブで検出できる内容
プローブは、MCP のハンドシェイクシーケンス全体を実行します。
- 初期化 — プロトコルバージョン、クライアント情報、機能を指定して JSON-RPC の
initializeを実行します。サーバー名、バージョン、プロトコルバージョン、サーバーの機能を報告します。 - ツール —
tools/list→ すべてのツール名、説明、完全な入力スキーマ(パラメーター名、型、必須/任意、デフォルト値、列挙値) - リソース —
resources/list→ すべてのリソース URI、名前、説明、MIME タイプ - プロンプト —
prompts/list→ すべてのプロンプトテンプレート名、説明、引数
MCP と MCP 設定スキルの比較
| 項目 | endpoint-probe --mcp | MCP 設定スキル |
|---|---|---|
| 目的 | サーバーが提供する機能を検出する | サーバーを設定して使用する |
| タイミング | サーバーを使うかどうかを決める前 | サーバーを使うと決めた後 |
| 出力 | ツールスキーマ、リソース、プロンプト | エージェントのツールセットに登録されたツール |
| 再起動が必要 | いいえ | はい(登録するにはエージェントの再起動が必要) |
| トランスポート | HTTP と stdio | HTTP と stdio |
ワークフロー: endpoint-probe --mcp でサーバーを評価する → 役に立つかどうかを判断する → MCP 設定スキルを使って登録する → エージェントを再起動する。
よくある落とし穴
-
ベース URL が誤っている、または具体的すぎる。
https://api.example.comは正しいですが、https://api.example.com/v1/users/123は具体的すぎます。プローブがパスを検出するにはルートが必要です。末尾のパスを取り除いてください。OpenAI 互換 API: ベース URL が
https://provider.ai/v1やhttps://provider.ai/zen/go/v1のような推論エンドポイントの場合、検出パス(/openapi.json、/docsなど)は推論プレフィックスではなくドメインルートから提供されるため、プローブでは何も見つかりません。OpenAPI 仕様と API 全体を見つけるには、必ずドメインルート(https://provider.ai)をプローブしてください。推論エンドポイント(/v1/chat/completions、/v1/models)は通常、より大きなプラットフォーム API の一部にすぎません。 -
GraphQL のイントロスペクションが無効になっている。 多くの本番環境の GraphQL API では、セキュリティ上の理由からイントロスペクションが無効になっています。プローブにステータス 200/400/403 と「introspection disabled」が表示される場合、GraphQL が存在するもののスキーマが非公開であることを確認できます。確認するには、
{"query": "{ __typename }"}のような簡単なクエリを送信してみてください。 -
認証が必要な API が 401 ではなく 404 を返す。 一部の API は、エンドポイントの存在を隠すため、認証されていないリクエストに 404 を返します。すべてが 404 の場合は、
--authの認証情報を指定してみてください。 -
プローブ中のレート制限。 スクリプトは約 80~100 件のリクエストを同時に行います(スレッド数 8)。ほとんどの API はこれに対応できますが、429 が返る場合は
--timeoutを増やすか、--no-guessを使ってリクエスト数を減らしてください。スクリプトはレート制限の上限到達(X-RateLimit-Remaining: 0による)を自動検出し、誤検知を防ぐためリソース推測をスキップします。レポートでrate_limited_skipped_guessing: trueを確認してください。 -
一律の 403 は認証が必要という意味ではありません。 すべての検出パスが同じエラーボディで 403 を返す場合、認証でブロックされているのではなく、レート制限されています。403 を認証要件と解釈する前に、レート制限ヘッダー(
X-RateLimit-Remaining)を確認してください。実際に認証が必要な API は 401(WWW-Authenticateを伴う)を返すか、パスによって 200/401/403 が混在します。一律に 403 を返すことはありません。 -
/graphqlの 403 はエンドポイントが存在することを意味します。/graphqlの 403 は、エンドポイントが存在するもののイントロスペクションがブロックされていることを示します。GraphQL が存在しないという意味ではありません。404 はエンドポイントが存在しないことを意味します。この 2 つを混同しないでください。 -
CORS ヘッダーが OPTIONS にしかない。 一部の API は GET ではなく、OPTIONS のプリフライト時にのみ CORS ヘッダーを送信します。このため、プローブでは OPTIONS を個別に確認します。
-
/health、/status での誤検知。 API 自体がダウンしていても、ロードバランサーや CDN がこれらのパスに 200 を返すことがあります。「何かが待ち受けている」と判断し、「API が正常」とは判断しないでください。
-
サーバーのフィンガープリントは信頼できない。
X-Powered-Byはプロキシによって削除されることがよくあります。フレームワークに関するヒントはあくまで参考情報です。確定的なものとして扱わないでください。 -
自己署名証明書。 このスクリプトは urllib を使用しており、デフォルトで証明書を検証します。
PYTHONHTTPSVERIFY=0は urllib に影響しません(requests/httpxのみに影響します)。現在、自己署名証明書を使用する接続先はサポートされていません。内部ホストには--allow-privateを使用できますが、自己署名 TLS には、将来的にカスタムのssl.SSLContextを使う--insecureフラグが必要です。 -
並行処理は不可欠です。 このプローブスクリプトは、well-known パスとリソースの推測の両方で
concurrent.futures.ThreadPoolExecutor(max_workers=8)を使用します。約90個のパスを順番にプローブすると、応答の遅い API ではタイムアウトします(120秒超)。スクリプトを変更する場合は、スレッドプールを維持してください。逐次リクエストに戻さないでください。 -
SPA のキャッチオールによる誤検知。 Next.js、Nuxt などの SPA フレームワークは、
/api/users、/health、/openapi.jsonなどを含む すべて のパスに対して、同じ HTML ページ(200 +text/html)を返します。その結果、SPA のシェルにすぎない偽の「エンドポイント」がレポートに大量に含まれます。このスクリプトは、REST リソースの推測時にこれを自動検出し(一律に 200 + text/html + 類似した本文の長さの場合は破棄)、SOAP の検出も保護します(WSDL パスが text/html を返す場合は SOAP と判定しません)。ただし、discovery-paths フェーズにはhtml-docsのエントリーが多数表示されることがあります。これらは実際の API ドキュメントではなく、SPA のルートです。サーバーのフィンガープリントに Next.js/Nuxt が示され、ほとんどの discovery paths が 200 text/html を返す場合は、OpenAPI 仕様(見つかった場合)以外はすべて SPA のノイズとして扱ってください。 -
MCP stdio サーバーがハングします。 一部の MCP サーバーは、stdin を閉じても正常に終了しません。プローブは
terminate()を送信し、その後5秒待ってからkill()を実行します。サーバーが SIGTERM を無視すると、プローブにさらに5秒かかる場合があります。これは想定どおりです。プローブは必ずクリーンアップを行います。 -
レポートでは認証情報の値を伏せますが、認証プロトコルは伏せません。 認証の検出では、スキーム(
Bearer、Basic、WWW-Authenticate、「API key required」)や Cookie の名前は引き続き表示されます。エコーバックされたAuthorization/X-API-Keyの値、Set-Cookieの値、エラー本文に含まれるトークン形式の文字列は***に置き換えられるため、レポートやログを共有できます。ヘッダーにシークレットが「含まれていない」ように見える場合は、***がないか確認してください。これはシークレットが存在し、削除されたことを意味します。 -
MCP プロトコルのバージョン不一致。 プローブはプロトコルバージョン
2025-06-18を送信します。古い MCP サーバーは2024-11-05を使用している場合があります。サーバーはバージョンをネゴシエーションし、応答でサポートしているバージョンを返します。プローブは、概要にネゴシエーション後のバージョンを報告します。initialize がプロトコルエラーで失敗する場合、サーバーは古いバージョンを必要としている可能性があります。 -
MCP HTTP エンドポイント URL。 HTTP 経由の MCP では、パスベースのルーティングではなく、単一のエンドポイント URL(例:
https://mcp.example.com/mcp)を使用します。すべての JSON-RPC リクエストは、同じ URL に POST で送信されます。/tools/listなどを追加しないでください。--mcpフラグが正しく処理します。 -
MCP のリソース/プロンプトがサポートされていない場合があります。 すべての MCP サーバーがリソースやプロンプトを実装しているわけではありません。プローブは
method not foundエラーを適切に処理し、サポートされていないプリミティブには「None」と報告します。これはエラーではありません。サーバーがツールのみを実装していることを意味します。 -
MCP StreamableHTTP には Accept ヘッダーが必要です。 最新の MCP サーバー(プロトコル 2025-06-18)は StreamableHTTP トランスポートを使用しており、リクエストヘッダーに
Accept: application/json, text/event-streamが必要です。これがない場合、サーバーは 406 Not Acceptable を返します。プローブはこのヘッダーを自動的に送信します。 -
MCP SSE の応答形式。 StreamableHTTP サーバーは、プレーンな JSON ではなく、
text/event-stream(SSE)形式(data: {"jsonrpc":"2.0","result":{...}})で応答する場合があります。プローブは SSE のdata:行を自動検出し、そこから JSON を抽出します。MCP サーバーに対して「Non-JSON response」エラーが表示される場合は、SSE パーサーの更新が必要な可能性があります。 -
プロセスの argv による認証情報の露出。
--auth、--mcp-env、--headerで渡したトークンは、ps、シェルの履歴、エージェントのログに表示されます。Basic 認証の場合、--authにはパスワードだけでなくuser:passwordを指定する必要があります。可能な場合は、環境変数または.envファイルから認証情報を読み込むことをおすすめします。SKILL.md の例ではトークンを伏せています。例に実際のトークンを使用しないでください。 -
SSRF 保護。 プローブは、プライベート/内部 IP 範囲(RFC1918、ループバック、リンクローカル、CGNAT
100.64/10、ULAfc00::/7、::ffff:127.0.0.1のような IPv4 マップ IPv6)と、クラウドメタデータエンドポイント(169.254.169.254)をブロックします。正確に検出するためにipaddressモジュールを使用し、脆弱な文字列プレフィックス判定は行いません。リダイレクトベースの SSRF を防ぐため、リダイレクトは無効になっています。上書きするには--allow-privateを使用してください(例:ローカル開発 API のプローブでlocalhostを使う場合)。プローブで接続エラーしか返されず、ターゲットが内部の場合は、JSON レポートのssrf_warningフィールドを確認してください。 -
--mcp-stdio用コマンド許可リスト。 許可されるのは既知のパッケージランナー(npx、uvx、python3、python、node、bunx)のみです。任意のコマンドや絶対パスは許可されません。これにより、プロンプトインジェクションされた「MCP サーバー」文字列が任意のコマンドを実行するのを防ぎます。 -
本文サイズは 5 MiB に制限されています。 メモリ DoS を防ぐため、レスポンス本文は 5 MiB に制限されています。切り詰められたレスポンスの本文には
[truncated at 5 MiB]が含まれます。OpenAPI 仕様や GraphQL スキーマがこのサイズを超える場合、内容は不完全になります。 -
MCP セッション ID のサポート。 プローブは初期化レスポンスから
Mcp-Session-Idを取得し、その後のすべてのリクエストで再送します。これは、セッションを使用する StreamableHTTP サーバーで必要です。ステートレスサーバー(Composio、AlphaVantage)はこのヘッダーを無視します。 -
MCP stdio は環境変数をサニタイズして引き継ぎます。 サブプロセスには、サニタイズした
os.environのコピーを引き継ぎます。安全な変数(PATH、HOME、USER、LANG、LC_*、TERM、SHELL、XDG_*)のみを保持し、シークレットを含む文字列(TOKEN、SECRET、PASSWORD、API_KEY、CREDENTIAL、PRIVATE_KEY、ACCESS_KEY、CLIENT_SECRET)を含む変数はすべて除外します。シークレットは--mcp-envで明示的に渡してください。npx/nodeが引き継がれるPATH上にあれば macOS でも動作します。必要に応じて--mcp-envでPATHを設定してください。 -
--mcpと--mcp-stdioは同時に指定できません。 CLI は両方のフラグが指定されると拒否します。同じサーバーで両方のトランスポートを試す必要がある場合は、別々のコマンドを実行してください。
既知の制限事項(v1.2.3 の修正後も残るもの)
- OpenAPI YAML 仕様は解析されません。
/openapi.yamlはプローブされますが、解析されるのは JSON のみです。YAML 仕様は汎用的な 200 の検出結果として表示されます。回避策:JSON に変換するか、YAML を読み取るツールを使用してください。 - gRPC-Web の検出はパスのみです。 プローブは GET で gRPC パスを確認します。コンテンツタイプや Connect プロトコルのチェックは行いません。実際の gRPC-Web 検出ではなく、パスのヒューリスティックのみが行われます。
- SSE パーサーが処理するのは最初のデータ行のみです。 複数行の
data:フレームや、1 つの SSE ストリーム内の複数の JSON-RPC メッセージは正しく解析されない場合があります。ほとんどの MCP サーバーは SSE イベントごとに 1 つのメッセージを送信します。そうでない場合は、パーサーの更新が必要になる可能性があります。 - stdio のプラットフォームサポート。
npx/nodeがPATH上にあれば macOS で動作します(環境変数は現在のプロセスから引き継がれます)。Windows での stdio MCP はテストされていません。 - DNS リバインディングによる TOCTOU。 ホスト名は検証時に 1 回解決されますが、urllib は接続時に再度解決します。検査時にパブリックな DNS 応答が返され、接続時にプライベートな応答が返されると、SSRF を回避できる可能性があります。悪意のある DNS 環境では IP の固定が必要ですが、現時点では対象範囲外です。
- 許可リストにあるランナーでも、リモートパッケージを取得できます。
npx -y pkgは npm からコードをダウンロードして実行します。許可リストによって任意のコマンドは防止できますが、パッケージ名を介したサプライチェーン攻撃は防止できません。 - インラインコード用フラグはブロックされます。 プロンプトインジェクションされたコマンド文字列によるインライン RCE を防ぐため、すべてのランナーで
-c、-e、-p、--call、--eval、--exec、--printは拒否されます。
検証チェックリスト
- ベース URL が API のルートである(
/v1/users/123のような末尾のパスがない) - API が認証を必要とする場合、認証情報が指定されている
- レポートに 404 以外の検出パスが少なくとも 1 つ表示されている
- OpenAPI が見つかった場合、エンドポイントの一覧が空ではない
- GraphQL が見つかった場合、イントロスペクションの結果が成功か失敗か明確に示されている
- 認証方式が特定されている(または「none/open」と確認されている)
- レート制限ヘッダーが確認されている(または存在しないと確認されている)
- プローブの実行中に 429 エラーが発生していない
- REST RESOURCES セクションが空なのに、検出で 200 の
text/htmlパスが多数見つかった場合、サーバーのフィンガープリントで Next.js/Nuxt を確認する — SPA のキャッチオールが誤検出を除外した可能性が高い - MCP モードの場合、initialize ハンドシェイクが成功している(status = "connected")
- MCP モードの場合、ツール数が 0 より多い(または、tools_error に理由が記載されている)
- MCP stdio の場合、サブプロセスがクリーンアップされている(孤立したプロセスがない)
参考資料
references/interpretation-guide.md— 実際の API(GitHub、Petstore、OpenRouter、OpenCode、Composio MCP、AlphaVantage MCP、library-rag MCP)を使ったテストから得られた、レポートの解釈パターン。ステータスコードのパターン、SPA キャッチオールの検出、OpenAI 互換の推論におけるプレフィックスの問題、OpenAPI 仕様の注意点、CORS の注意事項、MCP プロトコルのネゴシエーション、Composio のメタツールパターン、パフォーマンスのベンチマークを説明しています。プローブのレポートが曖昧な場合や、予期しないステータスコードの解釈が必要な場合にお読みください。references/code-review-history.md— 6 ラウンド(R1-R6)にわたるレビュー履歴の全容。収束テーブル、主なパターン(拒否リストのリグレッション、モデル間の多様性、修正を申告したものの適用されていないケース)、Codex サンドボックスに関する注意事項を含みます。スクリプトを変更する前、またはセキュリティ上の問題をデバッグする際にお読みください。