ipr-mcp-server 0.1.1
MCP server integrating with Unitrust ipr.tsa.cn copyright solidification APIs.
License: MIT
Requires Python: >=3.11

• # IPR MCP Server
  **为大模型提供面向 Unitrust IPR 网关的固化、检索与回调能力，支持 MCP stdio 工具链。**

  ---

## 目录

- [概览](#概览)

- [主要特性](#主要特性)

- [安装与运行](#安装与运行)

- [配置项](#配置项)

- [MCP 客户端集成](#mcp-客户端集成)

- [可用工具](#可用工具)

- [架构速览](#架构速览)

- [项目结构](#项目结构)

- [开发与测试](#开发与测试)

- [安全提示](#安全提示)

- [许可证](#许可证)
  
  ---

## 概览

  IPR MCP Server 是一个 Python 实现的 MCP（Model Context Protocol）服务器，面向 Unitrust ipr.tsa.cn 测试网关。它封装了脱敏哈希固化、源文件上传、证据下载、记录查询以及回调日志持久化等能力，
  支持被各种 MCP 客户端（如 Claude Desktop、Cherry Studio 等）直接调用。

  ---

## 主要特性

- **工具化接口**：`ipr_apply_desensitized`、`ipr_apply_with_source`、`ipr_download_assets`、`ipr_search_records`、`ipr_calc_file_hash` 全部暴露为 MCP `call_tool`。

- **RSA2 签名管线**：内置参数排序、私钥加载、SHA256withRSA 签名与 `Content-MD5` 生成。

- **源文件直传**：自动 PUT OSS 上传并携带 `Content-MD5`、`x-oss-forbid-overwrite`。

- **回调日志**：`ipr-mcp-callback` FastAPI 服务即时返回 `success`，同时写入 SQLite。

- **持久化与审计**：`Storage` 层将每次固化请求与回调记录入库，可用于调试或归档。

- **可脚本化示例**：`scripts/apply_source_demo.py` 演示端到端流程，`tests/manual_apply.py` 用于手动对拍。
  
  ---

## 安装与运行

```bash
git clone https://github.com/your-org/ipr-mcp-server.git
cd ipr-mcp-server

python -m venv .venv
. .venv/bin/activate
pip install -e .[dev]

cp .env.example .env  # 填写 TSA_APP_ID、TSA_PRIVATE_KEY_PEM 等
```

# 启动 MCP stdio 服务

```bash
ipr-mcp-server
```

# 启动 MCP WebSocket 服务（示例 :9000，路径 /mcp/ipr）

```bash
python -m ipr_mcp_server.server --ws 0.0.0.0:9000 --ws-path /mcp/ipr
# 或使用入口命令：
ipr-mcp-server --ws-host 0.0.0.0 --ws-port 9000 --ws-path /mcp/ipr
```

# 启动 FastAPI 回调监听（:8080）

```bash
ipr-mcp-callback
```

Docker 方式：

```bash
docker build -t ipr-mcp-server .
docker run --rm -it \
  -e TSA_APP_ID=xxx \
  -e TSA_PRIVATE_KEY_PEM="$(cat private.pem)" \
  -e CALLBACK_PUBLIC_URL=https://host/callbacks/tsa \
  ipr-mcp-server
```

———

## 配置项

| 环境变量                | 说明                                 | 默认值                       |
| ------------------- | ---------------------------------- | ------------------------- |
| TSA_BASE_URL        | 网关根地址                              | https://open-test.tsa.cn/ |
| TSA_GATEWAY_PATH    | 网关路径（允许空串）                         |                           |
| TSA_APP_ID          | Unitrust 分配的 appId                 | 必填                        |
| TSA_PRIVATE_KEY_PEM | PKCS#8 私钥（单行或 PEM）                 | 必填                        |
| CALLBACK_PUBLIC_URL | ipr.opus.apply.source 的 notify URL | 源文件流程必填                   |
| DATABASE_URL        | SQLAlchemy 连接串                     | sqlite:///./ipr_mcp.db    |
| TSA_REQUEST_TIMEOUT | HTTP 超时秒数                          | 15.0                      |

所有配置由 pydantic-settings 统一加载，可直接读取 .env。

———

## MCP 客户端集成

Claude Desktop 示例：

```json
{
  "mcpServers": {
    "ipr-mcp": {
      "command": "/path/to/.venv/bin/ipr-mcp-server",
      "cwd": "/data/application/dev/iprmcp3",
      "env": {
        "TSA_APP_ID": "...",
        "TSA_PRIVATE_KEY_PEM": "...",
        "CALLBACK_PUBLIC_URL": "https://example.com/callbacks/tsa"
      }
    }
  }
}
```

新增 WebSocket + 回调结果工具：

- 工具 `ipr_latest_callback`：输入 `oid`，返回最新回调载荷（含 PDF/TSA/源文件下载地址），便于在 LLM 里直接拿到下载链接，无需人工查库。

WebSocket 客户端示例（通用 MCP 客户端）：

```jsonc
{
  "mcpServers": {
    "ipr-mcp": {
      "url": "wss://your-domain.com/mcp/ipr"
    }
  }
}
```

Nginx 反向代理示例：

```nginx
location /mcp/ipr {
    proxy_pass http://127.0.0.1:9000;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_set_header Host $host;
}
```

Cherry Studio、OpenAI MCP SDK 等客户端均可采用相同思路：指定命令、工作目录与环境变量，启动后即可在对话中调用工具。

———

## 可用工具

```bash
| 工具                     | 说明                     | 关键字段                                    |
| ---------------------- | ---------------------- | --------------------------------------- |
| ipr_apply_desensitized | 以 64 字节 SHA-256 哈希提交固化 | fileHash, opusName, applyName, fileType |
| ipr_apply_with_source  | 申请源文件固化并上传原件           | filePath 或 fileBase64, md5Hash 自动生成     |
| ipr_download_assets    | 获取 PDF/TSA/源文件下载地址     | oid                                     |
| ipr_search_records     | 按 fileHash / 时间等查询记录   | page, size, opusApplyType 等             |
| ipr_calc_file_hash     | 计算本地文件 SHA-256 + 字节数   | filePath                                |

所有输入由 pydantic 校验，错误会返回 ConfigurationError 或 TsaAPIError，便于在客户端展示。
```

———

## 架构速览

- 配置层：Settings 统一处理 .env / 环境变量。
- 工具上下文：ToolContext 聚合 Storage + TsaClient。
- TsaClient：负责参数构造、签名、HTTP 调用、上传。
- Storage：目前使用 SQLite 存储证据与回调。
- 回调 API：FastAPI + SQLAlchemy，监听 Unitrust 推送。

———

## 项目结构

```
src/ipr_mcp_server/
├─ config.py        # 设置 & 缓存
├─ server.py        # MCP stdio 事件循环
├─ tools.py         # 各工具输入/输出模型与实现
├─ tsa_client.py    # 网关 HTTP 封装
├─ crypto_utils.py  # RSA2、哈希工具
├─ storage.py       # SQLAlchemy 存储
├─ callback_api.py  # FastAPI 回调服务
└─ cli.py           # 入口脚本
tests/
├─ test_tools.py
├─ test_tsa_client.py
├─ test_callback_api.py
├─ test_crypto.py
└─ manual_apply.py  # 手工对拍脚本
scripts/
└─ apply_source_demo.py
```

———

## 开发与测试

```
. .venv/bin/activate
ruff check .
pytest
pytest -k tsa_client        # 定位特定模块
python scripts/apply_source_demo.py
```

- ruff：lint + 自动修复（100 列限制）

- pytest-asyncio + respx：断言 HTTP 请求结构

- freezegun：固定时间戳确保签名一致

- uv 或 pip 都可管理依赖

———

## 安全提示

- 切勿提交任何私钥或 TSA 凭据，base64key.pem、private.pem 仅供本地测试。
- 生产环境建议将 DATABASE_URL 指向受控数据库并启用磁盘加密。
- 回调服务需放置在 HTTPS 域名后，并做好访问控制和日志审计。

———

## 许可证

本项目采用 MIT License (LICENSE)。欢迎在遵循许可的前提下进行二次开发、集成或商用，如有新工具/优化欢迎提出 PR。