fernforge/mcp-conform
GitHub: fernforge/mcp-conform
一款面向 MCP server 作者的发布前一致性与安全 linter,通过确定性规则检测注解缺失、schema 缺陷、工具投毒模式及注册表元数据问题。
Stars: 0 | Forks: 0
# mcp-conform
一款用于 MCP server 的 eslint。它是一个确定性的、作者端的一致性与安全 linter,可在你将 [Model Context Protocol](https://modelcontextprotocol.io) server 发布到 npm、PyPI 或官方 MCP 注册表之前运行。
它能检测出那些会导致 server 被应用目录拒绝,或导致 agent 错误调用你工具的问题:缺失 tool 注解、单薄或模糊的 schema、描述中的 tool 投毒模式,以及不完整的注册表元数据。每个问题都附带了一行修复建议。
```
npx @fernforge/mcp-conform --cmd "node dist/index.js"
```
```
mcp-conform — 7 tool(s) checked
delete_record
✖ error ann/missing-destructive-hint Tool "delete_record" may modify state but does not set destructiveHint.
fix: Set annotations.destructiveHint (true for irreversible ops like delete).
✖ error safety/injection-phrase Tool description contains an injection-style phrase (instruction override).
fix: Remove instruction-like text; describe behavior, don't issue commands to the agent.
1 error · 4 warning · 5 info
Conformance score: 76/100 FAIL
```
无需 LLM 密钥,无需网络,完全确定性。它是一个 linter 而不是模型,因此可以安全地在 CI 中运行,一天免费运行上千次,且其判定结果永远不会漂移。
## 2026-07-28 规范会破坏你的 server。准确找出问题所在。
2026-07-28 MCP 规范是自发布以来最大的一次修订,且不向下兼容。协议层中的 Session 已被移除(移除了 `Mcp-Session-Id`,SEP-2567),`initialize`/`initialized` 握手被移除(SEP-2575),错误码 `-32002` 变更为 `-32602`,新增了两个必需的路由 header(`Mcp-Method`, `Mcp-Name`),并且 `roots`/`sampling`/`logging` 已被弃用。关于这些内容有很多详细的说明文章。但唯独缺少一个工具能够读取*你的*代码,并告诉你究竟是哪几行出了问题。
`spec-migrate` 规则包就是为此而生的。它会扫描你的 TypeScript/JavaScript/Python 源代码,查找被移除和更改的 API,并针对每个匹配项报告 `file:line` 及其修复建议:
```
npx @fernforge/mcp-conform --ruleset spec-migrate --project .
```
```
server.ts:18
✖ error migrate/session-id-header Mcp-Session-Id is removed (SEP-2567). The 2026-07-28 transport is stateless; this header no longer exists.
fix: Read protocol version, client info and capabilities from params._meta on each request instead of a per-session store.
server.ts:21
✖ error migrate/error-code-32002 JSON-RPC error code -32002 is reassigned to -32602 (Invalid Params).
fix: Change -32002 to -32602.
```
严重的破坏性变更(sessions、握手、错误码)会被视为错误;处于 12 个月过渡期内的弃用功能(`roots`/`sampling`/`logging`,Tasks 转 extension)会被视为警告。这样一来,CI 就会在那些第一天就会导致破坏的问题上直接报错,而对其余部分仅作提示。运行 `--ruleset all` 可将其与常规的一致性 lint 结合使用。
它只对实际发布的内容进行 lint。将其指向你 server 的启动命令,它就会通过 stdio 启动该 server,调用 `tools/list`,并检查你的用户将会接收到的真实 schema,而不是根据你的源码进行猜测。
开箱即用的 GitHub Action 会为每个 PR 打分,并生成一份 job 总结。
## 为什么会有这个工具
MCP 生态系统正在交付数以万计的 server,而应用目录对于收录标准已变得非常严格。
不良的 tool 注解是 ChatGPT 和 Claude 应用目录拒绝收录的首要原因。规范指出,当缺失提示时,客户端必须按最坏情况(破坏性、开放世界)来处理,因此如果你没有设置 `readOnlyHint` / `destructiveHint` / `openWorldHint` / `title`,客户端就会将你安全的只读工具视为危险工具。
Tool 描述是一个注入面。它们会被直接注入到 agent 的上下文中,因此描述中的“忽略之前的指令”这一行,或者不可见的 Unicode 负载,都是真实的 tool 投毒载体。
官方注册表现在支持命名空间验证发布。反向 DNS 名称、`server.json` 清单以及干净的包元数据,都是确保你的 server 可发布且能被发现的前提。
社区正在起草一份发布前的一致性检查清单([modelcontextprotocol Discussion #2682](https://github.com/modelcontextprotocol/modelcontextprotocol/discussions))。`mcp-conform` 会将其自动化。
现有的 MCP 安全工具都是面向消费者/运行时的:它们扫描的是你即将安装的 server。而 `mcp-conform` 的作用正好相反。它能在任何人安装之前,让你的 server 达到合规要求。
## 安装
使用 npx 运行,无需安装:
```
npx @fernforge/mcp-conform --cmd "node dist/index.js"
```
若要在 CI 中固定版本或将其作为开发依赖项:
```
npm install --save-dev @fernforge/mcp-conform
```
需要 Node ≥ 18。MCP SDK 是一个可选的 peer dependency,仅在实时 `--cmd` 内省时需要(大多数项目通常已经包含了它)。
## 用法
`mcp-conform` 始终会检查你的**项目元数据**(`package.json`、`server.json`),并从以下三个来源之一获取要 lint 的 **tools**:
### 1. 实时 server(推荐 — 检查实际发布的内容)
```
mcp-conform --cmd "node dist/index.js"
mcp-conform --cmd "python -m my_server"
mcp-conform --cmd "uvx my-mcp-server"
```
它会通过 stdio 启动 server,初始化一个客户端,并对真实的 `tools/list` 输出以及能力/传输协议的规范性进行 lint。
### 2. 保存的 tools 清单
```
mcp-conform --manifest tools.json
```
这里的 `tools.json` 可以是 `tools/list` 的结果(`{ "tools": [...] }`),也可以是纯粹的工具定义数组。非常适合用于 Python/Go server 或者在测试中进行快照。
### 3. 仅元数据
```
mcp-conform # checks package.json + server.json in the current dir
```
### 输出 & CI
```
mcp-conform --cmd "node dist/index.js" --json # machine-readable
mcp-conform --cmd "node dist/index.js" --markdown --out report.md
mcp-conform --cmd "node dist/index.js" --min-score 80 # fail under 80
mcp-conform --cmd "node dist/index.js" --max-warnings 0 # fail on any warning
```
当存在任何严重级别为 error 的检查结果时,`mcp-conform` 会以非零状态码退出,因此默认情况下它会导致 CI 失败。你可以使用 `--min-score` 和 `--max-warnings` 来收紧限制门槛。
## GitHub Action
将 `.github/workflows/mcp-conform.yml` 添加到你的 server 仓库中:
```
name: MCP Conformance
on: [pull_request, push]
jobs:
conform:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with: { node-version: 20 }
- run: npm ci && npm run build
- uses: fernforge/mcp-conform@v0.2.0
with:
cmd: "node dist/index.js"
min-score: "80"
```
它会在 job 总结中写入一份 Markdown 报告,并在分数低于你设定的阈值时使检查失败。
## 检查内容
| 类别 | 示例 |
| --- | --- |
| **Annotations** | 缺失 `readOnlyHint` / `destructiveHint` / `openWorldHint`;缺失人类可读的 `title`;被标记为只读的 `delete_*`/`update_*` 工具 |
| **Schema hygiene** | 缺失/单薄的 tool 描述;没有描述或类型的参数;缺失 `inputSchema`;未设置 `additionalProperties`;缺失 `outputSchema` |
| **Safety / tool-poisoning** | “忽略之前的指令”及掩饰性词汇;隐藏的零宽 / bidi / Unicode 标记字符;超长描述;弱化了自身影响范围的高权限(`exec`/`sql`/`write_file`)工具 |
| **Distribution metadata** | 缺失 `name`/`version`/`license`/`repository`;没有 `keywords` 或没有 `mcp` 关键字;没有 `bin`/`main`;没有 `engines` |
| **Registry** | 没有 `server.json`;名称不是反向 DNS 命名空间格式;缺失清单字段 |
| **Transport** *(仅限实时模式)* | 声明了能力但未提供对应内容,或提供了 tools 但未声明相关能力 |
每条检查结果都包含一个 `rule` ID、一个严重级别(`error` / `warning` / `info`)以及具体的**修复建议**。**一致性得分 (0–100)** 是一个你可以随时间跟踪的确定性单一数值。
## 编程 API
```
import { lint, introspect, loadProjectMetadata } from "mcp-conform";
const live = await introspect({ command: "node", args: ["dist/index.js"] });
const meta = await loadProjectMetadata(process.cwd());
const result = lint({ ...live, ...meta });
console.log(result.score, result.pass);
for (const f of result.findings) console.log(f.severity, f.rule, f.message);
```
## 路线图
- 用于机械化修复注解/元数据缺失的 `--fix`
- 一个配置文件 (`mcpconform.json`),用于设置严重级别和禁用规则
- 发布一个 `mcpconform-config-recommended` 规则集,随着社区一致性检查清单的最终确定而保持同步更新
欢迎提交 Issues 和规则建议 —— 这个规则集旨在随着标准的形成而不断跟进。
## 许可证
MIT © fernforge
标签:AI安全, Chat Copilot, MCP, MITM代理, SOC Prime, TypeScript, 云安全监控, 安全插件, 开发工具, 数据可视化, 文档结构分析, 暗色界面, 自动化攻击, 逆向工具, 静态分析