@wukongcrm/mcp-server 0.1.3 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,149 +1,207 @@
1
- # @wukongcrm/mcp-server
1
+ # wukong-mcp
2
2
 
3
- WukongCRM MCP Server,用于给支持 Model Context Protocol 的本地 AI 客户端提供 CRM 查询和受控写入能力。
4
-
5
- 默认代理 `https://www.72crm.com/api-11/` 下的固定白名单接口,不提供任意 URL 透传。
3
+ 本项目是供本地 AI ChatGPT 网页端使用的 72CRM MCP Server,固定代理 `https://www.72crm.com/api-11/` 的白名单接口。
6
4
 
7
5
  ## 特点
8
6
 
9
- - 通过 `CRM_API_KEY` 登录,MCP 进程内部调用 `/login` 换取 `adminToken`。
10
- - 业务请求按 72CRM 要求发送 `Admin-Token` 请求头,token 只缓存在本地进程内存中。
7
+ - 本地 stdio 模式由用户配置 `CRM_API_KEY`;远程 HTTP 模式通过当前 72CRM 登录用户静默生成专用 API Key。
8
+ - 业务请求仍按 72CRM 要求发送 `Admin-Token` 请求头,该 token 只缓存在本地进程内存中。
9
+ - 远程模式不会把 API Key 暴露给 ChatGPT 模型,也不会把 API Key 明文写入服务端数据文件。
11
10
  - API Key 登录使用独立端类型 `type=4`,避免占用 PC 端 `type=1` 登录态。
12
11
  - 不读取 OpenAPI,不调用 `/v3/api-docs`。
13
12
  - 不支持附件上传、删除、下载流代理。
14
13
  - 查询能力覆盖线索、客户、联系人、商机、产品、合同、回款、发票、跟进记录等模块。
15
- - 写入只开放线索、客户、联系人、商机、跟进记录,并且必须传 `confirm=true`。
16
-
17
- ## 通用 MCP 配置
14
+ - 人力资源 HRM 保留员工、部门、岗位、考勤、请假等查询,并开放 HRM 域内固定路径写入。
15
+ - 独立财务 FM 保留凭证、账簿、报表、科目、币别、凭证字、仪表盘查询,并开放 FM 域内固定路径写入。
16
+ - 进销存 JXC 保留产品、供应商、仓库、库存和出入库明细查询,并开放 JXC 域内固定路径写入。
17
+ - 无代码能力覆盖应用、模块、字段、数据、角色、流程、阶段、跟进、打印、消息、开放配置和应用市场的 JSON 业务接口。
18
+ - 所有写入仍必须传 `confirm=true`;未确认时只返回预览,不调用 72CRM 写接口。
18
19
 
19
- 推荐直接通过 `npx` 启动,无需提前全局安装:
20
-
21
- ```json
22
- {
23
- "mcpServers": {
24
- "wukongcrm": {
25
- "type": "stdio",
26
- "command": "npx",
27
- "args": ["-y", "@wukongcrm/mcp-server"],
28
- "env": {
29
- "CRM_BASE_URL": "https://www.72crm.com/api-11/",
30
- "CRM_API_KEY": "你的 72CRM API Key"
31
- }
32
- }
33
- }
34
- }
35
- ```
20
+ ## ChatGPT 网页端(远程 MCP)
36
21
 
37
- 如果你的 MCP 客户端不支持 `type` 字段,可以去掉它:
22
+ ChatGPT 网页端不能启动本地 `stdio` 进程,也不支持在 MCP 配置中直接填写自定义 API Key。远程模式提供 Streamable HTTP MCP 和 OAuth 2.0:用户第一次连接时跳转到 72CRM;绑定页通过当前浏览器 `localStorage` 中的 `Admin-Token` 静默生成一把独立 MCP API Key,再通过一次性绑定码由服务端交换。wukong-mcp 验证该 Key 后,签发包含加密 API Key 的短期访问令牌和可轮换刷新令牌。
38
23
 
39
- ```json
40
- {
41
- "mcpServers": {
42
- "wukongcrm": {
43
- "command": "npx",
44
- "args": ["-y", "@wukongcrm/mcp-server"],
45
- "env": {
46
- "CRM_BASE_URL": "https://www.72crm.com/api-11/",
47
- "CRM_API_KEY": "你的 72CRM API Key"
48
- }
49
- }
50
- }
51
- }
52
- ```
24
+ 绑定请求明确不携带 Cookie,`Admin-Token` 也不会传给 wukong-mcp。远程模式不要配置公共的 `CRM_API_KEY`,否则所有 ChatGPT 用户会共用同一个 CRM 账号。
53
25
 
54
- ## pnpm 使用
26
+ ### 启动配置
55
27
 
56
- 不要求必须使用 npm。支持通过 `pnpm dlx` 启动:
28
+ 复制示例配置并填写两个不同用途的随机密钥:
57
29
 
58
- ```json
59
- {
60
- "mcpServers": {
61
- "wukongcrm": {
62
- "type": "stdio",
63
- "command": "pnpm",
64
- "args": ["dlx", "@wukongcrm/mcp-server"],
65
- "env": {
66
- "CRM_BASE_URL": "https://www.72crm.com/api-11/",
67
- "CRM_API_KEY": "你的 72CRM API Key"
68
- }
69
- }
70
- }
71
- }
30
+ ```bash
31
+ cp .env.example .env
32
+ chmod +x start-http.sh
33
+ ./start-http.sh
72
34
  ```
73
35
 
74
- ## 全局安装
36
+ 也可以传入其他配置文件:
75
37
 
76
38
  ```bash
77
- npm install -g @wukongcrm/mcp-server
39
+ ./start-http.sh /path/to/wukong-mcp.env
78
40
  ```
79
41
 
80
- 安装后可以直接启动:
42
+ 脚本默认在每次启动前执行 `npm run build`,并通过 `exec node dist/http-entry.js` 保持前台运行。已经构建完成时,可以在配置文件中设置 `WUKONG_MCP_BUILD_ON_START=0`。
43
+
44
+ 生产环境关键变量如下:
81
45
 
82
46
  ```bash
