TsvetanG2/mcpward

GitHub: TsvetanG2/mcpward

mcpward 是一款针对 MCP server 的黑盒安全与契约测试工具,用于在 CI 环境中检测 rug-pull、工具投毒、schema 漂移和协议违规等问题。

Stars: 0 | Forks: 0

# mcpward — 在你的 agent 之前,捕获你的 MCP server 中的 rug-pull、工具投毒和 schema 漂移。 [![CI](https://static.pigsec.cn/wp-content/uploads/repos/cas/ad/ad5834178f7599af9fdda11629d49cae07f2997beec49821b2920eff5bfd50e7.svg)](https://github.com/TsvetanG2/mcpward/actions/workflows/ci.yml) [![npm](https://img.shields.io/npm/v/mcpward)](https://www.npmjs.com/package/mcpward) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](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 "safe​tool" 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代理, 暗色界面, 自动化攻击