@ppdocs/mcp 3.10.0 → 3.13.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 +7 -3
- package/dist/cli.js +27 -2
- package/dist/index.js +48 -1
- package/dist/storage/httpClient.d.ts +22 -1
- package/dist/storage/httpClient.js +50 -0
- package/dist/storage/types.d.ts +62 -0
- package/dist/tools/analyzer.d.ts +1 -4
- package/dist/tools/analyzer.js +4 -7
- package/dist/tools/flowchart.js +1 -3
- package/dist/tools/index.d.ts +8 -9
- package/dist/tools/index.js +8 -27
- package/dist/tools/init.js +1 -1
- package/dist/tools/kg_status.d.ts +1 -1
- package/dist/tools/kg_status.js +4 -6
- package/dist/tools/refs.js +77 -71
- package/dist/tools/tasks.d.ts +1 -2
- package/dist/tools/tasks.js +32 -46
- package/dist/tools/workflow.js +2 -3
- package/package.json +1 -1
- package/dist/tools/discussion.d.ts +0 -15
- package/dist/tools/discussion.js +0 -264
- package/dist/tools/doc_query.d.ts +0 -10
- package/dist/tools/doc_query.js +0 -185
- package/dist/tools/files.d.ts +0 -6
- package/dist/tools/files.js +0 -107
- package/dist/tools/meeting.d.ts +0 -7
- package/dist/tools/meeting.js +0 -97
- package/dist/tools/projects.d.ts +0 -7
- package/dist/tools/projects.js +0 -19
package/dist/tools/refs.js
CHANGED
|
@@ -2,33 +2,19 @@ import { z } from 'zod';
|
|
|
2
2
|
import { getClient } from '../storage/httpClient.js';
|
|
3
3
|
import { decodeObjectStrings } from '../utils.js';
|
|
4
4
|
import { safeTool, wrap } from './shared.js';
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
});
|
|
13
|
-
const adoptedNodeSchema = z.object({
|
|
14
|
-
chartId: z.string(),
|
|
15
|
-
nodeId: z.string(),
|
|
16
|
-
nodeLabel: z.string(),
|
|
17
|
-
});
|
|
5
|
+
function formatBytes(bytes) {
|
|
6
|
+
if (bytes < 1024)
|
|
7
|
+
return `${bytes} B`;
|
|
8
|
+
if (bytes < 1048576)
|
|
9
|
+
return `${(bytes / 1024).toFixed(1)} KB`;
|
|
10
|
+
return `${(bytes / 1048576).toFixed(1)} MB`;
|
|
11
|
+
}
|
|
18
12
|
export function registerReferenceTools(server) {
|
|
19
13
|
const client = () => getClient();
|
|
20
|
-
server.tool('kg_ref', '
|
|
21
|
-
'
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
id: z.string().optional().describe('参考 ID'),
|
|
25
|
-
title: z.string().optional().describe('参考标题 (save)'),
|
|
26
|
-
summary: z.string().optional().describe('Markdown 总结 (save)'),
|
|
27
|
-
links: z.array(linkSchema).optional().describe('参考链接 (save)'),
|
|
28
|
-
files: z.array(fileSchema).optional().describe('参考文件 (save)'),
|
|
29
|
-
scripts: z.array(fileSchema).optional().describe('解析脚本 (save)'),
|
|
30
|
-
adoptedBy: z.array(adoptedNodeSchema).optional().describe('已采用该参考的节点 (save)'),
|
|
31
|
-
path: z.string().optional().describe('参考文件路径 (read_file)'),
|
|
14
|
+
server.tool('kg_ref', '外部参考管理。fetch: 输入URL拉取网页内容到本地持久化。list/get/delete: 管理已有参考。\nactions: list|get|fetch|delete', {
|
|
15
|
+
action: z.enum(['list', 'get', 'fetch', 'delete']).describe('操作类型'),
|
|
16
|
+
id: z.string().optional().describe('参考 ID (get/delete/fetch时指定ID则为refetch)'),
|
|
17
|
+
url: z.string().optional().describe('要拉取的文档 URL (fetch)'),
|
|
32
18
|
}, async (args) => safeTool(async () => {
|
|
33
19
|
const decoded = decodeObjectStrings(args);
|
|
34
20
|
switch (decoded.action) {
|
|
@@ -37,19 +23,20 @@ export function registerReferenceTools(server) {
|
|
|
37
23
|
if (refs.length === 0)
|
|
38
24
|
return wrap('当前没有外部参考');
|
|
39
25
|
const lines = [
|
|
40
|
-
|
|
26
|
+
`外部参考 (${refs.length})`,
|
|
41
27
|
'',
|
|
42
|
-
'| ID | 标题 | 链接 | 文件 |
|
|
28
|
+
'| ID | 标题 | 链接 | 文件 | 拉取次数 |',
|
|
43
29
|
'|:---|:---|---:|---:|---:|',
|
|
44
30
|
];
|
|
45
31
|
for (const ref of refs) {
|
|
46
|
-
|
|
32
|
+
const fetchCount = ref.fetchHistory?.length || 0;
|
|
33
|
+
lines.push(`| ${ref.id} | ${ref.title} | ${ref.links.length} | ${ref.files.length} | ${fetchCount} |`);
|
|
47
34
|
}
|
|
48
35
|
return wrap(lines.join('\n'));
|
|
49
36
|
}
|
|
50
37
|
case 'get': {
|
|
51
38
|
if (!decoded.id)
|
|
52
|
-
return wrap('
|
|
39
|
+
return wrap('get 需要 id');
|
|
53
40
|
const ref = await client().getReference(decoded.id);
|
|
54
41
|
if (!ref)
|
|
55
42
|
return wrap(`未找到外部参考: ${decoded.id}`);
|
|
@@ -59,11 +46,17 @@ export function registerReferenceTools(server) {
|
|
|
59
46
|
`- ID: ${ref.id}`,
|
|
60
47
|
`- Links: ${ref.links.length}`,
|
|
61
48
|
`- Files: ${ref.files.length}`,
|
|
62
|
-
`- Scripts: ${ref.scripts.length}`,
|
|
63
|
-
`- AdoptedBy: ${ref.adoptedBy.length}`,
|
|
64
|
-
'',
|
|
65
|
-
ref.summary || '(无摘要)',
|
|
66
49
|
];
|
|
50
|
+
if (ref.sourceUrl) {
|
|
51
|
+
lines.push(`- SourceURL: ${ref.sourceUrl}`);
|
|
52
|
+
}
|
|
53
|
+
if (ref.fetchHistory && ref.fetchHistory.length > 0) {
|
|
54
|
+
lines.push(`- FetchCount: ${ref.fetchHistory.length} 次`);
|
|
55
|
+
lines.push(`- LastFetch: ${ref.fetchHistory[ref.fetchHistory.length - 1].fetchedAt}`);
|
|
56
|
+
}
|
|
57
|
+
lines.push(`- Created: ${ref.createdAt}`);
|
|
58
|
+
lines.push(`- Updated: ${ref.updatedAt}`);
|
|
59
|
+
lines.push('', ref.summary || '(无摘要)');
|
|
67
60
|
if (ref.links.length > 0) {
|
|
68
61
|
lines.push('', '## Links');
|
|
69
62
|
for (const link of ref.links) {
|
|
@@ -76,53 +69,66 @@ export function registerReferenceTools(server) {
|
|
|
76
69
|
lines.push(`- ${file.name}: ${file.path}`);
|
|
77
70
|
}
|
|
78
71
|
}
|
|
79
|
-
if (ref.
|
|
80
|
-
lines.push('', '##
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
72
|
+
if (ref.fetchHistory && ref.fetchHistory.length > 0) {
|
|
73
|
+
lines.push('', '## Fetch History');
|
|
74
|
+
lines.push('| # | 时间 | 标题 | 大小 | 文件 |');
|
|
75
|
+
lines.push('|:--|:-----|:-----|-----:|:-----|');
|
|
76
|
+
ref.fetchHistory.forEach((h, i) => {
|
|
77
|
+
lines.push(`| ${i + 1} | ${h.fetchedAt.substring(0, 19)} | ${h.title} | ${formatBytes(h.contentLength)} | ${h.contentFile} |`);
|
|
78
|
+
});
|
|
84
79
|
}
|
|
85
80
|
return wrap(lines.join('\n'));
|
|
86
81
|
}
|
|
87
|
-
case '
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
}
|
|
110
|
-
|
|
82
|
+
case 'fetch': {
|
|
83
|
+
// 如果提供了 id 但没有 url,视为 refetch(从已有参考的 sourceUrl 重新拉取)
|
|
84
|
+
if (!decoded.url && decoded.id) {
|
|
85
|
+
const ref = await client().getReference(decoded.id);
|
|
86
|
+
if (!ref)
|
|
87
|
+
return wrap(`未找到参考: ${decoded.id}`);
|
|
88
|
+
if (!ref.sourceUrl)
|
|
89
|
+
return wrap(`参考 ${decoded.id} 没有 sourceUrl,请提供 url 参数`);
|
|
90
|
+
const result = await client().fetchRefUrl(ref.sourceUrl, decoded.id);
|
|
91
|
+
return wrap([
|
|
92
|
+
`文档已重新拉取 (第 ${result.fetchCount} 次)`,
|
|
93
|
+
'',
|
|
94
|
+
`| 字段 | 值 |`,
|
|
95
|
+
`|:---|:---|`,
|
|
96
|
+
`| 参考 ID | ${result.refId} |`,
|
|
97
|
+
`| 标题 | ${result.title} |`,
|
|
98
|
+
`| 内容大小 | ${formatBytes(result.contentLength)} |`,
|
|
99
|
+
'',
|
|
100
|
+
'### 内容预览',
|
|
101
|
+
'',
|
|
102
|
+
result.contentPreview.substring(0, 300),
|
|
103
|
+
].join('\n'));
|
|
104
|
+
}
|
|
105
|
+
if (!decoded.url)
|
|
106
|
+
return wrap('fetch 需要 url (要拉取的文档地址)');
|
|
107
|
+
const result = await client().fetchRefUrl(decoded.url, decoded.id);
|
|
108
|
+
const lines = [
|
|
109
|
+
`文档已拉取并保存`,
|
|
110
|
+
'',
|
|
111
|
+
`| 字段 | 值 |`,
|
|
112
|
+
`|:---|:---|`,
|
|
113
|
+
`| 参考 ID | ${result.refId} |`,
|
|
114
|
+
`| 标题 | ${result.title} |`,
|
|
115
|
+
`| 内容大小 | ${formatBytes(result.contentLength)} |`,
|
|
116
|
+
`| 累计拉取 | ${result.fetchCount} 次 |`,
|
|
117
|
+
'',
|
|
118
|
+
'### 内容预览',
|
|
119
|
+
'',
|
|
120
|
+
result.contentPreview.substring(0, 500),
|
|
121
|
+
];
|
|
122
|
+
return wrap(lines.join('\n'));
|
|
111
123
|
}
|
|
112
124
|
case 'delete': {
|
|
113
125
|
if (!decoded.id)
|
|
114
|
-
return wrap('
|
|
126
|
+
return wrap('delete 需要 id');
|
|
115
127
|
const ok = await client().deleteReference(decoded.id);
|
|
116
|
-
return wrap(ok ?
|
|
117
|
-
}
|
|
118
|
-
case 'read_file': {
|
|
119
|
-
if (!decoded.path)
|
|
120
|
-
return wrap('❌ read_file 需要 path');
|
|
121
|
-
const content = await client().readReferenceFile(decoded.path);
|
|
122
|
-
return wrap(content);
|
|
128
|
+
return wrap(ok ? `外部参考已删除 (${decoded.id})` : `未找到外部参考 (${decoded.id})`);
|
|
123
129
|
}
|
|
124
130
|
default:
|
|
125
|
-
return wrap(
|
|
131
|
+
return wrap(`未知 action: ${decoded.action}`);
|
|
126
132
|
}
|
|
127
133
|
}));
|
|
128
134
|
}
|
package/dist/tools/tasks.d.ts
CHANGED
package/dist/tools/tasks.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
* AI 只需说人话写内容,后端负责所有格式化、分类、时间戳
|
|
2
|
+
* kg_task — 任务管理
|
|
4
3
|
*/
|
|
5
4
|
import { z } from 'zod';
|
|
6
5
|
import { getClient } from '../storage/httpClient.js';
|
|
@@ -8,7 +7,7 @@ import { decodeObjectStrings } from '../utils.js';
|
|
|
8
7
|
import { wrap, safeTool } from './shared.js';
|
|
9
8
|
export function registerTaskTools(server, ctx) {
|
|
10
9
|
const client = () => getClient();
|
|
11
|
-
server.tool('kg_task', '
|
|
10
|
+
server.tool('kg_task', '任务记录 — action: create(创建)|get(查询)|update(追加进度)|archive(归档)|delete(删除)', {
|
|
12
11
|
action: z.enum(['create', 'get', 'update', 'archive', 'delete'])
|
|
13
12
|
.describe('操作类型'),
|
|
14
13
|
title: z.string().optional()
|
|
@@ -26,9 +25,9 @@ export function registerTaskTools(server, ctx) {
|
|
|
26
25
|
summary: z.string().optional()
|
|
27
26
|
.describe('经验总结Markdown (archive)'),
|
|
28
27
|
difficulties: z.array(z.string()).optional()
|
|
29
|
-
.describe('遇到的困难 (archive)'),
|
|
28
|
+
.describe('遇到的困难 (archive, 可选)'),
|
|
30
29
|
solutions: z.array(z.string()).optional()
|
|
31
|
-
.describe('解决方案 (archive)'),
|
|
30
|
+
.describe('解决方案 (archive, 可选)'),
|
|
32
31
|
status: z.enum(['active', 'archived', 'all']).optional()
|
|
33
32
|
.describe('状态筛选 (get, 默认active)'),
|
|
34
33
|
bindTo: z.string().optional()
|
|
@@ -40,12 +39,10 @@ export function registerTaskTools(server, ctx) {
|
|
|
40
39
|
switch (decoded.action) {
|
|
41
40
|
case 'create': {
|
|
42
41
|
if (!decoded.title)
|
|
43
|
-
return wrap('
|
|
44
|
-
if (!decoded.description)
|
|
45
|
-
return wrap('❌ create 需要 description');
|
|
42
|
+
return wrap('create 需要 title');
|
|
46
43
|
const task = await client().createTask({
|
|
47
44
|
title: decoded.title,
|
|
48
|
-
description: decoded.description,
|
|
45
|
+
description: decoded.description || '',
|
|
49
46
|
goals: decoded.goals || []
|
|
50
47
|
}, ctx.user);
|
|
51
48
|
// 自动绑定到流程图节点
|
|
@@ -63,22 +60,18 @@ export function registerTaskTools(server, ctx) {
|
|
|
63
60
|
node.boundTasks.push(task.id);
|
|
64
61
|
}
|
|
65
62
|
await client().saveFlowchart(chartId, chart);
|
|
66
|
-
bindMsg = `\n
|
|
63
|
+
bindMsg = `\n已绑定到节点: ${decoded.bindTo} [${chartId}]`;
|
|
67
64
|
}
|
|
68
65
|
else {
|
|
69
|
-
bindMsg = `\n
|
|
66
|
+
bindMsg = `\n节点 "${decoded.bindTo}" 不存在于流程图 "${chartId}"`;
|
|
70
67
|
}
|
|
71
68
|
}
|
|
72
69
|
}
|
|
73
70
|
catch {
|
|
74
|
-
bindMsg = `\n
|
|
71
|
+
bindMsg = `\n绑定失败`;
|
|
75
72
|
}
|
|
76
73
|
}
|
|
77
|
-
|
|
78
|
-
if (!decoded.bindTo) {
|
|
79
|
-
bindMsg = `\n\n⚠️ 【未关联知识锚点】此任务未绑定到任何流程图节点!\n💡 建议: 使用 kg_flowchart(get) 查看节点列表, 然后用 kg_flowchart(bind, nodeId, tasks:["${task.id}"]) 绑定\n📌 不关联的任务会成为孤岛数据, 无法被其他AI发现`;
|
|
80
|
-
}
|
|
81
|
-
return wrap(`✅ 任务已创建\nID: ${task.id}\n标题: ${task.title}\n验收标准: ${task.detail.goals.length}条${bindMsg}`);
|
|
74
|
+
return wrap(`任务已创建\nID: ${task.id}\n标题: ${task.title}\n验收标准: ${task.detail.goals.length}条${bindMsg}`);
|
|
82
75
|
}
|
|
83
76
|
case 'get': {
|
|
84
77
|
// 无参数 = 列出活跃任务
|
|
@@ -96,33 +89,33 @@ export function registerTaskTools(server, ctx) {
|
|
|
96
89
|
tasks = await client().listTasks(status);
|
|
97
90
|
}
|
|
98
91
|
if (tasks.length === 0)
|
|
99
|
-
return wrap(
|
|
92
|
+
return wrap(`${status === 'archived' ? '归档' : '活跃'}任务为空`);
|
|
100
93
|
const rows = tasks.map(t => {
|
|
101
|
-
const icon = t.status === 'active' ? '
|
|
94
|
+
const icon = t.status === 'active' ? '●' : '○';
|
|
102
95
|
const date = t.updated_at?.split('T')[0]?.slice(5) || '';
|
|
103
96
|
const log = (t.last_log || '').substring(0, 40);
|
|
104
97
|
return `| ${icon} | ${t.title} | ${t.id} | ${date} | ${log} |`;
|
|
105
98
|
}).join('\n');
|
|
106
|
-
return wrap(
|
|
99
|
+
return wrap(`共 ${tasks.length} 个任务\n\n| 状态 | 标题 | ID | 更新 | 最近日志 |\n|:-----|:-----|:---|:-----|:---------|\n${rows}`);
|
|
107
100
|
}
|
|
108
101
|
// 有 taskId = 获取详情 (结构化摘要)
|
|
109
102
|
if (decoded.taskId) {
|
|
110
103
|
const task = await client().getTask(decoded.taskId, 'smart');
|
|
111
104
|
if (!task)
|
|
112
|
-
return wrap('
|
|
105
|
+
return wrap('任务未找到');
|
|
113
106
|
const lines = [
|
|
114
|
-
|
|
107
|
+
`${task.title}`,
|
|
115
108
|
`ID: ${task.id} | 状态: ${task.status}`,
|
|
116
109
|
`创建: ${task.created_at?.split('T')[0] || ''}`,
|
|
117
110
|
];
|
|
118
111
|
if (task.detail?.description)
|
|
119
|
-
lines.push(`\n
|
|
112
|
+
lines.push(`\n${task.detail.description}`);
|
|
120
113
|
if (task.detail?.goals?.length) {
|
|
121
|
-
lines.push(`\n
|
|
114
|
+
lines.push(`\n验收标准:`);
|
|
122
115
|
task.detail.goals.forEach((g, i) => lines.push(` ${i + 1}. ☐ ${g}`));
|
|
123
116
|
}
|
|
124
117
|
if (task.logs?.length) {
|
|
125
|
-
lines.push(`\n
|
|
118
|
+
lines.push(`\n进度日志 (${task.logs.length}条, 最近3条):`);
|
|
126
119
|
for (const log of task.logs.slice(-3)) {
|
|
127
120
|
lines.push(` [${log.log_type}] ${log.time?.split('T')[0] || ''}: ${log.content?.substring(0, 120)}`);
|
|
128
121
|
}
|
|
@@ -151,18 +144,18 @@ export function registerTaskTools(server, ctx) {
|
|
|
151
144
|
if (!task)
|
|
152
145
|
return wrap('任务详情获取失败');
|
|
153
146
|
const lines = [
|
|
154
|
-
|
|
147
|
+
`${task.title}`,
|
|
155
148
|
`ID: ${task.id} | 状态: ${task.status}`,
|
|
156
149
|
`创建: ${task.created_at?.split('T')[0] || ''}`,
|
|
157
150
|
];
|
|
158
151
|
if (task.detail?.description)
|
|
159
|
-
lines.push(`\n
|
|
152
|
+
lines.push(`\n${task.detail.description}`);
|
|
160
153
|
if (task.detail?.goals?.length) {
|
|
161
|
-
lines.push(`\n
|
|
154
|
+
lines.push(`\n验收标准:`);
|
|
162
155
|
task.detail.goals.forEach((g, i) => lines.push(` ${i + 1}. ☐ ${g}`));
|
|
163
156
|
}
|
|
164
157
|
if (task.logs?.length) {
|
|
165
|
-
lines.push(`\n
|
|
158
|
+
lines.push(`\n进度日志 (${task.logs.length}条, 最近3条):`);
|
|
166
159
|
for (const log of task.logs.slice(-3)) {
|
|
167
160
|
lines.push(` [${log.log_type}] ${log.time?.split('T')[0] || ''}: ${log.content?.substring(0, 120)}`);
|
|
168
161
|
}
|
|
@@ -174,45 +167,38 @@ export function registerTaskTools(server, ctx) {
|
|
|
174
167
|
}
|
|
175
168
|
case 'update': {
|
|
176
169
|
if (!decoded.taskId)
|
|
177
|
-
return wrap('
|
|
170
|
+
return wrap('update 需要 taskId');
|
|
178
171
|
if (!decoded.content)
|
|
179
|
-
return wrap('
|
|
172
|
+
return wrap('update 需要 content');
|
|
180
173
|
// log_type 可选 — 不传则后端自动检测关键词
|
|
181
174
|
const task = await client().addTaskLog(decoded.taskId, decoded.content, decoded.log_type);
|
|
182
175
|
if (!task)
|
|
183
176
|
return wrap('更新失败(任务不存在或已归档)');
|
|
184
177
|
const lastLog = task.logs[task.logs.length - 1];
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
? task.detail.goals.map((g, i) => ` ${i + 1}. ☐ ${g}`).join('\n')
|
|
188
|
-
: ' (无验收标准)';
|
|
189
|
-
return wrap(`✅ 进度已记录 [${lastLog?.log_type || 'progress'}]\n` +
|
|
190
|
-
`📋 ${task.title} | 日志: ${task.logs.length}条\n` +
|
|
191
|
-
`\n🎯 验收标准:\n${goalsDisplay}`);
|
|
178
|
+
return wrap(`进度已记录 [${lastLog?.log_type || 'progress'}]\n` +
|
|
179
|
+
`${task.title} | 日志: ${task.logs.length}条`);
|
|
192
180
|
}
|
|
193
181
|
case 'archive': {
|
|
194
182
|
if (!decoded.taskId)
|
|
195
|
-
return wrap('
|
|
196
|
-
if (!decoded.summary)
|
|
197
|
-
return wrap('❌ archive 需要 summary');
|
|
183
|
+
return wrap('archive 需要 taskId');
|
|
198
184
|
const task = await client().completeTask(decoded.taskId, {
|
|
199
|
-
summary: decoded.summary,
|
|
185
|
+
summary: decoded.summary || '任务已完成',
|
|
200
186
|
difficulties: decoded.difficulties || [],
|
|
201
187
|
solutions: decoded.solutions || [],
|
|
202
188
|
references: []
|
|
203
189
|
});
|
|
204
190
|
if (!task)
|
|
205
191
|
return wrap('归档失败(任务不存在或已归档)');
|
|
206
|
-
return wrap(
|
|
192
|
+
return wrap(`任务已归档: ${task.title}`);
|
|
207
193
|
}
|
|
208
194
|
case 'delete': {
|
|
209
195
|
if (!decoded.taskId)
|
|
210
|
-
return wrap('
|
|
196
|
+
return wrap('delete 需要 taskId');
|
|
211
197
|
const ok = await client().deleteTask(decoded.taskId);
|
|
212
|
-
return wrap(ok ?
|
|
198
|
+
return wrap(ok ? `任务已删除 (ID: ${decoded.taskId})` : '删除失败(任务不存在)');
|
|
213
199
|
}
|
|
214
200
|
default:
|
|
215
|
-
return wrap(
|
|
201
|
+
return wrap(`未知 action: ${decoded.action}`);
|
|
216
202
|
}
|
|
217
203
|
}));
|
|
218
204
|
}
|
package/dist/tools/workflow.js
CHANGED
|
@@ -4,9 +4,8 @@ import { decodeObjectStrings } from '../utils.js';
|
|
|
4
4
|
import { safeTool, wrap } from './shared.js';
|
|
5
5
|
export function registerWorkflowTools(server, _ctx) {
|
|
6
6
|
const client = () => getClient();
|
|
7
|
-
server.tool('kg_workflow', '
|
|
8
|
-
'
|
|
9
|
-
'典型用法:拿到任务后先 kg_workflow() 看有无相关工作流,有则 kg_workflow(id:"xxx") 读取并遵循执行。', {
|
|
7
|
+
server.tool('kg_workflow', '文档工作流。AI 的标准操作手册,每个工作流定义特定场景下应遵循的步骤。空参数=列出全部;传id=获取正文;save/delete需显式action。' +
|
|
8
|
+
'actions: list|get|save|delete', {
|
|
10
9
|
action: z.enum(['list', 'get', 'save', 'delete']).optional().describe('省略时自动推断:无参数=list,有id=get'),
|
|
11
10
|
id: z.string().optional().describe('工作流 ID'),
|
|
12
11
|
scope: z.enum(['all', 'global', 'project']).optional().describe('范围:all(默认)|global|project'),
|
package/package.json
CHANGED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* 💬 kg_discuss (8 actions)
|
|
3
|
-
* 合并: list, read, create, reply, close, delete, complete, history
|
|
4
|
-
* 统一走 HTTP → Rust 后端 (单一写入者)
|
|
5
|
-
* sender 格式: "projectId:user" (如 "p-ca3sgejg:张三")
|
|
6
|
-
*
|
|
7
|
-
* 权限模型:
|
|
8
|
-
* list/history — 任何人可列出(全局可见)
|
|
9
|
-
* create — 任何人可发起(指定参与项目ID)
|
|
10
|
-
* read/reply — 仅讨论组内成员(initiator + participants)
|
|
11
|
-
* complete/close/delete — 仅发起人
|
|
12
|
-
*/
|
|
13
|
-
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
14
|
-
import { type McpContext } from './shared.js';
|
|
15
|
-
export declare function registerDiscussionTools(server: McpServer, ctx: McpContext): void;
|