83
- CRM_API_KEY="你的 72CRM API Key" \
84
- CRM_BASE_URL="https://www.72crm.com/api-11/" \
85
- wukongcrm-mcp
86
- ```
47
+ MCP_PUBLIC_URL=https://www.72crm.com/mcp
48
+ MCP_OAUTH_SECRET=<单独生成的至少32字符随机密钥>
49
+ MCP_DATA_DIR=/var/lib/wukong-mcp
87
50
 
88
- 对应 MCP 配置:
51
+ # 可选;配置后启用 Redis,不配置时继续使用 JSON 文件
52
+ MCP_REDIS_URL=rediss://default:<password>@<redis-host>:6380/0
53
+ MCP_REDIS_PREFIX=wukong-mcp:oauth
89
54
 
90
- ```json
91
- {
92
- "mcpServers": {
93
- "wukongcrm": {
94
- "type": "stdio",
95
- "command": "wukongcrm-mcp",
96
- "env": {
97
- "CRM_BASE_URL": "https://www.72crm.com/api-11/",
98
- "CRM_API_KEY": "你的 72CRM API Key"
99
- }
100
- }
101
- }
102
- }
55
+ CRM_BASE_URL=https://www.72crm.com/api-11/
56
+ CRM_BINDING_AUTHORIZE_URL=https://www.72crm.com/mcp-binding.html
57
+ CRM_BINDING_EXCHANGE_URL=https://www.72crm.com/api-11/adminMcpBinding/exchange
58
+ CRM_BINDING_EXCHANGE_ALLOW_HTTP=false
59
+ CRM_BINDING_CALLBACK_URL=https://www.72crm.com/mcp/oauth/72crm/callback
60
+ CRM_BINDING_CLIENT_ID=wukong-mcp
61
+ CRM_BINDING_CLIENT_SECRET=<与72CRM后端完全一致的至少32字符共享密钥>
62
+
63
+ MCP_HOST=127.0.0.1
64
+ MCP_PORT=3000
65
+ MCP_ALLOWED_HOSTS=www.72crm.com
66
+ MCP_TRUST_PROXY=1
103
67
  ```
104
68
 
105
- ## API Key 配置
69
+ - `MCP_OAUTH_SECRET` 用于 AES-256-GCM 加密 OAuth 令牌;更换后,已连接用户需要重新授权。
70
+ - 未配置 `MCP_REDIS_URL` 时,`MCP_DATA_DIR/oauth-state.json` 保存动态客户端、授权临时状态和撤销记录。
71
+ - 配置 `MCP_REDIS_URL` 后,上述 OAuth 状态改为保存到 Redis;支持 `redis://` 和启用 TLS 的 `rediss://`。
72
+ - `MCP_REDIS_PREFIX` 默认为 `wukong-mcp:oauth`。同一套 MCP 实例必须使用相同的前缀和 `MCP_OAUTH_SECRET`。
73
+ - 授权请求和授权码在写入 Redis 或 JSON 前均使用 AES-256-GCM 加密,不会保存明文 API Key;授权码通过 Redis `GETDEL` 原子消费,因此 Redis/Tair 需要兼容 Redis 6.2 或更高版本。
74
+ - 如果已经配置 Redis 但启动时连接失败,服务会启动失败,不会自动退回 JSON,以避免多个实例产生不一致状态。
75
+ - `CRM_BINDING_AUTHORIZE_URL` 必须指向 72CRM 前端中转页,不能直接填写后端授权接口。
76
+ - `CRM_BINDING_EXCHANGE_URL` 由 MCP 服务端请求,优先使用 HTTPS;仅当它是可信 VPC 内网 HTTP 地址时,才同时设置 `CRM_BINDING_EXCHANGE_ALLOW_HTTP=true`。此开关不会放开授权页或回调地址的 HTTPS 校验。
77
+ - `CRM_BINDING_CLIENT_SECRET` 必须与 72CRM `admin-web` 配置完全一致,只保存在服务端。
78
+ - `CRM_BINDING_CALLBACK_URL` 默认根据 `MCP_PUBLIC_URL` 的路径生成,显式配置时必须与其同域。
79
+ - `MCP_ALLOWED_HOSTS` 是逗号分隔的额外 Host 白名单;公开域名会由 `MCP_PUBLIC_URL` 自动加入。
80
+ - `MCP_TRUST_PROXY=1` 表示 MCP 服务前面有一层可信 Nginx 反向代理,使 Express 能正确读取客户端 IP 并避免限流器把所有请求识别为 Nginx;直接暴露 MCP 端口时应设置为 `false`,也可以填写可信代理 IP/CIDR。
81
+ - MCP 的初始 Bearer challenge 同时要求 `crm.read offline_access`,ChatGPT 完成授权后会获得刷新令牌;已经按旧范围授权的连接需要删除后重新连接。
82
+ - 动态 OAuth 客户端只支持 `none + PKCE` 公共客户端模式,不签发客户端密钥,以兼容 ChatGPT 和 Claude 的远程 MCP 授权流程。
106
83
 
107
- `CRM_API_KEY` 是运行时环境变量,不应在 `npm install` 阶段传入。
84
+ 远程端点布局:
108
85
 
109
- README 中示例里的 `CRM_API_KEY` 对应 72CRM 个人中心生成的 MCP Token。获取地址:
86
+ - MCP:`https://www.72crm.com/mcp`
87
+ - 健康检查:`https://www.72crm.com/mcp/healthz`
88
+ - OAuth:`/mcp/oauth/authorize`、`/mcp/oauth/token`、`/mcp/oauth/register`、`/mcp/oauth/revoke`
89
+ - 72CRM 回调:`/mcp/oauth/72crm/callback`
90
+ - 标准发现:`/.well-known/oauth-protected-resource/mcp`、`/.well-known/oauth-authorization-server`、`/.well-known/openid-configuration`
110
91
 
111
- ```text
112
- https://www.72crm.com/cloud/#/person/index?selectedIndex=1
92
+ ### 72CRM 配置
93
+
94
+ `admin-web` 需要配置:
95
+
96
+ ```bash
97
+ WUKONG_MCP_BINDING_CLIENT_ID=wukong-mcp
98
+ WUKONG_MCP_BINDING_CLIENT_SECRET=<与MCP服务一致的共享密钥>
99
+ WUKONG_MCP_BINDING_CALLBACK_URL=https://www.72crm.com/mcp/oauth/72crm/callback
100
+ WUKONG_MCP_BINDING_CODE_TTL_SECONDS=120
113
101
  ```
114
102
 
115
- MCP 客户端启动 server 时必须能把 `CRM_API_KEY` 注入到 `@wukongcrm/mcp-server` 进程环境中。常见方式是写在 MCP 客户端配置的 `env` 字段里,或由启动脚本/系统环境变量注入。
103
+ `mcp-binding.html` 72CRM 前端的 `localStorage["Admin-Token"]` 读取当前登录 Token,以 `Admin-Token` 请求头调用后端,并明确禁止携带 Cookie。Token 只用于本次绑定,不会发给 wukong-mcp。交换接口使用时间戳和 HMAC-SHA256 签名,一次性绑定码只能消费一次。
104
+
105
+ ### 在 ChatGPT 中加载
106
+
107
+ 1. 在 ChatGPT 设置中启用开发者模式,并创建自定义 App/Connector。
108
+ 2. MCP Server URL 填写 `https://www.72crm.com/mcp`,认证方式选择 OAuth。
109
+ 3. 保存并连接后,浏览器会跳转到 `https://www.72crm.com/mcp-binding.html`;当前已登录时将静默完成绑定。
110
+ 4. 授权完成后扫描工具,检查各工具的只读、写入和破坏性标记。
116
111
 
117
112
  ## 开发运行
118
113
 
119
- ```bash
120
- npm install
121
- CRM_API_KEY="你的 72CRM API Key" \
122
- CRM_BASE_URL="https://www.72crm.com/api-11/" \
114
+ ```powershell
115
+ cd D:\Desktop\wukong-mcp
116
+ npm ci
117
+ $env:CRM_API_KEY="你的 72CRM API Key"
118
+ $env:CRM_BASE_URL="https://www.72crm.com/api-11/"
123
119
  npm run build
124
120
  node dist/index.js
