TsvetanG2/mcpward
GitHub: TsvetanG2/mcpward
mcpward 是一款针对 MCP server 的黑盒安全与契约测试工具,用于在 CI 环境中检测 rug-pull、工具投毒、schema 漂移和协议违规等问题。
Stars: 0 | Forks: 0
# mcpward — 在你的 agent 之前,捕获你的 MCP server 中的 rug-pull、工具投毒和 schema 漂移。
[](https://github.com/TsvetanG2/mcpward/actions/workflows/ci.yml)
[](https://www.npmjs.com/package/mcpward)
[](https://opensource.org/licenses/MIT)
针对 MCP server 的黑盒安全与契约测试。支持本地和 CI 环境运行,并生成确定性、机器可读的报告(console / JSON / JUnit / SARIF)。
## 环境要求
- Node.js ≥ 20
- 一个待测试的 MCP server(支持 stdio 或 HTTP 传输)
## 快速开始
```
# 初始化 config
npx mcpward init
# 运行所有检查
npx mcpward run
# 捕获 baseline 以进行 drift detection
npx mcpward baseline
# 对照 baseline 检查 drift
npx mcpward diff
```
### 输出示例
检查通过时:
```
mcpward v0.1.0
──────────────────────────────────────────────────
Server: my-server v1.0.0
Protocol: 2025-11-25
COMPLIANCE (5 passed)
5 check(s) passed
SCHEMA (13 passed)
13 check(s) passed
SECURITY (1 passed)
1 check(s) passed
Summary: 19 passed
All checks passed
```
发现安全问题时:
```
SECURITY (9 failed)
✗ Tool "injection_tool" description contains injection-like pattern:
"Ignore all previous instructions"
✗ Tool "safetool" name contains hidden unicode: U+200B (zero-width)
✗ Tool "api_connector" schema solicits secrets: api_key, password
✗ Tool "delete_files" has readOnlyHint=true but name implies mutation
Summary: 10 passed | 9 failed
9 check(s) failed
```
## 为什么选择 mcpward?
**mcpward 能够在生产环境之前捕获这些问题。**
### 我们的差异点
| 功能 | mcpward | mcpvet | MCP-Contract-CI |
|---------|---------|--------|-----------------|
| Rug-pull(描述突变) | ✅ | ❌ | ❌ |
| 工具投毒启发式检测 | ✅ | ❌ | ❌ |
| SARIF 导出(GitHub Security) | ✅ | ❌ | ❌ |
| 双层错误契约 | ✅ | ❌ | ❌ |
| Schema 漂移检测 | ✅ | ✅ | ✅ |
| JUnit 输出 | ✅ | ✅ | ❌ |
| 行为测试套件 | ✅ | ❌ | ✅ |
| HTTP 传输 | ✅ | ✅ | ❌ |
**Rug-pull 检测** — 其他工具只能捕获 tool 被重命名或移除的情况。mcpward 还能检测到 tool 的*描述*何时被悄然更改。描述信息会在 lockfile 中进行哈希处理;任何突变都会被标记为 `description_changed`。
**工具投毒启发式检测** — 静态分析可检测注入式用语("ignore previous instructions")、隐藏的 unicode 字符、诱导提供敏感信息(`api_key`, `password`)的 schema,以及 `readOnlyHint` 不匹配的情况。检测结果可导出为 SARIF,并显示在 GitHub Security 标签页中。
**双层错误契约** — MCP 包含两种错误类型:协议错误(JSON-RPC)和工具错误(`isError: true`)。mcpward 会验证 server 是否在正确的场景下使用了正确的错误层级。
**行为测试套件** — 支持声明式 YAML 测试用例,包含 JSONPath 断言、`tool_is_error` 检查和延迟预算。
## 功能
- **协议合规性** — 握手、版本协商、能力声明、ping
- **Schema 验证** — tool 名称、描述、inputSchema(JSON Schema)
- **漂移检测** — 基准快照与破坏性变更分类
- **安全启发式检测** — 注入模式、隐藏的 unicode、诱导提供敏感信息的 schema
- **行为测试** — 带断言的声明式测试套件
- **延迟预算** — p50/p95 百分位检查
- **多种报告器** — console、JSON、JUnit、SARIF
- **对 CI 友好** — 退出码 `0`/`1`/`2`,机器可读输出
- **HTTP 传输** — 连接到远程 MCP server
- **GitHub Action** — 开箱即用的 composite action
## 配置
创建 `mcpward.yaml`:
```
server:
transport: stdio
command: npx
args: ["-y", "@modelcontextprotocol/server-filesystem", "/tmp/sandbox"]
env: {}
# 可选:Timeout 配置
timeouts:
connect_ms: 10000 # Connection timeout (default: 10s)
call_ms: 30000 # Per-tool-call timeout (default: 30s)
run_ms: 300000 # Total run timeout (default: 5min)
checks:
compliance: true
schema: true
security: true
drift:
baseline: ./mcpward.lock.json
fail_on:
- tool_removed
- description_changed
- breaking_schema_change
- annotation_changed
latency:
samples: 5
p95_budget_ms: 1000
suites:
- tool: read_file
cases:
- name: reads an existing file
args: { path: "/tmp/sandbox/hello.txt" }
expect:
tool_is_error: false
jsonpath:
"$.content[0].type": "text"
- name: returns error for missing file
args: { path: "/nonexistent" }
expect:
tool_is_error: true
```
### 环境变量
使用 `${ENV_VAR}` 语法来处理机密信息:
```
server:
transport: http
url: https://example.com/mcp
headers:
Authorization: "Bearer ${MCP_TOKEN}"
```
### 行为测试期望
测试用例中的 `expect` 块支持:
| 选项 | 类型 | 描述 |
|--------|------|-------------|
| `tool_is_error` | boolean | 断言 tool 响应是否为 `isError: true/false` |
| `protocol_error_code` | number | 断言 JSON-RPC 错误码(例如 -32602) |
| `jsonpath` | object | 断言 JSONPath 指定位置的值 |
| `output_matches_schema` | boolean | 根据 tool 的 outputSchema 验证输出 |
| `golden` | string | 用于比较的 golden snapshot 文件路径 |
## 检查类别
### 合规性
| 检查项 | 描述 |
|-------|-------------|
| `compliance/handshake` | 协议握手已完成 |
| `compliance/protocol-version` | 已协商有效的协议版本 |
| `compliance/server-info` | 存在 server 名称和版本 |
| `compliance/capabilities` | server 声明了能力 |
| `compliance/ping` | server 响应 ping |
### Schema
| 检查项 | 描述 |
|-------|-------------|
| `schema/tool-name` | 名称匹配 `^[a-zA-Z0-9_-]+$` |
| `schema/tool-description` | 描述非空 |
| `schema/tool-input-schema` | 有效的 JSON Schema |
| `schema/tool-annotations` | 有效的 annotation 值 |
| `schema/unique-names` | 没有重复名称 |
### 安全性
| 检查项 | 描述 |
|-------|-------------|
| `security/injection-pattern` | 描述中包含注入式用语 |
| `security/hidden-unicode` | 零宽字符或双向控制字符 |
| `security/secret-in-schema` | schema 中存在诱导提供敏感信息的字段 |
| `security/annotation-mismatch` | 破坏性 tool 上存在 readOnlyHint |
### 漂移
| 变更情况 | 分类 | 默认失败? |
|--------|----------------|---------------|
| Tool 被移除 | `tool_removed` | 是 |
| 新增 Tool | `tool_added` | 否 |
| 描述被更改 | `description_changed` | 是 |
| 新增必填字段 / 类型收窄 | `breaking_schema_change` | 是 |
| 新增可选字段 / 类型放宽 | `nonbreaking_schema_change` | 否 |
| readOnlyHint true→false | `annotation_changed` | 是 |
### 行为
| 检查项 | 描述 |
|-------|-------------|
| `behavioral/tool-is-error` | 断言 `isError` 符合预期 |
| `behavioral/jsonpath` | 断言 JSONPath 指定位置的值 |
| `behavioral/output-schema` | 根据 schema 验证输出 |
| `behavioral/protocol-error` | 断言协议错误码 |
### 延迟
| 检查项 | 描述 |
|-------|-------------|
| `latency/summary` | 整体 p50/p95 对比预算 |
| `latency/tool` | 单个 tool 的延迟测量 |
## CI 集成
### GitHub Actions
```
# 基本用法
- name: Run mcpward
run: npx mcpward run
# 用于测试结果的 JUnit output
- name: Run with JUnit output
run: npx mcpward run --reporter junit --out results.xml
- name: Upload test results
uses: actions/upload-artifact@v4
with:
name: mcpward-results
path: results.xml
# 用于 GitHub Security 标签页的 SARIF output
- name: Run with SARIF output
run: npx mcpward run --reporter sarif --out results.sarif
- name: Upload SARIF to GitHub Security
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: results.sarif
# 使用 mcpward action
- name: Run mcpward
uses: TsvetanG2/mcpward/action@main
with:
config: mcpward.yaml
reporter: junit
output: results.xml
```
## 退出码
| 代码 | 含义 |
|------|---------|
| `0` | 所有检查通过 |
| `1` | 一个或多个检查失败 |
| `2` | 配置或连接错误 |
## 开发
```
pnpm install
pnpm run build
pnpm run test
pnpm run lint
```
## 许可证
MIT
标签:MITM代理, 暗色界面, 自动化攻击