关于 peering-mcp
peering-mcp 是面向 Agent 和网络研究者的只读 MCP 服务,可查询互联网互联关系与 IP 注册信息。它整合 PeeringDB 和 RDAP,并返回经过校验的精简结果。
主要功能
- 01查询网络信息和对等互联策略
- 02列出交换中心与设施的接入情况
- 03查找网络间的共同交换中心
- 04查询交换中心内的网络
- 05查询 IP 和 AS 注册信息
适用场景
- 01确认网络可在哪里互联
- 02查找指定交换中心的对等网络
- 03识别 IP 地址段的注册机构
MCP 相关
向 MCP 客户端提供五种只读工具,数据来自 PeeringDB 和 RDAP。响应经过校验、清理和缓存,并实施速率限制与字节预算控制。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 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 Agent 查询互联网实际连接方式的 MCP 服务——哪些网络彼此互连、在哪些互联网交换中心和设施互连、遵循什么对等互联政策,以及某个地址范围登记在谁名下。
通过两个公共数据源提供五种只读工具:PeeringDB 用于查询互连信息,以及通过 RDAP 查询区域互联网注册管理机构的登记信息。上游响应经过验证和整理,纯文本内容在到达模型前会被移除结构,请求速率限制遵循 PeeringDB 的要求,答案会在运行期间缓存在磁盘上。每个响应都受字节数上限约束。
使用 uvx peering-mcp 安装。这是一个采用 MIT 许可的个人项目。
为什么要开发它
互联网由大约八万个独立网络组成,它们约定相互传输流量。哪些网络彼此互连、在哪里互连,以及遵循什么条款,都是公开、免费的结构化信息,由 PeeringDB 和区域互联网注册管理机构通过稳定的 API 发布。
AI Agent 却无法获取这些信息。询问编码助手某个运营商接入了哪些互联网交换中心,它就会凭记忆作答:措辞流畅、语气肯定,却往往有误。它无法核实,因此也不会核实。
这个服务提供了核实信息的途径。
功能介绍
| 工具 | 解答的问题 |
|---|---|
lookup_network | 这是哪个网络?它的对等互联政策是什么? |
list_presence | 它们出现在哪些互联网交换中心和设施? |
find_at_exchange | 这个交换中心还有哪些网络?它们愿意对等互联吗? |
find_common_presence | 这些网络可以在哪里互联? |
lookup_registration | 这个 IP 地址范围或 AS 号码注册给了谁? |
find_common_presence 是促成本项目诞生的工具。要找出两个或多个网络可以在哪里互联,需要逐个查询每个网络,列出它们出现的所有地点,再手动求交集。这大约需要一小时,还得打开十几个浏览器标签页。它本该只需问一个问题。
它接收两个到五个 AS 号码,无论网络数量多少,只需四次请求就能给出答案。共享交换中心按最窄瓶颈容量从高到低排列——也就是按任一网络在该处的最小容量排序,因为网络之间的连接能力会受此限制。
它还会返回每个网络各自拥有的地点数量,让空结果有据可解:要么这些网络确实没有共同地点,要么其中一个网络根本没有记录,这是完全不同的情况。
find_at_exchange 则从另一个角度提问:哪些网络已经接入了 DE-CIX Frankfurt?其中哪些愿意与任何网络对等互联?它接收交换中心名称或其 PeeringDB ID,可选地仅保留声明了某一种对等互联政策的网络,并按容量从高到低返回结果。一个名称匹配多个交换中心时——有十个交换中心都叫 LINX,分布在四大洲——它会返回候选项供选择,绝不猜测用户指的是哪一个。
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,系统无需发出请求即可返回结果。
答案示例
每个工具都返回相同的封装结构,让模型只需学习一种格式,而不是五种。使用 lookup_network 查询 AS3320 时会返回以下内容——整个响应在网络上传输时为 854 字节,而上游记录包含 42 个字段:
{
"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,并附注说明网络即使未注册,也可以路由流量。
另外三个示例,展示工具如何发挥作用
真实响应,已按标记裁剪。这里没有示意内容:每条都是工具于 2026-09-19 返回的结果。
“Deutsche Telekom 和 Hurricane Electric 可以在哪里互相对等互联?”——调用一次 find_common_presence,传入 [3320, 6939],发出四次上游请求:
{
"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
}
}
}
六个共同交换中心,按最窄瓶颈从大到小排列:NL-ix 位居首位,因为两个网络中较窄的那个在此有 220 Gbps,而不是因为任何一方的总容量更大。下方按网络列出的总数让空结果也清晰易懂——Deutsche Telekom 总共记录了 7 个交换中心,因此“没有重叠”与 Hurricane Electric 的 335 个所代表的情况截然不同。
“哪些网络已经接入 DE-CIX Frankfurt?它们愿意与任何人对等互联吗?”——使用 find_at_exchange,并设置 policy: "Open":
{
"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 个声明了开放策略。筛选条件应用于交换中心,而非页面,因此这是该交换中心的数量——不是“前五十个网络中采用开放策略的数量”。
“8.8.8.8 注册在谁名下?我该向哪里举报滥用行为?”——使用 lookup_registration,它查询的是注册机构,而不是 PeeringDB:
{
"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 }
}
问题问的是一个地址,答案则涵盖了它所属的地址块,这正是 covers 的用途。
工作原理
Agent 本身不会访问互联网。所有请求都经由服务端处理;只有在服务端才能真正实施速率限制、缓存、验证和清理。
请求会沿两条路径之一处理:
整形这一步并非表面功夫。单个网络的原始接入记录可能超过 130 KB,直接返回会淹没 Agent 的上下文窗口,并且会明显降低它执行实际任务的能力。list_presence 将 Hurricane Electric 的 336 个交换中心端口整理成一个不超过 6 KB 的交换中心页面,并按容量从大到小排列,同时说明省略了多少条——页面按预算截断,而非按数量截断,因此限制只是上限,字节数才是保证值。find_common_presence 会读取三个网络共 225 KB 的数据,并在不到 4 KB 的结果中给出答案。
设计原则
这些原则是必须遵守的,而非仅供参考;每个拉取请求都会依据这些原则进行审核。
- 永久只读。 始终只发送
GET请求,并在传输层强制执行,而非依赖约定。没有写入路径,也不会有。 - 不知道时会明确说明。 PeeringDB 的数据由用户自行报告,因此缺少记录很常见,不能据此认定某事不属实。服务会区分“这个网络不存在”和“没人填写这项信息”,绝不会用看似合理的猜测填补空缺。
- 每个回答都附带来源和数据时效。 包括上游记录最后编辑的时间,因为一条自 2019 年以来未更新的记录,不应与上个月刚编辑的记录同等看待。
- 响应刻意保持精简,并且会强制执行大小限制。 每个工具都会返回经过整理的精简结果,而不是直接传递上游 JSON;每个工具都有字节预算,并通过测试确保即使在自身限制允许的最坏情况下也不超出预算,而不只是适用于当前数据。列表会截断到符合预算的大小,并说明省略了多少项。
- 不信任上游文本。 自由文本字段——包括 PeeringDB 中由网络自行填写的内容,以及注册记录中的持有人名称和联系方式——都会进入大模型的上下文。这些内容在离开服务前会经过允许列表筛选、长度限制和清理。
- 礼貌地访问上游。 PeeringDB 允许每秒发送一个请求;服务会遵守这一限制、大力使用缓存,并在每个请求中标识自身。
数据来源
均为公开、免费数据,不进行抓取。
| 来源 | 用途 | 认证 | 费用 |
|---|---|---|---|
| PeeringDB API v2 | 网络、交换中心、设施、连接情况、对等互联政策 | 建议使用 API 密钥,但非必需 | 免费 |
| RDAP | 通过 IANA 引导文件获取 IP、前缀和 AS 号码的注册数据 | 无 | 免费 |
RIPEstat 的路由观测数据和 CAIDA AS Rank 的拓扑数据有意不在范围内:它们回答的是互联网正在做什么,而这里回答的是谁与谁互联,以及互联条件是什么。
要求
- Python 3.12 或更高版本
- uv
- 建议使用免费的 PeeringDB API 密钥,但并非必需——请参阅下文
与 Agent 搭配使用
无需预先安装: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。
然后向它询问 Agent 通常会答错的问题:“Deutsche Telekom 和 Hurricane Electric 可以在哪里进行对等互联?”
一个 PeeringDB API 密钥
推荐,但非必需。 所有工具都可以在没有密钥的情况下运行,不会限制任何功能,而且服务无需任何配置即可启动。
添加密钥的原因是,PeeringDB 对匿名调用者的限制比对已认证调用者更严格,它自己的限流响应也说明了这一点:“认证后限制更少。” /netixlan 最容易触及限额,因为它既是数据量最大的端点,也是每个网络存在情况查询都需要用到的端点——一个网络的原始端口记录超过 130 KB。匿名调用者超出限额后会收到限流通知,并被要求等待数十分钟。服务会如实处理这种情况,返回 rate_limited,而不是错误或空答案,但必须等到限流解除后才能回答。
密钥免费,申请大约需要一分钟: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 钩子后,每次提交前都会运行 lint、格式检查和类型检查:
uv run pre-commit install
图表
上方的两个图表由程序生成,而非手工绘制。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 无法获知所在页面的主题;动画采用 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 | 报告上游故障前的尝试次数 |
测试
测试分为四个层级,每个层级都能验证其他层级无法验证的内容:
| 目录 | 验证内容 |
|---|---|
tests/unit/ | 纯逻辑:结构整理、清理、引导匹配、速率限制,以及在其上限允许的最坏情况下对每种响应大小预算的验证 |
tests/contract/ | 验证服务器能够处理上游实际发送的内容,包括格式错误、截断和恶意响应 |
tests/integration/ | 通过 SDK 验证其作为 MCP 服务的行为:架构、信封格式和每一种状态 |
tests/eval/ | 验证模型能否仅凭描述选出正确的工具 |
评估测试需主动选择运行,且与测试套件分开:它会使用真实工具架构,向真实模型提出二十个自然语言问题,记录模型选择调用的工具,每次运行费用约为 0.50 美元。在 Claude Opus 5 的低推理强度设置下,该测试得分为 20 题全对。
export ANTHROPIC_API_KEY=...
uv run --group eval python tests/eval/run_eval.py
没有测试会访问真实 API。 传输层会模拟上游,因此测试套件可以离线运行,并且在任何环境中结果一致。live 标记专用于会访问 PeeringDB 的可选测试;CI 会通过 -m "not live" 排除这些测试。
贡献
欢迎提交问题和拉取请求。提交 PR 前,请确认:
uv run pytest、uv run ruff check .和uv run mypy src均通过。- 新增行为已在适当层级编写测试。
- 改动符合上述设计原则。特别是,对于返回大量或未经过结构化处理的响应,或可能将上游原始自由文本传递给模型的工具,我们会要求退回修改。
许可证
MIT。请参阅 LICENSE。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。