增加 SuperAgent MCP 内嵌接口和配置文档

This commit is contained in:
andy
2026-07-09 17:49:53 +08:00
parent a2119a8d06
commit e12bfd77e1
25 changed files with 2236 additions and 0 deletions

View File

@@ -0,0 +1,54 @@
# TH Hotel SuperAgent MCP 资料包
## 1. 目录定位
本目录集中放置当前项目提供给 SuperAgent 对接方、测试和运维参考的 MCP 文档。
运行时代码不在本目录,代码位于:
```text
server/src/main/java/cn/nianxx/thhotel/integrations/mcp/superagent/
```
中文说明:
- 当前 MCP endpoint 内嵌在现有 Spring Boot 后端中。
- 不需要额外部署独立 MCP 服务。
- 文档可以按本目录整体交付给对接方,但 Secret 必须通过安全通道单独交付。
## 2. 文档索引
| 文档 | 中文说明 |
| --- | --- |
| `integration-guide.md` | MCP 总体接入说明和调用顺序 |
| `tools.md` | 5 个 MCP tools 的工具契约 |
| `security-policy.md` | 鉴权、权限、正文、附件和日志边界 |
| `deployment-guide.md` | 部署参数、环境变量和上线顺序 |
| `test-cases.md` | SuperAgent 联调测试用例 |
| `mcp-client-config.example.json` | SuperAgent HTTP MCP 客户端配置模板,不包含真实 Secret |
## 3. 一期工具
| Tool | 中文用途 | 性质 |
| --- | --- | --- |
| `th_hotel_query_case_context` | 查询订单上下文 | 只读 |
| `th_hotel_query_object_detail` | 查询对象详情 | 只读 |
| `th_hotel_list_message_conversation_tasks` | 查询邮件会话下任务 | 只读 |
| `th_hotel_list_message_conversation_messages` | 查询邮件会话下受控正文 | 只读,读取正文会触发后端审计 |
| `th_hotel_submit_task_results` | 提交 SuperAgent AI 任务结果 | 写入,受开关控制 |
## 4. 对外交付提醒
可以交付:
- 本目录下的 MCP 文档。
- `mcp-client-config.example.json` 配置模板。
- dev/test MCP 地址。
- 通过安全通道交付的 `MCP_AUTH_TOKEN`
不能交付:
- REST HMAC secret。
- 数据库连接信息。
- 生产客户数据、原始邮件正文或附件 URL。
- 能绕过 MCP endpoint 直接调用后端写接口的凭证。

View File

