内容
# c2pa-mcp
**一个验证 C2PA 内容凭证并返回 LLM-ready 判决的 MCP 服务器。**
将任何 MCP 客户端(Claude Desktop、Claude Code、Cursor 等)指向本地文件或 URL,即可获得纯语言答案:此图像/视频/音频是 **可信、有效、篡改还是未签名**?谁签名的?是 **AI 生成的** 吗?它的编辑历史和来源血统是什么?
由 [c2paviewer.com](https://c2paviewer.com) 构建。验证在 [官方 C2PA Rust 引擎](https://github.com/contentauth/c2pa-rs) 上本地运行,通过 `@contentauth/c2pa-node`。文件永远不会离开您的机器。
> **只读。** 此服务器验证和检查内容凭证。 它不签名或创建它们。
## 安装
无需全局安装。将其添加到您的 MCP 客户端配置中,它将通过 `npx` 运行:
```json
{
"mcpServers": {
"c2pa": {
"command": "npx",
"args": ["-y", "@c2paviewer/c2pa-mcp"]
}
}
}
```
- **Claude Desktop**:设置 → 开发者 → 编辑配置,添加上面的块。
- **Claude Code**:`claude mcp add c2pa -- npx -y @c2paviewer/c2pa-mcp`
- **Cursor / 其他**:在客户端的 MCP 配置中添加相同的 `mcpServers` 条目。
需要 Node.js 18+。
## 工具
| 工具 | 功能 |
|------|--------------|
| `verify_c2pa_file` | 通过路径验证本地图像/视频/音频/PDF。 |
| `verify_c2pa_url` | 下载公共 https 媒体 URL 并验证它(SSRF 保护)。 |
| `scan_c2pa_directory` | 审计文件夹:哪些文件有凭证、它们的判决、签名者、AI 状态。 |
| `c2pa_info` | 报告引擎版本、支持的媒体类型和信任列表状态。 |
每个验证工具都返回人类可读的摘要和结构化的摘要:
```jsonc
{
"verdict": "invalid", // trusted | valid_untrusted | valid_trust_unknown | invalid | no_credentials
"summary": "内容凭证无效:完整性或签名检查失败...",
"signer": { "name": "示例签名者", "trusted": false },
"aiGenerated": { "isAI": true, "tools": ["DALL-E"], "digitalSourceTypes": ["...trainedAlgorithmicMedia"] },
"provenance": [ { "depth": 0, "title": "此文件", "relationship": "此文件", "verdict": "invalid" } ],
"edits": [ { "label": "创建", "agent": "Photoshop", "when": "...", "detail": "" } ],
"watermarks": [ { "kind": "synthid", "assertionLabel": "...", "algorithm": "" } ],
"issues": [ { "code": "assertion.dataHash.mismatch", "severity": "error",
"explanation": "媒体内容在签名后被更改。... " } ],
"trust": { "evaluated": true, "listSource": "https://.../C2PA-TRUST-LIST.pem" }
}
```
传递 `"includeRaw": true` 还可以获取完整的原始清单存储。
## 信任列表
要将签名者报告为 **`trusted`** (而不仅仅是加密有效),服务器会将签名证书与两个信任列表进行比较,**实时获取并缓存** (24 小时 TTL),以便决策保持最新而无需发布:
- 官方 [C2PA 一致性计划列表](https://github.com/c2pa-org/conformance-public) (未来签名者),以及
- 遗留 [CAI 临时信任列表](https://verify.contentauthenticity.org/trust/anchors.pem) (2026 年 1 月冻结,但仍然是唯一识别预一致性签名者的列表 - Adobe、徕卡、Truepic、佳能、三星和当今大多数现实世界内容)。
默认情况下,两者都启用;如果没有 ITL,主流签名内容将被读取为 `valid_untrusted`。
如果信任列表无法获取,服务器会 **明显降级**:验证仍然运行,但判决变为 `valid_trust_unknown`,并且 `trust.evaluated` 为 `false`,并带有原因。它永远不会默默地将未知签名者视为可信,也不会默默地使用过时的快照。
环境覆盖:
| 变量 | 默认值 | 目的 |
|----------|---------|---------|
| `C2PA_TRUST_LIST_URL` | 一致性 + ITL | 以逗号分隔的 PEM URL。替换默认值(一致性列表 + 临时信任列表)。 |
| `C2PA_TRUST_TTL_SECONDS` | `86400` | 获取的信任列表的缓存生命周期。 |
| `C2PA_MAX_FETCH_BYTES` | `104857600` | `verify_c2pa_url` 的最大下载大小(100 MB)。 |
| `C2PA_MAX_FILE_BYTES` | `524288000` | 文件/扫描工具将验证的本地文件的最大大小(500 MB)。 |
| `C2PA_ALLOWED_ROOTS` | (未设置) | 以逗号/分号分隔的绝对路径。当设置时,`verify_c2pa_file` 和 `scan_c2pa_directory` 拒绝任何路径超出这些根目录。 |
## 安全
- **本地处理。** 文件在您的机器上读取和验证;不会上传任何内容。
- **SSRF 保护的 URL 获取。** `verify_c2pa_url` 仅允许公共 `https`,将解析的 IP 地址固定在 DNS 重新绑定上,重新验证每个重定向,不发送 cookie 或身份验证,并强制执行内容类型允许列表和大小限制。
- **本地路径安全。** 文件/扫描工具拒绝远程 `file://` 和 UNC 路径,在允许的根目录检查之前解析符号链接,并为无法访问的路径返回通用错误。
- **在任何不受信任的上下文中设置 `C2PA_ALLOWED_ROOTS`。** 文件/扫描工具通过设计暴露主机文件系统,因此提示注入的模型可以指向任何位置。将它们限制在特定目录中是单个最重要的强化设置。
- **信任完整性。** 信任列表通过 HTTPS 获取(完整性依赖于 TLS 和上游源);缓存是每个用户的(`0700`/`0600`,所有权检查),并绑定到配置的 URL 集。
## 限制
- **实验性。不是法律证据。** C2PA 工具和信任基础设施仍在不断发展。不要将这些判决用于法律、合规或安全关键的决策。
- **水印被报告为声明的,而不是像素验证的。** `synthid` 条目意味着清单 **声明** 了 SynthID 水印;确认像素中的信号需要供应商的检测器。
- **AI 生成反映了清单通过 IPTC `digitalSourceType` 声明的内容。** AI 声明的缺失并不是内容不是 AI 生成的证明。
## 开发
```bash
npm install
npm run build
npm test # 构建,然后运行单元测试和端到端测试(需要网络来获取信任列表)
```
## 许可
源代码根据 [MIT](./LICENSE-MIT) 或 [Apache-2.0](./LICENSE-APACHE) 双重许可,您可以选择其中之一。
`test/fixtures/` 下的测试图像未经修改从 [`c2pa-org/public-testfiles`](https://github.com/c2pa-org/public-testfiles) 重新分发,单独根据 [CC BY-SA 4.0](https://creativecommons.org/licenses/by-sa/4.0/) 许可。
> 注意:如果您以非作用域名称而不是 `@c2paviewer/c2pa-mcp` 发布,请更改 `package.json` 中的 `name` 和上面的安装块中的 `args`;没有其他内容依赖于包名称。