contract-template-mcp-server 1.0.1 → 1.1.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 +24 -4
- package/package.json +1 -1
- package/src/index.js +20 -12
package/README.md
CHANGED
|
@@ -11,6 +11,7 @@ CRM 合同模版库管理 MCP Server,为智能体(如 CodeBuddy/WorkBuddy)
|
|
|
11
11
|
| `list_contract_templates` | 查询合同模板列表(支持分类/关键词筛选) | `GET /mcp/contract/template/list` |
|
|
12
12
|
| `get_contract_template` | 获取模板详情及文件下载URL | `GET /mcp/contract/template/detail` |
|
|
13
13
|
| `create_contract_template` | 在分类下创建新模板(含 v1.0 初版) | `POST /mcp/contract/template/create` |
|
|
14
|
+
| `upload_file_to_template_category` | 上传文件并一步创建模板(推荐) | `POST /mcp/contract/template/upload-and-create` |
|
|
14
15
|
|
|
15
16
|
## 安装与配置
|
|
16
17
|
|
|
@@ -88,6 +89,18 @@ AI: ① 先调用文件上传接口 /resource/nas-center/upload 上传文件,
|
|
|
88
89
|
→ 模板创建成功(v1.0 草稿状态)
|
|
89
90
|
```
|
|
90
91
|
|
|
92
|
+
### 上传文件一步创建模板(推荐)
|
|
93
|
+
|
|
94
|
+
```
|
|
95
|
+
用户: 帮我把这个文件上传到销售合同分类下
|
|
96
|
+
AI: 调用 upload_file_to_template_category(filePath="/path/to/file.docx", categoryId=销售合同分类ID)
|
|
97
|
+
→ 内部自动完成:文件读取 + 上传 NAS/OSS + 模板创建 + 版本初始化
|
|
98
|
+
→ 模板创建成功(v1.0 草稿状态)
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
> **性能说明**:MCP Server 与 WorkBuddy 同机运行,`upload_file_to_template_category` 直接通过 `filePath`
|
|
102
|
+
> 读取本地文件,无需客户端做 base64 编码,大文件上传速度大幅提升。
|
|
103
|
+
|
|
91
104
|
## 数据来源标记
|
|
92
105
|
|
|
93
106
|
所有通过 MCP Server 创建的分类和模板,数据库 `data_source` 字段会自动标记为 `MCP_SERVER`,
|
|
@@ -95,11 +108,18 @@ AI: ① 先调用文件上传接口 /resource/nas-center/upload 上传文件,
|
|
|
95
108
|
|
|
96
109
|
## 文件上传说明
|
|
97
110
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
111
|
+
### 方式一:`upload_file_to_template_category`(推荐)
|
|
112
|
+
|
|
113
|
+
直接传文件本地路径,MCP Server 自动完成文件读取、上传和模板创建:
|
|
114
|
+
- 参数 `filePath`:本地文件的绝对路径
|
|
115
|
+
- 参数 `fileName`:可选,不传则从路径自动提取
|
|
116
|
+
|
|
117
|
+
### 方式二:手动分步上传
|
|
101
118
|
|
|
102
|
-
|
|
119
|
+
1. 先上传文件获取 `fileId`:
|
|
120
|
+
- **NAS 上传**:`POST /resource/nas-center/upload`(multipart/form-data)
|
|
121
|
+
- **OSS 上传**:`POST /resource/oss/upload`(multipart/form-data)
|
|
122
|
+
2. 使用 `create_contract_template` 传入 `fileId` 创建模板
|
|
103
123
|
|
|
104
124
|
## 技术架构
|
|
105
125
|
|
package/package.json
CHANGED
package/src/index.js
CHANGED
|
@@ -28,6 +28,7 @@
|
|
|
28
28
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
29
29
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
30
30
|
import { z } from "zod";
|
|
31
|
+
import fs from "fs";
|
|
31
32
|
import {
|
|
32
33
|
listCategories,
|
|
33
34
|
createCategory,
|
|
@@ -41,7 +42,7 @@ import {
|
|
|
41
42
|
// 创建 MCP Server 实例
|
|
42
43
|
const server = new McpServer({
|
|
43
44
|
name: "contract-template-mcp-server",
|
|
44
|
-
version: "1.0
|
|
45
|
+
version: "1.1.0",
|
|
45
46
|
});
|
|
46
47
|
|
|
47
48
|
// ============================================================
|
|
@@ -427,17 +428,18 @@ server.tool(
|
|
|
427
428
|
"使用示例:用户说\u201C帮我把这个文件上传到销售合同分类下\u201D,智能体调用此工具即可一步完成。",
|
|
428
429
|
].join("\n"),
|
|
429
430
|
{
|
|
430
|
-
|
|
431
|
+
filePath: z
|
|
431
432
|
.string()
|
|
432
433
|
.describe(
|
|
433
|
-
"
|
|
434
|
-
|
|
434
|
+
"文件的本地绝对路径(必填)。由于 MCP Server 与 WorkBuddy 运行在同一台机器上," +
|
|
435
|
+
"直接传文件路径即可,服务端会自动读取文件内容,无需客户端做 base64 编码。" +
|
|
436
|
+
"例如:\"/Users/user/Desktop/销售合同模板.docx\""
|
|
435
437
|
),
|
|
436
438
|
fileName: z
|
|
437
439
|
.string()
|
|
438
|
-
.
|
|
440
|
+
.optional()
|
|
439
441
|
.describe(
|
|
440
|
-
"
|
|
442
|
+
"文件名(可选)。不传则从 filePath 中自动提取文件名"
|
|
441
443
|
),
|
|
442
444
|
categoryId: z
|
|
443
445
|
.string()
|
|
@@ -462,7 +464,7 @@ server.tool(
|
|
|
462
464
|
.describe("创建该模板的AI模型名称(可选),用于追溯数据来源"),
|
|
463
465
|
},
|
|
464
466
|
async ({
|
|
465
|
-
|
|
467
|
+
filePath,
|
|
466
468
|
fileName,
|
|
467
469
|
categoryId,
|
|
468
470
|
categoryName,
|
|
@@ -471,12 +473,13 @@ server.tool(
|
|
|
471
473
|
modelName,
|
|
472
474
|
}) => {
|
|
473
475
|
try {
|
|
474
|
-
//
|
|
475
|
-
const
|
|
476
|
+
// 直接读取本地文件(MCP Server 与 WorkBuddy 同机运行,无需 base64 编码)
|
|
477
|
+
const actualFileName = fileName || filePath.split("/").pop() || "unknown";
|
|
478
|
+
const fileData = fs.readFileSync(filePath);
|
|
476
479
|
|
|
477
480
|
const result = await uploadAndCreateTemplate({
|
|
478
481
|
fileData,
|
|
479
|
-
fileName,
|
|
482
|
+
fileName: actualFileName,
|
|
480
483
|
categoryId,
|
|
481
484
|
templateName,
|
|
482
485
|
description,
|
|
@@ -491,7 +494,7 @@ server.tool(
|
|
|
491
494
|
text: JSON.stringify(
|
|
492
495
|
{
|
|
493
496
|
success: true,
|
|
494
|
-
message: `文件「${
|
|
497
|
+
message: `文件「${actualFileName}」已成功上传到${categoryName || categoryId}分类下,模板创建完成(v1.0 草稿状态)`,
|
|
495
498
|
data: newTemplate
|
|
496
499
|
? {
|
|
497
500
|
id: newTemplate.id ? String(newTemplate.id) : undefined,
|
|
@@ -511,6 +514,11 @@ server.tool(
|
|
|
511
514
|
],
|
|
512
515
|
};
|
|
513
516
|
} catch (error) {
|
|
517
|
+
let errorMessage = error.message;
|
|
518
|
+
// 提供更友好的文件不存在错误提示
|
|
519
|
+
if (error.code === "ENOENT") {
|
|
520
|
+
errorMessage = `文件不存在或无法访问: ${filePath}`;
|
|
521
|
+
}
|
|
514
522
|
return {
|
|
515
523
|
content: [
|
|
516
524
|
{
|
|
@@ -518,7 +526,7 @@ server.tool(
|
|
|
518
526
|
text: JSON.stringify(
|
|
519
527
|
{
|
|
520
528
|
success: false,
|
|
521
|
-
message: `上传文件并创建模板失败: ${
|
|
529
|
+
message: `上传文件并创建模板失败: ${errorMessage}`,
|
|
522
530
|
},
|
|
523
531
|
null,
|
|
524
532
|
2
|