@@ -0,0 +1,131 @@
# TH Hotel SuperAgent MCP 部署指南
## 1. 文档信息
| 项目 | 内容 |
| --- | --- |
| 文档版本 | 0.2 |
| 日期 | 2026-07-09 |
| 状态 | 已调整为 Spring Boot 内嵌 MCP endpoint |
| 适用范围 | `server/` 内嵌 SuperAgent MCP endpoint 的部署配置 |
## 2. 部署拓扑
当前不新增独立 MCP 服务,仍部署现有后端:
```text
SuperAgent
-> HTTPS
-> th-hotel-simple-server /mcp
-> 现有业务 Service
-> 数据库和业务规则
```
中文说明:
- `POST /mcp` 与现有后端 API 同进程。
- MCP endpoint 不再通过 HMAC REST 调用本后端。
- 原有 REST HMAC 接口继续保留。
- 部署包仍是 `server/` 的 Spring Boot 应用。
## 3. HTTP 端点
| Endpoint | 中文说明 |
| --- | --- |
| `POST /mcp` | MCP HTTP 入口,路径可用 `MCP_HTTP_PATH` 覆盖 |
| `GET /api/health` | 当前后端健康检查 |
## 4. 环境变量
| 变量 | 是否必填 | 是否 Secret | 中文说明 |
| --- | --- | --- | --- |
| `MCP_ENABLED` | 是 | 否 | 是否启用内嵌 MCP endpoint |
| `MCP_HTTP_PATH` | 否 | 否 | MCP HTTP path默认 `/mcp` |
| `MCP_AUTH_TOKEN` | 是 | 是 | SuperAgent 到 MCP endpoint 的访问凭证 |
| `MCP_ENABLE_SUBMIT_TASK_RESULTS` | 是 | 否 | 是否启用写入工具 |
| `MCP_MAX_BODY_BYTES` | 否 | 否 | MCP 单次请求体最大字节数,默认 `10485760`,即 10MB |
生产要求:
- `MCP_AUTH_TOKEN` 必须通过 Secret 注入。
- `MCP_AUTH_TOKEN` 应使用高熵随机字符串,建议至少 32 字节随机值,例如 `openssl rand -base64 32``openssl rand -hex 32`
- dev、test、prod 必须使用不同的 `MCP_AUTH_TOKEN`
- `MCP_ENABLED` 生产启用前必须经过联调验证。
- `MCP_ENABLE_SUBMIT_TASK_RESULTS` 生产启用前必须单独审批。
- 不得把生产 Secret 写入 `.env.example`、README、SuperAgent skill、镜像或普通日志。
说明:
- REST HMAC 相关变量仍用于原有 REST API不是 MCP endpoint 的鉴权方式。
- SuperAgent 使用 MCP 时只需要 `MCP_AUTH_TOKEN`,不需要 REST HMAC secret。
## 5. SuperAgent 连接配置
建议给 SuperAgent 提供:
```text
MCP URL: https://<server-domain>/mcp
Authorization: Bearer <由安全渠道交付的 MCP_AUTH_TOKEN>
```
也可以提供本目录下的配置模板:
```text
docs/project/integrations/superagent-mcp/mcp-client-config.example.json
```
中文说明:
- 模板中的 `https://<server-domain>/mcp` 需要替换为 dev/test/prod 对应后端地址。
- 模板中的 `${MCP_AUTH_TOKEN}` 只是占位符,真实 token 通过部署平台 Secret 或安全通道注入。
- 如果 SuperAgent 平台有自己的 MCP 配置 schema以平台字段名为准但连接地址、鉴权 Header、10MB 请求限制和 tool allowlist 应保持一致。
不要给 SuperAgent 提供:
- REST HMAC secret。
- 数据库地址。
- 邮件原文样本和附件 URL。
- 可以绕过 MCP endpoint 的写接口调用凭证。
## 6. 本地启动
本地启动仍使用后端命令:
```bash
cd server
MCP_ENABLED=true MCP_AUTH_TOKEN=test-token MCP_ENABLE_SUBMIT_TASK_RESULTS=false ./mvnw spring-boot:run
```
中文说明:
- `MCP_ENABLE_SUBMIT_TASK_RESULTS=false` 时,写入 tool 会返回 `MCP_TOOL_DISABLED`
- `MCP_MAX_BODY_BYTES` 默认 10MB通常不需要本地覆盖。
- dev/test 联调确认写入链路时,可临时启用写入 tool。
## 7. 监控指标
建议监控:
- `/mcp` 请求总数。
- 每个 tool 的调用次数。
- 每个 tool 的成功率和失败率。
- `MCP_AUTH_INVALID` 数量。
- `MCP_TOOL_DISABLED` 数量。
- `th_hotel_submit_task_results` 写入成功和失败数量。
- 受控正文读取量和后端原文访问审计记录。
## 8. 灰度和回滚
建议上线顺序:
1. dev 启用 `MCP_ENABLED=true`
2. dev 连接 SuperAgent 联调 5 个工具。
3. test 环境跑完整测试用例。
4. prod 先启用 MCP endpoint 和 4 个只读工具。
5. 确认日志、监控和告警正常后启用写入工具。
回滚策略:
- 可通过 `MCP_ENABLED=false` 关闭 MCP endpoint。
- 可通过 `MCP_ENABLE_SUBMIT_TASK_RESULTS=false` 快速禁用写入工具。
- 不需要单独下线一个 MCP 服务。

View File

