@ppdocs/mcp 2.6.14 → 2.6.16

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.
@@ -103,7 +103,7 @@ export function registerTools(server, projectId, _user) {
103
103
  return wrap(projectId, node ? JSON.stringify(node, null, 2) : '更新失败(根节点已锁定)');
104
104
  });
105
105
  // 3.6 获取项目规则 (独立方法,按需调用)
106
- server.tool('kg_get_rules', '获取项目规则列表(按需调用,不再自动附加到每个方法返回)', {}, async () => {
106
+ server.tool('kg_get_rules', '获取项目规则列表(按需调用)', {}, async () => {
107
107
  const style = await getRootStyle(projectId);
108
108
  if (!style || style.trim() === '') {
109
109
  return { content: [{ type: 'text', text: '暂无项目规则' }] };
@@ -175,13 +175,13 @@ export function registerTools(server, projectId, _user) {
175
175
  for (const r of relations) {
176
176
  if (r.direction === 'outgoing' && (direction === 'outgoing' || direction === 'both')) {
177
177
  if (!outgoing.some(o => o.id === r.nodeId)) {
178
- outgoing.push({ id: r.nodeId, title: r.title, desc: r.description, edge: r.edgeType, depth: currentDepth });
178
+ outgoing.push({ id: r.nodeId, title: r.title, edge: r.edgeType });
179
179
  await fetchRelations(r.nodeId, currentDepth + 1, 'outgoing');
180
180
  }
181
181
  }
182
182
  if (r.direction === 'incoming' && (direction === 'incoming' || direction === 'both')) {
183
183
  if (!incoming.some(i => i.id === r.nodeId)) {
184
- incoming.push({ id: r.nodeId, title: r.title, desc: r.description, edge: r.edgeType, depth: currentDepth });
184
+ incoming.push({ id: r.nodeId, title: r.title, edge: r.edgeType });
185
185
  await fetchRelations(r.nodeId, currentDepth + 1, 'incoming');
186
186
  }
187
187
  }
@@ -193,6 +193,65 @@ export function registerTools(server, projectId, _user) {
193
193
  }
194
194
  return wrap(projectId, JSON.stringify({ outgoing, incoming }, null, 2));
195
195
  });
196
+ // 9. 读取单个节点详情
197
+ server.tool('kg_read_node', '读取单个节点的完整内容(描述、关联文件、依赖、历史记录)', {
198
+ nodeId: z.string().describe('节点ID')
199
+ }, async (args) => {
200
+ const node = await storage.getNode(projectId, args.nodeId);
201
+ if (!node) {
202
+ return wrap(projectId, '节点不存在');
203
+ }
204
+ // 构建结构化输出
205
+ const lines = [];
206
+ // 基础信息
207
+ lines.push(`## ${node.title}\n`);
208
+ lines.push('**基础信息**');
209
+ lines.push(`| 字段 | 值 |`);
210
+ lines.push(`|:---|:---|`);
211
+ lines.push(`| ID | ${node.id} |`);
212
+ lines.push(`| 类型 | ${node.type} |`);
213
+ lines.push(`| 状态 | ${node.status} |`);
214
+ lines.push(`| 签名 | ${node.signature} |`);
215
+ if (node.categories && node.categories.length > 0) {
216
+ lines.push(`| 标签 | ${node.categories.join(', ')} |`);
217
+ }
218
+ lines.push('');
219
+ // 关联文件
220
+ if (node.relatedFiles && node.relatedFiles.length > 0) {
221
+ lines.push('**关联文件**');
222
+ node.relatedFiles.forEach(f => lines.push(`- ${f}`));
223
+ lines.push('');
224
+ }
225
+ // 依赖关系
226
+ if (node.dependencies && node.dependencies.length > 0) {
227
+ lines.push('**依赖关系**');
228
+ node.dependencies.forEach(d => lines.push(`- ${d.name}: ${d.description}`));
229
+ lines.push('');
230
+ }
231
+ // 描述内容
232
+ if (node.description) {
233
+ lines.push('**描述内容**');
234
+ lines.push(node.description);
235
+ lines.push('');
236
+ }
237
+ // 更新历史
238
+ if (node.versions && node.versions.length > 0) {
239
+ lines.push('**更新历史**');
240
+ lines.push('| 版本 | 日期 | 变更 |');
241
+ lines.push('|:---|:---|:---|');
242
+ node.versions.forEach(v => lines.push(`| ${v.version} | ${v.date} | ${v.changes} |`));
243
+ lines.push('');
244
+ }
245
+ // 修复历史
246
+ if (node.bugfixes && node.bugfixes.length > 0) {
247
+ lines.push('**修复历史**');
248
+ lines.push('| ID | 日期 | 问题 | 方案 |');
249
+ lines.push('|:---|:---|:---|:---|');
250
+ node.bugfixes.forEach(b => lines.push(`| ${b.id} | ${b.date} | ${b.issue} | ${b.solution} |`));
251
+ lines.push('');
252
+ }
253
+ return wrap(projectId, lines.join('\n'));
254
+ });
196
255
  // ===================== 任务管理工具 =====================
197
256
  // 10. 创建任务
198
257
  server.tool('task_create', '创建开发任务,记录目标和关联节点', {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ppdocs/mcp",
3
- "version": "2.6.14",
3
+ "version": "2.6.16",
4
4
  "description": "ppdocs MCP Server - Knowledge Graph for Claude",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -1,139 +1,82 @@
1
1
  ---
2
- description: 代码同步知识图谱:增量更新节点,保持代码与知识库一致
3
- argument-hint: "[init|diff|check]"
2
+ description: 代码同步知识图谱:Git变更检测 + 智能节点更新
3
+ argument-hint: "[all|recent|check]"
4
4
  ---
5
5
 
6
- # /sync 代码同步
6
+ # /sync 代码同步知识库
7
7
 
8
- 执行 `task_create("代码同步")` 分阶段执行 → 完成后 `task_complete`
8
+ 执行 `task_create("代码同步")` 开始,完成后 `task_complete` 归档
9
9
 
10
- **参数**: `init`=全量初始化 | `diff`=仅变更文件 | `check`=检查覆盖率
10
+ **参数**: `all`=全量同步 | `recent`=最近变更(默认) | `check`=检查覆盖率
11
11
 
12
- ## Phase 1: 项目探测
12
+ ---
13
+
14
+ ## Step 1: 变更检测
13
15
 
14
- **技术栈识别**: package.json→Node/React | Cargo.toml→Rust | go.mod→Go | requirements.txt→Python
15
- **架构分析**: 读取入口配置 → Glob扫描源码目录 按目录聚类 → 输出架构树等用户确认
16
+ **recent模式**: 执行 `git status` + `git diff --name-only HEAD~3` 获取变更文件列表,过滤非代码文件(.md/.json/lock等)
17
+ **all模式**: Glob扫描 `src/**/*.{ts,tsx,rs,go,py}` 获取全部源码,按目录聚类输出架构树等用户确认
16
18
 
17
19
  ```
18
- ┌─ 推断架构 ────────────────────┐
19
- [intro] 项目根: {名称} │
20
- ├─ [intro] {模块A}: {路径} │
21
- ├─ [logic] {模块B}: {路径} │
22
- │ └─ [data] 共享类型 │
23
- └───────────────────────────────┘
20
+ 检测结果示例:
21
+ ├─ 修改: src/auth.ts, src/utils.ts
22
+ ├─ 新增: src/newFeature.ts
23
+ └─ 删除: src/deprecated.ts
24
24
  回复 OK 继续
25
25
  ```
26
26
 
27
- ## Phase 2: 节点生成规则
28
-
29
- | 识别模式 | type | signature | categories |
30
- |:---|:---|:---|:---|
31
- | pages/views/routes | logic | `Page:{名称}` | `[ui, page]` |
32
- | components | logic | `Comp:{名称}` | `[ui, component]` |
33
- | use*.ts (Hook) | logic | `{名称}()` | `[hook]` |
34
- | services/api | logic | `Svc:{名称}` | `[service, api]` |
35
- | store/storage | logic | `Store:{名称}` | `[storage]` |
36
- | utils/helpers | logic | `{函数名}()` | `[util, reusable]` |
37
- | types/interfaces | data | `Type:{名称}` | `[type]` |
38
- | config/*.json | intro | `Config:{名称}` | `[config]` |
39
- | *.rs (Rust) | logic | `{mod}::{fn}` | `[rust]` |
40
- | *.go (Go) | logic | `{pkg}.{Func}` | `[go]` |
41
-
42
- ## Phase 3: 字段规范 (MUST 全部填写)
43
-
44
- | 字段 | 规则 | 示例 |
45
- |:---|:---|:---|
46
- | title | 中文描述 | `用户认证服务` |
47
- | type | logic/data/intro | `logic` |
48
- | signature | 唯一标识 | `useAuth()` |
49
- | categories | 分类数组 | `["hook", "auth"]` |
50
- | **relatedFiles** | **MUST: 源文件路径数组** | `["src/hooks/useAuth.ts"]` |
51
- | dependencies | 依赖节点 | `[{name: "xxx", description: "用途"}]` |
52
- | description | 见下方模板 | |
53
-
54
- ### relatedFiles 提取规则 (MUST)
55
- ```
56
- 1. 当前处理的文件路径 → relatedFiles[0]
57
- 2. 该文件 import 的本地模块 → relatedFiles[1..n]
58
- 3. NEVER 留空,至少包含当前文件
59
- ```
27
+ ## Step 2: 节点匹配
60
28
 
61
- ### dependencies 推断规则 (MUST)
62
- ```
63
- 处理每个文件时执行:
64
- 1. 解析 import/require 语句 提取本地模块路径
65
- 2. 对每个本地模块:
66
-
67
- ├─ 匹配方式1: 路径匹配
68
- │ kg_list_nodes → 遍历 relatedFiles 字段
69
- │ 若模块路径 ∈ 某节点的 relatedFiles → 匹配成功
70
-
71
- ├─ 匹配方式2: 签名匹配
72
- │ 从 import 提取函数名/类名 → 匹配节点 signature
73
- │ 如: import { useAuth } → 匹配 signature="useAuth()"
74
-
75
- └─ 匹配成功 → dependencies.push({
76
- name: 目标节点的 signature,
77
- description: "用途说明 (从import上下文推断)"
78
- })
79
-
80
- 3. 依赖 description 规则:
81
- - Hook: "状态管理" / "数据获取" / "交互逻辑"
82
- - Service: "API调用" / "数据服务"
83
- - Utils: "工具函数" / "格式化"
84
- - Types: "类型定义"
85
- - Component: "UI组件" / "子组件"
86
- ```
29
+ 对每个变更文件执行: `kg_search(文件名关键词)` 匹配 relatedFiles 字段 → 确定关联节点
30
+ - 匹配成功 → 标记为"更新"
31
+ - 无匹配 → 标记为"新增"
32
+ - 节点存在但文件已删标记为"清理"
87
33
 
88
- ### description 模板
89
- ```markdown
90
- ## 职责
91
- [读取 JSDoc/docstring,无则根据代码推断]
34
+ ## Step 3: 读取分析
92
35
 
93
- ## 核心逻辑
94
- | 导出 | 类型 | 说明 |
95
- |:---|:---|:---|
96
- | funcA | function | 功能描述 |
36
+ 批量读取变更文件(每轮≤10个),分析: 导出函数/类型 → import依赖 → 功能职责
97
37
 
98
- ## 依赖
99
- | 模块 | 用途 |
38
+ **节点字段规则**:
39
+ | 字段 | 规则 |
100
40
  |:---|:---|
101
- | xxx | 依赖原因 |
102
- ```
103
-
104
- > 注: 输入输出类型通过 dependencies 关联到 data 节点表达,不再使用独立的数据流字段
41
+ | title | 中文模块名 |
42
+ | type | logic(函数/类) / data(类型) / intro(配置/说明) |
43
+ | signature | 唯一标识如 `useAuth()` `AuthService` |
44
+ | categories | 分类标签如 `["hook","auth"]` |
45
+ | relatedFiles | **MUST** 当前文件+import的本地模块路径 |
46
+ | dependencies | 解析import匹配已有节点signature,填写 `{name, description}` |
47
+ | description | 职责+核心逻辑表格+依赖说明 (Markdown) |
105
48
 
106
- ## Phase 4: 执行同步
49
+ ## Step 4: 执行更新
107
50
 
108
51
  ```
109
- 扫描文件 → kg_list_nodes → 匹配signature → 差异对比
110
-
111
- ┌─────────────────────────────────────────┘
112
- 新文件kg_create_node (MUST 填 relatedFiles)
113
- 内容变化 kg_update_node
114
- │ 无变化 → 跳过
115
-
116
- 进度: 每5文件 task_add_log("progress", "[X/N] 已处理: [文件列表]")
52
+ 遍历变更文件:
53
+ ├─ 新增文件 → kg_create_node (MUST填relatedFiles+dependencies)
54
+ ├─ 修改文件 → kg_read_node获取旧内容 → 对比差异 → kg_update_node
55
+ ├─ 删除文件kg_update_node将status改为deprecated kg_delete_node
56
+ └─ 进度: 每5个文件 task_add_log("progress", "[X/N] 已处理...")
117
57
  ```
118
58
 
119
- ## Phase 5: 完成报告
59
+ ## Step 5: 完成报告
120
60
 
121
61
  ```
122
- ┌─────────────────────────────────┐
123
- 同步完成
124
- 文件: XX | ✅新增: X | 🔄更新: X
125
- 未覆盖: [列表]
126
- │ 覆盖率: XX.X% │
127
- └─────────────────────────────────┘
62
+ ┌─ 同步完成 ──────────────────────────┐
63
+ 扫描: XX文件 | ✅新增: X | 🔄更新: X
64
+ ⚠️ 未覆盖: [文件列表]
65
+ 覆盖率: XX.X%
66
+ ├─────────────────────────────────────┤
67
+ │ 💡 建议执行 git add . && git commit │
68
+ │ 备份本次同步后的代码状态 │
69
+ └─────────────────────────────────────┘
128
70
  ```
129
71
 
130
- 执行 `task_complete` 归档任务
72
+ 执行 `task_complete` 归档,提醒用户 Git 提交备份
73
+
74
+ ---
131
75
 
132
76
  ## 约束
133
77
 
134
- 1. **批量限制**: 每轮 ≤10 文件
135
- 2. **顺序**: types → utils → services → components → pages (底层优先)
136
- 3. **去重**: 写入前 `kg_search(signature)` 检查冲突
137
- 4. **依赖**: MUST 解析 import 匹配已有节点,NEVER 留空
138
- 5. **relatedFiles**: NEVER 留空,至少填当前文件路径
139
- 6. **依赖验证**: 创建节点前检查 dependencies 中的 name 是否存在于知识库
78
+ 1. **顺序**: types utils → services → components → pages (依赖优先)
79
+ 2. **去重**: 写入前 `kg_search(signature)` 检查已存在
80
+ 3. **依赖**: MUST解析import匹配节点,NEVER留空dependencies
81
+ 4. **relatedFiles**: NEVER留空,至少填当前文件路径
82
+ 5. **清理**: 已删除文件的节点标记deprecated或删除