关于 EchelonGraph CVE & Exposure
EchelonGraph MCP server 为安全团队和开发者提供 CVE、漏洞利用、修复版本及互联网暴露情况查询。它融合多个漏洞来源的数据,并为结果标注测量状态、覆盖范围和时效信息。
主要功能
- 01查询 CVE 记录及修复信息
- 02查看 EPSS 历史和厂商公告
- 03查询 KEV 漏洞暴露足迹
- 04检查产品版本、SBOM 和锁文件
- 05提供提示词、资源和模板
适用场景
- 01评估某个 CVE 的实际暴露范围
- 02核查产品版本是否受漏洞影响
- 03审查项目 SBOM 或锁文件
- 04整理最新 CISA KEV 漏洞
MCP 相关
该服务向 MCP 客户端提供 16 个只读工具、5 个提示词、2 个资源和 1 个资源模板。可通过本地 stdio 或无需密钥的 Streamable HTTP 端点连接。
配置
远程服务无需本地安装。选择你使用的客户端,复制配置或使用一键安装。
https://mcp.echelongraph.io/mcpclaude mcp add --transport http io-echelongraph-echelongraph https://mcp.echelongraph.io/mcp{"mcpServers":{"io-echelongraph-echelongraph":{"type":"http","url":"https://mcp.echelongraph.io/mcp"}}}在 Cursor 中打开{"servers":{"io-echelongraph-echelongraph":{"type":"http","url":"https://mcp.echelongraph.io/mcp"}}}在 VS Code 中打开{"mcpServers":{"io-echelongraph-echelongraph":{"type":"http","url":"https://mcp.echelongraph.io/mcp"}}}{"mcpServers":{"io-echelongraph-echelongraph":{"serverUrl":"https://mcp.echelongraph.io/mcp"}}}命令在终端中运行;JSON 粘贴到对应客户端的 MCP 配置后重启。需要授权的服务会在首次连接时提示登录。
工具
16| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| full | boolean | 否 | true:结构化结果中的 data 是完整答案,无论长度如何。未指定时,如果结构化结果的 JSON 超过 30,000 个字符,其 data 会被截取(DATA CUT):按照备注说明的顺序,最长列表中的条目先仅保留部分字段,随后列表仅保留部分条目;data_truncated 为 true,truncated 会列出每个被截取的列表及其总数、返回数量和条目是否经过精简。完整 data 适用于程序;像 Claude Code 这样会根据 MAX_MCP_OUTPUT_TOKENS 限制结构化结果大小的客户端,可能会拒绝超过上限的答案。 |
详细介绍
EchelonGraph MCP 服务
为 Claude、Cursor、VS Code、Cline 和任何 MCP 客户端提供 CVE 和互联网暴露数据,数据直接来自 EchelonGraph 的免费公共数据源。
它提供 EchelonGraph 的 CVE Pulse(将 NVD + MITRE-CNA NVD 发布前 + CISA-KEV + EPSS + GitHub GHSA 融合为一个评分),以及每个 CVE 的互联网暴露情况:EchelonGraph 的 KEV 暴露雷达记录中,有多少互联网可访问服务(不同的 ip:port)运行着可映射到该 CVE 的版本。暴露数量基于 Shodan 数据。Shodan 数据归 Shodan 所有,版权亦由其持有(© Shodan)。
这 16 个工具可查询单个 CVE(记录、漏洞利用代码和修复版本、其来源所述的修复方式、EPSS 历史记录、供应商公告、暴露情况),列出 CISA 最新添加的 KEV,检查产品或软件包版本是否受影响,检查 SBOM 或项目锁定文件,并读取 CWE 及其 CVE。每个结果都会说明测量方式(state、measured_at、method、coverage、freshness、notes),确保模型不会把服务中断或尚未评估的查询误认为一切正常。
它还提供五个提示词,即客户端可显示为斜杠命令的现成工作流(triage_cve、kev_weekly_brief、am_i_affected、sbom_review、workload_triage;参见“提示词”),两个资源(echelongraph://methodology 和 echelongraph://sources),以及一个资源模板(cve://{cve_id};参见“资源”)。
免费且无需密钥:无需 API 密钥,无需身份验证,只读。除工具回答问题所需的 API 调用外,服务不会发出其他请求。
- npm:
echelongraph-mcp· 官方 MCP Registry:io.echelongraph/echelongraph-mcp· 文档:https://echelongraph.io/pulse/mcp - 源码:https://github.com/echelongraph/echelongraph-mcp · 变更记录:CHANGELOG.md · 安全:SECURITY.md
- 也收录于:Smithery,其注册条目对应
https://mcp.echelongraph.io/mcp(其代理、API 和 CLI 已于 2026-10-31 关闭)· Glama
快速开始
本地服务通过 npx 运行,需要 Node.js 20 或更高版本;不会全局安装任何内容。下方的一键扩展适用于 Claude Desktop,无需安装任何内容。将以下任一配置块添加到客户端,完全退出并重新打开客户端,然后提问:“CVE-2023-44487 是否正在遭受攻击?EchelonGraph 的雷达记录中有多少个暴露服务受到影响?”
Claude Desktop
有三种接入方式。前两种不需要 Node.js:一种是一键安装扩展,在你的机器上运行服务;另一种是连接托管端点的自定义连接器。第三种通过 npx 运行服务。
1. 在 Claude Desktop 中安装
(一键安装,无需 Node.js)。 此链接会下载 echelongraph-mcp.mcpb,这是一个 Claude Desktop 扩展。打开它,或者在 Claude Desktop 中选择 Settings → Extensions → Advanced settings → Install Extension,然后选中该文件,再选择 Install。Claude Desktop 会使用自带的 Node.js 运行服务,并写入自己的配置:无需设置 PATH,也无需编辑 JSON。要更新,请用相同方式安装下一个版本的扩展包。GitHub 上的每个新版本都会附带该扩展包(2.6.5 及更早版本除外);扩展包由发布 npm 包的工作流基于版本标签构建,并附有 SLSA 构建来源证明。验证下载文件:
gh attestation verify echelongraph-mcp.mcpb --repo echelongraph/echelongraph-mcp。
2. 自定义连接器(无需安装)。 Claude Desktop 使用你的 claude.ai 账号中的连接器:依次选择 Customize → Connectors → + Add → Add custom connector。将其命名为 EchelonGraph,粘贴 https://mcp.echelongraph.io/mcp,选择 No sign in,然后添加。在 claude.ai 上添加的连接器也会显示在 Claude Desktop 中;套餐规则遵循 claude.ai 的规则(见下文“远程(无需安装)”)。
3. 通过 npx 运行本地服务。
-
检查 Node.js。 在终端(macOS)或 PowerShell(Windows)中运行
node -v。输出必须为v20或更高版本。如果输出的是更早版本或command not found,请从 https://nodejs.org 安装 LTS 版本,或者在 macOS 上使用 Homebrew 运行brew install node。 -
在纯文本编辑器中打开配置文件。 Settings → Developer → Edit Config 会显示
claude_desktop_config.json(macOS:~/Library/Application Support/Claude/claude_desktop_config.json;Windows:%APPDATA%\Claude\claude_desktop_config.json)。请使用 VS Code、Notepad 或nano等纯文本编辑器打开。macOS 上的 TextEdit 在启用 Smart Quotes 时会把"转成弯引号(“ ”),导致 JSON 出错且不显示错误:请在 Edit → Substitutions → Smart Quotes 中关闭该选项,或改用其他编辑器。 -
合并,不要替换。 该文件通常已经存在,并包含 Claude Desktop 自身的设置(例如
"preferences"对象)。请保留其中的所有内容。在顶层添加"mcpServers"键,与现有键并列;如果已经有"mcpServers",就在其中添加"echelongraph"条目。注意条目之间的逗号。最终内容如下,其中preferences处应为你自己的设置:{ "preferences": { "…": "the settings already in your file stay as they are" }, "mcpServers": { "echelongraph": { "command": "npx", "args": ["-y", "echelongraph-mcp"] } } }要检查文件能否解析,请在终端(macOS)中运行:
node -e "JSON.parse(require('fs').readFileSync(process.argv[1], 'utf8'))" "$HOME/Library/Application Support/Claude/claude_desktop_config.json"或在 PowerShell(Windows)中运行:
node -e "JSON.parse(require('fs').readFileSync(process.argv[1], 'utf8'))" "$env:APPDATA\Claude\claude_desktop_config.json"没有输出表示 JSON 有效。
SyntaxError表示文件有错误(通常是弯引号或缺少逗号);ENOENT表示该路径下还没有文件。 -
完全退出后再重新打开。 仅关闭窗口不会重新加载配置。在 macOS 上选择 Claude → Quit Claude(⌘Q);在 Windows 上,右键单击系统托盘中的 Claude 图标,然后选择 Quit。首次启动可能需要更长时间,因为
npx需要下载软件包。 -
检查是否成功。 Settings → Developer 会显示
echelongraph正在运行,聊天框中的工具菜单会列出 EchelonGraph 的工具,也就是下文“工具”部分列出的工具。然后提出本节开头的问题。
Claude Desktop 故障排查
-
spawn npx ENOENT(或服务显示为失败)。在 macOS 上,从 Dock 打开的应用无法获取 shell 的 PATH,因此 Claude Desktop 找不到 Homebrew(Apple silicon:/opt/homebrew/bin;Intel:/usr/local/bin)或 nvm 安装的npx。在 Terminal 中运行which npx,然后将 Claude Desktop 的"command"设为该绝对路径,并将其所在文件夹设为"env"下的PATH(npx会从同一文件夹启动node)。使用 Apple silicon 上的 Homebrew 时:{ "mcpServers": { "echelongraph": { "command": "/opt/homebrew/bin/npx", "args": ["-y", "echelongraph-mcp"], "env": { "PATH": "/opt/homebrew/bin:/usr/bin:/bin" } } } }使用 nvm 时,请填写
which npx输出的完整路径(JSON 不会展开~)。然后完全退出并重新打开应用。在 Windows 上,使用 nodejs.org 提供的安装程序安装 Node.js,这会将npx添加到系统 PATH,然后完全退出并重新打开 Claude Desktop。 -
服务完全没有显示。 文件不是有效的 JSON(缺少逗号或使用了弯引号),或者应用未完全退出:请参阅步骤 2 到 4。
-
日志。 macOS:
~/Library/Logs/Claude/mcp-server-echelongraph.log(此服务的输出)和~/Library/Logs/Claude/mcp.log(连接)。Windows:%APPDATA%\Claude\logs\,文件名相同。
Claude Code
claude mcp add --transport stdio echelongraph -- npx -y echelongraph-mcp
在 -- 前添加 --scope user,即可在每个项目中使用;添加 --scope project,则可通过项目的 .mcp.json 共享。Claude Code 会将每个结果的 structuredContent 交给模型;除非调用传入 full: true(参见“长回答”),否则此服务会将内容限制为 30,000 个字符。MAX_MCP_OUTPUT_TOKENS(默认 25,000 个 token)是 Claude Code 对工具输出设置的上限,提高此值即可让 full: true 的回答完整通过。
Cursor
~/.cursor/mcp.json(所有项目)或 .cursor/mcp.json(单个项目):
{
"mcpServers": {
"echelongraph": {
"command": "npx",
"args": ["-y", "echelongraph-mcp"]
}
}
}
VS Code
工作区中的 .vscode/mcp.json(VS Code 使用的键是 servers,而不是 mcpServers):
{
"servers": {
"echelongraph": {
"command": "npx",
"args": ["-y", "echelongraph-mcp"]
}
}
}
或从终端运行:
code --add-mcp '{"name":"echelongraph","command":"npx","args":["-y","echelongraph-mcp"]}'
Windsurf、Cline 和其他客户端
读取 mcpServers 块的客户端(Windsurf 的 mcp_config.json、Cline 的 MCP 设置以及大多数其他客户端)都可以使用与上文 Cursor 相同的配置块。
远程(无需安装)
相同的 16 个工具、5 个提示词、2 个资源和 1 个资源模板通过 Streamable HTTP 提供,地址为:
https://mcp.echelongraph.io/mcp
无需密钥、无需登录、无状态;支持两个协议时代。托管端点已投入服务:
https://mcp.echelongraph.io/health 会返回 {"status":"ok","version":…},其中包含其运行的包版本。
-
claude.ai(Free、Pro、Max、Team 和 Enterprise 计划): Customize → Connectors → + Add → Add custom connector。将名称设为
EchelonGraph,粘贴 URL,选择 No sign in,然后添加。在 Team 和 Enterprise 计划中,Owner 需先为组织添加连接器,然后每位成员再进行连接。Free 计划允许添加一个自定义连接器。 -
Claude Code:
claude mcp add --transport http echelongraph https://mcp.echelongraph.io/mcp -
Cursor(
mcp.json):{ "mcpServers": { "echelongraph": { "url": "https://mcp.echelongraph.io/mcp" } } } -
VS Code(
.vscode/mcp.json):{ "servers": { "echelongraph": { "type": "http", "url": "https://mcp.echelongraph.io/mcp" } } } -
Windsurf(
mcp_config.json):{ "mcpServers": { "echelongraph": { "serverUrl": "https://mcp.echelongraph.io/mcp" } } }
托管端点会使用此包的代码(下文的 dist/http.js)访问同一公共 API,因此其回答与 npm 包的回答一致(“隐私”部分说明了它会记录哪些内容)。
工具
所有工具均为只读(readOnlyHint: true),并声明了标题和 outputSchema。示例问题均可由客户端仅使用相应工具回答。
| 工具 | 标题 | 可回答的问题 | 示例问题 |
|---|---|---|---|
cve_summary | CVE 源摘要 | 按严重性等级统计的活跃 CVE 数量;没有任何来源严重性等级的 CVE 数量(summary.none,也会再次作为 summary.unscored 返回:表示尚未评分的 CVE,而不是评分为 None);按 NVD 严重性标签统计的相同 CVE 数量,用作来源信息(summary.nvd_critical 至 summary.nvd_none);不计入总数的已拒绝(已撤回)记录(summary.rejected);以及源上次更新时间。 | 源中有多少个严重 CVE?上次更新时间是什么时候? |
search_cves | 搜索 CVE | 搜索/筛选 CVE(严重性、最低 CVSS、文本、排序),并提供 EchelonGraph 评分和 score_assessed;使用 limit 和 offset 分页;备注会列出每条尚未评分的记录。 | 查找提及 Tomcat 且 CVSS 为 9 或更高的严重 CVE。 |
get_cve | CVE 详情 | 单个 CVE 的记录:CVSS v3 和(已评分时的)v4、EchelonGraph 评分及其置信度、EchelonGraph 是否已为其评分(score_assessed)、EPSS、CISA-KEV 状态和已知勒索软件利用情况;对于列入 KEV 的 CVE,还会逐字转述 CISA 自己的文本(kev_required_action,即 CISA 要求美国联邦民事机构采取的行动,并非 EchelonGraph 的建议;kev_short_description;kev_notes_urls);GitHub GHSA ID、参考资料,以及发布时间、修改时间和 updated_at。 | CVE-2024-3094 的 CVSS、EPSS 和 CISA-KEV 状态是什么? |
cve_exposure | 单个 CVE 的互联网暴露情况 | 某个 CVE 的互联网暴露范围:暴露的服务数量(不同的 ip:port,即 exposed_hosts 字段)以及国家/产品细分数据,来源为 KEV 暴露雷达。 | EchelonGraph 的雷达记录了多少个 CVE-2023-44487 暴露服务? |
exposure_radar | 暴露雷达总计 | 所有暴露雷达的汇总数据:运行 CISA-KEV CVE 的服务;通过 Shodan(Shodan 查询额度不足时使用 LeakIX)发现、随后经 EchelonGraph 自有识别检查确认的未授权数据存储和可观测性 UI;泄露的凭据;影子 AI;以及 EchelonGraph 自有 Certificate Transparency 源中发现的 MCP 服务,按 RFC 9728 判定、协议时代和传输方式分类。每个数字都标明了统计对象;工具无法标注的字段会被省略并明确列出。 | EchelonGraph 的雷达确认了多少个未授权数据存储? |
kev_recent | CISA KEV 最新收录项 | CISA 添加到已知被利用漏洞目录中的 CVE,按最新优先排序(kev_added_date),数据来自 EchelonGraph 的目录副本,该副本每 5 分钟从 CISA 轮询一次:到期日期、供应商、产品、已知勒索软件利用情况、EchelonGraph 严重性、CVSS、EPSS、eg_kev_tier 和 our_first_seen_kev。可按日期范围、勒索软件和供应商筛选;使用 limit 和 next_cursor 分页。日期依据 last_successful_fetch_at,即我们上次成功获取 CISA 源的时间;筛选条件通过请求标头传递,绝不放在 URL 中。 | 自 9 月 1 日以来,CISA 将哪些 CVE 添加到了 KEV?其中哪些已知被勒索软件利用? |
epss_history | 单个 CVE 的 EPSS 变化历史 | EchelonGraph 记录的某个 CVE 的 EPSS 评分变化情况:每次记录到的变化对应一个数据点(series_kind 为 change_only),而不是每日序列,并附当前值;complete_since 表示从何时起每次变化都有一个数据点(在此之前记录会漏掉一些变化,因此缺失数据点不代表没有变化,且该序列绝不会被称为完整);coverage 说明记录包含和缺少哪些 FIRST 评分日期(days_missing、days_partial、days_in_progress);series_starts_at 表示开始记录的时间;早于该时间的缺失数据点表示未记录,而不是没有变化。 | CVE-2023-44487 的 EPSS 评分发生了哪些变化?请按 EchelonGraph 的记录说明。 |
check_affected | 我是否受到影响?(给定版本的产品或软件包) | 某个给定版本的产品(其 NVD CPE 产品令牌)或注册表软件包(ecosystem 和 package)是否受已知 CVE 影响,数据来自 echelongraph.io/am-i-affected 背后的匹配器:首先返回 assessed(false 表示未评估,并附 not_assessed_reason;此时数量为 0 并不表示“未受影响”);匹配到的 CVE 包含 kev_listed、ransomware、epss_score、effective_score 和 score_assessed(注册表匹配还包含 fixed_in,即该版本以上、且记录中的任何受影响区间都不包含的最低版本;如果该版本跨过重叠区间,则附 fixed_in_detail;若为 null,则附 fixed_in_reason,这并不代表已判定不存在修复版本);以及无法判定的公告数量 undetermined_count,绝不会将其视为安全。查询内容通过请求标头传递,绝不放在 URL 中。 | openssl 3.0.0 是否受已知 CVE 影响?npm 上的 lodash 4.17.15 呢? |
check_sbom | 根据公告语料库检查 SBOM | 根据 EchelonGraph 的公告语料库(OSV.dev 记录)检查依赖项列表,每个组件给出一个判定:affected、not_affected、undetermined 或 not_assessed,并附 not_assessed_reason。每行都会说明用于查询公告的软件包(matched_package)及匹配方式(matched_via:当 deb、apk 或 alpine purl 的 upstream 限定符指定源软件包时为 upstream,Debian 和 Alpine 正是以此方式发布公告;否则为 purl_name)。每个匹配项还包含 fixed_in,即高于组件版本且不在记录任何受影响区间内的最低版本(fixed_in_detail 会指出跨过的任何重叠区间);若为 null,则附 fixed_in_reason。最多可传入 2,000 个不同的 purl,列表最多包含 10,000 项;也可传入 CycloneDX JSON 或 SPDX JSON 文档:MCP 服务会从中读取 purl,且只会将 purl 发送至 API,每批 POST 请求最多 200 个,并依次发送;文档本身不会继续发送。通过 npm 运行时,服务在你的计算机上;通过托管端点(mcp.echelongraph.io)运行时,服务属于 EchelonGraph,文件则作为请求正文发送。达到 API 的单组件速率限制(429)时,工具会等待 Retry-After 指定的时间;一次调用最多等待 50 秒,超出后会返回已有结果,并在 coverage.not_sent 中统计未发送的 purl,在 coverage.not_sent_reason 中说明原因,在 data.not_sent_purls 中列出这些 purl(完整列表时为 full: true;列表可能被 DATA CUT 截断),绝不会静默丢弃。缺少指定发行版的 distro 限定符的 deb、apk 或 rpm purl 不会被评估(distro_release_unknown):EchelonGraph 不会猜测发行版。只有 not_affected 才表示安全。不排序,不评分。 | 根据公告语料库检查此 CycloneDX SBOM。 |
scan_manifest | 根据公告语料库检查锁文件 | 根据同一公告语料库检查项目的锁文件或固定版本清单,每个依赖项给出一个判定;使用与 check_sbom 相同的批量路由、批次、50 秒时限和 Retry-After 等待方式。传入 files,包含 1 至 20 个 filename 和 content(文件文本),总计最多 5,000,000 个字符;根据文件名读取格式,也可通过 format 指定。可读取:requirements.txt(仅支持 == 和 === 固定版本;会去除 extras 和标记)、go.mod(require 单行和代码块形式,包含 // indirect,并应用 replace 和 exclude)、package-lock.json 和 npm-shrinkwrap.json(lockfileVersion 1 至 3)、Cargo.lock、Gemfile.lock(去除平台后缀)、composer.lock(去除开头的 v)、poetry.lock 和 gradle.lockfile。package.json、pyproject.toml、Pipfile、Gemfile、Cargo.toml、composer.json 和 build.gradle 包含版本范围,因此会被拒绝,并指出应传入的锁文件;go.sum 也会被拒绝,因为它列出的模块版本并非构建所选用的版本;目前尚不读取 pom.xml、yarn.lock 和 pnpm-lock.yaml。MCP 服务会将文件解析为 purl,且只会将 purl 发送至 API;文件名和文件内容不会继续发送。通过 npm 运行时,服务在你的计算机上;通过托管端点(mcp.echelongraph.io)运行时,服务属于 EchelonGraph,文件则作为请求正文发送。data.results 按不同 purl 各返回一行,内容与 check_sbom 相同,每个匹配项都包含 kev_listed、epss_score 和 fixed_in。每个未发送的条目都会列在 data.not_checked 中,包含其文件、行号和 reason:version_unpinned(例如 django>=4 这样的版本范围;其边界值绝不会作为版本发送)、version_unresolved、local_path、vcs_source 或 unsupported_line,并按原因计入 coverage.not_checked_by_reason;这些条目不代表安全。若文件不包含此工具可检查的任何版本,工具会返回 not_assessed,而不调用 API。只有 not_affected 才表示安全。不排序,不评分。 | 根据公告语料库检查此 package-lock.json。 |
cve_intel | CVE 弱点、漏洞利用和软件包 | 单个 CVE 的弱点、漏洞利用代码和检测检查(Nuclei 模板或 API 提供用作检查器的 GitHub 仓库,用于检查系统是否受影响;不一定是漏洞利用代码,备注会单独统计两者)、受影响的软件包和修复版本,数据来自 EchelonGraph 按 CVE 丰富的信息:cwes、exploits(最多 10 项,已验证的优先)以及 exploits_total、exploits_capped、exploits_by_kind 和 exploits_by_status、affected_packages、fixed_versions 和 timeline。每条 affected_packages 记录都包含 fixed_branches,即该软件包每个受影响区间及其修复信息(introduced,以及 fixed;若没有已记录的修复,则为 last_affected);每条记录都会指出发布它的 OSV 记录(advisory_id、source),并按该记录中的顺序排列:已安装版本的修复版本,是高于它且不在该记录任何区间内的首个 fixed;若有仍包含该版本的区间,则会跨过这些区间(不跨过没有 fixed 的区间),并按该生态系统的版本顺序进行比较。fixed_version 是为保持兼容而保留的单个区间修复版本,并非所有区间的修复版本;若某软件包的区间从未加载,fixed_branches 为 null;若没有已记录的版本区间,则为 [],这并不代表已判定不存在修复版本。verified_status 是随每条引用保存的标签,并不保证漏洞利用有效。exploits 列表为空并不能证明不存在公开漏洞利用;API 无法读取的部分会列在 coverage.sections_failed 中,绝不会以空列表转述。 | CVE-2021-44228 是否有公开漏洞利用代码?哪些版本可以修复它? |
cve_remediation | 如何修复单个 CVE | 在一个回答中说明如何修复单个 CVE,并依据其来源所述内容;所有文本均按来源原文转述,未经 EchelonGraph 验证:cisa(对于列入 KEV 的 CVE,逐字提供 CISA 的 required_action、due_date、short_description 和 notes_urls;CISA 要求美国联邦民事机构采取该行动,这并非 EchelonGraph 的建议)、fixed_branches(每个受影响软件包及其所有受影响区间和修复版本)、vendor_remediations(提及该 CVE 的每条供应商公告,最多 20 条,包含其 remediation_state 及其中针对该 CVE 列出的条目,每项附 kind,即供应商自己的分类:vendor_fix、workaround、mitigation、no_fix_planned、none_available 或 other)、fix_references(NVD 或 CNA 标记为 Patch 或 Mitigation 的参考资料)、patches、coverage 和 failed_sections,以及 CVE Pulse 页面显示的 API 修复状态规则 fix_status。如果提供了已安装的 ecosystem、package 和 version(三项要么全部提供,要么都不提供),还会返回 installed(该版本的判定)和 fixed_in:高于该版本且不在任何已记录受影响区间内的首个版本;若为 null,则附 fixed_in_reason。remediation_state 为 none_in_source 或 not_parsed,或者列表为空,都不代表已判定不存在修复版本。REJECTED CVE 会返回 not_assessed。 | CVE-2021-44228 是如何修复的?请依据其来源所述内容说明。 |
get_cwe | CWE 及其 CVE | 一个 CWE(弱点类别)及归类到该类别下的 CVE:name 和 description 来自 EchelonGraph 内嵌的 MITRE CWE 目录;还包括 total 和一页 50 条 cves,排序方式由 order 指定(优先列出 CISA-KEV 收录项,然后按 EchelonGraph 评分排序)。total 为 0 表示 EchelonGraph 的源中没有 CVE 被归类到该 CWE,并不表示不存在此类 CVE。 | 哪些 CVE 被归类到 CWE-79?请优先列出 CISA-KEV 收录项。 |
vendor_advisories_for_cve | 单个 CVE 的供应商公告 | 供应商发布的公告(Microsoft MSRC、Red Hat、Cisco、Palo Alto Networks、GitHub GHSA 及 EchelonGraph 轮询的其他源)中提及某个 CVE 的公告,按最新优先排序,最多 20 条;每条都包含 remediation_kinds 和 remediation_state(not_parsed 表示 EchelonGraph 未读取该供应商的修复信息,并不代表不存在修复信息)。 | 哪些供应商公告提及 CVE-2024-3400? |
get_vendor_advisory | 供应商公告详情 | 完整显示一条供应商公告:描述、严重性、cve_ids 和其中在此处有 CVE 记录的子集(known_cve_ids)、affected_products、remediation 和 references,以及 remediations;每项修复信息都是供应商列出的内容,包含供应商自己的分类 kind、原文和 URL,并附 remediation_state。 | 完整显示其中一条公告:受影响产品、修复信息和参考资料。 |
search_vendor_advisories | 搜索供应商公告 | 按文本(标题、描述、供应商、公告 ID、产品、CVE ID)、供应商、严重性以及是否提及 CVE 搜索供应商公告。搜索文本通过请求标头发送,绝不放在 URL 中。 | 搜索 FortiOS 相关的供应商公告,仅显示严重性为严重的公告。 |
这三个供应商公告工具会转发 vendor_published_at(供应商的发布日期)、our_first_seen_at | |||
(EchelonGraph 首次记录该公告的时间)和 withdrawn(供应商撤回了该公告;说明中会列出具体公告,搜索结果会排除这些公告)。 |
每个工具还会转发 coverage 中每家供应商的窗口(vendor_windows;详情中为
vendor_window):纳入的公告数量、其中最早和最晚的 vendor_published_at、
held_since 和 history_backfill。held_since 是 EchelonGraph 开始读取该供应商公告的窗口起始时间:在此之前发布的公告可能未被纳入。对于尚未读取历史公告的供应商(history_backfill
为 not_supported),这个时间可能比最早纳入的公告晚数年:Cisco 的轮询器首次读取的是过去 90 天内变更的公告,Red Hat 和 GitHub 的轮询器首次读取的是过去 7 天内变更的公告,因此,较早发布但后来修订的公告会被纳入,而同期发布的其他公告则不会。
vendor_advisories_for_cve 会在 vendors_not_fully_held 中列出以下供应商:其没有出现在答案中的公告,且 EchelonGraph 未纳入该供应商的任何公告;其 held_since 晚于 CVE ID 年份的 1 月 1 日或未知;或其历史公告仍在读取中:没有来自此类供应商的公告,并不表示该供应商没有发布过公告。
每个数值的时效都取决于生成它的最近一次检查。CVE 订阅源会按计划轮询各个源。每个雷达都有自己的计划,且只会在运行时刷新;exposure_radar 的 freshness 会提供各雷达最近一次已完成检查的时间(last_run_at),前提是 API 提供该字段。
各工具如何解读其答案
每个工具会转发哪些内容、各字段的含义,以及每个数值的计数对象,详见随软件包附带的 docs/ 文件夹中的页面:
cve_summary如何解读其计数:summary.none统计尚未评分的 CVE,而不是评级为 None 的 CVE;summary.nvd_critical到summary.nvd_none则按 NVD 的严重性标签(或作为替代的 NVD 前标签)计数,用作来源信息。get_cve和search_cves如何解读 EchelonGraph 评分:score_assessed: false表示尚未评分,绝不表示评分为 0。patch_available表示什么, 以及patch_evidence列出的证据,其中包括 CVE 记录自身的修复说明 (cna_solution、description_fix):false表示记录中没有修复证据,并不表示不存在修复。cve_exposure如何计数: 统计的是 ip:port 服务数量,而非机器数量;这些数量是根据部分 Shodan 数据样本中的横幅版本推断得出的。对于不在雷达跟踪范围内的 CVE,状态为未评估,其 0 并非测量结果。exposure_radar如何计数: 说明五个雷达各自统计的内容,并为每个雷达的数值标注计数对象。check_affected如何判断: 先读取assessed,再读取count;注册表匹配项的fixed_in是高于该版本且不在该记录任何受影响版本区间内的最低版本;否则为 null,并附有fixed_in_reason。
提示词
现成的工作流,客户端可以将其显示为斜杠命令。每个提示词都会按顺序列出要调用的工具,并指示模型读取每个结果的 state、measured_at、method、coverage
和 notes:not_assessed 绝不会被报告为正常;assessed: false 下计数为 0 绝不会被表述为“未受影响”;每个数值都会注明其 measured_at。提示词不会发出 API 请求。
| 提示词 | 参数 | 要求模型执行的操作 |
|---|---|---|
triage_cve | cve_id | 调用 get_cve(若该 CVE 列入 KEV,则包含 CISA 的截止日期 kev_due_date)、cve_intel、vendor_advisories_for_cve、epss_history 和 cve_exposure,然后按模板给出判断:是否已被利用、可能性、是否可触达、补丁、截止日期、结论。补丁一栏会列出每个受影响范围及其在 cve_intel 的 fixed_branches 中对应的修复版本;若某个软件包没有修复分支,则将 fixed_version 作为 cve_intel 对该软件包的记录列出,每个软件包列一个(通常是公告中最后一个范围的版本),绝不将其当作每个受影响分支的修复版本;并指出 get_cve 中标记为 Vendor Advisory 或 Patch 的参考资料,作为该分支的修复依据。 |
kev_weekly_brief | days(1 到 365,默认值为 7) | 根据 days 算出起始日期,从该日期起按每页 50 条翻页读取 kev_recent,并按供应商分组撰写简报,注明勒索软件标记和截止日期。 |
am_i_affected | product,或 ecosystem 和 package;version | 调用 check_affected,先读取 assessed 再读取 count,并使用未评估时的措辞。 |
sbom_review | sbom(CycloneDX 或 SPDX JSON 文本,最多 5,000,000 个字符) | 将文档传给 check_sbom(如果速率限制或剩余时间导致部分 purl 未发送,则再次传入这些 purl:data.not_sent_purls;如果文本或 DATA CUT 截断了该列表,则按文档说明的位置和顺序传入文档中的 purl)。从各 purl 读取每个组件的 ecosystem、package 和 version,方式与 check_sbom 的映射规则一致(包括其映射的每种 purl 类型,以及通过 distro 限定符识别 Debian、Ubuntu 或 Alpine 发行版的 deb、apk、alpine 和 rpm;其他发行版未知,且不提供固定版本;如果 deb、apk 或 alpine purl 带有 upstream 限定符,则使用该限定符指定的源软件包;当某行的 matched_via 为 upstream 时,使用该行的 matched_package,修复列表会在 purl 旁标出该值),对每个受影响的 CVE 调用 get_cve 和 cve_intel 查找,并按 CISA-KEV 列入情况、EPSS、分数排序编写修复列表,并注明每个排序依据。若文本保留了匹配结果,其固定版本仅使用该匹配项的 fixed_in,即高于已安装版本、且该记录中没有受影响区间涵盖的最低版本;若 fixed_in 为 null,则写作“记录中没有修复版本”,并按原样附上 fixed_in_reason,不得据此断言不存在修复版本(若 DATA CUT 将其截断且未留下原因,则绝不能称为没有修复版本),也不得从文本描述(match_reason、fixed_in_reason)中读取固定版本。若文本未保留该组件的匹配结果,或匹配结果没有 fixed_in,则仅在版本高于已安装版本时提供固定版本:取 cve_intel 行的 fixed_branches 中高于该版本且不属于任何范围的第一个 fixed;若软件包没有 fixed_branches,则使用 cve_intel 的 fixed_version,每个软件包列一个(即最后一个范围的版本),该版本不一定是该组件所在分支的修复版本;否则,该行写明结果没有提供该分支的固定版本,并指出该 CVE 的公告。 |
workload_triage | source(可选:kubernetes、github_actions 或 images;默认描述全部三种) | 使用你自己的工具对 Pod、CI 作业容器或镜像进行排序:列出工作负载,并自行判断其暴露情况;为每个镜像摘要生成 SBOM,并仅将 purl 传给 check_sbom(不发送工作负载、命名空间、镜像、注册表名称、凭据或暴露标签;不包含镜像自身的 pkg:oci/pkg:docker purl)。各行按 CISA-KEV 列入情况、调用方断言的暴露情况(未知绝不与未暴露一起排序)、EPSS、分数排序,并注明每个排序依据。若某行匹配结果被 DATA CUT 截断,则读取其 matches_truncated(其中包含列入 KEV 和涉及勒索软件的 CVE ID);对每个已保留但没有匹配结果的 CVE,或缺少其所依据排序字段的匹配结果,调用 get_cve 查询;超过 30 个 CVE 后停止调用 get_cve。统计 not_assessed 行,且绝不将其报告为安全。提示词不接收任何工作负载数据。 |
资源
两个资源由 resources/list 列出,一个资源模板由 resources/templates/list 列出(例如,客户端会读取 cve://CVE-2024-3400):
| 资源 | 内容 |
|---|---|
echelongraph://methodology | 说明每个信封字段和 state 值的含义,以及每个工具的测量方式(Markdown)。 |
echelongraph://sources | 读取该资源时,API 会报告其数据源的哪些信息:NVD 轮询器的 interval、last_poll_at、poll_count 和 poll_errors,这些信息都来自实际响应的那个实例(来自 /api/v1/public/cves/summary;两个计数是该实例自上次启动以来的计数,每次重启都会归零,并不表示数据源的可靠性);以及 CISA KEV 目录最近一次成功获取的时间和方法(来自 /api/v1/public/kev/recent)。它会列出没有任何端点报告其计划的数据源,并说明这些数据源均未报告计划(JSON)。 |
cve://{cve_id} | get_cve 返回的单个 CVE:结构化结果、信封和记录,以 JSON 格式呈现。JSON 超过 30,000 个字符后,data 会像 get_cve 的第一个文本块那样被截断,data_truncated 为 true,truncated 列出每个被截断的列表,并附上一条以 DATA CUT 开头的说明,指出截断遗漏的内容;get_cve 的 structuredContent.data 会完整保留记录,并带有 full: true。如果 ID 不是 CVE ID,则会在发出任何请求前拒绝;如果 API 没有该 CVE 的记录,则会返回未找到。 |
结果意味着什么
每个工具都会以两种形式之一作答,因此读取结果的模型不会把服务中断误认为一切正常:
- 成功 — 第一个文本块是 API 的 JSON 原文(超过 30,000 个字符时会截断以适应长度限制:见下文“长答案”);第二个文本块是一行说明,指出调用成功、哪个基础 URL 返回了响应,以及发现了什么;第三个文本块是结构化结果的 JSON,去掉前两个文本块已经说明的内容(见下文)。如果查询对应的数据源确实没有内容,说明会用文字明确指出(“我们查过了,但没有找到……这不是查询失败”),因为经过测量的零也是一种测量结果。以下情况除外:
cve_summary会省略答案中类型为非 outputSchema 类型的poller字段(或既不是 JSON 对象也不是 null 的poller),并在说明中指出;exposure_radar:每个雷达只保留 docs/exposure-radar.md 列出的字段,且每个kev_exposure.newest_kev条目都会新增一个exposure_state。其shadow_ai计数会按该页面所述重新归组,且poller块仅包含running和last_run_at,若其中没有实际完成时间,则会省略该块。该块的其他字段描述的是响应请求的服务实例,而不是雷达。其last_run_at表示雷达的 leader 最近一次完成 Certificate Transparency(crt.sh)周期的时间;只有在答案生成前 30 分钟内完成时,running才为 true。running为 true 时,说明会指出雷达的 leader 最近一次在该时间完成周期;为 false 时,说明会指出自该时间起尚未完成周期;若缺少last_run_at,说明会指出雷达的新鲜度未知,并省略该块。较旧的 API 会从处理请求的任意服务实例返回响应,而 follower 实例会发送running: false和零时间0001-01-01T00:00:00Z;这同样表示新鲜度未知,绝不会被描述为雷达已停止。 - 失败 — 只要查询未完成,就返回 MCP 错误结果(
isError: true):主机无法访问、响应状态码非 2xx、耗时超过超时限制,或以 2xx 状态码响应但正文不是 JSON 对象。文本会指出工具名称、原因(状态码或错误类型)、路径和基础 URL,并说明这不是一项发现;第二个文本块是结构化结果的 JSON,去掉消息中的句子(见下文)。失败绝不会被呈现为字段为 null 的成功结果。
这两种形式都包含下文所述的结构化结果,并会在最后一个文本块中重复该结果,因此只将 content 传给模型的客户端也能看到答案是如何测量得出的。
长答案
模型读取的每个字符都需要付费,而且不同客户端会将结果的不同部分交给模型,因此每个部分都采用相同的 30,000 个字符预算,并分别按各自规则截断:
- Claude Code 会将
structuredContent而非文本块交给模型,并按MAX_MCP_OUTPUT_TOKENS(默认 25,000 个 token)计算大小:超过 10,000 个 token 时会发出警告,超过上限时会将结果保存到文件,并把文件路径交给模型。在 2.7.x 及更早版本中,structuredContent.data始终是完整答案(get_cve的 CVE-2021-44228:2026-10-11 时为 65,540 个字符,Claude Code 将其保存到了文件)。从 3.0.0 起,该字段会截断以适应限制(见下文)。在 Claude Code 启动时所处的环境中设置MAX_MCP_OUTPUT_TOKENS,可以提高其上限。 - 仅传递文本块的客户端(
content)会读取第一个文本块,并按下一项之后所述的方式截断。 - 程序若读取
structuredContent.data且需要完整答案(无论多长),可传入full: true:所有工具都接受该参数。像 Claude Code 这样会限制结构化结果大小的客户端,可能会在答案超过上限时拒绝该答案。 结构化结果。当整个结果(信封、其中的说明和data,按紧凑 JSON 计算) 超过 30,000 个字符,且调用未指定full: true时,会按每个工具说明的顺序截断data。对于较大的行,会先精简每一行,同时保留所有行:check_sbom和scan_manifest会保留每行的判定结果和cve_ids,以及提示词读取的每个匹配字段;如果这样能让每个受影响行保留所有匹配项,则先移除其not_affected和not_assessed行(说明);check_affected会保留每个匹配项的评分、标志、条件和fixed_in,之后再精简更多内容;cve_remediation会先移除每个条目的product_ids,再移除其文本,同时保留每条公告的状态、类型、URL 和修复版本(get_vendor_advisory会返回每条文本),精简fixed_branches(然后限制每个软件包的范围)和patches,接着截断fix_references,然后是patches,再然后是fixed_branches,最后才是公告;说明中会注明vendor_advisories_for_cve,该工具会列出所有公告;search_cves会先保留每行的描述和评分,然后只保留评分;供应商公告工具会先移除affected_products,然后移除summary。只有在此之后才会移除行(check_sbom和scan_manifest:如该页面所述);check_affected会先移除其excluded和undetermined示例,最后移除会列出所有匹配项的cve_ids;其他返回行的工具会从末尾移除行,而该页面会说明通过offset或limit读取剩余行(search_cves和search_vendor_advisories还会说明能完整放入data的行数对应的页面大小,以完整行数计算)。get_cve会将cpe_match和references各自截断至相同的最多条目数,然后截断cpe_configurations;exposure_radar会截断其每日和每周序列,各自保留最新条目,然后截断所有排名,最后截断kev_exposure.newest_kev;之后,data顶层的任何其他列表也会按相同方式截断。列表能完整放入后剩余的空间会返还给先前被清空的列表,让它们尽可能多地恢复条目(序列恢复最新条目)。不会缩短任何字符串,也不会更改任何值(精简后的行会保留部分字段,这些字段在 outputSchema 中均为可选,因此data仍然有效;截断操作只会添加matches_truncated和fixed_branches_truncated)。结果随后会显示data_truncated: true(其他所有成功结果均为false);truncated会按列表在data中的路径列出每个被截断的列表及其total、返回数量returned,以及在条目经过精简时标注thinned: true;说明末尾会包含以DATA CUT开头的句子,说明截断了哪些内容、如何读取剩余内容,以及使用相同调用并设置full: true可返回完整的data。 第一个文本块。在 2.6.2 及更早版本中,它是 API 的 JSON,无论大小。因此,当 API 的 JSON 超过 30,000 个字符时,第一个文本块会截断内容以适应长度限制;截断的是完整答案(不是截断后的data),无论是否使用full: true,方式都相同。首先,将相同的 JSON 排版为每行一条记录,这不会删掉答案中的任何字符,只会去掉缩进。如果这样仍然太长,返回记录列表的工具会将每条记录截断为其指定的字段,并优先保留最重要的字段(search_cves会保留cve_id、severity、cvss_v3_score、echelongraph_score、score_assessed、epss_score、kev_listed和描述的前 200 个字符等),所有过长的字符串都会以“…”结尾。记录旁的列表会在任何记录从文本中省略前先行截断:check_affected的excluded和undetermined样本会保留前 10 个条目,每项包含其cve_id和reason;其cve_ids(按顺序列出每个匹配项的cve_id)会保留前 10 个,因此每个 CPE 匹配项都会保留在文本中,且至少包含cve_id、kev_listed、ransomware、epss_score、effective_score和score_assessed(注册表匹配项还包含fixed_in;接近 200 条上限的注册表列表可能会省略最后几项匹配项,最后省略 KEV 列出的项和勒索软件项,并在说明中注明省略数量和这些项的名称);check_sbom的not_sent_purls会保留前 10 个,说明中会指出未发送的 purl 从输入的哪个位置开始,以及输入的 purl 按什么顺序计数,这样第二次调用时无需读取列表即可发送它们。scan_manifest会像check_sbom一样截断记录,其not_checked列表会保留前 20 个条目。cve_remediation会先精简其公告,然后是fixed_branches和patches,接着将每个包的范围限制在可容纳的最大数量(被截断的包会带有fixed_branches_truncated,并在说明中列出;说明会提示使用full: true读取其修复信息),然后按data中的顺序移除fix_references、patches和fixed_branches记录。当最精简的截断结果仍然太长时,文本中会省略记录(check_sbom和scan_manifest会先省略not_affected记录,然后省略not_assessed记录;最后省略带有 KEV 列出项或勒索软件匹配项的记录,并按index列出所有省略项;这两类记录会先精简到最简形式;如果这样能让其他记录保留其匹配项,它们就会更早被省略;如果不能,则所有记录都会先精简到该级别:参见 docs/tools.md),说明中会指出如何读取这些记录:下次调用所用的offset、更小的limit,或者对于公告,使用vendor_advisories_for_cve。其他任何答案都会保留每个列表的前几项(get_cve的cpe_match和references)。随后,说明会以一句以TEXT CUT开头的话结尾,说明第一个文本块省略了什么,以及哪个工具会返回某条记录(get_cve、get_vendor_advisory、check_affected,以及cve_intel返回的某个 CVE 的修复版本):这些内容完整保存在该工具的structuredContent.data中,使用full: true即可获取,因为该工具自己的第一个文本块也会在超过 30,000 个字符后被截断。能完整放入文本块的答案仍会像以前一样,以美化格式完整发送。同一个答案总是以相同方式截断。cve://{cve_id}资源会完整读取get_cve的记录,并像截断get_cve的第一个文本块那样截断其data,同时会说明这一点:data_truncated: true,truncated列出每个被截断的列表,说明以DATA CUT开头。提示词只会要求文本中保留的内容:kev_weekly_brief每页读取 50 条kev_recent记录,文本会完整保留这些记录;triage_cve会从get_cve读取 CISA 的到期日期;sbom_review会读取每个匹配项的fixed_in,而cve_intel会读取文本中未保留某个组件匹配项时的fixed_branches。
结构化结果
自 2.0.0 起,工具返回的每个结果,无论成功还是失败,都包含 structuredContent;每个工具也会在 tools/list 中通过 outputSchema 声明其结构,并带有标题以及注释 readOnlyHint: true、destructiveHint: false、idempotentHint: true 和 openWorldHint: true(这些提示不可信,客户端会将其视为不可信信息)。
| 字段 | 内容 |
|---|---|
state | measured、not_assessed、failed 或 invalid_input(见下文)。 |
measured_at | 底层观测的时间,按 API 的表述填写。若答案未说明或没有观测记录,则为 null;绝不会使用 Go 的零值时间。 |
method | 数值的生成方式。失败时为 null。 |
coverage | 答案涵盖的内容,具体取决于工具:cve_exposure 为 in_scope;search_cves 为列表对其计数的自行说明;exposure_radar 为已返回结果的雷达;check_affected 则为 assessed、not_assessed_reason、查询路径和匹配数量。 |
freshness | 生成该结果的雷达上次完成检查的时间(last_run_at),仅在 API 提供此信息时填写;否则为 null。 |
notes | 注意事项,每条一句:先说明结果封装本身需要说明的内容,再附上文本块中的说明。 |
data_truncated | 仅成功时提供:当 data 被截断(DATA CUT,见“长答案”)时为 true;若答案完整,则为 false。 |
truncated | 当 data_truncated 为 true 时,列出每个被截断的列表,使用其在 data 中的路径,并注明 total、returned;若列表项仅保留了部分字段,还需注明 thinned: true。 |
data | 仅成功时提供:API 返回的 JSON。若完整,则 full: true;默认情况下,若结构化结果超过 30,000 个字符,则会截断(DATA CUT):第一个文本块包含相同的 JSON;若超过 30,000 个字符,则包含答案整体的截断版本,具体见说明(TEXT CUT)。 |
error | 仅失败时提供:kind、path、status 和 message。 |
每个结果的最后一个文本块都会将此结构化结果序列化为 JSON,但会省略较早文本块中已逐字说明的内容,因为客户端可能只会将 content 传给模型。该文本块包含相同的 state、measured_at、coverage 和 freshness(成功时还包括 data_truncated 和 truncated;失败时则包括 error),字段逐一对应。它不包含 data,因为成功时 data 位于第一个文本块;也不包含说明中的句子,因为这些句子位于其前一个文本块中(失败时为错误消息),且 notes 以这些句子结尾:notes 只包含结果封装对自身的补充说明,没有补充说明时则省略。如果说明逐字引用了 method,它也会省略该字段,例如 cve_exposure 的说明(“Method: …”)。因此,所有文本块合起来就包含了结构化结果;但对于 TEXT CUT 所省略的答案内容(见“长答案”),这些文本块无法提供;而与 DATA CUT 不同,第一个文本块是从完整答案截取的,而不是从截断后的 data 中截取的。
state | 含义 |
|---|---|
measured | 对所询问内容进行了测量。只有当答案说明了所计数内容的观测时间(measured_at)和生成方式(method)时,暴露数量才属于 measured。没有暴露相关答案会说明截至今天的时间,因此两个暴露工具都不会返回 measured。 |
not_assessed | 答案没有所询问内容的带日期测量,因此不会将其中的任何数量呈现为测量结果:雷达不会查找此 CVE;答案没有说明雷达是否会查找;或者答案没有说明所计数内容的观测时间。答案仍可传达一个数量,作为来源记录中的未注明日期的数量:exposure_state 为 exposed 时,cve_exposure 的 exposed_hosts;以及 exposure_radar 中标明的总数。说明以及结果中包含的 exposure_state 会说明每个数量的含义。 |
failed | 查询未完成。并非调查结果。 |
invalid_input | 此服务端或 API 拒绝了输入,因此未进行查询。并非调查结果。 |
每个工具的 state、measured_at、coverage 和 freshness 分别包含什么,详见 | |
| docs/structured-results.md,其中按工具逐一说明。 | |
每个字段都取自 API 发送的内容;如果 API 没有说明,字段值就是 null,并会在备注中说明。 |
如果成功响应中的字段不符合工具的 outputSchema(字段类型不在架构允许范围内),则会作为失败返回,error.kind 为 unexpected_shape,绝不会转发;唯一例外是:cve_summary 中 poller 字段的 JSON 类型不同时,会将其从 data 中省略,并在备注中指出,同时转发答案的其余部分以及 summary。API 后续新增的字段仍会由所有将 API 的 JSON 作为数据转发的工具转发;而 exposure_radar 和 cve_intel 会转发部分内容,因此会省略这些字段并指出省略了什么。
协议版本
该服务通过 stdio 同时响应新旧两个时期的 Model Context Protocol:
- 2026-07-28:使用
server/discover启动的客户端会收到一个 DiscoverResult,其中列出2026-07-28、工具、提示词和资源能力,以及服务端说明;之后客户端会在每个请求中发送各自的_meta信封。 - 2025 及更早版本:使用
initialize启动的客户端(所有 1.x SDK 客户端均如此)会协商使用2025-11-25、2025-06-18、2025-03-26或2024-11-05;如果服务端不认识某个版本,则会以2025-11-25响应。
连接的第一条消息决定其所属时期,之后会一直保持该时期。两种握手都会携带软件包名称和版本(serverInfo),并且每个 API 请求的 User-Agent 都会包含它们,格式为 echelongraph-mcp/<version>。
两种握手也都会携带服务端说明:数据是公开的;Shodan 数据属于 Shodan;state、measured_at 和 freshness 的含义;每个结果都会在其结构化结果和文本中再次包含这些信息;暴露数量是 ip:port 服务的汇总计数,并非整个互联网的普查结果。
说明和每个工具描述都不超过 2,048 个字符,这是已知客户端会截断的最短长度,因此没有客户端会因为在此处截断而丢失句子。描述会说明工具返回什么,以及哪些规则可避免将零值、false 或失败误读为发现结果;每个字段的完整计数定义都在工具的 outputSchema 中,而结果备注也会针对其转发的数字再次说明。
隐私:数据发送到哪里
npm 软件包(stdio)。 服务在你的计算机上运行,并向一个主机 ECHELONGRAPH_API_BASE(默认为 https://app.echelongraph.io)发送 HTTPS 请求;每次工具调用 API 都会发送一个请求(exposure_radar 会发送五个请求;其他每个工具都会发送一个请求)。没有遥测:它不会向 EchelonGraph 或任何其他对象发送任何额外内容。每个请求都会携带 User-Agent
echelongraph-mcp/<version> (+https://echelongraph.io/pulse/mcp);如果你设置了 ECHELONGRAPH_MCP_UA,则该令牌会置于其前,因此 API 的访问日志可以按版本统计使用情况。与任何 HTTPS 请求一样,API 也会收到来自你网络地址的请求。
每个工具的输入会发送到哪里:
| 输入 | 发送位置 |
|---|---|
CVE ID(get_cve、cve_exposure、epss_history、cve_intel、cve_remediation、vendor_advisories_for_cve)、CWE ID 和页码(get_cwe)、供应商和公告 ID(get_vendor_advisory) | URL 路径。 |
search_cves:search | X-EG-Search 请求标头,不会放入 URL。严重性、最低 CVSS、排序方式、限制数量和偏移量会放入查询字符串。 |
search_vendor_advisories:query | X-EG-Advisory-Search 请求标头,不会放入 URL。供应商、严重性、CVE 筛选条件、限制数量和偏移量会放入查询字符串。 |
check_affected:product、version、ecosystem、package | X-EG-Product、X-EG-Version、X-EG-Ecosystem 和 X-EG-Package 请求标头,不会放入 URL。 |
cve_remediation:ecosystem、package、version | X-EG-Ecosystem、X-EG-Package 和 X-EG-Version 请求标头,不会放入 URL。CVE ID 会放入 URL 路径。 |
kev_recent:since、until、ransomware、vendor、limit、cursor | X-EG-Since、X-EG-Until、X-EG-Ransomware、X-EG-Vendor、X-EG-Limit 和 X-EG-Cursor 请求标头,不会放入 URL。 |
check_sbom:purls 或 sbom 文档 | purls 会放入 POST 请求正文,每个正文最多包含 200 个。CycloneDX 或 SPDX 文档会在你的计算机上读取,只会发送其中的 purls;不会发送文档。(使用托管端点时,文档会发送到 EchelonGraph 的服务器:见下文。) |
scan_manifest:files | 从文件中读取的 purls 会放入 POST 请求正文,每个正文最多包含 200 个;文件名、文件文本以及未检查的条目不会发送到 API。通过 npm 运行时,读取文件的服务在你的计算机上;使用托管端点时,该服务则是 EchelonGraph 的服务器,文件会作为请求正文发送(见下文)。 |
cve_summary、exposure_radar | 无输入。 |
API 会将通过标头传递的查询结果标记为 no-store,因此共享缓存不会保留这些结果;记录 URL 的请求日志和跟踪跨度也不会包含在其中查询的内容。
托管端点。 请求 https://mcp.echelongraph.io/mcp 会先到达 EchelonGraph 的
服务,然后由它调用上述同一个 API。每个请求都会记录 HTTP 方法(GET、
HEAD、POST、PUT、PATCH、DELETE、OPTIONS、CONNECT 或 TRACE,否则为 (other))和路径、状态码、
耗时、等待空位的时间(以及等待大型请求体时段的时间)、同时处理的请求数、占用的大型请求体时段
(以及最早占用的时长)、请求体大小、JSON-RPC 方法(MCP 定义的方法,否则为 (other))和工具或提示词名称、协议版本、是否发送了 Origin
标头、客户端 User-Agent 的第一个单词、客户端地址是否为公网地址(不记录该地址)、客户端是否提前关闭连接,以及请求是否受到限流或拒绝,以及原因。当某个 API 调用失败时,它会记录工具和 JSON-RPC 方法、调用的路由(不含 ID 或查询字符串,例如 /api/v1/public/cves/:id)、失败原因(例如超时、连接重置或 API 返回的状态码)、耗时,以及该请求是否来自我们的监控程序。记录错误时,只记录错误类型、固定的原因标签及其代码,以及请求的 JSON-RPC 方法和协议版本,从不记录错误消息。它从不记录工具参数或查询字符串。check_sbom 文档(或 sbom_review 提示词的文档)在此处和其他工具参数一样:它位于请求体中,因此整个文档都会发送到 EchelonGraph 的服务。服务会在内存中读取其中的 purl,仅将这些 purl 发送给 API,既不记录也不保留该文档。若要让文档留在你的计算机上,请运行 npm 包,或向 check_sbom 传入 purl。scan_manifest 的文件也一样:其全文位于请求体中,在内存中读取其中的 purl,只有这些 purl 会发送给 API;文件既不记录也不保留。若要让锁文件留在你的计算机上,请运行 npm 包。超过每个客户端的限额后,服务会记录该客户端的地址键。它会在一个标头中将客户端的公网地址传给 API;API 仅在验证通过其检查的令牌后才信任该标头,因此 API 的限流会按你的请求计数,而不是按托管服务计数。随后,API 的访问日志会按你的地址(IPv6 地址按其 /64 网段)记录每个此类调用及其 URL 路径:对于 CVE、CWE 或公告查询,还会记录你查询的 ID。它不会记录查询字符串,也不会记录上述通过标头传递的词项(对于 search_cves,会记录是否提供了词项及其长度,但不记录词项内容);对于 check_sbom 和 scan_manifest 的 purl,只记录数量,不记录具体内容。
EchelonGraph 的隐私政策:https://echelongraph.io/privacy。
速率限制
无需 API 密钥,因此 API 会在 60 秒窗口内汇总每个调用方的所有请求,并按单个 IPv4 地址或单个 IPv6 /64 网段进行限流:每分钟对 /api/v1/public/cves 及其下属路径限额 12,000 次;对 CWE、供应商公告、KEV 和 shadow-AI 路径限额 6,000 次;对任何其他公共路径限额 600 次;check_sbom 和 scan_manifest 的批量路由按组件计费,每分钟限额 1,200 个组件。超出限额时,工具会返回失败(state 为 failed,error.status 为 429),绝不会返回空数据;check_sbom 和 scan_manifest 会在单次调用的 50 秒内等待 429 响应的 Retry-After 时间,并返回已获取的结果,其余部分计入 coverage.not_sent。托管端点还会按每个客户端地址限制为每分钟 120 个 MCP 请求,并拒绝超过 64 KiB 的请求体(对于 check_sbom 或 scan_manifest 调用,以及 sbom_review 提示词,限额为 6 MiB)。所有限额按路径列于:
docs/rate-limits.md。
配置
npm 包(stdio):
| 环境变量 | 默认值 | 用途 |
|---|---|---|
ECHELONGRAPH_API_BASE | https://app.echelongraph.io | 覆盖 API 基地址(自托管/代理)。结果引用该基地址时,URL 中的凭据会被隐藏。 |
ECHELONGRAPH_API_TIMEOUT_MS | 15000 | 单次请求的超时时间。较慢的响应会报告为查询失败,而不是空数据。 |
ECHELONGRAPH_MCP_UA | 未设置 | 一个产品标识(例如 my-monitor/1.0),会置于此包自身的 User-Agent 前,以便区分监控器等自动调用方与使用该服务的人。若值不是单个标识,则会被忽略。 |
HTTP 入口 dist/http.js(npm run start:http)通过 POST /mcp,以 Streamable HTTP 提供相同的工具,并通过 GET /health 提供存活检查。在小型容器中,请限制 V8 堆内存(如何设置见 docs/rate-limits.md)。它会读取上述三个变量,以及以下变量:
| 环境变量 | 默认值 | 用途 |
|---|---|---|
PORT | 8080 | 监听的端口。 |
MCP_RATE_LIMIT_PER_MIN | 120 | 每个客户端地址、每个实例每分钟可发出的 MCP 请求数。 |
MCP_MAX_BODY_BYTES | 65536 | 可读取的最大请求正文大小,SBOM 除外(见下文)。 |
MCP_MAX_SBOM_BODY_BYTES | 6291456 | tools/call 调用 check_sbom 或 scan_manifest,或 prompts/get 调用 sbom_review 时可读取的最大正文大小。 |
MCP_LARGE_BODY_SLOTS | 2 | 可同时读取并处理的、超过 MCP_MAX_BODY_BYTES 的正文数量;超过此数量时,另外两个请求最多等待 MCP_LARGE_BODY_WAIT_MS(15000)以等待空位,之后返回 503 和 Retry-After。 |
MCP_MAX_IN_FLIGHT | 64 | 可同时处理的请求数,不包括 subscriptions/listen 流;之后的请求及其正文读取会等待。 |
MCP_ADMISSION_WAIT_MS | 10000 | 请求等待处理的最长时间,超时后返回 503 和 Retry-After。 |
MCP_BODY_IDLE_MS、MCP_REQUEST_TIMEOUT_MS | 10000、60000 | 读取正文时,若正文在这段时间内没有任何内容,则返回 408;请求整体运行超过此时长则会被停止(见 docs/rate-limits.md)。 |
MCP_H2C | 未设置 | 1:提供 HTTP/2 明文(h2c,先验知识),而不是 HTTP/1.1,这是 Cloud Run 的 --use-http2 所要求的;此时 HTTP/1.1 请求不会收到响应。 |
ECHELONGRAPH_FORWARD_TOKEN、ECHELONGRAPH_FORWARD_HOST、MCP_REQUIRE_FORWARD_TOKEN | 未设置 | 仅用于 EchelonGraph 托管部署:用于在 API 中标识每个客户端的令牌。自行运行时请保持未设置;此时 API 会将每个请求都计为来自你的服务。 |
开发
npm install
npm run build # tsc → dist/
npm test # build, then the behavioural suite over both protocol eras, against a stub API
npm run smoke # spawn the server + call cve_exposure against the production API
npm run smoke 会使用此包的 User-Agent 调用生产 API:从我们工作区以外的任何机器调用,都会计为 MCP 使用情况,除非你设置了 ECHELONGRAPH_MCP_UA(见“配置”)。
npm test 不会离开本机。
npm test 会针对 2026-07-28 的 server/discover 和 2025-06-18 的 initialize 运行。若要测试已安装的包而非 dist/,请将 ECHELONGRAPH_MCP_BIN 设置为其 echelongraph-mcp 可执行文件。
版本管理
语义化版本:主版本更新会改变协议行为或移除某个 Node.js 版本;次版本更新会添加工具或字段;补丁版本更新会修正文案或行为,但不改变工具的结构。每次发布都会由公共仓库的发布工作流从标记为 v<version> 的提交发布到 npm,并附带来源证明。各版本的变更:
CHANGELOG.md。
自 3.1.0 起,成功响应的 outputSchema 在所有层级均为开放结构:每个对象都允许包含未列出的字段;除 state 外,每个枚举除了列出的值,也允许任意字符串;工具以 null 返回的 coverage 或 freshness 也允许是对象。因此,次版本更新新增的字段或值不会导致使用 3.1.0 或更高版本工具列表的客户端验证失败。失败分支中的所有对象仍为封闭结构,除以下四个枚举外,所有枚举也仍然封闭;这四个枚举原本就接受任意字符串:
coverage.not_assessed_reason(check_affected)、coverage.vendor_windows[].history_backfill(vendor_advisories_for_cve、search_vendor_advisories)以及 coverage.vendor_window.history_backfill(get_vendor_advisory)。使用 3.0.2 或更早版本列出工具的客户端必须重新连接一次(CHANGELOG 中列出了相关调用)。如果客户端显示“does not match the tool's output schema”,说明它使用的是旧版架构:重新连接(Claude Code:输入 /mcp,然后重新连接 echelongraph),或重启客户端。
安全
请将漏洞私下报告至 [email protected],不要在公开问题中报告。相关政策、受支持版本和适用范围详见 SECURITY.md。
许可证
代码采用 MIT 许可证。
CVE Pulse 汇编(即 EchelonGraph 如何整合其 CVE 来源及其 EchelonGraph 评分)© EchelonGraph,依据 CVE Pulse 免费访问条款提供;其汇编所用的源记录仍受其发布者的条款约束。
暴露数量根据 Shodan 数据得出。Shodan 数据归 Shodan 所有,版权亦归 Shodan(© Shodan)。EchelonGraph 不主张拥有该数据或其版权。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。