@@ -0,0 +1,148 @@
# TH Hotel SuperAgent MCP 接入指南
## 1. 文档信息
| 项目 | 内容 |
| --- | --- |
| 文档版本 | 0.2 |
| 日期 | 2026-07-09 |
| 状态 | 已调整为 Spring Boot 内嵌 MCP endpoint |
| 适用范围 | SuperAgent 通过 HTTP MCP 调用 TH Hotel 后端内嵌 MCP endpoint |
| 主要读者 | SuperAgent 对接方、后端、测试、运维 |
## 2. 文档定位
本文说明如何把 `superagent-api-contract.md` 中的 5 个 REST 能力以 MCP tools 暴露给
SuperAgent。
本文不是 MCP 官方规范。MCP 协议细节以官方文档为准:
- https://modelcontextprotocol.io/specification/2025-06-18/basic/transports
- https://modelcontextprotocol.io/specification/2025-06-18/server/tools
## 3. 总体架构
当前选择 **现有 Spring Boot 后端内嵌 MCP endpoint**,不额外部署独立 MCP 服务。
```text
SuperAgent
-> HTTP MCP /mcp
-> th-hotel-simple/server
-> integrations.mcp.superagent
-> Reservation / SuperAgent Service
-> 数据库和业务规则
```
中文说明:
- SuperAgent 只感知 MCP tools。
- MCP endpoint 与现有后端同进程部署。
- MCP endpoint 直接复用已有 Service不通过 HTTP 再调本机 REST。
- 原有 HMAC REST 接口继续保留,供直接 REST 对接或排查使用。
- MCP 层使用独立 Bearer TokenSuperAgent 不需要知道 REST HMAC 规则。
## 4. HTTP MCP 连接约定
后端暴露统一 HTTP MCP endpoint
```text
POST {SERVER_BASE_URL}/mcp
```
SuperAgent 连接时携带 MCP 层鉴权 Header
```text
Authorization: Bearer <MCP_AUTH_TOKEN>
```
中文说明:
- `MCP_AUTH_TOKEN` 是 SuperAgent 到当前后端 MCP endpoint 的访问凭证。
- `MCP_AUTH_TOKEN` 应使用高熵随机字符串dev、test、prod 分环境配置。
- REST HMAC secret 仍只用于原有 REST API不用于 MCP endpoint。
- `MCP_AUTH_TOKEN` 不应写入 SuperAgent prompt、skill 文件、仓库文档或普通日志。
- MCP 单次请求体默认限制为 10MB超过后返回受控错误。
## 5. 一期工具范围
一期开放 5 个 MCP tools
| Tool | 对应后端能力 | 性质 |
| --- | --- | --- |
| `th_hotel_query_case_context` | `ReservationAiQueryService.queryCaseContext` | 只读 |
| `th_hotel_query_object_detail` | `ReservationAiQueryService.queryObjectDetail` | 只读 |
| `th_hotel_list_message_conversation_tasks` | `ReservationAiQueryService.queryMessageConversationTasks` | 只读 |
| `th_hotel_list_message_conversation_messages` | `ReservationAiQueryService.queryMessageConversationMessages` | 只读,读取正文会触发后端审计 |
| `th_hotel_submit_task_results` | `ReservationAiTaskIntakeService.accept` | 写入 |
`th_hotel_submit_task_results` 会写入业务数据,不能当作普通查询工具使用。
## 6. 与 REST 契约的关系
MCP tools 与 REST API 共享业务语义和 DTO但调用链不同
```text
MCP tool input
-> MCP endpoint 校验和补充默认值
-> 现有 Service 请求 DTO
-> 现有业务 Service
-> MCP tool result
```
REST 直接对接仍走:
```text
REST request
-> HMAC 校验
-> Controller
-> 现有业务 Service
-> REST response
```
若 REST 契约或 Service DTO 升级,必须同步检查 MCP tools 文档和实现。
## 7. SuperAgent 需要拿到的资料
给 SuperAgent 对接方的资料包建议包含:
- `docs/project/integrations/superagent-mcp/README.md`
- `docs/project/integrations/superagent-mcp/integration-guide.md`
- `docs/project/integrations/superagent-mcp/tools.md`
- `docs/project/integrations/superagent-mcp/security-policy.md`
- `docs/project/integrations/superagent-mcp/test-cases.md`
- dev/test 后端 MCP 地址
- MCP 层访问凭证的安全交付方式
不要提供:
- REST HMAC secret 明文。
- 生产数据库、邮件正文、附件 URL 或客户个人信息样本。
- 可以绕过 MCP endpoint 直接调用后端写接口的普通凭证。
## 8. 调用顺序建议
典型邮件处理流程:
1. SuperAgent 从 AgentBus payload 中拿到外部 `source_message_id` 和业务候选字段。
2. 调用 `th_hotel_query_case_context` 判断订单上下文。
3. 必要时调用 `th_hotel_query_object_detail` 查看对象详情。
4. 必要时调用 `th_hotel_list_message_conversation_messages` 读取受控历史正文。
5. 必要时调用 `th_hotel_list_message_conversation_tasks` 查询同一邮件会话下已有任务。
6. 最终只在明确产出任务结果时调用 `th_hotel_submit_task_results`
## 9. 当前 checkpoint
当前 checkpoint
```text
checkpoint-superagent-mcp-embedded-endpoint
```
验收标准:
- `server/` 提供内嵌 `POST /mcp` endpoint。
- 5 个 MCP tools 均可通过 `tools/list` 发现。
- 只读 tool 直接复用现有查询 Service。
- 写入 tool 受 `MCP_ENABLE_SUBMIT_TASK_RESULTS` 开关控制。
- MCP endpoint 使用 Bearer Token 鉴权。
- 文档不包含生产 Secret、真实客户数据、附件 URL 或原始邮件正文。

View File

@@ -0,0 +1,36 @@
{
"format": "th-hotel-superagent-mcp-client-config/v1",
"mcpServers": {
"th-hotel-simple-superagent": {
"transport": "http",
"protocolVersion": "2025-06-18",
"url": "https://<server-domain>/mcp",
"method": "POST",
"headers": {
"Authorization": "Bearer ${MCP_AUTH_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json"
},
"requestLimits": {
"maxBodyBytes": 10485760
},
"tools": {
"allow": [
"th_hotel_query_case_context",
"th_hotel_query_object_detail",
"th_hotel_list_message_conversation_tasks",
"th_hotel_list_message_conversation_messages",
"th_hotel_submit_task_results"
],
"writeTools": [
"th_hotel_submit_task_results"
]
},
"runtimeNotes": {
"authTokenSource": "Use a per-environment high-entropy secret. Do not commit the real token.",
"submitTaskResultsServerSwitch": "MCP_ENABLE_SUBMIT_TASK_RESULTS must be true before using write tools.",
"messageBodyPolicy": "Conversation message tools return controlled body only, not attachments or raw HTML."
}
}
}
}

View File