125
121
  ```
126
122
 
127
- ## 发布
123
+ ## 打包分发
128
124
 
129
- 发布前验证:
125
+ 发布到 npm 前,先完成依赖安装和测试:
130
126
 
131
- ```bash
127
+ ```powershell
128
+ cd D:\Desktop\wukong-mcp
129
+ npm ci
132
130
  npm test
133
131
  npm run build
134
- npm pack --dry-run
132
+ npm publish
135
133
  ```
136
134
 
137
- 首次公开发布 scoped 包:
135
+ 包使用 `@wukongcrm/mcp-server` 作用域公开发布。使用者可以直接安装:
138
136
 
139
- ```bash
140
- npm publish
137
+ ```powershell
138
+ npm install -g @wukongcrm/mcp-server
139
+ ```
140
+
141
+ 如需离线分发,可以在本机生成 npm tarball:
142
+
143
+ ```powershell
144
+ npm pack
145
+ ```
146
+
147
+ 生成文件示例:
148
+
149
+ ```text
150
+ wukongcrm-mcp-server-0.2.0.tgz
151
+ ```
152
+
153
+ 这个包只包含运行所需的 `dist`、`README.md` 和 `package.json`,不会携带源码、测试文件或用户 API Key。
154
+
155
+ 使用者拿到 `.tgz` 后安装:
156
+
157
+ ```powershell
158
+ npm install -g .\wukongcrm-mcp-server-0.2.0.tgz
159
+ ```
160
+
161
+ 安装后可以直接用命令启动:
162
+
163
+ ```powershell
164
+ $env:CRM_API_KEY="使用者自己的 72CRM API Key"
165
+ $env:CRM_BASE_URL="https://www.72crm.com/api-11/"
166
+ wukong-mcp
141
167
  ```
142
168
 
143
- `package.json` 已配置 `publishConfig.access=public`,因此不需要额外追加 `--access public`。
169
+ ## 本地 AI 配置示例
170
+
171
+ ```json
172
+ {
173
+ "mcpServers": {
174
+ "wukong-crm": {
175
+ "command": "wukong-mcp",
176
+ "env": {
177
+ "CRM_BASE_URL": "https://www.72crm.com/api-11/",
178
+ "CRM_API_KEY": "请在这里填写 72CRM API Key"
179
+ }
180
+ }
181
+ }
182
+ }
183
+ ```
144
184
 
145
185
  ## 支持工具
146
186
 
187
+ ### 无代码工具
188
+
189
+ 无代码工具只调用源码中声明的固定接口,不提供任意 URL 透传。写工具保持既有 MCP 语义:未传 `confirm=true` 时返回将要调用的接口、请求体和查询参数;明确确认后才执行。
190
+
191
+ - 应用与模块:`nocode_list_applications`、`nocode_get_application`、`nocode_list_modules`、`nocode_get_module`、`nocode_write_application`、`nocode_write_module`
192
+ - 字段与数据:`nocode_get_module_schema`、`nocode_query_fields`、`nocode_search_records`、`nocode_get_record`、`nocode_query_records`、`nocode_calculate_formula`、`nocode_check_duplicate`、`nocode_write_field`、`nocode_write_record`
193
+ - 权限与团队:`nocode_list_team_members`、`nocode_get_permissions`、`nocode_write_team`、`nocode_write_role`
194
+ - 场景与页面:`nocode_list_scenes`、`nocode_list_tabs`、`nocode_get_module_file`、`nocode_write_scene`、`nocode_write_tab`
195
+ - 流程与阶段:`nocode_list_flows`、`nocode_list_stages`、`nocode_list_custom_buttons`、`nocode_query_workflow`、`nocode_write_flow`、`nocode_write_stage`、`nocode_write_custom_button`、`nocode_write_workflow`
196
+ - 跟进:`nocode_query_followups`、`nocode_write_followup`
197
+ - 业务配置:`nocode_query_configuration`、`nocode_write_configuration`
198
+ - 打印与消息:`nocode_query_printing`、`nocode_write_printing`、`nocode_query_messages`、`nocode_write_message`
199
+ - 开放能力与应用市场:`nocode_query_integrations`、`nocode_write_integration`、`nocode_query_marketplace`、`nocode_write_marketplace`
200
+
201
+ 文件流仍有意不经 MCP 代理,因此应用导入/导出、Excel 导入/导出、跟进导出、打印 PDF/Word 下载不在工具中;打印内容生成和预览 JSON 接口仍可使用。内部测试接口 `/moduleMQ/send` 也不会暴露。
202
+
203
+ ### CRM、OA、HRM、财务、进销存与工单工具
204
+
147
205
  - `crm_auth_status`
148
206
  - `crm_list_modules`
149
207
  - `crm_list_customer_pools`
@@ -156,16 +214,137 @@ npm publish
156
214
  - `crm_get_record_timeline`
157
215
  - `crm_get_action_records`
158
216
  - `crm_list_files`
217
+ - `crm_search_products`
218
+ - `crm_search_sale_products`
219
+ - `crm_get_product`
220
+ - `crm_get_product_information`
221
+ - `crm_get_product_schema`
222
+ - `crm_list_product_files`
223
+ - `crm_get_product_num`
224
+ - `crm_get_simple_products`
159
225
  - `crm_list_users`
160
226
  - `crm_find_user_id`
161
227
  - `crm_list_departments`
162
228
  - `crm_find_dept_id`
229
+ - `crm_list_address_book_contacts`
230
+ - `crm_get_address_book_contact`
231
+ - `crm_list_address_book_departments`
232
+ - `crm_list_address_book_auth_departments`
233
+ - `crm_list_address_book_dept_user_ids`
234
+ - `crm_list_address_book_dept_users`
235
+ - `crm_list_address_book_auth_users`
236
+ - `crm_get_address_book_user_dept_role_info`
237
+ - `crm_get_address_book_organization`
238
+ - `crm_get_address_book_user_count`
239
+ - `crm_toggle_address_book_attention`
240
+ - `crm_list_hrm_employees`
241
+ - `crm_get_hrm_employee`
242
+ - `crm_list_hrm_employee_fields`
243
+ - `crm_list_hrm_departments`
244
+ - `crm_get_hrm_department`
245
+ - `crm_list_hrm_department_employees`
246
+ - `crm_get_hrm_employee_post`
247
+ - `crm_list_hrm_attendance_month_records`
248
+ - `crm_get_hrm_attendance_daily_detail`
249
+ - `crm_list_hrm_leave_records`
250
+ - `crm_list_hrm_leave_types`
251
+ - `crm_write_hrm`
252
+ - `crm_create_hrm_record`
253
+ - `crm_update_hrm_record`
254
+ - `crm_list_finance_modules`
255
+ - `crm_search_finance_vouchers`
256
+ - `crm_get_finance_voucher`
257
+ - `crm_summarize_finance_vouchers`
258
+ - `crm_query_finance_ledger`
259
+ - `crm_query_finance_report`
260
+ - `crm_list_finance_subjects`
261
+ - `crm_list_finance_currencies`
262
+ - `crm_list_finance_voucher_words`
263
+ - `crm_query_finance_dashboard`
264
+ - `crm_write_finance`
265
+ - `crm_create_finance_voucher`
266
+ - `crm_update_finance_voucher`
267
+ - `crm_list_jxc_modules`
268
+ - `crm_search_jxc_records`
269
+ - `crm_get_jxc_record`
270
+ - `crm_get_jxc_record_information`
271
+ - `crm_get_jxc_module_schema`
272
+ - `crm_list_jxc_files`
273
+ - `crm_list_jxc_stock_products`
274
+ - `crm_get_jxc_product_inventory`
275
+ - `crm_list_jxc_stock_movements`
276
+ - `crm_get_jxc_warehouse_product_stock`
277
+ - `crm_get_jxc_warehouse_names`
278
+ - `crm_write_jxc`
279
+ - `crm_create_jxc_record`
280
+ - `crm_update_jxc_record`
281
+ - `crm_list_calendar_events`
282
+ - `crm_get_calendar_event`
283
+ - `crm_list_oa_examine_categories`
284
+ - `crm_list_oa_examine_groups`
285
+ - `crm_list_oa_examines`
286
+ - `crm_get_oa_examine`
287
+ - `crm_get_oa_examine_fields`
288
+ - `crm_list_oa_examine_record_logs`
289
+ - `crm_list_oa_examine_flow_records`
290
+ - `crm_list_oa_announcements`
291
+ - `crm_get_oa_announcement`
292
+ - `crm_create_oa_announcement`
293
+ - `crm_update_oa_announcement`
294
+ - `crm_delete_oa_announcement`
295
+ - `crm_mark_oa_announcement_read`
296
+ - `crm_list_oa_logs`
297
+ - `crm_get_oa_log`
298
+ - `crm_get_oa_log_information`
299
+ - `crm_list_oa_log_templates`
300
+ - `crm_get_oa_log_fields`
301
+ - `crm_get_oa_log_welcome`
302
+ - `crm_get_oa_log_bulletin`
303
+ - `crm_get_oa_log_complete_stats`
304
+ - `crm_list_oa_log_complete_records`
305
+ - `crm_list_oa_log_incomplete_records`
306
+ - `crm_list_oa_tasks`
307
+ - `crm_list_related_oa_tasks`
163
308
  - `crm_preview_write`
164
309
  - `crm_create_record`
165
310
  - `crm_update_customer`
166
311
  - `crm_update_record_fields`
312
+ - `crm_create_product`
313
+ - `crm_update_product`
314
+ - `crm_update_product_fields`
315
+ - `crm_update_product_status`
316
+ - `crm_transfer_products_owner`
317
+ - `crm_delete_products`
318
+ - `crm_create_contract`
319
+ - `crm_update_contract`
320
+ - `crm_create_receivables`
321
+ - `crm_update_receivables`
322
+ - `crm_create_receivables_plan`
323
+ - `crm_update_receivables_plan`
324
+ - `crm_create_invoice`
325
+ - `crm_update_invoice`
326
+ - `crm_create_quotation`
327
+ - `crm_update_quotation`
328
+ - `crm_create_calendar_event`
329
+ - `crm_update_calendar_event`
330
+ - `crm_create_oa_examine`
331
+ - `crm_save_oa_examine_draft`
332
+ - `crm_audit_oa_examine`
333
+ - `crm_batch_audit_oa_examine`
334
+ - `crm_create_oa_log`
335
+ - `crm_update_oa_log`
336
+ - `crm_delete_oa_log`
337
+ - `crm_toggle_oa_log_favour`
338
+ - `crm_create_oa_task`
339
+ - `crm_update_oa_task_fields`
167
340
  - `crm_add_followup`
168
341
  - `crm_update_followup`
342
+ - `workorder_search_records`
343
+ - `workorder_get_record`
344
+ - `workorder_get_schema`
345
+ - `workorder_preview_write`
346
+ - `workorder_create_record`
347
+ - `workorder_update_record`
169
348
 
170
349
  ### `crm_search_records` 语义搜索
171
350
 
@@ -182,6 +361,50 @@ npm publish
182
361
 
183
362
  客户模块会转换为“客户名称 / 手机 / 电话”三个高级筛选条件,使用 `type=3`(包含)和不同 `groupId` 做 OR 查询。也支持 `query`、`q`、`phone`、`mobile`、`name` 等字段。
184
363
 
364
+ 负责人和创建人可以直接传用户 ID。单个和多个 ID 分别使用 `ownerUserId` / `ownerUserIds`、`createUserId` / `createUserIds`:
365
+
366
+ ```json
367
+ {
368
+ "module": "customer",
369
+ "ownerUserIds": [9, 10],
370
+ "createUserId": 11
371
+ }
372
+ ```
373
+
374
+ 只有昵称时,可以使用 `ownerUserName` / `ownerUserNames`、`createUserName` / `createUserNames`。MCP 会先调用员工列表接口做模糊召回,再按昵称精确比对;唯一命中后才把用户 ID 写入 `formType=user` 的筛选值。查无此人会报错,重名时会列出候选用户 ID,必须改传明确 ID,避免筛错人:
375
+
376
+ ```json
377
+ {
378
+ "module": "customer",
379
+ "ownerUserName": "张三"
380
+ }
381
+ ```
382
+
383
+ 通用高级筛选也支持相同的昵称解析。以下调用最终发送给 72CRM 的 `values` 会是用户 ID,而不是昵称:
384
+
385
+ ```json
386
+ {
387
+ "module": "customer",
388
+ "filters": [
389
+ {
390
+ "fieldName": "ownerUserId",
391
+ "formType": "user",
392
+ "type": 1,
393
+ "values": ["张三"]
394
+ }
395
+ ]
396
+ }
397
+ ```
398
+
399
+ 如需单独核对用户 ID,可调用 `crm_find_user_id`:
400
+
401
+ ```json
402
+ {
403
+ "name": "张三",
404
+ "mode": "realname"
405
+ }
406
+ ```
407
+
185
408
  ### 客户更新
186
409
 
187
410
  推荐优先使用 `crm_update_customer` 修改客户字段。它支持直接传客户 ID,也支持通过手机号、客户名或关键字唯一匹配客户;正式写入前会读取客户字段结构,自动补齐 `fieldId`、`fieldType`、`type`、`formType`,避免下拉字段或自定义字段写错结构。
@@ -214,6 +437,655 @@ npm publish
214
437
 
215
438
  写入成功后默认会再次读取 `/crmCustomer/information/{id}` 做字段级校验;如只想写入不校验,可传 `verify=false`。
216
439
 
440
+ ### CRM 产品
441
+
442
+ 产品模块同时支持通用 CRM 读接口和专用产品工具。产品列表固定调用 `/crmProduct/queryPageList`,销售产品列表固定调用 `/crmProduct/querySaleProductPageList`:
443
+
444
+ ```json
445
+ {
446
+ "page": 1,
447
+ "limit": 20,
448
+ "keyword": "云服务",
449
+ "categoryId": 5,
450
+ "status": 1
451
+ }
452
+ ```
453
+
454
+ 详情、详情页字段、字段结构、附件元数据、数量和简要实体分别调用:
455
+
456
+ - `/crmProduct/queryById/{productId}`
457
+ - `/crmProduct/information/{productId}`
458
+ - `/crmProduct/field` 或 `/crmProduct/field/{productId}`
459
+ - `/crmProduct/queryFileList`
460
+ - `/crmProduct/num`
461
+ - `/crmProduct/querySimpleEntity`
462
+
463
+ 产品新增和编辑可以直接传 72CRM 保存 payload,也可以使用 `entity + field`:
464
+
465
+ ```json
466
+ {
467
+ "entity": {
468
+ "name": "云服务"
469
+ },
470
+ "field": [],
471
+ "confirm": true
472
+ }
473
+ ```
474
+
475
+ `crm_create_product` 固定调用 `/crmProduct/add`,`crm_update_product` 固定调用 `/crmProduct/update`,编辑时必须提供 `productId` 或 `id`。字段更新使用 `crm_update_product_fields`,固定调用 `/crmProduct/updateInformation`,会先读取 `/crmProduct/field/{productId}` 自动补齐字段结构,并默认读取 `/crmProduct/information/{productId}` 做写后校验。
476
+
477
+ 上下架、负责人转移和删除分别调用 `/crmProduct/updateStatus`、`/crmProduct/changeOwnerUser`、`/crmProduct/deleteByIds`,这些写入都必须传 `confirm=true`。导入导出、multipart 上传和文件流下载仍不代理。
478
+
479
+ ### CRM 审批单据写入
480
+
481
+ 合同、回款、回款计划、发票、报价单不再走通用 `crm_create_record`,而是使用专用工具绑定真实固定接口:
482
+
483
+ - 合同:`crm_create_contract` -> `/crmContract/add`,`crm_update_contract` -> `/crmContract/update`
484
+ - 回款:`crm_create_receivables` -> `/crmReceivables/add`,`crm_update_receivables` -> `/crmReceivables/update`
485
+ - 回款计划:`crm_create_receivables_plan` -> `/crmReceivablesPlan/add`,`crm_update_receivables_plan` -> `/crmReceivablesPlan/update`
486
+ - 发票:`crm_create_invoice` -> `/crmInvoice/add`,`crm_update_invoice` -> `/crmInvoice/update`
487
+ - 报价单:`crm_create_quotation` -> `/crmQuotation/add`,`crm_update_quotation` -> `/crmQuotation/update`
488
+
489
+ 这些工具支持两种传法。第一种是直接传 72CRM 原始保存 payload,适合前端或线上接口已经抓到完整结构的场景:
490
+
491
+ ```json
492
+ {
493
+ "body": {
494
+ "entity": {
495
+ "contractNum": "HT-001"
496
+ },
497
+ "field": [],
498
+ "product": [],
499
+ "examineFlowData": {
500
+ "label": 6,
501
+ "dataMap": {},
502
+ "flowDataList": []
503
+ }
504
+ },
505
+ "confirm": true
506
+ }
507
+ ```
508
+
509
+ 第二种是传 `fields/updates/fieldValues`,MCP 会先调用对应 `/field` 接口读取字段结构,再自动组装 `entity + field + product/contract + examineFlowData`:
510
+
511
+ ```json
512
+ {
513
+ "fields": {
514
+ "合同编号": "HT-001",
515
+ "合同金额": 1000,
516
+ "产品": {
517
+ "product": [
518
+ {
519
+ "productId": 10,
520
+ "name": [{ "name": "云服务" }],
521
+ "salesPrice": "288.5",
522
+ "num": 2,
523
+ "discount": "90"
524
+ }
525
+ ],
526
+ "totalPrice": "577",
527
+ "discountRate": "90"
528
+ }
529
+ },
530
+ "examineFlowData": {
531
+ "label": 6,
532
+ "dataMap": {},
533
+ "flowDataList": []
534
+ },
535
+ "confirm": true
536
+ }
537
+ ```
538
+
539
+ 合同、回款、发票、报价单通常受审批流配置影响。MCP 不会伪造审批流;如果没有传 `examineFlowData`,预览和写入结果会带 `approvalNotice` 提醒。若只想保存草稿,可传 `draft=true`,MCP 会补 `entity.checkStatus=5`。所有写入仍必须传 `confirm=true`。
540
+
541
+ ### 通讯录
542
+
543
+ 通讯录列表固定调用 `/adminUser/queryListName`,支持分页、搜索、部门、关注状态、首字母和首字母排序:
544
+
545
+ ```json
546
+ {
547
+ "page": 1,
548
+ "limit": 20,
549
+ "keyword": "张三",
550
+ "deptId": 8,
551
+ "status": 1,
552
+ "acronym": "Z",
553
+ "initial": 1
554
+ }
555
+ ```
556
+
557
+ 联系人详情固定调用 `/adminUser/queryUserInfo`:
558
+
559
+ ```json
560
+ {
561
+ "userId": 1001
562
+ }
563
+ ```
564
+
565
+ 组织和部门相关只读工具:
566
+
567
+ - `crm_list_address_book_departments` -> `/adminDept/queryDeptTree`
568
+ - `crm_list_address_book_auth_departments` -> `/adminDept/queryDeptByAuth`
569
+ - `crm_list_address_book_dept_user_ids` -> `/adminUser/queryUserByDeptIds`
570
+ - `crm_list_address_book_dept_users` -> `/adminUser/queryListByDeptIds`
571
+ - `crm_list_address_book_auth_users` -> `/adminUser/queryAuthUserList`
572
+ - `crm_get_address_book_user_dept_role_info` -> `/adminUser/queryUserDeptOrRoleInfo`
573
+ - `crm_get_address_book_organization` -> `/adminUser/queryOrganizationInfo`
574
+ - `crm_get_address_book_user_count` -> `/adminUser/queryUserNumInfo`
575
+
576
+ 按部门查询简要用户:
577
+
578
+ ```json
579
+ {
580
+ "deptIds": [8, 9]
581
+ }
582
+ ```
583
+
584
+ 按用户、部门、角色批量查询聚合信息:
585
+
586
+ ```json
587
+ {
588
+ "userIds": [1001],
589
+ "deptIds": [8],
590
+ "roleIds": [2]
591
+ }
592
+ ```
593
+
594
+ 关注状态切换固定调用 `/adminUser/attention`,`userId` 按 72CRM 后端要求走查询参数,必须传 `confirm=true` 才会写入:
595
+
596
+ ```json
597
+ {
598
+ "userId": 1001,
599
+ "confirm": true
600
+ }
601
+ ```
602
+
603
+ ### 办公审批
604
+
605
+ 审批类型固定调用 `/examines/queryPartList`,默认按 OA 审批传 `label=0`、`pageType=0`;审批分组固定调用 `/examineSuperExamines/queryExamineGroup`,默认 `groupType=0`。
606
+
607
+ 审批列表统一使用 `crm_list_oa_examines`,MCP 会按 `listType` 和 `tab` 映射到新版前端接口:
608
+
609
+ ```json
610
+ {
611
+ "listType": "upcoming",
612
+ "tab": "todo",
613
+ "page": 1,
614
+ "limit": 15,
615
+ "search": "报销"
616
+ }
617
+ ```
618
+
619
+ 常用映射包括:`upcoming/todo` -> `/examineSuperExamine/todo/me`,`upcoming/copy` -> `/examineSuperExamine/copy/me`,`track/me|do|copy`,`archive/me|audit|follow|tovoid|copy`,`draft`,`all`。也保留旧版 `legacyWaiting` -> `/examineWaiting/queryOaExamineList` 和 `legacyRecord` -> `/examineRecord/queryExamineRecordList`。
620
+
621
+ 审批详情固定调用 `/oaExamine/queryOaExamineInfo/{examineId}`。字段查询支持三种模式:传 `categoryId` 时默认调用 `/oaExamineField/queryField/{categoryId}` 获取新建审批自定义字段;传 `categoryId` 且 `mode=list` 时调用 `/oaExamineField/queryFieldList/{categoryId}`;传 `examineId` 或 `id` 时调用 `/oaExamine/getField` 获取详情字段。审批流转日志固定调用 `/examineRecord/queryExamineRecordLog`。
622
+
623
+ 新增审批、保存草稿、审批处理分别调用 `/oaExamine/setOaExamine`、`/oaExamine/setOaExamineDraft`、`/examineRecord/auditExamine`,批量审批调用 `/examineRecord/batchAuditExamine`。这些写操作都必须传 `confirm=true` 才会请求 72CRM;未传时只返回预览。
624
+
625
+ 新建审批支持两种传法。第一种是直接传 72CRM 原始 payload;第二种是传 `categoryId + fields/updates/fieldValues`,MCP 会先读取自定义字段结构,再自动组装为 `oaExamine + oaExamineRelation + field + oaExamineTravelList`:
626
+
627
+ ```json
628
+ {
629
+ "categoryId": 7,
630
+ "batchId": "可选附件批次ID",
631
+ "fields": {
632
+ "审批内容": "客户拜访报销",
633
+ "金额": 128.5,
634
+ "申请人": [{ "userId": 9 }]
635
+ },
636
+ "customerIds": [1001],
637
+ "confirm": true
638
+ }
639
+ ```
640
+
641
+ 系统字段会进入 `oaExamine`,自定义字段会进入 `field`;人员、部门、复选、分类、附件 batchId、明细表、出差/报销事项会按前端提交规则做转换。传 `strictRequired=true` 时会按字段元数据检查必填字段。
642
+
643
+ ### 日历日程
644
+
645
+ 日程列表固定调用 `/oaEvent/queryList`,详情固定调用 `/oaEvent/queryById`。列表查询的 `startTime`、`endTime` 按 72CRM 接口使用毫秒时间戳:
646
+
647
+ ```json
648
+ {
649
+ "startTime": 1782470400000,
650
+ "endTime": 1782556799999,
651
+ "typeIds": [1, 2],
652
+ "userId": 9
653
+ }
654
+ ```
655
+
656
+ 新增和修改日程分别调用 `/oaEvent/save`、`/oaEvent/update`,同样必须传 `confirm=true` 才会写入。可以直接传 72CRM 的 `SetEventBO` 结构:
657
+
658
+ ```json
659
+ {
660
+ "event": {
661
+ "eventId": 12,
662
+ "title": "客户回访",
663
+ "typeId": 3,
664
+ "startTime": "2026-06-26 10:00:00",
665
+ "endTime": "2026-06-26 11:00:00",
666
+ "ownerUserIds": "9",
667
+ "repetitionType": 1,
668
+ "endType": 1
669
+ },
670
+ "relation": {
671
+ "customerIds": "1001"
672
+ },
673
+ "notice": [
674
+ {
675
+ "type": 1,
676
+ "value": 15
677
+ }
678
+ ],
679
+ "confirm": true
680
+ }
681
+ ```
682
+
683
+ 也可以把 `title`、`typeId`、`startTime`、`endTime`、`ownerUserIds`、`customerIds`、`notices` 等字段放在顶层,MCP 会组装成 `SetEventBO`。删除日程、状态更新、单独增删关联仍不开放。
684
+
685
+ ### OA 公告
686
+
687
+ 公告列表和详情分别固定调用 `/oaAnnouncement/queryList`、`/oaAnnouncement/queryById/{announcementId}`:
688
+
689
+ ```json
690
+ {
691
+ "page": 1,
692
+ "limit": 20,
693
+ "type": 1
694
+ }
695
+ ```
696
+
697
+ 新增、编辑、删除和标记已读分别调用 `/oaAnnouncement/addAnnouncement`、`/oaAnnouncement/setAnnouncement`、`/oaAnnouncement/delete/{announcementId}`、`/oaAnnouncement/readAnnouncement`。写入类操作必须传 `confirm=true`;未确认时只返回目标地址和请求体预览。`deptIds`、`ownerUserIds`、`readUserIds` 支持传数组,MCP 会转成 72CRM 接口常用的逗号字符串。
698
+
699
+ ```json
700
+ {
701
+ "title": "公告标题",
702
+ "content": "公告内容",
703
+ "ownerUserIds": [9, 10],
704
+ "confirm": true
705
+ }
706
+ ```
707
+
708
+ ### OA 日志
709
+
710
+ 日志列表、详情、详情页字段、模板、模板字段、欢迎语、公告栏、完成统计、已完成/未完成记录分别固定调用:
711
+
712
+ - `/oaLog/queryList`
713
+ - `/oaLog/queryById`
714
+ - `/oaLog/information/{logId}`
715
+ - `/oaLogTemplate/queryPartList`
716
+ - `/oaLogTemplateField/field` 或 `/oaLogTemplateField/field/{logId}`
717
+ - `/oaLog/getLogWelcomeSpeech`
718
+ - `/oaLog/queryLogBulletin`
719
+ - `/oaLog/queryCompleteStats`
720
+ - `/oaLog/queryCompleteOaLogList`
721
+ - `/oaLog/queryIncompleteOaLogList`
722
+
723
+ 新增和编辑日志固定调用 `/oaLog/addOrUpdate`。可以直接传 `body` 原始 payload,也可以传 `categoryId + fields/updates/fieldValues`,MCP 会先读取日志模板字段并组装系统字段和自定义字段:
724
+
725
+ ```json
726
+ {
727
+ "categoryId": 7,
728
+ "title": "日报",
729
+ "sendUserIds": [9],
730
+ "fields": {
731
+ "日志内容": "今天完成客户回访",
732
+ "明日工作": "继续跟进报价",
733
+ "工时": 8
734
+ },
735
+ "confirm": true
736
+ }
737
+ ```
738
+
739
+ 删除日志和关注/取消关注分别调用 `/oaLog/deleteById`、`/oaLog/favourOrCancel`,都必须传 `confirm=true`。导出、打印和附件流下载仍不代理。
740
+
741
+ ### OA 任务
742
+
743
+ OA 任务列表固定调用 `/oaTask/queryTaskList`,支持 72CRM 的 `OaTaskListBO` 常用筛选字段:
744
+
745
+ ```json
746
+ {
747
+ "page": 1,
748
+ "limit": 20,
749
+ "type": 1,
750
+ "status": 1,
751
+ "priority": 3,
752
+ "keyword": "客户回访",
753
+ "mainUserIds": [9, 10]
754
+ }
755
+ ```
756
+
757
+ 关联业务任务固定调用 `/oaTask/queryTypeTaskList`:
758
+
759
+ ```json
760
+ {
761
+ "type": 2,
762
+ "typeId": 1001
763
+ }
764
+ ```
765
+
766
+ 新增主任务固定调用 `/workTask/saveWorkTask`,必须传 `confirm=true` 才会写入。可以直接传 `task`,也可以使用顶层字段:
767
+
768
+ ```json
769
+ {
770
+ "name": "客户回访",
771
+ "description": "确认续费计划",
772
+ "mainUserId": 9,
773
+ "ownerUserId": [9, 10],
774
+ "startTime": "2026-06-27",
775
+ "stopTime": "2026-06-28",
776
+ "priority": 3,
777
+ "labelId": [1, 2],
778
+ "customerIds": [1001],
779
+ "confirm": true
780
+ }
781
+ ```
782
+
783
+ 更新主任务字段固定映射到 72CRM 的独立接口,必须传 `confirm=true` 才会写入:
784
+
785
+ ```json
786
+ {
787
+ "taskId": 12,
788
+ "updates": {
789
+ "name": "客户回访-已更新",
790
+ "description": "带上报价单",
791
+ "mainUserId": 9,
792
+ "ownerUserId": [9, 10],
793
+ "startTime": "2026-06-27",
794
+ "stopTime": "2026-06-28",
795
+ "labelId": [1, 2],
796
+ "priority": 3,
797
+ "status": 5
798
+ },
799
+ "confirm": true
800
+ }
801
+ ```
802
+
803
+ 其中标题、描述、负责人、参与人、时间、标签、优先级、状态会分别调用 `/workTask/setWorkTaskTitle`、`/workTask/setWorkTaskDescription`、`/workTask/setWorkTaskMainUser`、`/workTask/setWorkTaskOwnerUser`、`/workTask/setWorkTaskTime`、`/workTask/setWorkTaskLabel`、`/workTask/setWorkTaskPriority`、`/workTask/setWorkTaskStatus`。删除任务、导出、子任务删除、删除参与人、删除标签暂不开放。
804
+
805
+ ### 人力资源 HRM
806
+
807
+ HRM 查询工具仍走固定只读接口;写入按“全部放开”开放到 HRM 域内固定路径。`crm_write_hrm` 只允许调用 `/hrm...` 开头的接口,支持直接传 `targetPath`,也支持传 `module + operation` 组合。未传 `confirm=true` 时只返回预览。
808
+
809
+ 员工列表固定调用 `/hrmEmployee/queryPageList`,`keyword`、`name`、`search` 会映射为 HRM 的 `employeeName`:
810
+
811
+ ```json
812
+ {
813
+ "page": 1,
814
+ "limit": 15,
815
+ "keyword": "张三",
816
+ "deptId": 8,
817
+ "status": 11
818
+ }
819
+ ```
820
+
821
+ 员工详情、字段表头、部门树、部门员工、岗位信息分别调用:
822
+
823
+ - `/hrmEmployee/queryById/{employeeId}`
824
+ - `/hrmEmployeeField/queryListHeads`
825
+ - `/hrmDept/queryTreeList`
826
+ - `/hrmDept/queryEmployeeByDeptId`
827
+ - `/hrmEmployeePost/postInformation/{employeeId}`
828
+
829
+ 考勤月汇总固定调用 `/hrmAttendanceEmpMonthRecord/queryAttendanceEmpMonthRecordPageList`:
830
+
831
+ ```json
832
+ {
833
+ "page": 1,
834
+ "limit": 20,
835
+ "search": "张三",
836
+ "deptIds": [8],
837
+ "times": ["2026-06-01", "2026-06-30"],
838
+ "isFullAttendance": 1
839
+ }
840
+ ```
841
+
842
+ 每日打卡明细固定调用 `/hrmAttendanceClock/queryAttendanceDailyDetail`:
843
+
844
+ ```json
845
+ {
846
+ "employeeId": 100,
847
+ "date": "2026-06-29"
848
+ }
849
+ ```
850
+
851
+ 请假记录和请假类型分别调用 `/hrmEmployeeLeaveRecord/queryLeaveRecordPageList`、`/hrmEmployeeLeaveRecord/queryLeaveTypeList`:
852
+
853
+ ```json
854
+ {
855
+ "employeeId": 100,
856
+ "times": ["2026-06-01", "2026-06-30"],
857
+ "leaveTypes": ["年假"]
858
+ }
859
+ ```
860
+
861
+ HRM 写入示例:
862
+
863
+ ```json
864
+ {
865
+ "targetPath": "/hrmEmployee/addEmployee",
866
+ "body": {
867
+ "field": [
868
+ { "fieldName": "employeeName", "value": "张三" }
869
+ ]
870
+ },
871
+ "confirm": true
872
+ }
873
+ ```
874
+
875
+ 也可以用组合形式调用任意 HRM 域内接口:
876
+
877
+ ```json
878
+ {
879
+ "module": "hrmEmployeePost",
880
+ "operation": "updatePostInformation",
881
+ "body": {
882
+ "employeeId": 100,
883
+ "post": "研发工程师"
884
+ },
885
+ "confirm": true
886
+ }
887
+ ```
888
+
889
+ ### 独立财务 FM
890
+
891
+ FM 当前接入独立财务模块,不包含 JXC 财务单据。查询工具仍固定调用只读接口;写入可使用 `crm_write_finance` 调用 `/finance...` 开头的独立财务接口,凭证新增/编辑提供了便捷工具。
892
+
893
+ 凭证列表、详情和汇总分别固定调用 `/financeCertificate/queryPageList`、`/financeCertificate/queryById`、`/financeCertificate/summary`:
894
+
895
+ ```json
896
+ {
897
+ "page": 1,
898
+ "limit": 20,
899
+ "accountId": 3,
900
+ "keyword": "付货款",
901
+ "certificateTime": ["2026-06-01", "2026-06-30"]
902
+ }
903
+ ```
904
+
905
+ 账簿查询使用 `crm_query_finance_ledger`,`ledger` 支持:
906
+
907
+ - `detail`: `/financeCertificate/queryDetailAccount`
908
+ - `general`: `/financeCertificate/queryGeneralLedger`
909
+ - `balance`: `/financeCertificate/queryDetailBalanceAccount`
910
+ - `multiColumn`: `/financeCertificate/queryDiversification`
911
+ - `itemsDetail`: `/financeCertificate/queryItemsDetailAccount`
912
+ - `itemsBalance`: `/financeCertificate/queryItemsDetailBalanceAccount`
913
+ - `amountDetail`: `/financeCertificate/queryAmountDetailAccount`
914
+ - `amountGeneral`: `/financeCertificate/queryAmountDetailUpAccount`
915
+
916
+ 财务报表使用 `crm_query_finance_report`,`report` 支持:
917
+
918
+ - `balanceSheet`: `/financeReport/balanceSheetReport`
919
+ - `incomeStatement`: `/financeReport/incomeStatementReport`
920
+ - `cashFlow`: `/financeReport/cashFlowStatementReport`
921
+
922
+ 传 `checkBalance=true` 时会调用对应报表的 `/balanceCheck` 接口。科目、币别、凭证字和仪表盘分别使用 `/financeSubject/list`、`/financeCurrency/queryAllList` 或 `/financeCurrency/queryListByAccountId`、`/financeVoucher/queryList`、`/financeDashboard/*` 的固定白名单查询。
923
+
924
+ 凭证新增和编辑:
925
+
926
+ ```json
927
+ {
928
+ "body": {
929
+ "accountId": 3,
930
+ "certificateTime": "2026-06-30",
931
+ "certificateItems": []
932
+ },
933
+ "confirm": true
934
+ }
935
+ ```
936
+
937
+ `crm_create_finance_voucher` 固定调用 `/financeCertificate/add`,`crm_update_finance_voucher` 固定调用 `/financeCertificate/update`,编辑时必须提供 `certificateId` 或 `id`:
938
+
939
+ ```json
940
+ {
941
+ "certificateId": 77,
942
+ "body": {
943
+ "accountId": 3,
944
+ "remark": "updated"
945
+ },
946
+ "confirm": true
947
+ }
948
+ ```
949
+
950
+ 其他 FM 写接口使用域级写入工具:
951
+
952
+ ```json
953
+ {
954
+ "targetPath": "/financeDigest/add",
955
+ "body": {
956
+ "accountId": 3,
957
+ "digestContent": "付货款"
958
+ },
959
+ "confirm": true
960
+ }
961
+ ```
962
+
963
+ ### 进销存 JXC
964
+
965
+ JXC 查询保留产品、供应商、仓库、库存和出入库明细的固定接口。写入按“全部放开”开放到 JXC 域内固定路径:产品、供应商、仓库提供便捷新增/编辑工具,其他 JXC 单据、资金、库存、设置类写接口可使用 `crm_write_jxc`。
966
+
967
+ 主数据模块可以先用 `crm_list_jxc_modules` 查看固定白名单,再用统一查询工具访问:
968
+
969
+ ```json
970
+ {
971
+ "module": "product",
972
+ "page": 1,
973
+ "limit": 20,
974
+ "keyword": "电机",
975
+ "warehouseId": 8
976
+ }
977
+ ```
978
+
979
+ `crm_search_jxc_records` 会按模块固定调用 `/jxcProduct/queryPageList`、`/jxcSupplier/queryPageList` 或 `/jxcWarehouse/queryPageList`。详情、详情页字段、字段结构、附件元数据分别调用:
980
+
981
+ - `/jxcProduct|jxcSupplier|jxcWarehouse/queryById/{id}`
982
+ - `/jxcProduct|jxcSupplier|jxcWarehouse/information/{id}`
983
+ - `/jxcProduct|jxcSupplier|jxcWarehouse/field`
984
+ - `/jxcProduct|jxcSupplier|jxcWarehouse/queryFileList`
985
+
986
+ 库存列表固定调用 `/jxcWarehouseProduct/queryPageList`:
987
+
988
+ ```json
989
+ {
990
+ "page": 1,
991
+ "limit": 20,
992
+ "keyword": "电机",
993
+ "productCode": "P-100",
994
+ "warehouseId": 8,
995
+ "stock": "1"
996
+ }
997
+ ```
998
+
999
+ 产品库存、出入库明细、仓库产品库存数量和仓库名称分别调用:
1000
+
1001
+ - `/jxcProduct/queryProductInventory/{productId}`
1002
+ - `/jxcDetailed/queryPageList`
1003
+ - `/jxcWarehouse/queryProductWarehouseNumBatch`
1004
+ - `/jxcWarehouse/queryWarehouseNameByIds`
1005
+
1006
+ 产品、供应商、仓库主数据新增/编辑:
1007
+
1008
+ ```json
1009
+ {
1010
+ "module": "product",
1011
+ "entity": {
1012
+ "name": "电机"
1013
+ },
1014
+ "field": [],
1015
+ "confirm": true
1016
+ }
1017
+ ```
1018
+
1019
+ ```json
1020
+ {
1021
+ "module": "supplier",
1022
+ "id": 88,
1023
+ "entity": {
1024
+ "name": "新供应商"
1025
+ },
1026
+ "field": [],
1027
+ "confirm": true
1028
+ }
1029
+ ```
1030
+
1031
+ 其他 JXC 写接口示例:
1032
+
1033
+ ```json
1034
+ {
1035
+ "module": "jxcPurchase",
1036
+ "operation": "add",
1037
+ "body": {
1038
+ "entity": {
1039
+ "orderNo": "PO-001"
1040
+ },
1041
+ "field": []
1042
+ },
1043
+ "confirm": true
1044
+ }
1045
+ ```
1046
+
1047
+ ## 工单
1048
+
1049
+ 工单工具用于兼容 PHP 工单能力,同时保持标准 MCP 的固定接口和确认写入边界。
1050
+
1051
+ - `workorder_search_records`:普通工单、工单池和线下工单分页查询。`scope=pool` 时固定调用 `/wkoWorkorder/queryPageList` 并传 `isPool=1`,`scope=offline` 时调用 `/wkoOfflineWorkorder/queryPageList`。
1052
+ - `workorder_get_record`:查询普通工单或线下工单详情,并同时读取详情字段 `/information/{id}`。
1053
+ - `workorder_get_schema`:查询普通工单或线下工单字段结构,可传 `id` 获取编辑字段。
1054
+ - `workorder_preview_write`:只生成新建或更新请求体,不调用写接口。
1055
+ - `workorder_create_record`:显式 `confirm=true` 后调用 `/wkoWorkorder/add` 或 `/wkoOfflineWorkorder/add`,写入后自动回读。
1056
+ - `workorder_update_record`:显式 `confirm=true` 后调用 `/wkoWorkorder/update` 或 `/wkoOfflineWorkorder/update`,写入后自动回读。
1057
+
1058
+ 普通工单新建示例:
1059
+
1060
+ ```json
1061
+ {
1062
+ "entity": {
1063
+ "name": "测试工单"
1064
+ },
1065
+ "field": [],
1066
+ "confirm": true
1067
+ }
1068
+ ```
1069
+
1070
+ 线下工单新建示例:
1071
+
1072
+ ```json
1073
+ {
1074
+ "scope": "offline",
1075
+ "body": {
1076
+ "name": "线下维修工单"
1077
+ },
1078
+ "confirm": true
1079
+ }
1080
+ ```
1081
+
217
1082
  ## 安全边界
218
1083
 
219
- 以下操作前期全部拒绝:删除、转移负责人、公海流转、导入导出、审批/状态流转、字段配置修改、附件上传。
1084
+ HRM、JXC、FM 和工单写入已按要求开放到域内固定路径,但仍保留这些硬边界:
1085
+
1086
+ - 必须传 `confirm=true` 才会请求 72CRM;否则只返回预览。
1087
+ - `crm_write_hrm` 只能调用 `/hrm...`,`crm_write_jxc` 只能调用 `/jxc...`,`crm_write_finance` 只能调用 `/finance...`。
1088
+ - 工单工具只调用 `/wkoWorkorder...` 与 `/wkoOfflineWorkorder...` 固定路径,不开放任意工单路径透传。
1089
+ - 不允许 `targetPath` 使用完整 URL、跨域路径、`..`、查询串或片段。
1090
+ - 不代理文件流下载,不处理 multipart 文件上传;附件上传仍不支持。
1091
+ - 这些写入会真实修改 HRM/JXC/FM/工单业务数据,调用前请先用 `confirm=false` 看预览体。