mcpField
E
endpoint-probe

endpoint-probe

github.com/moonlight-lupin開発113126 回インストール1 日前に更新
リポジトリ

endpoint-probe について

endpoint-probe は、API の連携や評価に先立ち、公開されている機能を調べるコマンドラインスキルです。HTTP または stdio で MCP サーバーも調査し、ツール、リソース、プロンプトと入力スキーマを一覧表示します。

主な機能

  1. 01API パスと OpenAPI 仕様の検出
  2. 02認証、CORS、レート制限の確認
  3. 03HTTP または stdio による MCP の調査
  4. 04MCP のツール、リソース、プロンプトの一覧
  5. 05MCP 入力スキーマの表示

活用シーン

  1. 01連携前に未文書化 API を調査
  2. 02API の認証要件を確認
  3. 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.md
code-review-v1.2.1.md
interpretation-guide.md
scripts/
probe_api.py
tests/
conftest.py
test_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-typebearer、basic、または apikeybearer
--header "Key: Value"カスタムヘッダー(複数回指定可能)なし
--timeout Nリクエストのタイムアウト(秒)10
--json整形済みレポートではなく、生の JSON を出力します無効
--no-guessREST リソースの推測をスキップします無効
--api-version v1リソースのプローブに使う API バージョンのプレフィックスなし
--mcpHTTP(StreamableHTTP)経由で MCP サーバーとしてプローブします無効
--mcp-stdiostdio 経由で 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 つのフェーズを順番に実行します。

  1. サーバーのフィンガープリント — Server および X-Powered-By ヘッダーから、フレームワーク(Express、FastAPI、Django、Rails、Spring など)を特定します
  2. 既知のパス — /openapi.json、/swagger.json、/docs、/graphql、/.well-known/、/health、/version など、約 40 の検出用パスを確認します
  3. GraphQL イントロスペクション — /graphql、/api/graphql、/query にイントロスペクションクエリを POST し、成功した場合は型を抽出します
  4. OPTIONS/CORS — /、/api、/api/v1 に OPTIONS リクエストを送信し、許可されたメソッドと CORS ポリシーを調べます
  5. 認証の検出 — 認証情報なしで認証が必要と思われるエンドポイントにアクセスし、401/403 応答と WWW-Authenticate ヘッダーを調べます
  6. レート制限 — X-RateLimit-*、RateLimit-*、Retry-After ヘッダーを確認します
  7. 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 のハンドシェイクシーケンス全体を実行します。

  1. 初期化 — プロトコルバージョン、クライアント情報、機能を指定して JSON-RPC の initialize を実行します。サーバー名、バージョン、プロトコルバージョン、サーバーの機能を報告します。
  2. ツール — tools/list → すべてのツール名、説明、完全な入力スキーマ(パラメーター名、型、必須/任意、デフォルト値、列挙値)
  3. リソース — resources/list → すべてのリソース URI、名前、説明、MIME タイプ
  4. プロンプト — prompts/list → すべてのプロンプトテンプレート名、説明、引数
MCP と MCP 設定スキルの比較
項目endpoint-probe --mcpMCP 設定スキル
目的サーバーが提供する機能を検出するサーバーを設定して使用する
タイミングサーバーを使うかどうかを決める前サーバーを使うと決めた後
出力ツールスキーマ、リソース、プロンプトエージェントのツールセットに登録されたツール
再起動が必要いいえはい(登録するにはエージェントの再起動が必要)
トランスポートHTTP と stdioHTTP と stdio

ワークフロー: endpoint-probe --mcp でサーバーを評価する → 役に立つかどうかを判断する → MCP 設定スキルを使って登録する → エージェントを再起動する。

