关于 MCP Compliance
MCP Compliance 是用于检查 MCP 服务规范兼容性的 CLI、MCP 服务和程序化 API,面向开发与 CI 测试。它支持 HTTP 和 stdio 目标,并按规范版本运行测试、生成评分报告。
主要功能
- 01覆盖两版 MCP 规范测试
- 02自动检测或指定规范版本
- 03按声明能力调整测试
- 04生成 A–F 等级与评分
- 05支持 CI 严格模式及 JSON、SARIF
- 06提供 CLI、MCP 服务和 API
适用场景
- 01发布前验证 MCP 服务
- 02在 CI 中阻止必需测试失败
- 03检查传输、工具与资源行为
MCP 相关
作为 MCP 服务,它向 AI 助手暴露规范合规性测试能力;也能通过 CLI 或 API 测试 MCP 服务。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
工具
2收录的工具列表 · 更新于 3 周前
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| url | string | 是 | 要测试的 MCP 服务 URL(必须使用 HTTP 或 HTTPS) |
| auth | string | 否 | Authorization 请求头值(例如:"Bearer tok123") |
| only | array | 否 | 仅运行匹配这些类别或测试 ID 的测试 |
| skip | array | 否 | 跳过匹配这些类别或测试 ID 的测试 |
| headers | object | 否 | 在所有请求中附加的请求头(例如:{"X-Api-Key": "abc"}) |
| retries | integer | 否 | 失败测试的重试次数(默认:0,最大:10) |
| timeout | integer | 否 | 请求超时时间,单位为毫秒(默认:15000,最大:300000) |
| specVersion | enum | 否 | 要测试的 MCP 规范修订版。"auto"(默认)会探测服务器,并根据其支持的最新修订版进行评分;指定 "2025-11-25" 或 "2026-07-28" 可强制使用相应套件。auto | 2025-11-25 | 2026-07-28 |
详细介绍
@yawlabs/mcp-compliance
点击一次即可将其添加到本地 Yaw MCP 配置中,使其在每个 Yaw Terminal 会话中都可用。也可以按下文所述手动安装。
测试任意 MCP 服务是否符合规范。 两套测试套件——针对 MCP 2025-11-25 的 88 项测试,以及针对 MCP 2026-07-28 的 103 项测试——涵盖传输、生命周期、工具、资源、提示词、错误处理、架构验证和安全性。该工具会探测服务并根据其支持的最新规范修订版进行评分,也可以通过 --spec-version 固定版本。既适用于 HTTP 端点(https://my-server.com/mcp),也适用于 stdio 服务(npx @modelcontextprotocol/server-filesystem /tmp)。提供 CLI、MCP 服务和编程 API。
由 Yaw Labs 构建并维护。
为什么选择此工具?
MCP 服务的数量正在迅速增长,但大多数服务在发布时都没有经过合规性测试。传输处理故障、错误代码缺失、架构格式错误以及未提示的能力违规十分常见。手动编写测试脚本既繁琐又不完整。
此工具解决了这些问题:
- 两个规范修订版,一个工具 — 针对 MCP 2025-11-25(
initialize+ 会话时代)的 88 项测试,以及针对 MCP 2026-07-28(无状态、每个请求的_meta、server/discover、缓存提示、MRTR)的 103 项测试。两者都涵盖相同的 8 个类别:传输、生命周期、工具、资源、提示词、错误处理、架构验证和安全性。HTTP 专属测试(CORS、TLS、标头验证、速率限制)不会在 stdio 上运行:2025-11-25 测试套件在 HTTP 上运行 85 项测试,在 stdio 上运行 55 项;2026-07-28 测试套件则分别运行 99 项和 75 项。 - 自动检测修订版 — 一次
server/discover探测即可告知工具服务支持哪个时代;同时支持两个时代的服务将按 2026-07-28 评分,并附带警告。可通过--spec-version固定任一修订版。请参阅规范版本。 - 由能力驱动 — 测试会根据服务声明的能力进行调整。如果服务声明支持工具,工具测试就会成为必测项。服务未声明支持的功能不会导致误报。
- 分级评分 — 采用 A-F 字母等级和加权分数(必测测试占 70%,可选测试占 30%)。用一个数字即可传达合规情况。
- 适用于 CI —
--strict模式会在必测项失败时以代码 1 退出。可直接将其接入任何流水线。 - 引用规范 — 每项测试都链接到其所验证的 MCP 规范中的确切章节。测试内容和原因一目了然。
- 三种接口 — 面向用户的 CLI、面向 AI 助手的 MCP 服务,以及用于集成的编程 API。
- 公开的方法论 — 测试方法论和规则目录均采用开放许可(CC BY 4.0),任何人都可以据此构建兼容工具或派生规则。
快速开始
远程 HTTP 服务:
npx @yawlabs/mcp-compliance@latest test https://my-server.com/mcp
本地 stdio 服务(npm 上绝大多数 MCP 服务):
# Pass the command directly, Inspector-style
npx @yawlabs/mcp-compliance@latest test npx @modelcontextprotocol/server-filesystem /tmp
# Or a local build
npx @yawlabs/mcp-compliance@latest test node ./dist/server.js
# With env vars
npx @yawlabs/mcp-compliance@latest test -E GITHUB_TOKEN=$GITHUB_TOKEN -- npx @modelcontextprotocol/server-github
全局安装:
npm install -g @yawlabs/mcp-compliance
mcp-compliance test https://my-server.com/mcp
就是这样。你将看到彩色终端报告,其中包含字母等级(A-F)、逐项测试的通过/失败状态以及合规分数。
CLI 用法
HTTP 目标
# Terminal output with colors and grade
mcp-compliance test https://my-server.com/mcp
# JSON / SARIF for scripting + GitHub Code Scanning
mcp-compliance test https://my-server.com/mcp --format json
mcp-compliance test https://my-server.com/mcp --format sarif > compliance.sarif
# Strict mode for CI — exits 1 on required-test failure
mcp-compliance test https://my-server.com/mcp --strict
# Auth (shorthand or full header)
mcp-compliance test https://my-server.com/mcp --auth "Bearer tok123"
mcp-compliance test https://my-server.com/mcp -H "X-Api-Key: abc"
# Focus the run
mcp-compliance test https://my-server.com/mcp --only transport,lifecycle
mcp-compliance test https://my-server.com/mcp --skip prompts,resources
mcp-compliance test https://my-server.com/mcp --verbose
stdio 目标
将命令及其参数作为位置参数传递(MCP Inspector 风格)。如果目标所需的标志与我们的标志冲突,请使用 -- 消除歧义。
# npm-distributed stdio servers
mcp-compliance test npx -y @modelcontextprotocol/server-filesystem /tmp
mcp-compliance test uvx mcp-server-git
# Local build
mcp-compliance test node ./dist/server.js
# With env vars (repeatable -E, or --env-file)
mcp-compliance test -E API_KEY=secret -E REGION=us-east-1 -- npx my-server
mcp-compliance test --env-file .env -- node ./server.js
# Set working directory
mcp-compliance test --cwd ./services/mcp -- node ./dist/server.js
# Target uses a flag that collides with ours — use `--` to separate
mcp-compliance test --verbose -- node ./server.js --verbose
在 Windows 上,npx 和其他 .cmd 垫片会自动通过 shell 启动。
规范版本
该工具针对其支持的每个 MCP 规范修订版提供一套测试目录:2025-11-25(88 项测试:initialize 握手、会话、ping)和 2026-07-28(103 项测试:无状态、按请求设置的 _meta、server/discover、缓存提示、MRTR)。每次运行只对一个修订版进行评分,由 --spec-version 选择:
# auto (default): probe the server, grade the newest revision it speaks
mcp-compliance test https://my-server.com/mcp
# pin a revision — no probe, the named catalog runs regardless of what the server answers
mcp-compliance test https://my-server.com/mcp --spec-version 2026-07-28
mcp-compliance test https://my-server.com/mcp --spec-version 2025-11-25
# --list never connects: under auto (the default) it prints every catalog in its own
# section; --spec-version <date> previews just that one
mcp-compliance test --list --spec-version 2026-07-28 --transport stdio
auto 如何依据规范自身针对双时代客户端的规则作出判断:工具会发送一个符合规范的 2026-07-28 server/discover(通过 HTTP 时,它同时充当预检连接检查,因此检测不会增加额外的往返;通过 stdio 时,它是首次交互)。收到 DiscoverResult,或带有现代错误代码(-32020、-32021、-32022)的 JSON-RPC 错误时,会选择 2026-07-28。其他任何情况——-32601、-32000、400“未初始化”、404、HTML 页面,或超时内无响应——都会选择 2025-11-25;如果 401/403 没有现代错误正文,也会选择 2025-11-25,说明中会指出无法确定所属时代,且报告中的第一条警告(适用于所有输出格式)会说明以下评分没有参考意义。如果未配置 Authorization 标头,401 或携带 WWW-Authenticate: Bearer 质询的 403 表示需要身份验证(说明为 authentication required -- pass --auth;警告建议使用 --auth 重新运行)。如果已配置该标头,401 或 Bearer 质询中带有 error 参数的 403 表示凭据被拒绝(说明为 credential rejected -- check --auth;警告会指出该错误中的原因,例如 invalid_token 表示令牌无效或已过期,insufficient_scope 表示缺少作用域或权限)。其他任何 403(例如 SDK 在隧道主机名后进行的 Host 验证、Origin 验证或网关拦截)都会采用中性措辞,无论是否有标头:说明为 forbidden -- Host/Origin validation, a gateway, or missing credentials(有标头时为 ... or token permissions);如果正文包含 JSON-RPC 错误消息,警告会引用该消息,并优先指出 Host/Origin 验证和任何网关;未配置标头时,只有服务器确实要求凭据才会建议使用 --auth。回退逻辑不会只依据某个特定错误代码;即使旧版服务器忽略未知方法,也仍会被正确分类,只是需要等到超时后才会确定。报告头部会注明原因(auto-detected from server/discover: supportedVersions [2026-07-28]、... JSON-RPC error -32601, legacy、... no response, legacy),JSON 中的 warnings 也会包含相同说明(Spec version auto-detected as <v> (server/discover -> <reason>). Pin with --spec-version to override.)。无法访问的服务器会按 2025-11-25 进行评分,因此所有需要服务器的测试都会失败(如果没有收到任何内容,2026-07-28 的事后扫描也会失败,而不会在空记录上通过)。
探测有两项超时限制。在 stdio 模式下,超时由 --startup-timeout 限定;在终端模式下,约 2 s 后会在 stderr 上显示一条暗色状态行,说明正在等待以及跳过 --spec-version 2025-11-25,这样,对于遇到未知方法时保持静默的旧版服务,就不会让人误以为程序卡住了。如果子进程在探测时退出(例如,某个旧版服务的分发器会对 initialize 之前的未知方法抛出异常),报告会显示警告,其中包含退出代码和 stderr 的末尾内容,随后启动一个新实例,并按 2025-11-25 为其评分。如果新实例也在启动时退出,尚未响应 initialize,警告会说明服务器无论是否进行探测都会在启动时退出,并将排查重点指向命令、参数和环境,而不是建议固定版本。benchmark 也会以同样方式重新启动被探测终止的子进程,使用自己的 --startup-timeout 限制探测时间,打印相同的状态行,并在输出中附带警告。在 HTTP 模式下,探测即预检,超时由 --preflight-timeout 限定;如果预检超时,会在 --startup-timeout 限定的时间内再探测一次,然后才将本次运行默认按 2025-11-25 处理,这样,冷启动缓慢的服务就会按其实际所属时期评分,而不会被判定为无法访问。
能响应两个时期的服务器(基于官方 SDK 2.0 构建的服务器默认如此)会按 2026-07-28 评分,报告会附带警告,指出另一个时期以及如何固定版本。判断依据是 supportedVersions 列出了 2025-11-25,或 信息性探测 lifecycle-dual-era 收到了 InitializeResult(SDK 2.0 服务器只会公布现代版本,但仍会响应 initialize;在 stdio 模式下,该探测会发往一个新进程,因为双时期服务器会按进程固定时期)。如需同时评估其旧版行为,请使用 --spec-version 2025-11-25 再运行一次。若服务器能响应 initialize,却拒绝符合规范的 server/discover,则它并非双时期,而是仅支持旧版:lifecycle-dual-era 会显示 legacy-only: ...,警告会提示你使用 --spec-version 2025-11-25(或 auto)重新运行。报告中的 specVersion 始终是解析后的版本,绝不会是 auto。
固定版本运行会按指定版本运行对应目录中的测试,不论服务器如何响应,但有两点说明需要注意。在 HTTP 模式下,预检仍会发送现代的 server/discover,因此,如果服务器明确以另一时期响应,固定版本运行会收到警告(Server answered the 2026-07-28 server/discover probe with a DiscoverResult ...; this run is pinned to 2025-11-25. Re-run with --spec-version 2026-07-28 (or auto) to grade it)。警告必须有时期信号作为依据——DiscoverResult、JSON-RPC 正文或 HTTP 4xx;5xx 或 HTML 页面无法表明所属时期,因此不会触发警告。若双时期服务器的 supportedVersions 列出了 2025-11-25,且运行固定到 2025-11-25,则会提示 Server is dual-era (...); this run grades its 2025-11-25 side.,而不是建议切换到另一个固定版本。另外,仅支持旧版的服务器若固定到 2026-07-28,则 lifecycle-discover 和六项 _meta/标准标头拒绝测试都会标记为不可评估:拒绝符合规范的 server/discover 的服务器,即使也拒绝格式错误的变体,也不能证明任何问题,因此这些必需测试会判定为失败,而不会记为通过。
在 CI 中依赖 auto 时,需要了解以下两点:
- 即使配置未变,评分也可能变化。 服务器升级到支持 2026-07-28 的 SDK 后,
auto就会切换测试套件:测试 ID、必需测试集和新的基准都会不同。如果你希望只有在明确指定时才切换套件,请固定--spec-version(或在配置文件中设置"specVersion")。 diff拒绝比较不同版本的报告(ID 只能在同一目录中比较),并会告知你应该固定哪个--spec-version。SARIF 上传会按版本分别跟踪(automationDetails.id为mcp-compliance/<specVersion>/),因此切换版本会创建一组新的提醒,而不会悄无声息地关闭旧提醒。--only/--skip的值会与已解析的测试目录进行匹配;如果某个值在其中匹配不到任何项(例如在 2026-07-28 的运行中指定lifecycle-init),系统会发出警告,而不会默默地执行空测试。空测试会显示No tests ran -- check --only/--skip,而不是All tests passed。在 2026-07-28 的测试套件中,筛选后的运行仍会测量服务:被筛掉的功能测试原本会缓存的tools/list/resources/list/prompts/list结果,会按需获取一次,由需要这些结果的测试调用。因此,--only security、--only schema或--only lifecycle会执行实际检查,而不会因跳过测试而误报通过。如果此类列表调用失败,而对应的-list测试被筛掉了,那么需要该列表的检查会根据记录的原因判定失败(tools/list failed (JSON-RPC error -32603 (boom)); no tools list to validate),而不会在列表调用已损坏的情况下仍评为 A。对于只匹配因目标传输方式而被禁用的测试(在 stdio 服务上指定transport-post)的--only值,系统也会发出警告;--list会在其列出的每个测试目录下显示相同的警告。
选项
| 选项 | 适用对象 | 说明 |
|---|---|---|
--spec-version <v> | 两者 | 要评测的 MCP 规范修订版:auto(探测服务,优先使用最新版本)、2025-11-25 或 2026-07-28(默认值:auto,或配置中的 specVersion)。请参阅规范版本 |
--format <format> | 两者 | 输出格式:terminal、json、sarif、github、markdown 或 html(默认值:terminal) |
--config <path> | 两者 | 从配置文件加载默认值(默认值:当前工作目录中的 mcp-compliance.config.json) |
--output <file> | 两者 | 运行后将本地 SVG 徽章写入指定路径 |
--list | 两者 | 打印在当前筛选条件下将运行的测试 ID,然后退出(不建立连接;使用默认值 --spec-version auto 时,每个目录会单独列出;使用 --spec-version <date> 时则预览指定版本) |
--transport <kind> | 两者 | 按 http 或 stdio 筛选(仅在未提供目标且使用 --list 时生效) |
--strict | 两者 | 任何必需测试失败时都以代码 1 退出(用于 CI) |
--min-grade <grade> | 两者 | 等级低于此门槛(A–F)时以代码 1 退出 |
-H, --header <h> | HTTP | 为所有请求添加标头,格式为 "Key: Value"(可重复指定) |
--auth <token> | HTTP | -H "Authorization: <token>" 的简写 |
-E, --env <var> | stdio | 为 stdio 命令设置环境变量,格式为 "KEY=VALUE"(可重复指定) |
--env-file <path> | stdio | 从文件加载环境变量(每行一个 KEY=VALUE) |
--cwd <dir> | stdio | stdio 命令的工作目录 |
--watch | stdio | 当前目录下的文件发生变化时重新运行测试套件(防抖 500 ms;忽略 node_modules、.git、dist、coverage、构建缓存以及日志、交换和临时文件),直到按下 Ctrl+C。仅适用于 stdio 目标,且 --format 只能为 terminal、markdown 或 html;--strict 和 --min-grade 不适用 |
--timeout <ms> | 两者 | 初始交互后每个请求的超时时间,单位为毫秒(默认值:15000) |
--startup-timeout <ms> | 两者 | 为服务的首次响应设定的时限:auto 模式下的 stdio 时代探测、任一传输方式上的 2025-11-25 initialize 握手,以及 HTTP 预检超时时发送的第二次时代探测(默认值:max(--timeout, 60000);包含 stdio 服务启动前冷缓存中的 npx 获取时间) |
--preflight-timeout <ms> | HTTP | server/discover 预检请求的截止时间;在 auto 模式下,该请求也用于时代探测。此处超时后,会在 --startup-timeout 内再次探测,然后在运行开始时默认使用 2025-11-25(默认值:min(--timeout, 10000)) |
--retries <n> | 两者 | 失败测试的重试次数(默认值:0) |
--only <items> | 两者 | 仅运行与这些类别或测试 ID 匹配的测试(以逗号分隔) |
--skip <items> | 两者 | 跳过与这些类别或测试 ID 匹配的测试(以逗号分隔) |
--concurrency <n> | 两者 | 同时运行的可安全并行测试的最大数量(默认值:1;调高可缩短总耗时,但可能影响对时序敏感的服务) |
--verbose | 两者 | 运行时打印每项测试结果,显示为 PASS、FAIL 或 SKIP(同时转发 stdio stderr) |
--no-color | 两者 | 禁用彩色输出(设置 NO_COLOR 环境变量也有相同效果) |
CI 集成
GitHub Action(可直接添加到任意 .github/workflows/*.yml 文件中):
- uses: YawLabs/mcp-compliance@v0
with:
target: 'node ./dist/server.js' # or a URL like https://my-server.com/mcp
format: github # ::error per required failure, ::warning per optional failure and per report warning, ::notice summary with the spec version
strict: 'true' # exit non-zero if any required test fails
min-grade: 'A' # also exit if grade slips
spec-version: auto # or pin 2025-11-25 / 2026-07-28; the resolved value is the `spec-version` output
手动调用 CLI:
# GitHub Actions: ::error per required failure, ::warning per optional failure and per
# report warning, and a ::notice summary naming the grade and the spec version graded
mcp-compliance test https://my-server.com/mcp --format github --strict
# Slack/Linear/PR comment: drop the body straight into a comment
mcp-compliance test https://my-server.com/mcp --format markdown > report.md
# HTML report (self-contained, share anywhere — issue comments, S3, GitHub Pages)
mcp-compliance test https://my-server.com/mcp --format html > report.html
# Block release if grade slips below B
mcp-compliance test https://my-server.com/mcp --min-grade B
# Preview which tests will run before connecting (handy for --only/--skip authoring)
mcp-compliance test --list --transport stdio --skip security --spec-version 2026-07-28
# Diff two runs — exit 1 if anything that was passing (or skipped) is now failing;
# checks that start or stop skipping are listed as "Newly skipped" / "No longer skipped" and never fail the diff.
# A baseline from an earlier version works too: its skips are read from their wording, and both
# reports are scored from their results as this version scores them (skips left out).
# Both reports must grade the same spec revision; pin --spec-version on both runs
# so a server upgrade cannot flip the suite under the baseline.
mcp-compliance test https://my-server.com/mcp --format json --spec-version 2026-07-28 > current.json
mcp-compliance diff baseline.json current.json
# Watch mode for stdio dev loop — re-runs on file changes in cwd
mcp-compliance test --watch -- node ./dist/server.js
# Latency benchmark (--spec-version and --startup-timeout work as for test)
mcp-compliance benchmark -- node ./dist/server.js -r 200 -c 4
Docker:
docker run --rm ghcr.io/yawlabs/mcp-compliance test https://my-server.com/mcp
创建配置文件
mcp-compliance init
交互式提示会引导你设置传输方式(http/stdio)、命令或 URL、环境变量、超时时间和严格模式,然后写入可提交的 mcp-compliance.config.json。
配置文件
将 mcp-compliance.config.json 纳入版本控制,这样 CI 和本地开发流程就可以不带参数运行 mcp-compliance test。支持的位置(按搜索顺序):mcp-compliance.config.json、.mcp-compliancerc.json、.mcp-compliancerc,以及 package.json 的 "mcp-compliance" 字段。传入 --config <path> 可加载指定文件。
HTTP:
{
"target": {
"type": "http",
"url": "https://my-server.com/mcp",
"headers": { "Authorization": "Bearer tok123" }
},
"timeout": 20000,
"specVersion": "2026-07-28",
"strict": true
}
stdio:
{
"target": {
"type": "stdio",
"command": "node",
"args": ["./dist/server.js"],
"env": { "LOG_LEVEL": "error" }
},
"skip": ["security"],
"strict": true
}
优先级:CLI 标志 > 配置文件 > 默认值。任何字段都可以通过命令行覆盖。specVersion 接受 auto、2025-11-25 或 2026-07-28,并在 0.19 中新增——较旧的工具版本(包括 0.18.x)会将设置了该字段的配置视为包含未知键并拒绝,因此凡是使用此配置的地方,都应固定为 @yawlabs/mcp-compliance@^0.19。
本地 SVG 徽章
生成反映实际评级的本地 SVG,并将其提交到代码库:
mcp-compliance test https://my-server.com/mcp --output badge.svg
mcp-compliance test node ./dist/server.js --output badge.svg
然后将其嵌入 README:

88 项测试检查的内容(2025-11-25)
2025-11-25 目录对 initialize + 会话时代的协议进行评级。对于所有未响应现代 server/discover 的服务,它是 --spec-version auto 选择的版本。
传输(16 项测试)
仅 HTTP(13 项):
- transport-post — 服务接受 HTTP POST 请求(必需)
- transport-content-type — 响应类型为 application/json 或 text/event-stream(必需)
- transport-notification-202 — 通知恰好返回 202 Accepted
- transport-content-type-reject — 拒绝非 JSON 请求 Content-Type
- transport-session-id — 初始化后强制要求 MCP-Session-Id
- transport-session-invalid — 未知会话 ID 返回 404
- transport-get — GET 返回 SSE 流或 405
- transport-delete — 接受 DELETE 请求或返回 405
- transport-batch-reject — 拒绝 JSON-RPC 批量请求(必需)
- transport-content-type-init — 初始化响应具有有效的内容类型
- transport-get-stream — 携带会话的 GET 请求返回 SSE 或 405
- transport-concurrent — 处理并发请求
- transport-sse-event-field — SSE 响应包含必需的 event: message 字段
仅 stdio(3 项):
- stdio-framing — 以换行符分隔的 JSON 帧格式(必需)
- stdio-unicode — UTF-8 Unicode 往返可保留非 ASCII 负载
- stdio-unknown-method-recovers — 未知方法返回 -32601,且服务继续运行
生命周期(21 项测试)
- **lifecycle-init** — 初始化握手成功(必需) - **lifecycle-proto-version** — 返回有效的 YYYY-MM-DD 协议版本(必需) - **lifecycle-server-info** — 包含带有名称的 serverInfo - **lifecycle-capabilities** — 返回 capabilities 对象(必需) - **lifecycle-jsonrpc** — 响应符合有效的 JSON-RPC 2.0 格式(必需) - **lifecycle-ping** — 响应 ping 方法(必需) - **lifecycle-instructions** — 如果存在,Instructions 字段为有效字符串 - **lifecycle-id-match** — 响应 ID 与请求 ID 匹配(必需) - **lifecycle-string-id** — 支持字符串请求 ID(JSON-RPC 2.0) - **lifecycle-version-negotiate** — 妥善处理未知协议版本 - **lifecycle-reinit-reject** — 拒绝第二次 initialize 请求 - **lifecycle-logging** — 接受 logging/setLevel(如果声明了 logging capability,则为必需) - **lifecycle-completions** — 接受 completion/complete(如果声明了 completions capability,则为必需) - **lifecycle-cancellation** — 处理取消通知 - **lifecycle-progress** — 妥善处理进度通知 - **lifecycle-list-changed** — 接受已声明 capabilities 的 listChanged 通知 - **lifecycle-progress-token** — 支持通过 SSE 在请求中使用进度令牌 - **lifecycle-sampling-capability** — 对服务端使用客户端 sampling capability 进行提示性检查 - **lifecycle-roots-capability** — 对服务端使用客户端 roots capability 进行提示性检查 - **lifecycle-elicitation-capability** — 对 2025-11-25 客户端 elicitation capability 进行提示性检查 - **lifecycle-meta-tolerance** — 服务端忽略传入请求中未知的 `_meta` 字段工具(4 项测试)
- tools-list — tools/list 返回有效数组(如果声明了 tools capability,则为必需)
- tools-call — tools/call 返回格式正确的响应
- tools-pagination — tools/list 支持基于游标的分页
- tools-content-types — 工具内容项具有有效类型
资源(5 项测试)
- resources-list — resources/list 返回有效数组(如果声明了 resources capability,则为必需)
- resources-read — resources/read 返回内容项
- resources-templates — resources/templates/list 可正常工作或返回 method-not-found
- resources-pagination — resources/list 支持基于游标的分页
- resources-subscribe — 资源订阅/取消订阅(如果声明了 subscribe capability,则为必需)
提示词(3 项测试)
- prompts-list — prompts/list 返回有效数组(如果声明了 prompts capability,则为必需)
- prompts-get — prompts/get 返回有效消息
- prompts-pagination — prompts/list 支持基于游标的分页
错误处理(10 项测试)
- error-unknown-method — 对未知方法返回 JSON-RPC 错误(必需)
- error-method-code — 使用正确的 -32601 错误代码
- error-invalid-jsonrpc — 处理格式错误的 JSON-RPC(必需)
- error-invalid-json — 处理无效的 JSON 请求体
- error-missing-params — 对缺少 name 的 tools/call 返回错误
- error-parse-code — 对无效 JSON 返回 -32700
- error-invalid-request-code — 对无效请求返回 -32600
- tools-call-unknown — 对不存在的工具名称返回错误
- error-capability-gated — 拒绝未声明 capabilities 对应的方法
- error-invalid-cursor — 妥善处理无效的分页游标
架构验证(6 项测试)
- **tools-schema** — 所有工具都具有有效的名称和 inputSchema(声明了 tools 能力时为必需项) - **tools-annotations** — 存在时,工具注释有效 - **tools-title-field** — 工具包含 title 字段(2025-11-25) - **tools-output-schema** — 包含 outputSchema 的工具有效(2025-11-25) - **prompts-schema** — 提示词具有有效的 name 字段(声明了 prompts 能力时为必需项) - **resources-schema** — 资源具有有效的 uri 和 name(声明了 resources 能力时为必需项)安全性(23 项测试)
- security-auth-required — 拒绝未经身份验证的请求
- security-www-authenticate — 401 响应包含 WWW-Authenticate 标头
- security-auth-malformed — 拒绝格式错误的身份验证凭据
- security-tls-required — 强制使用 HTTPS/TLS
- security-session-entropy — 会话 ID 具有高熵
- security-session-not-auth — 会话 ID 不会绕过身份验证
- security-oauth-metadata — 存在受保护资源元数据端点(RFC 9728)
- security-token-in-uri — 拒绝查询字符串中的身份验证令牌
- security-cors-headers — CORS 标头受到严格限制
- security-origin-validation — 验证 Origin 标头以防范 DNS 重绑定
- security-command-injection — 防范工具参数中的命令注入
- security-sql-injection — 防范工具参数中的 SQL 注入
- security-path-traversal — 防范工具参数中的路径遍历
- security-ssrf-internal — 防范针对内部网络的 SSRF
- security-oversized-input — 妥善处理超大输入
- security-extra-params — 拒绝或忽略多余的工具参数
- security-tool-schema-defined — 所有工具都定义了 inputSchema
- security-tool-rug-pull — 工具定义在多次调用之间保持稳定
- security-tool-description-poisoning — 工具描述不含注入模式
- security-tool-cross-reference — 工具不会通过名称引用其他工具
- security-error-no-stacktrace — 错误响应不会泄露堆栈跟踪
- security-error-no-internal-ip — 错误响应不会泄露内部 IP
- security-rate-limiting — 已实施速率限制
这 103 项测试的检查内容(2026-07-28)
2026-07-28 版目录评估无状态、按请求传递 _meta 的时代:使用 server/discover 而不是 initialize,不使用会话,在每个可缓存结果上提供缓存提示,在每个结果上提供 resultType,使用 MRTR input_required 结果而不是由服务端发起的请求,并对缺失资源返回 -32602。与 2025-11-25 列表共用的 ID 指向同一功能,但两个目录的评判标准和必选标记可能不同(stdio-framing 和 error-invalid-jsonrpc 在此处为可选,error-method-code 为必选),因此 ID 只能在同一目录内比较;判定结果有变化的检查会获得新 ID,而 diff 会拒绝比较不同修订版的报告。事后测试会扫描运行期间服务端发送的每条消息记录(如果没有收到任何消息,则会判定失败,而不是空洞地通过)。_meta 和标准标头拒绝测试可追溯归因:只有在提供了符合规范的 server/discover 时,拒绝才会计入,因此仅支持旧版协议的服务端使用此目录测试时,这些测试会以“无法评估”判定失败。设置阶段的 server/discover 在收到 429 后会重发一次,每条读取它的规则都会以最终采用的答复作为判定依据。会将任何拒绝计入的检查——transport-batch-reject、transport-content-type-reject、lifecycle-jsonrpc、lifecycle-subscriptions-listen 和六项错误检查(error-unknown-method、error-invalid-jsonrpc、error-invalid-json、error-missing-params、error-capability-gated、error-invalid-cursor),以及 error-parse-code 和 error-invalid-request-code 接受的无响应正文 4xx——也会确认答复来自谁:网关返回的带 -32001 正文的 401、看起来像拒绝身份验证的 403(未使用 --auth 时,任何 Bearer 质询都符合;使用 --auth 时,需带有 error 参数)、重发一次后仍为 429 的 429,或者任何其他 403——若符合规范的同类请求无法通过(server/discover;对于 error-invalid-cursor,则是未带游标的列表方法),则判定为“无法评估”;若 5xx 不含该检查专属的错误代码,则判定为服务端处理请求失败。lifecycle-jsonrpc 的探测本身就是符合规范的 server/discover,因此不会发送同类请求:对此探测返回的任何 403,以及不带服务端专属拒绝代码的 5xx,都会判定为“无法评估”。如果设置阶段的 server/discover 本身遭到拒绝,transport-batch-reject 和 transport-content-type-reject 也会将任何拒绝判定为“无法评估”。tools-call-unknown 目前尚未采用这种判定方式:网关对其 tools/call 返回 -32001 仍会使其通过。四项注入测试会从最安全且包含字符串参数的注解层级中选择单个(工具,参数)目标——依次为 readOnlyHint: true、destructiveHint: false、未标注的工具(规范默认 destructiveHint 为 true),然后是 destructiveHint: true;警告中会列出跳过和实际探测的工具——并使用符合架构的占位值填充其他必需参数,同时报告被拒绝、返回且无执行证据,或从未到达工具的载荷数量(全部未到达表示结果不确定,会附带警告并标记为跳过)。在 stdio 上,如果检查自身的请求导致服务端退出(注入载荷、1 MB 参数、未知工具参数、stdio-unicode 的中日韩文字/表情符号探测,以及 lifecycle-progress-token 的某次调用),则会重启服务端,以供之后的检查使用;每次都会重启,包括 --retries 指定的重试。安全检查和 stdio-unicode 会因服务端退出而失败;随后 security-tool-rug-pull 会比较新进程的两份列表。stdio-unicode 和 lifecycle-progress-token 也会将作答后立即退出的子进程计为失败(答复后会紧接着发送普通的 server/discover);若 stdio-unicode 收到答复后服务端停止响应,该检查也会失败。若存在只读且无需参数的工具,security-rate-limiting 会向其突发发送 50 个 tools/call 请求;突发请求未造成问题即可通过,并会附带警告。
传输(20 项测试)
仅 HTTP(15 项): - **transport-post** — 接受 HTTP POST(必需) - **transport-content-type** — 响应为 JSON 或 SSE(必需) - **transport-content-type-reject** — 拒绝非 JSON 请求 Content-Type - **transport-batch-reject** — 拒绝 JSON-RPC 批量请求(必需) - **transport-notification-202** — 通知返回 202 Accepted - **transport-concurrent** — 处理并发请求 - **transport-get-removed** — GET 返回 405 - **transport-delete-removed** — DELETE 返回 405 - **transport-session-ignored** — 忽略 Mcp-Session-Id - **transport-header-version-required** — 拒绝缺少 MCP-Protocol-Version 标头的请求(必需) - **transport-header-version-mismatch** — 拒绝标头/_meta 版本不匹配的请求(必需) - **transport-header-method-required** — 拒绝缺少 Mcp-Method 标头的请求(必需) - **transport-header-method-mismatch** — 拒绝 Mcp-Method 与请求正文不匹配的请求(必需) - **transport-header-name-mismatch** — 拒绝 Mcp-Name 与请求正文不匹配的请求 - **transport-header-case-insensitive** — 标头名称不区分大小写两种传输方式均适用(1 项,事后检查):
- transport-no-server-requests — 任何流上都没有由服务端发起的请求(必需)
仅 stdio(4 项):
- stdio-framing — 以换行符分隔的 JSON 帧
- stdio-unicode — UTF-8 Unicode 往返
- stdio-unknown-method-recovers — 遇到未知方法后恢复
- stdio-cancellation — 忽略对未知请求的取消
生命周期(22 项测试)
- lifecycle-discover — server/discover 返回 DiscoverResult(必需)
- lifecycle-discover-versions — supportedVersions 格式正确(必需)
- lifecycle-discover-caching — server/discover 包含缓存提示(必需)
- lifecycle-jsonrpc — 响应是有效的 JSON-RPC 2.0(必需)
- lifecycle-id-match — 响应 id 与请求 id 匹配(必需)
- lifecycle-string-id — 支持字符串请求 id
- lifecycle-capabilities — 返回 capabilities 对象(必需)
- lifecycle-server-info — 在 _meta 中包含 serverInfo
- lifecycle-instructions — Instructions 字段有效
- lifecycle-meta-required — 拒绝不含 _meta 的请求(必需)
- lifecycle-meta-protocol-version-required — 拒绝 _meta 不含 protocolVersion 的请求(必需)
- lifecycle-meta-client-capabilities-required — 拒绝 _meta 不含 clientCapabilities 的请求(必需)
- lifecycle-meta-client-info-optional — 接受不含 clientInfo 的 _meta(必需)
- lifecycle-version-unsupported — 拒绝不支持的协议版本(必需)
- lifecycle-removed-methods — 拒绝已移除的旧版方法
- lifecycle-dual-era — 旧版 initialize 探测(仅供参考)
- lifecycle-capability-handlers-match — 能力声明与处理程序相符
- lifecycle-subscriptions-listen — subscriptions/listen 会先确认
- lifecycle-log-level-gating — 未设置 logLevel 时不发送日志通知(必需)
- lifecycle-meta-tolerance — 容忍未知的 _meta 键
- lifecycle-completions — 接受 completion/complete(声明了 completions 能力时必需)
- lifecycle-progress-token — 进度通知会回显令牌
工具(6 项测试)
- tools-list — tools/list 返回有效响应(声明了 tools 能力时必需)
- tools-list-caching — tools/list 包含缓存提示(声明了 tools 能力时必需)
- tools-list-deterministic-order — tools/list 顺序确定
- tools-call — tools/call 正确响应(声明了 tools 能力时必需)
- tools-content-types — 工具内容项的类型有效(声明了 tools 能力时必需)
- tools-pagination — tools/list 支持分页
资源(8 项测试)
- **resources-list** — resources/list 返回有效响应(如果声明了 resources 能力,则为必需项) - **resources-list-caching** — resources/list 携带缓存提示(如果声明了 resources 能力,则为必需项) - **resources-read** — resources/read 返回内容(如果声明了 resources 能力,则为必需项) - **resources-read-caching** — resources/read 携带缓存提示(如果声明了 resources 能力,则为必需项) - **resources-not-found** — 不存在的资源返回 -32602(如果声明了 resources 能力,则为必需项) - **resources-templates** — resources/templates/list 返回有效响应 - **resources-templates-caching** — resources/templates/list 携带缓存提示 - **resources-pagination** — resources/list 支持分页提示词(4 项测试)
- prompts-list — prompts/list 返回有效响应(如果声明了 prompts 能力,则为必需项)
- prompts-list-caching — prompts/list 携带缓存提示(如果声明了 prompts 能力,则为必需项)
- prompts-get — prompts/get 返回有效消息(如果声明了 prompts 能力,则为必需项)
- prompts-pagination — prompts/list 支持分页
错误处理(12 项测试)
- error-unknown-method — 未知方法返回 JSON-RPC 错误(必需)
- error-method-code — 未知方法使用 -32601(必需)
- error-invalid-jsonrpc — 处理格式错误的 JSON-RPC
- error-invalid-json — 处理无效的 JSON 请求体
- error-parse-code — JSON 无效时返回 -32700
- error-invalid-request-code — 请求无效时返回 -32600
- error-missing-params — 不带 name 的 tools/call 返回错误
- tools-call-unknown — 未知工具名称返回错误
- error-capability-gated — 拒绝未声明能力对应的方法
- error-invalid-cursor — 处理无效的分页游标
- error-id-echo — 错误响应回显请求 id
- error-retired-codes — 不使用已弃用的错误代码
架构验证(10 项测试)
- tools-schema — 所有工具都有 name 和 inputSchema
- tools-annotations — 工具注释有效
- tools-title-field — 工具包含 title 字段
- tools-output-schema — 带有 outputSchema 的工具有效
- prompts-schema — 提示词有 name 字段
- resources-schema — 资源有 uri 和 name
- schema-result-type — 每个结果都带有 resultType(必需)
- schema-no-input-required-on-lists — input_required 仅用于 MRTR 方法(必需)
- schema-input-required-shape — InputRequiredResult 格式正确
- schema-wire-valid — 消息符合 2026-07-28 架构
安全(21 项测试)
- **security-auth-required** — 拒绝未经身份验证的请求 - **security-www-authenticate** — 401 响应包含 WWW-Authenticate - **security-auth-malformed** — 拒绝格式错误的身份验证凭据 - **security-tls-required** — 强制使用 HTTPS/TLS - **security-oauth-metadata** — 受保护资源元数据端点存在 - **security-token-in-uri** — 拒绝查询字符串中的身份验证令牌 - **security-cors-headers** — CORS 标头限制严格 - **security-origin-validation** — 验证 Origin 标头 - **security-command-injection** — 防止工具参数中的命令注入 - **security-sql-injection** — 防止工具参数中的 SQL 注入 - **security-path-traversal** — 防止工具参数中的路径遍历 - **security-ssrf-internal** — 防止针对内部网络的 SSRF - **security-oversized-input** — 妥善处理超大输入 - **security-extra-params** — 拒绝或忽略多余的工具参数 - **security-tool-schema-defined** — 所有工具均定义 inputSchema - **security-tool-rug-pull** — 工具定义在多次调用间保持稳定 - **security-tool-description-poisoning** — 工具描述不含注入模式 - **security-tool-cross-reference** — 工具不会通过名称引用其他工具 - **security-error-no-stacktrace** — 错误响应不会泄露堆栈跟踪 - **security-error-no-internal-ip** — 错误响应不会泄露内部 IP - **security-rate-limiting** — 已启用速率限制评分
| 等级 | 分数 |
|---|---|
| A | 90-100 |
| B | 75-89 |
| C | 60-74 |
| D | 40-59 |
| F | 0-39 |
必需测试占总分的 70%,可选测试占 30%,按实际测得结果的测试计算。未测得任何结果的测试(跳过项)完全不计入分数,既不算通过也不算失败;当所有必需测试或所有可选测试都被跳过时,另一组测试将占据全部分数;如果一次运行中的所有测试都被跳过,则得分为 0(F),与没有运行任何测试的情况相同。终端、Markdown、HTML 和 GitHub 报告、SARIF 调用属性(note)以及 MCP mcp_compliance_test 工具都会显示“没有测试测得任何结果”;JSON 报告会在计数中显示这一点(summary.skipped 等于 summary.total)。跳过项仍计入通过总数(summary.passed 和类别计数);每种报告格式都会统计或列出它们(终端会在 SKIPPED CHECKS 下列出),终端类别进度条和 HTML 类别卡片按实际测得的结果评分,--verbose 会将跳过项显示为 SKIP,而 diff 会列出开始或停止跳过的检查。0.19.0 及更早版本生成的报告会将跳过项计为通过,因此相同结果的得分会更高。分数下降幅度取决于运行情况:在参考服务上,四舍五入后的分数没有变化;但随着某个测试组中的失败数与跳过数增加,分数降幅也会增大,甚至可能使必需检查全部通过的服务降低一个完整等级;大多数检查未测得结果时,分数可能下降好几个等级。diff 会按照此版本的方式,根据结果为两份报告评分,因此与 0.19.0 及更早版本生成的基准报告比较时仍然公平,并会注明该文件记录的分数。请参阅方法文档中的完整评分算法。
CI 集成
# GitHub Actions example
- name: MCP Compliance Check
run: npx @yawlabs/mcp-compliance@latest test ${{ env.MCP_SERVER_URL }} --strict
# With JSON output for parsing
- name: MCP Compliance Check
run: |
npx @yawlabs/mcp-compliance@latest test ${{ env.MCP_SERVER_URL }} --format json > compliance.json
cat compliance.json | jq '.grade'
# With retries for flaky network conditions
- name: MCP Compliance Check
run: npx @yawlabs/mcp-compliance@latest test ${{ env.MCP_SERVER_URL }} --strict --retries 2 --timeout 30000
# SARIF output for GitHub Code Scanning
- name: MCP Compliance Check
run: npx @yawlabs/mcp-compliance@latest test ${{ env.MCP_SERVER_URL }} --format sarif > compliance.sarif
- name: Upload SARIF
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: compliance.sarif
MCP 服务(适用于 Claude Code、Cursor 等)
此软件包还提供一个 MCP 服务,其中包含 2 个工具,可在 Claude Code、Cursor 或任何 MCP 客户端中使用。
设置
Claude Code(单行命令):
claude mcp add mcp-compliance -- npx -y @yawlabs/mcp-compliance@latest mcp
或在项目根目录中创建 .mcp.json:
macOS / Linux / WSL:
{
"mcpServers": {
"mcp-compliance": {
"command": "npx",
"args": ["-y", "@yawlabs/mcp-compliance@latest", "mcp"]
}
}
}
Windows:
{
"mcpServers": {
"mcp-compliance": {
"command": "cmd",
"args": ["/c", "npx", "-y", "@yawlabs/mcp-compliance@latest", "mcp"]
}
}
}
提示: 此文件可以安全地提交到代码仓库,不包含任何机密信息。
重启 MCP 客户端,并在出现提示时批准该服务。
工具
- mcp_compliance_test — 针对 HTTP MCP 端点(URL)运行完整的合规性测试套件。支持身份验证、自定义标头、超时、重试、类别/测试筛选,以及
specVersion(auto|2025-11-25|2026-07-28,默认值为auto)。返回等级、分数、解析后的specVersion和详细结果(每项测试均标记为 PASS、FAIL 或 SKIP;Tests 行会统计跳过项)。stdio 目标仅支持 CLI。 - mcp_compliance_explain — 说明特定测试 ID 检查的内容及其重要性,并附上规范章节链接。ID 按目录划分:传入
specVersion可读取单个目录,省略则搜索两个目录(共享 ID 会在每个套件中各说明一次,并注明所需标志/类别是否也不同;仅存在于另一个套件中的 ID 则会特别指出)。
所有工具都带有 MCP 工具注解(readOnlyHint、destructiveHint、idempotentHint、openWorldHint),因此 MCP 客户端可以跳过安全操作的确认对话框。
编程方式使用
import { runComplianceSuite } from '@yawlabs/mcp-compliance';
const report = await runComplianceSuite('https://my-server.com/mcp');
console.log(`Grade: ${report.grade} (${report.score}%)`);
// With options
const report2 = await runComplianceSuite('https://my-server.com/mcp', {
headers: { 'Authorization': 'Bearer tok123' },
timeout: 30000,
retries: 1,
only: ['transport', 'lifecycle'],
specVersion: '2026-07-28', // 'auto' (default) | '2025-11-25' | '2026-07-28'
});
console.log(report2.specVersion); // always the resolved revision, never 'auto'
// Per-revision catalogs and helpers
import { getTestDefinitions, specBaseFor, SUPPORTED_SPEC_VERSIONS } from '@yawlabs/mcp-compliance';
getTestDefinitions('2026-07-28'); // 103 TestDefinitions; TEST_DEFINITIONS stays the 2025-11-25 list
specBaseFor(report2.specVersion); // base URL for that revision's spec links
// Live progress for streaming UIs (e.g. server-sent-events to a browser)
await runComplianceSuite('https://my-server.com/mcp', {
onTestComplete: (result) => {
// result has the full TestResult: id, name, category, required,
// passed, skipped (true when the check measured nothing), details,
// durationMs, specRef. Push it to your client. (onProgress carries no
// skip flag: a skip arrives there as passed.)
sendToClient(result);
},
// Pre-test status lines: the stdio era probe still waiting after ~2 s,
// or an HTTP preflight timeout being re-probed within startupTimeout.
// The CLI prints these dimmed on stderr in terminal mode only.
onStatus: (message) => sendToClient({ status: message }),
});
报告架构
测试套件的 JSON 输出是一份稳定且有版本号的契约。每份报告的顶层都包含 schemaVersion 字段。完整的 JSON Schema 位于 schemas/report.v1.json,并随 npm 包一同发布。
{
"schemaVersion": "1", // bumped on breaking changes to the report shape
"specVersion": "2026-07-28", // MCP spec revision the run graded — the RESOLVED value ("2025-11-25" or "2026-07-28"), never "auto"
"toolVersion": "0.19.0", // mcp-compliance version that produced the report
"url": "...",
"timestamp": "...",
"grade": "A",
"score": 92.5,
"summary": { "total": 99, "passed": 97, "failed": 2, "required": 24, "requiredPassed": 24, "skipped": 4 },
"tests": [ // ids are only meaningful together with specVersion
{ "id": "security-auth-malformed", "passed": true, "skipped": true,
"details": "Skipped: needs a valid credential to compare against (pass --auth)", ... },
...
],
// ...
}
如果某项测试已运行但未测得任何内容(没有 --auth、未声明工具、检查不适用于该传输方式,或先前检查无法归因的拒绝),则会将其记录为 passed: true 且 skipped: true;summary.skipped 和每个 categories[*].skipped 都会统计这些项目。跳过项计入 passed,但不计入 score(0.19.0 及更早版本生成的报告会将其作为通过项计分),因此在将通过总数视为证据之前,请同时查看 skipped 和 passed。SARIF 输出的 results 仅包含失败项,并会在本次运行的调用属性中列出跳过项(testsSkipped、skippedTests),因此 Code Scanning 不会为它们生成警报。
使用者指南:
- 根据
schemaVersion固定版本。遇到未知版本的报告时应拒绝,而不是猜测其结构。 - 解读
tests前先检查report.specVersion。从 0.19 开始,同一工具版本可生成任一修订版的报告,因此仅以toolVersion为依据的仪表板会看到同一版本生成的2025-11-25和2026-07-28报告;测试 ID、必需集合和serverInfo.protocolVersion都属于该字段所指定的修订版。对待未知specVersion时,应与对待未知schemaVersion一样:拒绝,不要猜测。 - 任何 Draft 2020-12 验证器(例如
ajv)都可以验证该架构。该架构采用严格模式(additionalProperties: false),因此应使用生成报告的工具版本随附的report.v1.json验证报告:0.19 为 v1 添加了可选的skipped字段(位于测试项、summary和categories中),旧版架构副本会拒绝这些字段。 - 重命名、移除或类型变更都会提升
schemaVersion;除此之外,报告结构在同一主版本内保持稳定。 - 对同一服务端进行两次运行,会得到等效的等级、分数和逐项测试通过/失败结果(计时/时间戳除外)——前提是两次解析得到的
specVersion相同。使用auto时,具体结果取决于服务端,因此若部署间需要保持确定性,请固定--spec-version。
方法论与文档
测试方法论公开发布,以便对评分过程进行审查:
- 测试方法论 — 按规范修订版划分的测试执行模型、评分算法,以及全部 88 + 103 条测试规则及其通过/失败标准(CC BY 4.0)
- 机器可读的规则目录 — 每条规则均标注其适用的规范修订版,供程序使用(通过
src/tests/catalog-parity.test.ts与代码保持同步) - 为什么选择
mcp-compliance— 问题、现有替代方案,以及此工具的不同之处 - 修复常见失败 — 针对最常见测试失败的处理方法和代码片段,适用于两个修订版
- 规范版本策略 — 一个工具版本,多个规范目录:
auto如何做出选择、如何固定版本,以及服务升级时会有哪些变化 - 性能深入解析 — 套件采用顺序执行的原因,以及并行执行的代价
- 规范 PR 草案 — 针对我们遇到的模糊情况提出的 MCP 规范澄清建议
此方法论并非权威的一致性标准,而是单个工具的选择,并将其公开发布,以供审查、采用或分叉。官方 MCP 规范(2025-11-25、2026-07-28)定义了服务必须执行的操作;本文档介绍 @yawlabs/mcp-compliance 如何验证这些要求。
要求
- Node.js 20+
运行时
mcp-compliance 命令是一个小型启动器。若已安装可用的 oam 运行时,它会优先使用;否则会直接使用 npm 已启动的 Node 运行 CLI,不产生额外开销。CLI 在两种运行时上的行为相同。
| 变量 | 作用 |
|---|---|
MCP_COMPLIANCE_RUNTIME=auto | 默认值。使用找到的最新 oam 0.18.0 或更高版本,否则回退到 Node。如果找到的 oam 不可用,或 OAM_BIN 设置有误,它会在 stderr 中说明(mcp-compliance: ...; using Node instead.)。 |
MCP_COMPLIANCE_RUNTIME=oam | 仅使用 oam。如果找不到 oam 0.18.0 或更高版本,则退出并返回代码 1,并提供修复方法:对于过时的 oam,运行 oam self-update;对于 OAM_BIN,提供相应的修复方法;如果完全没有 oam,则提供安装链接。 |
MCP_COMPLIANCE_RUNTIME=node | 仅使用 Node,即使已安装 oam 也不例外。 |
OAM_BIN=/path/to/oam | 在搜索其他位置之前,先尝试使用此 oam。如果该文件不存在、版本低于 0.18.0 或无法运行,启动器会说明情况并继续搜索。 |
OAM_INSTALL_DIR=/dir | 除了 ~/.oam/bin、%LOCALAPPDATA%\oam\bin 和 PATH,还会检查此目录;oam 安装程序会将二进制文件放在这里。 |
oam 的最低版本要求是 0.18.0,这是最新的 oam 版本。此要求不可更改,因为 CLI 仅在此版本上经过检查。在 0.9.0 之前,oam 的 child_process 会以某些方式处理 stdio 和参数,导致一致性测试评估的是运行时,而不是服务。要更新旧版 oam,请运行 oam self-update。
oam run <path-to-package>/dist/index.js -- test <target> 可直接在 oam 上运行 CLI,并跳过启动器。此时,上述规则均不适用:不会检查最低版本,不会回退,也不会切换运行时。
贡献
git clone https://github.com/YawLabs/mcp-compliance.git
cd mcp-compliance
npm install
npm run build
npm test
开发命令:
| 命令 | 说明 |
|---|---|
npm run build | 使用 tsup 编译 |
npm run dev | 监视模式 |
npm test | 运行测试(vitest) |
npm run lint | 使用 Biome 检查 |
npm run lint:fix | 使用 Biome 自动修复 |
npm run typecheck | TypeScript 类型检查 |
npm run test:ci | 构建并运行测试(适用于 CI) |
链接
License
MIT — see LICENSE.
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。