peering-mcp について
peering-mcpは、エージェントやネットワーク研究者向けの読み取り専用MCPサーバーです。PeeringDBとRDAPを使って、インターネットの相互接続やIP登録情報を検証済みの簡潔な形式で取得します。
主な機能
- 01ネットワーク情報とピアリングポリシーの検索
- 02交換拠点と施設の接続状況の一覧
- 03ネットワーク間で共通する交換拠点の検索
- 04交換拠点に接続するネットワークの検索
- 05IPとASの登録情報の確認
活用シーン
- 01ネットワーク間の相互接続候補の確認
- 02指定した交換拠点のピアの特定
- 03IPアドレス範囲の登録者の特定
MCP 対応
PeeringDBとRDAPを利用する5つの読み取り専用ツールをMCPクライアントに公開します。応答は検証・サニタイズ・キャッシュされ、レート制限とバイト上限が適用されます。
設定
ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。
uvx peering-mcpPEERINGDB_API_KEYシークレットA free PeeringDB API key. Recommended, not required: it raises the rate limit, and every tool works without one.PEERING_MCP_CACHE_TTLHow long a cached upstream response stays usable, in seconds.PEERING_MCP_CACHE_DIRWhere the on-disk cache lives. Defaults to $XDG_CACHE_HOME/peering-mcp.PEERING_MCP_NO_CACHESet to 1 to disable caching. Slower, and harder on the upstream APIs.PEERING_MCP_TIMEOUTPer-request timeout in seconds.PEERING_MCP_MAX_RETRIESAttempts before an upstream failure is reported.ローカルサーバーにはマシン上の実行環境(Node.js 18 以上など)が必要です。設定ファイルの場所はクライアントごとに異なります。
ツール
ローカルサーバーのツールはマシン上で起動して初めて取得できます。メンテナーはまだツール一覧を提供していません。
詳細
peering-mcp
AI エージェントがインターネットの実際の接続構成を調べられる MCP サーバーです — どのネットワーク同士が、どのインターネットエクスチェンジや施設で、どのようなピアリングポリシーのもと接続しているか、また特定のアドレス範囲が誰に登録されているかを確認できます。
2 つの公開情報源を利用する、読み取り専用の 5 つのツールを提供します。相互接続には PeeringDB、登録情報には RDAP 経由で地域インターネットレジストリを利用します。上流からの応答を検証して整形し、モデルに渡す前に自由記述テキストの構造を取り除き、PeeringDB が求める頻度にリクエストを制限します。また、実行間で回答をディスクにキャッシュします。すべての応答にはバイト数の上限が設けられています。
uvx peering-mcp でインストールできます。個人プロジェクトで、MIT ライセンスです。
これが作られた理由
インターネットは、お互いのトラフィックを運ぶことに合意した、およそ 8 万の独立したネットワークで成り立っています。どのネットワーク同士が、どこで、どのような条件で接続しているかは、PeeringDB と地域インターネットレジストリが安定した API を通じて公開しており、誰でも無料で利用できる、よく構造化された情報です。
その情報には、AI エージェントからアクセスできません。特定の通信事業者がどのインターネットエクスチェンジに参加しているかをコーディングアシスタントに尋ねても、記憶をもとに答えるだけです。流ちょうで自信に満ちていますが、間違っていることもよくあります。確認する手段がないため、確認しないのです。
このサーバーは、その確認手段を提供します。
できること
| ツール | 答えられる質問 |
|---|---|
lookup_network | このネットワークは何で、ピアリングポリシーはどのようなものですか? |
list_presence | どのインターネットエクスチェンジや施設に接続していますか? |
find_at_exchange | このエクスチェンジにはほかに誰がいて、ピアリングに応じてくれますか? |
find_common_presence | これらのネットワークはどこで相互接続できますか? |
lookup_registration | この IP 範囲または AS 番号は誰に登録されていますか? |
find_common_presence は、このプロジェクトのきっかけとなったツールです。2 つ以上のネットワークがどこで相互接続できるかを調べるには、それぞれを検索し、接続している場所をすべて一覧にして、手作業で結果を照合する必要があります。これには約 1 時間と、十数個のブラウザータブが必要です。必要なのは、ひとつの質問だけです。
このツールでは 2〜5 個の AS 番号を指定でき、ネットワーク数にかかわらず、4 回のリクエストで回答します。共有エクスチェンジは、最も狭いボトルネックが大きい順に返されます。つまり、各ネットワークがその場所で持つ容量のうち最小のものを基準に並べ替えます。ネットワーク間の接続は、その容量によって制限されるためです。
また、各ネットワークが単独で接続している場所の数も返すため、結果が空でも理由がわかります。ネットワークが実際に接続場所を共有していないのか、それとも片方に記録がまったくないのかでは、状況がまったく異なります。
find_at_exchange は逆の質問をします。DE-CIX Frankfurt にはすでに誰がいて、そのうちどのネットワークがどことでもピアリングするのか、という質問です。エクスチェンジ名または PeeringDB の ID を指定し、任意で特定のピアリングポリシーを表明しているネットワークだけに絞り込めます。結果は容量の大きい順に返されます。同じ名前に該当するエクスチェンジが複数ある場合(4 つの大陸に LINX という名前のエクスチェンジが 10 個あります)、どれを指すのか推測するのではなく、候補を選べるように返します。
lookup_registration は、ここで唯一 PeeringDB を参照しないツールです。割り当てを行ったレジストリ(RIPE NCC、ARIN、APNIC、LACNIC、AFRINIC)に問い合わせ、保有者、割り当て日、登録が実際に対象とする範囲、そして不正利用の報告先を回答します。問い合わせ先のレジストリ自体も検索します。サードパーティのリダイレクターを経由せず、IANA 独自のブートストラップファイルから解決するため、回答元を明示できます。
単一のアドレスを尋ねると、そのアドレスを含むブロックが返されます。たとえば、8.8.8.8 には 8.8.8.0 - 8.8.8.255 と回答し、登録者は Google LLC と示されます。240.0.0.0/8 のように、どのレジストリも管轄していない範囲については、マシンの外部にリクエストを送らずに回答します。
回答の例
すべてのツールは同じ形式で回答するため、モデルは 5 種類の形式ではなく、ひとつの形式を学習できます。AS3320 を指定して lookup_network を呼び出すと、次のように返されます。上流の 42 フィールドのレコードに対して、ワイヤー上のレスポンス全体は 854 バイトです。
{
"status": "ok",
"data": {
"network": {
"asn": 3320,
"name": "Deutsche Telekom",
"long_name": "Deutsche Telekom AG",
"website": "https://wholesale.telekom.com",
"network_type": "NSP",
"traffic_estimate": "50-100Tbps",
"scope": "Global",
"traffic_ratio": "Mostly Inbound",
"ipv4_prefixes": 150000,
"ipv6_prefixes": 40000,
"exchange_count": 7,
"facility_count": 53,
"policy": {
"general": "Restrictive",
"locations": "Required - International",
"ratio_required": true,
"contract_required": "Required",
"url": null
},
"irr_as_set": "AS3320:AS-DTAG AS3320:AS-DTAG-V6",
"looking_glass": "https://lg.telekom.com"
},
"candidates": []
},
"note": "PeeringDB records are maintained by the networks themselves. Treat a missing field as unrecorded, not as evidence it is untrue.",
"provenance": {
"source": "peeringdb",
"fetched_at": "2026-09-14T16:44:53.916085Z",
"record_updated": "2026-08-31T13:30:19Z",
"from_cache": false
}
}
最初に確認するのは status フィールドです。ok が意味するのは、回答が data に含まれているということだけです。名前に該当するネットワークが複数ある場合は、どれを指すのか推測するのではなく、候補とともに ambiguous が返されます。登録されていない AS 番号の場合は not_found が返され、ネットワークは登録されていなくてもトラフィックをルーティングできるという説明が添えられます。
作業を担うツールから、さらに3つ
実際の応答を、明記した箇所で短縮しています。ここにある内容はすべて実例です。それぞれ、2026-09-19 にツールが返したものです。
「Deutsche Telekom と Hurricane Electric は、どこで相互接続できるでしょうか?」 — [3320, 6939] を指定して find_common_presence を1回呼び出し、上流へのリクエストを4回実行しました。
{
"status": "ok",
"data": {
"networks": [
{ "asn": 3320, "name": "Deutsche Telekom", "exchanges": 7, "facilities": 53 },
{ "asn": 6939, "name": "Hurricane Electric", "exchanges": 335, "facilities": 342 }
],
"exchanges": {
"items": [
{
"name": "NL-ix",
"city": "Amsterdam, Rotterdam, Brussels, Luxembourg, Frankfurt,…",
"country": "NL",
"networks": [
{ "asn": 3320, "speed_mbps": 220000, "ports": 2, "route_server": false },
{ "asn": 6939, "speed_mbps": 400000, "ports": 1, "route_server": true }
]
},
{
"name": "DE-CIX Frankfurt",
"city": "Frankfurt",
"country": "DE",
"networks": [
{ "asn": 3320, "speed_mbps": 110000, "ports": 1, "route_server": false },
{ "asn": 6939, "speed_mbps": 800000, "ports": 1, "route_server": true }
]
}
],
"total": 6,
"truncated": false
}
}
}
共有している6つの交換拠点を、ボトルネックの幅が広い順に示しています。NL-ix が先頭なのは、どちらかのネットワークの容量が合計で大きいからではなく、2つのうち容量の小さいほうでも、そこで220 Gbpsを確保しているためです。その下にある各ネットワークの合計値があることで、空の応答も読み取りやすくなります。Deutsche Telekom は交換拠点を合計7つ記録しているため、「重複なし」という結果は、335か所ある Hurricane Electric の場合とは意味が異なります。
「DE-CIX Frankfurt には、すでにどのネットワークがあり、相互接続を受け入れるところはありますか?」 — policy: "Open" を指定して find_at_exchange を呼び出しました。
{
"status": "ok",
"data": {
"exchange": { "exchange_id": 31, "name": "DE-CIX Frankfurt", "city": "Frankfurt", "country": "DE", "networks_recorded": 1020 },
"networks": {
"items": [
{ "asn": 24940, "name": "Hetzner Online", "speed_mbps": 2800000, "ports": 3, "route_server": true, "policy": "Open" },
{ "asn": 20940, "name": "Akamai Technologies", "speed_mbps": 2100000, "ports": 4, "route_server": true, "policy": "Open" }
],
"total": 649,
"truncated": true
}
},
"note": "Participation is self-reported by each network in PeeringDB; a network missing here is unrecorded, not absent. Showing the 2 largest of the 649 networks (of 1020 here) stating policy Open; raise limit for more, at most 200."
}
そこにある1,020のネットワークのうち、649がオープンポリシーを表明しています。フィルターはページではなく交換拠点に適用されるため、これは交換拠点全体の数であり、「上位50件のうちオープンなもの」の数ではありません。
「8.8.8.8 の登録者は誰で、不正利用はどこに報告すればよいですか?」 — PeeringDB ではなくレジストリを参照する lookup_registration を呼び出しました。
{
"status": "ok",
"data": {
"target": "8.8.8.8",
"kind": "address",
"registry": "ARIN",
"handle": "NET-8-8-8-0-2",
"holder": "Google LLC",
"covers": "8.8.8.0 - 8.8.8.255",
"allocation_type": "DIRECT ALLOCATION",
"registered": "2023-12-28T17:24:33-05:00",
"abuse": { "name": "Abuse", "email": "[email protected]" }
},
"note": "Registry data: it says who an allocation was made to, which is not always who operates the resource today.",
"provenance": { "source": "rdap", "record_updated": "2023-12-28T17:24:56-05:00", "from_cache": true }
}
質問は1つのアドレスについてですが、応答ではそのアドレスが含まれるブロック全体を扱っています。それが covers の役割です。
動作の仕組み
エージェント自体がインターネットに接続することはありません。すべての処理はサーバーを経由します。レート制限、キャッシュ、検証、サニタイズを実際に適用できるのは、サーバーだけです。
リクエストは、次の2つの経路のいずれかを通ります。
この整形の工程は、見た目だけのものではありません。1つのネットワークの未加工の接続記録は130 KBを超えることがあり、それを返すとエージェントのコンテキストウィンドウが埋まり、実際のタスクの精度が目に見えて低下します。list_presence は、Hurricane Electric の336個の交換ポートを、6 KBに収まる交換拠点のページに変換します。容量の大きい順に並べ、省略した数も示します。ページは件数ではなく予算に合わせて切り詰められるため、上限は目安で、バイト数が保証値です。find_common_presence は、3つのネットワークから225 KBを読み取り、4 KB未満の応答を返します。
設計原則
これらは単なる理想ではなく、基盤となる原則であり、プルリクエストはこれらに照らしてレビューされます。
- 恒久的に読み取り専用です。 送信するのは常に
GETのみです。これは慣例ではなく、トランスポート層で強制されます。書き込み経路はなく、今後も設けません。 - 不明な場合はそう伝えます。 PeeringDB の情報は自己申告なので、レコードが見つからないことはよくあり、それは「事実ではない」ことの証拠にはなりません。サーバーは「このネットワークは存在しない」と「誰も情報を入力していない」を区別し、もっともらしい推測で情報の欠落を埋めることはありません。
- すべての回答に情報源とその新しさを付けます。 上流のレコードが最後に編集された時期も含みます。2019 年以降更新されていないレコードは、先月編集されたレコードより重みを低くすべきだからです。
- 意図的にレスポンスを小さくし、サイズ上限を強制します。 各ツールは上流の JSON をそのまま渡すのではなく、整形されたコンパクトな結果を返します。また、それぞれにバイト数の上限が設けられており、テストでは今日のデータだけでなく、各ツールの上限で想定される最悪のケースに対しても、その上限を守ることを検証します。リストは上限に収まるよう切り詰められ、省略した件数も示します。
- 上流のテキストは信頼できないものとして扱います。 PeeringDB の自由記述欄(ネットワーク自身が記入したもの)や、レジストリレコードの登録者名と連絡先は、LLM のコンテキストに入ります。これらは許可リストに基づいて扱い、長さを制限し、サーバーから出る前にサニタイズします。
- 上流に配慮します。 PeeringDB ではリクエストは 1 秒に 1 回までと定められています。サーバーはこの制限を守り、積極的にキャッシュし、すべてのリクエストで自身を識別します。
データソース
すべて公開情報で、無料で利用でき、スクレイピングは行いません。
| ソース | 用途 | 認証 | 費用 |
|---|---|---|---|
| PeeringDB API v2 | ネットワーク、エクスチェンジ、施設、接続状況、ピアリングポリシー | API キーの利用を推奨しますが、必須ではありません | 無料 |
| RDAP | IANA bootstrap files を介した、IP、プレフィックス、AS 番号の登録情報 | なし | 無料 |
RIPEstat による観測済みのルーティング情報と、CAIDA AS Rank によるトポロジー情報は、意図的に対象外としています。これらがインターネット上で何が起きているかに答えるのに対し、ここでは誰が誰と、どのような条件で接続しているかを扱います。
必要条件
- Python 3.12 以降
- uv
- 無料の PeeringDB API キー の利用を推奨しますが、必須ではありません。詳しくはこちらをご覧ください。
エージェントでの使用
事前のインストールは不要です。uvx がパッケージを取得して実行します。
Claude Code:
claude mcp add peering-mcp -- uvx peering-mcp
JSON MCP 設定を読み込む各種クライアント:
{
"mcpServers": {
"peering-mcp": {
"command": "uvx",
"args": ["peering-mcp"]
}
}
}
開発用、または変更を試すためにローカルのチェックアウトを実行するには、コマンドを uv run --directory /path/to/peering-mcp peering-mcp に置き換えてください。
次に、エージェントが通常間違えやすい質問をしてみてください。「Deutsche Telekom と Hurricane Electric は、どこで相互にピアリングできる可能性がありますか?」
PeeringDB API キー
推奨されていますが、必須ではありません。 すべてのツールはキーなしで動作し、制限される機能はなく、サーバーは設定なしで起動します。
キーを追加する理由は、PeeringDB が匿名ユーザーに対して認証済みユーザーより厳しい制限を設けており、PeeringDB 自身のスロットル応答にもその旨が記載されているためです。「制限を緩和するには認証してください。」 制限に最も達しやすいのは /netixlan です。これは最大のエンドポイントであり、プレゼンスに関するすべての質問に必要です。ネットワークの生のポートレコードは 130 KB を超えます。制限を超えた匿名ユーザーには、数十分単位の待ち時間を示すスロットル通知が返されます。サーバーはこれを正確に処理し、誤った回答や空の回答ではなく rate_limited を返しますが、待ち時間が終わるまでは回答できません。
キーは無料で、取得には約 1 分かかります:docs.peeringdb.com/howto/api_keys/。自分のキーを使用してください。キーによって PeeringDB への呼び出しが識別され、アカウントに紐付けられます。
サーバープロセスの環境変数 PEERINGDB_API_KEY として渡してください。MCP クライアント独自の設定に保存すると、シークレットを必要なプロセスだけに限定できます。
claude mcp add peering-mcp -e PEERINGDB_API_KEY=your-key-here -- \
uv run --directory /path/to/peering-mcp peering-mcp
{
"mcpServers": {
"peering-mcp": {
"command": "uv",
"args": ["run", "--directory", "/path/to/peering-mcp", "peering-mcp"],
"env": { "PEERINGDB_API_KEY": "your-key-here" }
}
}
}
サーバーは環境変数からのみキーを読み込みます。.env ファイルは読み込まないため、そこにキーを記載しても警告なしで無視されます。
開発
git clone https://github.com/LeonardMichalas/peering-mcp.git
cd peering-mcp
uv sync --all-groups
uv run pytest # tests
uv run ruff check . # lint
uv run ruff format . # format
uv run mypy src # types
環境は uv run が処理します。有効化する仮想環境はありません。
Git フックを一度インストールすると、コミットのたびにリンター、フォーマッター、型チェックが実行されます。
uv run pre-commit install
図
上記の 2 つの図は手描きではなく、生成されています。docs/diagrams/*.json がソースで、docs/images/ 内のアニメーション SVG が README に表示される図です。
docs/diagrams/animate.mjs は、レンダリング済みの図を SVG のペアに変換します。PATH 上に Chromium 系ブラウザーが必要です。
node docs/diagrams/animate.mjs <rendered.html> docs/images/<name>
SVG を画像として読み込むと、表示先のページのテーマを認識できないため、テーマごとに 1 つのファイルを出力します。また、アニメーションには SMIL を使用しているため、GitHub が単なる画像としてレンダリングしても動作します。
設定
すべてに実用的なデフォルト値があります。何も設定しなくてもサーバーは起動し、質問に回答します。
| 変数 | デフォルト値 | 用途 |
|---|---|---|
PEERINGDB_API_KEY | 未設定 | PeeringDB のレート制限を緩和します。推奨ですが必須ではありません |
PEERING_MCP_CACHE_TTL | 86400 | キャッシュの有効期間(秒) |
PEERING_MCP_CACHE_DIR | $XDG_CACHE_HOME/peering-mcp、未設定の場合は ~/.cache/peering-mcp | ディスク上のキャッシュの保存場所 |
PEERING_MCP_NO_CACHE | 未設定 | キャッシュを無効にするには 1 を設定します(テスト用) |
PEERING_MCP_TIMEOUT | 10 | リクエストごとのタイムアウト(秒) |
PEERING_MCP_MAX_RETRIES | 3 | 上流の障害を報告するまでの試行回数 |
テスト
4 つのレベルがあり、それぞれ他のレベルでは検証できない内容を確認します。
| ディレクトリ | 検証する内容 |
|---|---|
tests/unit/ | 純粋なロジック:整形、サニタイズ、ブートストラップの照合、レート制限、および上限が許す最悪のケースに対するすべての応答サイズ予算 |
tests/contract/ | 不正な形式、切り詰められた応答、悪意のある応答を含め、上流から実際に送られてくる内容をサーバーが処理できること |
tests/integration/ | SDK を通じて、スキーマ、エンベロープ、すべてのステータスを含め、MCP サーバーとして動作すること |
tests/eval/ | 説明だけをもとにモデルが適切なツールを選択すること |
評価はオプトイン方式で、テストスイートとは別に実行されます。実際のツールスキーマを使用して、実際のモデルに自然言語の質問を 20 件提示し、選択したツールを記録します。1 回の実行にかかる費用は約 0.50 ドルです。Claude Opus 5 の低エフォート設定では、20 問中 20 問のスコアを達成します。
export ANTHROPIC_API_KEY=...
uv run --group eval python tests/eval/run_eval.py
実際の API にアクセスするテストはありません。 トランスポート層で上流をモックするため、テストスイートはオフラインで実行でき、どこでも同じ結果になります。live マーカーは、オプトイン方式で PeeringDB にアクセスするテスト用に予約されており、CI では -m "not live" によって除外されます。
貢献
Issue とプルリクエストを歓迎します。PR を作成する前に、次の点をご確認ください。
uv run pytest、uv run ruff check .、uv run mypy srcがすべて成功すること。- 新しい動作には、適切なレベルのテストがあること。
- 変更が上記の設計原則に沿っていること。特に、大量の、または整形されていないレスポンスを返すツールや、上流の生のフリーテキストをモデルに渡す可能性のあるツールは、差し戻されます。
ライセンス
MIT。詳しくはLICENSEをご覧ください。
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。