よくある落とし穴

  1. ベース 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 の一部にすぎません。

  2. GraphQL のイントロスペクションが無効になっている。 多くの本番環境の GraphQL API では、セキュリティ上の理由からイントロスペクションが無効になっています。プローブにステータス 200/400/403 と「introspection disabled」が表示される場合、GraphQL が存在するもののスキーマが非公開であることを確認できます。確認するには、{"query": "{ __typename }"} のような簡単なクエリを送信してみてください。

  3. 認証が必要な API が 401 ではなく 404 を返す。 一部の API は、エンドポイントの存在を隠すため、認証されていないリクエストに 404 を返します。すべてが 404 の場合は、--auth の認証情報を指定してみてください。

  4. プローブ中のレート制限。 スクリプトは約 80~100 件のリクエストを同時に行います(スレッド数 8)。ほとんどの API はこれに対応できますが、429 が返る場合は --timeout を増やすか、--no-guess を使ってリクエスト数を減らしてください。スクリプトはレート制限の上限到達(X-RateLimit-Remaining: 0 による)を自動検出し、誤検知を防ぐためリソース推測をスキップします。レポートで rate_limited_skipped_guessing: true を確認してください。

  5. 一律の 403 は認証が必要という意味ではありません。 すべての検出パスが同じエラーボディで 403 を返す場合、認証でブロックされているのではなく、レート制限されています。403 を認証要件と解釈する前に、レート制限ヘッダー(X-RateLimit-Remaining)を確認してください。実際に認証が必要な API は 401(WWW-Authenticate を伴う)を返すか、パスによって 200/401/403 が混在します。一律に 403 を返すことはありません。

  6. /graphql の 403 はエンドポイントが存在することを意味します。 /graphql の 403 は、エンドポイントが存在するもののイントロスペクションがブロックされていることを示します。GraphQL が存在しないという意味ではありません。404 はエンドポイントが存在しないことを意味します。この 2 つを混同しないでください。

  7. CORS ヘッダーが OPTIONS にしかない。 一部の API は GET ではなく、OPTIONS のプリフライト時にのみ CORS ヘッダーを送信します。このため、プローブでは OPTIONS を個別に確認します。

  8. /health、/status での誤検知。 API 自体がダウンしていても、ロードバランサーや CDN がこれらのパスに 200 を返すことがあります。「何かが待ち受けている」と判断し、「API が正常」とは判断しないでください。

  9. サーバーのフィンガープリントは信頼できない。 X-Powered-By はプロキシによって削除されることがよくあります。フレームワークに関するヒントはあくまで参考情報です。確定的なものとして扱わないでください。

  10. 自己署名証明書。 このスクリプトは urllib を使用しており、デフォルトで証明書を検証します。PYTHONHTTPSVERIFY=0 は urllib に影響しません(requests/httpx のみに影響します)。現在、自己署名証明書を使用する接続先はサポートされていません。内部ホストには --allow-private を使用できますが、自己署名 TLS には、将来的にカスタムの ssl.SSLContext を使う --insecure フラグが必要です。

  11. 並行処理は不可欠です。 このプローブスクリプトは、well-known パスとリソースの推測の両方で concurrent.futures.ThreadPoolExecutor(max_workers=8) を使用します。約90個のパスを順番にプローブすると、応答の遅い API ではタイムアウトします(120秒超)。スクリプトを変更する場合は、スレッドプールを維持してください。逐次リクエストに戻さないでください。

  12. 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 のノイズとして扱ってください。

  13. MCP stdio サーバーがハングします。 一部の MCP サーバーは、stdin を閉じても正常に終了しません。プローブは terminate() を送信し、その後5秒待ってから kill() を実行します。サーバーが SIGTERM を無視すると、プローブにさらに5秒かかる場合があります。これは想定どおりです。プローブは必ずクリーンアップを行います。

  14. レポートでは認証情報の値を伏せますが、認証プロトコルは伏せません。 認証の検出では、スキーム(Bearer、Basic、WWW-Authenticate、「API key required」)や Cookie の名前は引き続き表示されます。エコーバックされた Authorization/X-API-Key の値、Set-Cookie の値、エラー本文に含まれるトークン形式の文字列は *** に置き換えられるため、レポートやログを共有できます。ヘッダーにシークレットが「含まれていない」ように見える場合は、*** がないか確認してください。これはシークレットが存在し、削除されたことを意味します。

  15. MCP プロトコルのバージョン不一致。 プローブはプロトコルバージョン 2025-06-18 を送信します。古い MCP サーバーは 2024-11-05 を使用している場合があります。サーバーはバージョンをネゴシエーションし、応答でサポートしているバージョンを返します。プローブは、概要にネゴシエーション後のバージョンを報告します。initialize がプロトコルエラーで失敗する場合、サーバーは古いバージョンを必要としている可能性があります。

  16. MCP HTTP エンドポイント URL。 HTTP 経由の MCP では、パスベースのルーティングではなく、単一のエンドポイント URL(例:https://mcp.example.com/mcp)を使用します。すべての JSON-RPC リクエストは、同じ URL に POST で送信されます。/tools/list などを追加しないでください。--mcp フラグが正しく処理します。

  17. MCP のリソース/プロンプトがサポートされていない場合があります。 すべての MCP サーバーがリソースやプロンプトを実装しているわけではありません。プローブは method not found エラーを適切に処理し、サポートされていないプリミティブには「None」と報告します。これはエラーではありません。サーバーがツールのみを実装していることを意味します。

  18. MCP StreamableHTTP には Accept ヘッダーが必要です。 最新の MCP サーバー(プロトコル 2025-06-18)は StreamableHTTP トランスポートを使用しており、リクエストヘッダーに Accept: application/json, text/event-stream が必要です。これがない場合、サーバーは 406 Not Acceptable を返します。プローブはこのヘッダーを自動的に送信します。

  19. MCP SSE の応答形式。 StreamableHTTP サーバーは、プレーンな JSON ではなく、text/event-stream(SSE)形式(data: {"jsonrpc":"2.0","result":{...}})で応答する場合があります。プローブは SSE の data: 行を自動検出し、そこから JSON を抽出します。MCP サーバーに対して「Non-JSON response」エラーが表示される場合は、SSE パーサーの更新が必要な可能性があります。

  20. プロセスの argv による認証情報の露出。 --auth、--mcp-env、--header で渡したトークンは、ps、シェルの履歴、エージェントのログに表示されます。Basic 認証の場合、--auth にはパスワードだけでなく user:password を指定する必要があります。可能な場合は、環境変数または .env ファイルから認証情報を読み込むことをおすすめします。SKILL.md の例ではトークンを伏せています。例に実際のトークンを使用しないでください。

  21. SSRF 保護。 プローブは、プライベート/内部 IP 範囲(RFC1918、ループバック、リンクローカル、CGNAT 100.64/10、ULA fc00::/7、::ffff:127.0.0.1 のような IPv4 マップ IPv6)と、クラウドメタデータエンドポイント(169.254.169.254)をブロックします。正確に検出するために ipaddress モジュールを使用し、脆弱な文字列プレフィックス判定は行いません。リダイレクトベースの SSRF を防ぐため、リダイレクトは無効になっています。上書きするには --allow-private を使用してください(例:ローカル開発 API のプローブで localhost を使う場合)。プローブで接続エラーしか返されず、ターゲットが内部の場合は、JSON レポートの ssrf_warning フィールドを確認してください。

  22. --mcp-stdio 用コマンド許可リスト。 許可されるのは既知のパッケージランナー(npx、uvx、python3、python、node、bunx)のみです。任意のコマンドや絶対パスは許可されません。これにより、プロンプトインジェクションされた「MCP サーバー」文字列が任意のコマンドを実行するのを防ぎます。

  23. 本文サイズは 5 MiB に制限されています。 メモリ DoS を防ぐため、レスポンス本文は 5 MiB に制限されています。切り詰められたレスポンスの本文には [truncated at 5 MiB] が含まれます。OpenAPI 仕様や GraphQL スキーマがこのサイズを超える場合、内容は不完全になります。

  24. MCP セッション ID のサポート。 プローブは初期化レスポンスから Mcp-Session-Id を取得し、その後のすべてのリクエストで再送します。これは、セッションを使用する StreamableHTTP サーバーで必要です。ステートレスサーバー(Composio、AlphaVantage)はこのヘッダーを無視します。

  25. 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 を設定してください。

  26. --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 サンドボックスに関する注意事項を含みます。スクリプトを変更する前、またはセキュリティ上の問題をデバッグする際にお読みください。

コメント