docs: add project write design

This commit is contained in:
nac
2026-07-12 22:34:17 +00:00
parent f84be83245
commit 2fc1b31d3f
@@ -0,0 +1,133 @@
# 项目写入与附件上传设计
## 目标
为现有只读 NocoBase CRM MCP 增加受限的项目创建与更新能力,并支持通过同一 HTTP 服务上传文件、再将其增量关联到项目附件。
范围仅覆盖 NocoBase 项目集合 `t_projects`。服务不得提供任意集合、任意字段或删除项目的能力。
## 已确认的数据模型
项目集合:`t_projects`(标题:项目)。
| MCP 参数 | NocoBase 字段 | 说明 |
| --- | --- | --- |
| `name` | `f_project_name` | 项目名;创建时必填 |
| `customer_id` | `client_ID` | 客户外键,目标集合为 `t_nt3pjadelqi` |
| `inquiry_date` | `xm_project_inquiry_date` | 项目收到日期,`YYYY-MM-DD` |
| `progress` | `f_projects_progress` | 项目进展 |
| `applications` | `f_projects_applications` | 应用 |
| `part_numbers` | `f_projects_part_numbers` | 涉及产品料号 |
| `period_usage` | `f_projects_period_usage` | 项目用量 |
| `details` | `f_projects_details` | 详细信息 |
附件关联字段为 `f_projects_attachments`,类型为 `belongsToMany`,目标为 NocoBase 内置 `attachments` 集合,存储为 `local`。联系人、跟进记录、项目情况更新、系统字段和其它字段均不在首版写入范围内。
允许的项目进展为:`询价阶段`、`已报价`、`送样`、`已定点`、`SOP`、`终止`。MCP 接受这些中文标签,并映射到 NocoBase 已配置的内部枚举值。
## 方案选择
采用分步上传方案:HTTP 上传端点先将文件写入 NocoBase 附件库并返回附件 ID;MCP 项目工具再使用该 ID 建立项目关联。
此方案将二进制 multipart 上传与 MCP JSON 工具调用分开,便于客户端重试、明确上传与项目写入的失败边界,也避免客户端持有 NocoBase JWT。单请求中同时提交项目和文件、以及让客户端直接调用 NocoBase 均不采用。
## HTTP 上传接口
新增 `POST /uploads`,与 `/mcp` 部署在同一个 HTTP 服务中,并复用现有 MCP Bearer Token 中间件。
请求必须为 `multipart/form-data`,每次仅接收一个名为 `file` 的文件字段。默认单文件上限为 25 MiB。首版不额外限制 MIME 类型;部署者可在配置中收紧允许的类型。
服务将文件流式写入受控临时目录,随后转发到 NocoBase:
`POST <NOCOBASE_MCP_UPLOAD_API_BASE_URL>/attachments:create?attachmentField=t_projects.f_projects_attachments`
转发请求使用 `NOCOBASE_MCP_UPLOAD_JWT` 中配置的 NocoBase 用户 JWT。该 JWT、NocoBase API 地址和文件内容均不得写入日志、MCP 结果或 `config.json`。临时文件无论成功或失败都必须立即清理。
成功响应:
```json
{
"upload_id": 123,
"filename": "quote.pdf",
"size": 456,
"mimetype": "application/pdf"
}
```
`upload_id` 是 NocoBase `attachments.id`。上传成功但尚未关联到项目的附件会保留;首版不运行自动清理任务,以避免误删业务文件。
## MCP 工具
新增:
```text
create_project(
name, customer_id?, inquiry_date?, progress?,
applications?, part_numbers?, period_usage?, details?,
attachment_ids?
)
update_project(
project_id,
name?, customer_id?, inquiry_date?, progress?,
applications?, part_numbers?, period_usage?, details?,
add_attachment_ids?, remove_attachment_ids?
)
```
### 规则
- `name` 创建时必填,且去除首尾空白后不能为空。
- `inquiry_date` 必须为 `YYYY-MM-DD`。
- `progress` 必须是上表中定义的六个中文标签之一。
- `customer_id` 只写入 `client_ID`。
- `attachment_ids` 仅用于创建后建立附件关联。
- 更新附件只接受 `add_attachment_ids` 和 `remove_attachment_ids`;不提供覆盖整个附件集合的语义。
- 同一个附件 ID 不得同时出现在 add 和 remove 列表中。
- 输入列表必须去重;不存在或无权访问的附件使该次附件关联操作失败。
创建或更新标量字段后,再执行附件关联。若关联操作失败,响应必须包含已创建或已更新的 `project_id` 和结构化失败详情;不回滚已经成功写入的项目字段。关联操作使用 NocoBase `belongsToMany` 的 `add` 与 `remove` 资源操作。
## 错误契约
所有业务失败均保持现有 MCP 的结构化错误格式。首版增加:
- `invalid_project_input`
- `invalid_progress`
- `project_not_found`
- `attachment_not_found`
- `upload_too_large`
- `unsupported_media_type`
- `nb_upload_failed`
- `nb_upload_unauthorized`
上传端点对缺失或无效的 MCP Bearer Token 返回 401。上游 JWT 失效或被拒绝时,上传端点返回明确的认证失败,不重试登录,也不暴露上游令牌。
## 配置与权限
`config.json` 追加固定的 `projects` 映射,包含项目资源、八个可写字段、客户外键和附件关联字段。该映射不允许调用方覆盖。
运行时环境变量:
- `NOCOBASE_MCP_UPLOAD_API_BASE_URL`
- `NOCOBASE_MCP_UPLOAD_JWT`
- `NOCOBASE_MCP_UPLOAD_MAX_BYTES`(默认 `26214400`)
- 可选 MIME 白名单环境变量或配置项
服务角色必须拥有:`t_projects` 的 create/update、`attachments` 的上传/create,以及 `t_projects.f_projects_attachments` 的 add/remove 权限。README 和 systemd 服务配置必须明确这些新增权限与密钥配置。
## 验证
- 为 NocoBase 客户端新增创建、更新和关联 add/remove 的命令构造单元测试。
- 为项目服务增加字段白名单、日期、进展、附件冲突和结构化错误测试。
- 为上传 ASGI 接口增加认证、multipart、文件上限、上游失败和临时文件清理测试。
- 为 MCP server 增加新工具的 schema、参数传递和附件增量语义测试。
- 自动化测试全部使用模拟的 NocoBase/HTTP 调用;不得连接真实 NocoBase 或写入真实项目、附件。
## 非目标
- 删除项目或附件。
- 管理联系人、跟进记录、项目更新记录或任意其它关联。
- 任意字段写入或调用方指定资源。
- 自动清理未关联附件。
- 客户端直接持有或提交 NocoBase JWT。