@@ -0,0 +1,145 @@
# TH Hotel SuperAgent MCP 安全策略
## 1. 文档信息
| 项目 | 内容 |
| --- | --- |
| 文档版本 | 0.1 |
| 日期 | 2026-07-09 |
| 状态 | 草案 |
| 适用范围 | `server/` 内嵌 SuperAgent MCP endpoint 安全、权限和日志边界 |
## 2. 安全目标
内嵌 MCP endpoint 的安全目标是:
- 让 SuperAgent 通过语义化工具调用业务能力。
- 不让 SuperAgent 直接接触后端 HMAC secret。
- 不绕过现有后端鉴权、幂等、审计和业务校验。
- 不返回附件 URL、原始未清洗 HTML、客户敏感信息或生产 Secret。
- 对写操作建立清晰边界。
## 3. 两层鉴权
### 3.1 SuperAgent 到 MCP Endpoint
建议使用 MCP 层访问凭证:
```text
Authorization: Bearer <MCP_AUTH_TOKEN>
```
中文说明:
- `MCP_AUTH_TOKEN` 用于限制谁可以调用后端内嵌 MCP endpoint。
- 该 token 与后端 HMAC secret 不是同一个值。
- 该 token 应是高熵随机字符串,不使用手机号、项目名、酒店名、固定短语或可猜测文本。
- dev、test、prod 必须使用不同 token生产 token 建议至少 32 字节随机值。
- token 应通过部署平台 Secret 或安全通道交付,不写入仓库。
### 3.2 MCP Endpoint 到业务 Service
MCP endpoint 与后端业务 Service 同进程,不再通过 HMAC REST 调用本后端。
中文说明:
- REST HMAC 规则继续用于原有 REST API。
- MCP endpoint 只校验 MCP Bearer Token。
- MCP endpoint 必须通过现有 Service 进入业务逻辑,不能直接访问 Mapper 或数据库。
- SuperAgent 不需要知道 REST HMAC 签名串,也不能拿到 REST HMAC secret。
## 4. Tool 权限边界
| Tool | 权限级别 | 安全说明 |
| --- | --- | --- |
| `th_hotel_query_case_context` | 只读 | 不写订单、不写任务、不写 OPERA |
| `th_hotel_query_object_detail` | 只读 | 不写订单、不写任务、不写 OPERA |
| `th_hotel_list_message_conversation_tasks` | 只读 | 不创建任务、不修改任务 |
| `th_hotel_list_message_conversation_messages` | 受控读取 | 读取正文会写后端访问审计 |
| `th_hotel_submit_task_results` | 写入 | 写 AI 过渡层、订单、任务和任务卡 |
写入工具要求:
- dev/test 可以用于联调。
- prod 必须经过上线审批后启用。
- 生产建议保留独立开关,例如 `MCP_ENABLE_SUBMIT_TASK_RESULTS=true`
- 日志必须能定位调用方、request id、trace id 和 source message但不能输出正文和 Secret。
## 5. 邮件正文和附件边界
`th_hotel_list_message_conversation_messages` 只允许返回受控正文。
禁止返回:
- 原始未清洗 HTML。
- 附件 URL。
- 内嵌图片 URL。
- `attachments``inline_images``external_url`
- HTML 中的 `href/src` 外链属性。
如果 SuperAgent 后续需要附件内容,应新增独立的受控附件接口和权限策略,不能复用当前正文工具绕过限制。
## 6. ID 边界
SuperAgent 可以使用:
- `hotel_id`
- 外部 `source_message_id`
- `external_conversation_id`
- 业务 key例如 `group_code``confirmation_number`
SuperAgent 不应依赖:
- 内部 SourceMessage Inbox ID。
- 数据库主键表达业务含义。
- 前端内部路由或展示字段。
接口响应中如果出现内部 ID只能用于本系统排查或后续本系统 API 的对象定位,不应当作外部系统稳定业务 ID。
## 7. 日志与脱敏
MCP endpoint 日志允许记录:
- tool 名称。
- request id。
- trace id。
- hotel id。
- 外部 source message id。
- HTTP 状态码。
- 错误码。
- 调用耗时。
禁止记录:
- REST HMAC secret。
- MCP auth token。
- 完整 HMAC signature。
- 原始邮件正文。
- 附件 URL。
- 客户证件、支付信息、Token、Cookie。
- 未清洗 HTML。
## 8. 重试策略
只读工具:
- MCP endpoint 与业务 Service 同进程,不做 HTTP 重试。
- 如果内部 Service 返回受控错误,应原样包装为 tool result。
写入工具:
- 默认不自动重试已发送的写请求。
- 如果调用方需要重试,必须依赖后端幂等机制和任务结果中的幂等信息。
- 对于响应丢失但请求可能已到达后端的场景,应优先查询已有任务或人工排查,避免重复写入。
## 9. 生产上线前检查
上线前必须确认:
- 生产 `MCP_AUTH_TOKEN` 已通过 Secret 注入。
- `MCP_MAX_BODY_BYTES` 已确认,默认 10MB。
- dev/test 临时 token 没有进入生产。
- 日志脱敏规则已经生效。
- 写入工具生产开关已经明确。
- 所有接口只暴露在 HTTPS 和可信网络边界内。
- 监控覆盖 `/mcp` 可用性、tool 调用失败率和写入错误率。

View File

@@ -0,0 +1,129 @@
# TH Hotel SuperAgent MCP 联调测试用例
## 1. 文档信息
| 项目 | 内容 |
| --- | --- |
| 文档版本 | 0.1 |
| 日期 | 2026-07-09 |
| 状态 | 草案 |
| 适用范围 | SuperAgent HTTP MCP endpoint 联调和回归测试 |
## 2. 测试前置条件
测试前应确认:
- 后端 `server/` 已部署并暴露 `/mcp`
- SuperAgent 已拿到 MCP 层访问凭证。
- 后端已配置 `MCP_ENABLED=true``MCP_AUTH_TOKEN`
- 后端 `server/` dev/test 环境可访问。
- 测试数据不包含真实客户隐私、生产 Token、附件 URL 或支付信息。
## 3. 工具发现测试
| 用例 ID | 场景 | 期望结果 |
| --- | --- | --- |
| MCP-T00-001 | SuperAgent 连接 `/mcp` 并获取工具列表 | 能看到 5 个 TH Hotel tools |
| MCP-T00-002 | 未携带 MCP auth token | 返回 MCP 鉴权失败 |
| MCP-T00-003 | 使用错误 MCP auth token | 返回 MCP 鉴权失败,不调用后端 |
| MCP-T00-004 | 请求体不是合法 JSON | 返回 JSON-RPC parse error |
## 4. th_hotel_query_case_context
| 用例 ID | 场景 | 输入要点 | 期望结果 |
| --- | --- | --- | --- |
| MCP-T01-001 | 按 group code 查询 | `hotel_id` + `group_code` | 返回成功 envelope |
| MCP-T01-002 | 按 confirmation 查询 | `hotel_id` + `confirmation_number` | 返回成功 envelope |
| MCP-T01-003 | 缺少查询 key | 只有 `hotel_id` | 返回 `QUERY_KEY_REQUIRED` |
| MCP-T01-004 | 缺少 hotel id | 不传 `hotel_id` | 返回 `HOTEL_ID_REQUIRED` |
## 5. th_hotel_query_object_detail
| 用例 ID | 场景 | 输入要点 | 期望结果 |
| --- | --- | --- | --- |
| MCP-T02-001 | 查询存在的订单对象 | `object_id=ORDER:{order_id}` | 返回对象详情 |
| MCP-T02-002 | 查询不存在对象 | 不存在的 `object_id` | 返回 `OBJECT_NOT_FOUND` |
| MCP-T02-003 | 缺少 object id | 只传 `hotel_id` | 返回请求参数错误 |
## 6. th_hotel_list_message_conversation_tasks
| 用例 ID | 场景 | 输入要点 | 期望结果 |
| --- | --- | --- | --- |
| MCP-T03-001 | 按外部会话 ID 查询任务 | `external_conversation_id` | 返回任务列表 |
| MCP-T03-002 | 按外部 source message id 锚点查询 | `source_message_id` | 返回该邮件所属会话任务 |
| MCP-T03-003 | 同 conversation id 不同 provider 隔离 | `source_provider=AGENTBUS` | 不返回其他 provider 的任务 |
| MCP-T03-004 | 会话不存在 | 不存在的 `external_conversation_id` | 返回 `MESSAGE_CONVERSATION_NOT_FOUND` |
| MCP-T03-005 | 缺少查询 key | 不传 `external_conversation_id``source_message_id` | 返回 `MESSAGE_CONVERSATION_QUERY_KEY_REQUIRED` |
排序验证:
- 任务先按邮件接收时间正序。
- 同一封邮件下按任务创建时间正序。
- 时间相同时按任务 ID 正序。
## 7. th_hotel_list_message_conversation_messages
| 用例 ID | 场景 | 输入要点 | 期望结果 |
| --- | --- | --- | --- |
| MCP-T04-001 | 按 source message id 查询邮件链正文 | `source_message_id` | 返回受控正文 |
| MCP-T04-002 | 按 external conversation id 查询邮件链正文 | `external_conversation_id` | 按接收时间正序返回正文 |
| MCP-T04-003 | 正文含图片和附件 URL | 测试 HTML 含 `src/href` | 响应不包含附件 URL 和图片 URL |
| MCP-T04-004 | 正文含原始 HTML | 后端有原文 HTML | 响应只包含 `html_body_sanitized` |
| MCP-T04-005 | 读取正文审计 | 调用正文工具 | 后端写入原文访问审计 |
禁止项验证:
- 响应不得包含 `attachments`
- 响应不得包含 `inline_images`
- 响应不得包含 `external_url`
- 响应不得包含附件 URL。
- 响应不得包含原始未清洗 HTML。
## 8. th_hotel_submit_task_results
| 用例 ID | 场景 | 输入要点 | 期望结果 |
| --- | --- | --- | --- |
| MCP-T05-001 | 提交单个 normal task | `ai_task_results` 1 条 | 返回 `accepted_count=1` |
| MCP-T05-002 | 提交 manual review | `result_type=manual_review` | 写入人工复核任务 |
| MCP-T05-003 | 提交 informational message | `result_type=informational_message` | 写入提示类信息 |
| MCP-T05-004 | source message 不存在 | 不存在的外部 `source_message_id` | 返回 `SOURCE_MESSAGE_NOT_FOUND` |
| MCP-T05-005 | 缺少 hotel id | 不传 `hotel_id` | 返回 `HOTEL_ID_REQUIRED` |
| MCP-T05-006 | 重复提交同一幂等任务 | 使用相同幂等信息 | 不重复创建业务任务 |
写入验证:
- `ai_task_results[]` 顺序不能被 MCP endpoint 改变。
- MCP endpoint 不能在日志输出完整 `extracted_fields` 中的敏感内容。
- 失败响应应保留后端错误码和 message。
## 9. MCP 鉴权和开关测试
| 用例 ID | 场景 | 期望结果 |
| --- | --- |
| MCP-AUTH-001 | `MCP_ENABLED=false` | `/mcp` 不暴露或不可调用 |
| MCP-AUTH-002 | 未携带 Bearer token | 返回 `MCP_AUTH_INVALID` |
| MCP-AUTH-003 | Bearer token 错误 | 返回 `MCP_AUTH_INVALID` |
| MCP-AUTH-004 | `MCP_ENABLE_SUBMIT_TASK_RESULTS=false` | 写入 tool 返回 `MCP_TOOL_DISABLED` |
| MCP-AUTH-005 | 请求体超过 `MCP_MAX_BODY_BYTES`,默认 10MB | 返回 `MCP_REQUEST_BODY_TOO_LARGE` |
## 10. 协议和内部异常测试
| 用例 ID | 场景 | 期望结果 |
| --- | --- |
| MCP-PROTO-001 | 调用不存在的 MCP method | 返回 `MCP_METHOD_NOT_FOUND` |
| MCP-PROTO-002 | 调用不存在的 tool | 返回 `MCP_TOOL_NOT_FOUND` |
| MCP-PROTO-003 | tool arguments 不合法 | 返回 `MCP_TOOL_ARGUMENTS_INVALID` |
| MCP-PROTO-004 | 发送 `notifications/initialized` | 返回 202 空响应体 |
## 11. 回归测试清单
每次 MCP endpoint 或 REST 契约变更后,至少回归:
- 5 个工具均能被发现。
- 5 个工具正常成功调用。
- 查询接口错误 envelope 不丢失。
- 任务结果写入成功和幂等重放正常。
- provider/channel 隔离正常。
- 受控正文不返回附件 URL。
- MCP auth 失败不进入业务 Service。
- REST HMAC 接口仍保持原有测试覆盖。

View File

@@ -0,0 +1,445 @@
# TH Hotel SuperAgent MCP Tools 契约
## 1. 文档信息
| 项目 | 内容 |
| --- | --- |
| 文档版本 | 0.1 |
| 日期 | 2026-07-09 |
| 状态 | 草案 |
| 适用范围 | SuperAgent 可调用的 TH Hotel MCP tools |
## 2. 通用约定
内嵌 MCP endpoint 对 SuperAgent 暴露工具,并在当前 Spring Boot 进程内直接调用已有业务 Service。
通用默认值:
| 字段 | 默认值 | 中文说明 |
| --- | --- | --- |
| `source_provider` | `AGENTBUS` | 来源提供方 |
| `source_channel` | `EMAIL` | 来源渠道 |
通用返回建议:
```json
{
"success": true,
"request_id": "req-from-backend-or-mcp",
"trace_id": "trace-from-superagent",
"data": {},
"warnings": [],
"error": null
}
```
中文说明:
- 只读查询工具优先保持后端查询响应 envelope。
- 写入工具保持后端任务结果响应的业务字段。
- MCP tool result 中可以同时提供机器可读结构化数据和简短中文摘要。
- 如果业务 Service 返回受控错误MCP endpoint 应把错误码和中文 message 保留到结构化结果中。
## 3. Tool: th_hotel_query_case_context
### 3.1 用途
查询订单上下文,用于判断当前邮件提到的 group、confirmation 或 reservation key 是否已经存在、
是否存在未完成任务,以及是否可以创建新任务。
### 3.2 何时使用
- SuperAgent 识别出 `group_code``confirmation_number``reservation_no` 后。
- 需要判断当前邮件应新建任务、更新已有对象、取消对象或进入人工复核时。
### 3.3 不应使用
- 不应把该工具当作全文搜索。
- 不应使用历史邮件中不确定的 key 直接创建业务结论。
### 3.4 输入 Schema
```json
{
"type": "object",
"additionalProperties": false,
"properties": {
"hotel_id": {
"type": "string",
"description": "酒店上下文 ID"
},
"group_code": {
"type": ["string", "null"],
"description": "Group / Allotment 查询 key"
},
"confirmation_number": {
"type": ["string", "null"],
"description": "FIT confirmation number 查询 key"
},
"reservation_no": {
"type": ["string", "null"],
"description": "OPERA reservation no"
},
"object_type_hint": {
"type": ["string", "null"],
"description": "调用方推测的对象类型"
},
"target_key_source": {
"type": ["string", "null"],
"description": "key 来源,例如 body_current 或 body_thread_evidence"
},
"body_thread_used_only_as_evidence": {
"type": "boolean",
"description": "历史线程 key 是否仅作为证据"
}
},
"required": ["hotel_id"]
}
```
补充约束:`group_code``confirmation_number``reservation_no` 至少一个非空。
### 3.5 输出
输出对应 REST 接口:
```text
POST /api/ai-query/v1/case-context
```
核心字段:
- `matched_order_records[]`:匹配到的订单。
- `pending_or_open_tasks[]`:未完成或可见任务。
- `target_object_validation`:是否允许创建、更新、取消或附加凭证。
- `warnings[]`:缺少 OPERA 投影等限制。
完整字段以 `superagent-api-contract.md` 第 4 节为准。
## 4. Tool: th_hotel_query_object_detail
### 4.1 用途
查询指定对象详情。第一版主要用于查询 `ORDER:{order_id}` 对象。
### 4.2 何时使用
- 已通过上下文查询拿到 `object_id`
- 需要查看订单状态、业务 key、可更新/可取消状态或已知字段。
### 4.3 输入 Schema
```json
{
"type": "object",
"additionalProperties": false,
"properties": {
"hotel_id": {
"type": "string",
"description": "酒店上下文 ID"
},
"object_id": {
"type": "string",
"description": "查询对象 ID第一版支持 ORDER:{order_id}"
},
"object_type": {
"type": ["string", "null"],
"description": "调用方对象类型提示"
}
},
"required": ["hotel_id", "object_id"]
}
```
### 4.4 输出
输出对应 REST 接口:
```text
POST /api/ai-query/v1/object-detail
```
核心字段:
- `object_id`:对象 ID。
- `order_id`:订单内部 ID 字符串。
- `group_code``confirmation_number``reservation_no`:业务 key。
- `status`:订单状态。
- `can_update``can_cancel`:可操作状态。
- `hard_validation_warnings[]`:硬校验提示。
说明:该响应中的 `source_message_id` 当前是本系统内部 SourceMessage Inbox ID不应作为
SuperAgent 提交任务结果时的外部 `source_message_id`
完整字段以 `superagent-api-contract.md` 第 5 节为准。
## 5. Tool: th_hotel_list_message_conversation_tasks
### 5.1 用途
查询某个邮件会话下已经生成的所有任务,避免 SuperAgent 对同一邮件链重复拆同类任务。
### 5.2 何时使用
- 当前邮件属于一个已有邮件会话。
- 需要判断历史邮件是否已经生成任务。
- 需要按时间顺序查看同一邮件链上的任务进展。
### 5.3 输入 Schema
```json
{
"type": "object",
"additionalProperties": false,
"properties": {
"hotel_id": {
"type": "string",
"description": "酒店上下文 ID"
},
"source_provider": {
"type": ["string", "null"],
"description": "来源提供方,默认 AGENTBUS"
},
"source_channel": {
"type": ["string", "null"],
"description": "来源渠道,默认 EMAIL"
},
"external_conversation_id": {
"type": ["string", "null"],
"description": "外部邮件会话 ID"
},
"source_message_id": {
"type": ["string", "null"],
"description": "外部来源消息 ID可作为锚点反查会话"
}
},
"required": ["hotel_id"]
}
```
补充约束:
- `external_conversation_id``source_message_id` 至少一个非空。
- 两者同时传入时,后端按 `external_conversation_id` 查询为准。
- 查询按 `hotel_id + source_provider + source_channel + external_conversation_id` 隔离。
### 5.4 输出
输出对应 REST 接口:
```text
POST /api/ai-query/v1/message-conversation/tasks
```
排序规则:
1. 先按邮件接收时间正序。
2. 同一封邮件下按任务创建时间正序。
3. 时间相同时按任务 ID 正序。
核心字段:
- `task_count`:任务数量。
- `tasks[].external_source_message_id`:外部来源消息 ID。
- `tasks[].task_id`:任务 ID。
- `tasks[].task_status`:任务状态。
- `tasks[].system_task_type`:系统任务类型。
- `tasks[].task_created_at`:任务创建时间。
完整字段以 `superagent-api-contract.md` 第 6 节为准。
## 6. Tool: th_hotel_list_message_conversation_messages
### 6.1 用途
查询邮件会话下所有受控正文,供 SuperAgent 在需要历史上下文时读取。
### 6.2 何时使用
- 当前邮件需要结合历史邮件判断。
- 需要给业务人员后续展示原文能力预留接口证据。
- 需要按时间顺序读取邮件链正文。
### 6.3 安全边界
该工具不返回:
- 原始未清洗 HTML。
- 附件 URL。
- 内嵌图片 URL。
- `attachments``inline_images``external_url`
- HTML 中的 `href/src` 外链属性。
后端读取正文时会写 SourceMessage 原文访问审计。
### 6.4 输入 Schema
输入字段与 `th_hotel_list_message_conversation_tasks` 相同:
```json
{
"type": "object",
"additionalProperties": false,
"properties": {
"hotel_id": {
"type": "string",
"description": "酒店上下文 ID"
},
"source_provider": {
"type": ["string", "null"],
"description": "来源提供方,默认 AGENTBUS"
},
"source_channel": {
"type": ["string", "null"],
"description": "来源渠道,默认 EMAIL"
},
"external_conversation_id": {
"type": ["string", "null"],
"description": "外部邮件会话 ID"
},
"source_message_id": {
"type": ["string", "null"],
"description": "外部来源消息 ID可作为锚点反查会话"
}
},
"required": ["hotel_id"]
}
```
### 6.5 输出
输出对应 REST 接口:
```text
POST /api/ai-query/v1/message-conversation/messages
```
核心字段:
- `message_count`:邮件数量。
- `messages[].external_source_message_id`:外部来源消息 ID。
- `messages[].received_at`:邮件接收时间。
- `messages[].text_body`:纯文本正文。
- `messages[].html_body_sanitized`:清洗后的 HTML。
- `messages[].html_render_mode`HTML 渲染模式。
完整字段以 `superagent-api-contract.md` 第 7 节为准。
## 7. Tool: th_hotel_submit_task_results
### 7.1 用途
提交 SuperAgent 对单封外部来源消息的 AI 任务识别结果。该工具会写入 AI 过渡层、订单、任务和任务卡。
### 7.2 何时使用
- SuperAgent 已完成当前邮件的最终任务拆分。
- 已确认 `hotel_id` 和外部 `source_message_id` 来自 AgentBus payload。
- 需要把 AI 任务结果交给 TH Hotel 后端进入人工确认流程。
### 7.3 不应使用
- 不应在试探、草稿、未完成推理阶段调用。
- 不应把历史邮件中的外部来源消息 ID 当作当前邮件 ID 提交。
- 不应在缺少 `hotel_id``source_message_id` 时调用。
### 7.4 输入 Schema
```json
{
"type": "object",
"additionalProperties": false,
"properties": {
"hotel_id": {
"type": "string",
"description": "酒店上下文 ID"
},
"source_provider": {
"type": ["string", "null"],
"description": "来源提供方,默认 AGENTBUS"
},
"source_channel": {
"type": ["string", "null"],
"description": "来源渠道,默认 EMAIL"
},
"source_message_id": {
"type": "string",
"description": "外部来源消息 ID对应 AgentBus source.external_message_id"
},
"ai_task_results": {
"type": "array",
"description": "AI 拆分出的任务结果,必须保留数组顺序",
"items": {
"type": "object"
}
},
"extraction_warnings": {
"type": "array",
"description": "AI 抽取警告",
"items": {
"type": "object"
}
}
},
"required": ["hotel_id", "source_message_id", "ai_task_results"]
}
```
说明:
- `ai_task_results[]` 内部字段较多,完整结构以 `superagent-api-contract.md` 第 8 节为准。
- MCP endpoint 不应重排 `ai_task_results[]`
- 如后续需要强 schema 校验,可在 MCP endpoint 内复制 REST 契约中的细粒度字段约束。
### 7.5 输出
输出对应 REST 接口:
```text
POST /api/integrations/superagent/task-results
```
核心字段:
- `batch_id`:批次 ID。
- `idempotent_replay`:是否幂等重放。
- `accepted_count`:接收数量。
- `items[].ai_transition_id`AI 过渡层 ID。
- `items[].order_id`:订单 ID。
- `items[].task_id`:任务 ID。
- `items[].task_status`:任务状态。
完整字段以 `superagent-api-contract.md` 第 8 节为准。
## 8. 错误处理约定
MCP endpoint 应保留业务错误信息:
```json
{
"success": false,
"request_id": "req-001",
"trace_id": "trace-001",
"data": null,
"warnings": [],
"error": {
"code": "AUTH_SIGNATURE_INVALID",
"message": "签名校验失败。",
"details": {}
}
}
```
常见错误码以 `superagent-api-contract.md` 第 9 节为准。
MCP 层新增错误建议:
| 错误码 | 中文说明 |
| --- | --- |
| `MCP_AUTH_INVALID` | MCP 层访问凭证缺失或无效 |
| `MCP_TOOL_DISABLED` | 工具未启用,例如生产临时关闭写入工具 |
| `MCP_REQUEST_INVALID` | MCP JSON-RPC 请求体不合法 |
| `MCP_REQUEST_BODY_TOO_LARGE` | MCP 请求体超过 10MB 默认限制或环境配置限制 |
| `MCP_METHOD_NOT_FOUND` | MCP 方法不存在 |
| `MCP_TOOL_NOT_FOUND` | MCP 工具不存在 |
| `MCP_INTERNAL_ERROR` | MCP endpoint 内部异常 |