@ppdocs/mcp 3.2.8 → 3.2.10

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.
@@ -4,4 +4,5 @@
4
4
  * kg_discussion_reply, kg_discussion_close_and_archive, kg_discussion_delete
5
5
  */
6
6
  import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
7
- export declare function registerDiscussionTools(server: McpServer, projectId: string): void;
7
+ import { type McpContext } from './shared.js';
8
+ export declare function registerDiscussionTools(server: McpServer, ctx: McpContext): void;
@@ -8,7 +8,7 @@ import { getClient } from '../storage/httpClient.js';
8
8
  import { decodeObjectStrings } from '../utils.js';
9
9
  import { wrap, safeTool } from './shared.js';
10
10
  import { DiscussionManager } from '../storage/discussion.js';
11
- export function registerDiscussionTools(server, projectId) {
11
+ export function registerDiscussionTools(server, ctx) {
12
12
  const client = () => getClient();
13
13
  server.tool('kg_discuss', '💬 跨项目讨论 — 发起、回复、归档协同讨论。action: list(列出活跃讨论)|read(读取详情)|create(发起)|reply(回复)|close(结案归档)|delete(删除)', {
14
14
  action: z.enum(['list', 'read', 'create', 'reply', 'close', 'delete'])
@@ -35,8 +35,8 @@ export function registerDiscussionTools(server, projectId) {
35
35
  const active = DiscussionManager.listActive();
36
36
  const cleanMsg = cleaned > 0 ? `\n⚠️ 已自动清理 ${cleaned} 条超过7天不活跃的讨论` : '';
37
37
  if (active.length === 0)
38
- return wrap(`当前无活跃的讨论 (本项目ID: ${projectId})${cleanMsg}`);
39
- return wrap(`本项目ID: ${projectId}\n活跃讨论区 (${active.length} 个):${cleanMsg}\n\n` + JSON.stringify(active, null, 2));
38
+ return wrap(`当前无活跃的讨论 (本项目ID: ${ctx.projectId})${cleanMsg}`);
39
+ return wrap(`本项目ID: ${ctx.projectId}\n活跃讨论区 (${active.length} 个):${cleanMsg}\n\n` + JSON.stringify(active, null, 2));
40
40
  }
41
41
  case 'read': {
42
42
  const readIds = decoded.ids || (decoded.id ? [decoded.id] : []);
@@ -57,15 +57,15 @@ export function registerDiscussionTools(server, projectId) {
57
57
  const count = DiscussionManager.activeCount();
58
58
  if (count >= 10)
59
59
  return wrap('❌ 活跃讨论已达上限(10条)');
60
- const id = DiscussionManager.create(decoded.title, projectId, decoded.participants, decoded.content);
61
- return wrap(`✅ 讨论已发起,ID: ${id}\n发起方: ${projectId}\n参与方: ${decoded.participants.join(', ')}`);
60
+ const id = DiscussionManager.create(decoded.title, ctx.projectId, decoded.participants, decoded.content);
61
+ return wrap(`✅ 讨论已发起,ID: ${id}\n发起方: ${ctx.projectId}\n参与方: ${decoded.participants.join(', ')}`);
62
62
  }
63
63
  case 'reply': {
64
64
  if (!decoded.id)
65
65
  return wrap('❌ reply 需要 id');
66
66
  if (!decoded.content)
67
67
  return wrap('❌ reply 需要 content');
68
- const success = DiscussionManager.reply(decoded.id, projectId, decoded.content, decoded.newSummary);
68
+ const success = DiscussionManager.reply(decoded.id, ctx.projectId, decoded.content, decoded.newSummary);
69
69
  return wrap(success ? `✅ 回复成功 (ID: ${decoded.id})` : `❌ 回复失败,讨论不存在或已关闭`);
70
70
  }
71
71
  case 'close': {
@@ -27,12 +27,12 @@ export function registerTools(server, projectId, user, onProjectChange) {
27
27
  registerStatusTool(server, ctx);
28
28
  // 📚 知识 (kg_doc + kg_tree + kg_projects + kg_rules)
29
29
  registerDocTools(server, ctx.projectId);
30
- registerProjectTools(server, ctx.projectId);
31
- registerRuleTools(server, ctx.projectId);
30
+ registerProjectTools(server, ctx);
31
+ registerRuleTools(server, ctx);
32
32
  // 📝 工作流 (kg_task + kg_files + kg_discuss)
33
33
  registerTaskTools(server, ctx.projectId, ctx.user);
34
34
  registerFileTools(server);
35
- registerDiscussionTools(server, ctx.projectId);
35
+ registerDiscussionTools(server, ctx);
36
36
  // 🔬 代码分析 (不变)
37
37
  registerAnalyzerTools(server, ctx.projectId);
38
38
  }
@@ -4,4 +4,5 @@
4
4
  * 删除: kg_create_project (桌面端操作)
5
5
  */
6
6
  import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
7
- export declare function registerProjectTools(server: McpServer, projectId: string): void;
7
+ import { type McpContext } from './shared.js';
8
+ export declare function registerProjectTools(server: McpServer, ctx: McpContext): void;
@@ -5,14 +5,14 @@
5
5
  */
6
6
  import { getClient } from '../storage/httpClient.js';
7
7
  import { wrap, safeTool } from './shared.js';
8
- export function registerProjectTools(server, projectId) {
8
+ export function registerProjectTools(server, ctx) {
9
9
  const client = () => getClient();
10
10
  server.tool('kg_projects', '📋 列出所有可访问的项目(返回名称和ID)。跨项目操作的第一步: 获取项目ID后用于其他工具的 targetProject 参数', {}, async () => safeTool(async () => {
11
11
  const projects = await client().crossListProjects();
12
12
  if (projects.length === 0)
13
13
  return wrap('暂无可访问的项目');
14
14
  const lines = projects.map(p => {
15
- const isCurrent = p.id === projectId ? ' ★当前' : '';
15
+ const isCurrent = p.id === ctx.projectId ? ' ★当前' : '';
16
16
  return `- ${p.name} (${p.id})${isCurrent}`;
17
17
  });
18
18
  return wrap(`可访问的项目 (${projects.length} 个):\n\n${lines.join('\n')}`);
@@ -4,4 +4,5 @@
4
4
  * 删除: kg_get_global_rules_meta, kg_save_global_rules_meta (管理员操作)
5
5
  */
6
6
  import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
7
- export declare function registerRuleTools(server: McpServer, projectId: string): void;
7
+ import { type McpContext } from './shared.js';
8
+ export declare function registerRuleTools(server: McpServer, ctx: McpContext): void;
@@ -7,7 +7,7 @@ import { z } from 'zod';
7
7
  import { getClient } from '../storage/httpClient.js';
8
8
  import { decodeObjectStrings, getRules, RULE_TYPE_LABELS } from '../utils.js';
9
9
  import { wrap, safeTool, crossPrefix } from './shared.js';
10
- export function registerRuleTools(server, projectId) {
10
+ export function registerRuleTools(server, ctx) {
11
11
  const client = () => getClient();
12
12
  server.tool('kg_rules', '📏 项目规则管理 — 读取或保存代码风格、审查规则等。action: get(读取规则)|save(保存规则)|get_meta(读取触发配置)|save_meta(保存触发配置)', {
13
13
  action: z.enum(['get', 'save', 'get_meta', 'save_meta'])
@@ -51,7 +51,7 @@ export function registerRuleTools(server, projectId) {
51
51
  return wrap(`暂无项目规则(项目: ${decoded.targetProject})`);
52
52
  return wrap(`${crossPrefix(decoded.targetProject)}${allRules.join('\n\n')}`);
53
53
  }
54
- const rules = await getRules(projectId, decoded.ruleType || undefined);
54
+ const rules = await getRules(ctx.projectId, decoded.ruleType || undefined);
55
55
  if (!rules || rules.trim() === '') {
56
56
  const meta = await client().getRulesMeta();
57
57
  const typeName = decoded.ruleType ? (meta[decoded.ruleType]?.label || decoded.ruleType) : '项目';
package/dist/web/ui.js CHANGED
@@ -111,7 +111,8 @@ function init(){
111
111
  var entry=items[i].webkitGetAsEntry&&items[i].webkitGetAsEntry();
112
112
  if(entry&&entry.isDirectory){
113
113
  go('add',{addStep:1,addDir:entry.name});
114
- toast('📂 检测到 '+entry.name+',可直接发送授权或补全路径');
114
+ toast('📂 检测到 '+entry.name+',请补全绝对路径后发送授权');
115
+ setTimeout(function(){var inp=document.getElementById('iDir');if(inp){inp.focus();inp.setSelectionRange(0,0)}},150);
115
116
  return;
116
117
  }
117
118
  }
@@ -193,14 +194,14 @@ function renderAddStep1(){
193
194
  return '<span class="back" onclick="cancelAuth();go(\\x27list\\x27)">← 返回项目列表</span>'+
194
195
  '<div class="card no-hover"><div class="section"><h2>➕ 添加项目</h2>'+
195
196
  '<p style="font-size:13px;color:#64748b;margin-bottom:12px">点击发送授权,在主机端 PPDocs 应用中选择项目并批准</p>'+
196
- '<div class="fg"><label>本地项目目录 (可选,MCP安装时需要)</label><input id="iDir" value="'+S.addDir+'" placeholder="(可选) D:/projects/my-app" oninput="S.addDir=this.value"></div>'+
197
+ '<div class="fg"><label>本地项目目录 (可选,MCP安装时需要)</label><input id="iDir" value="'+S.addDir+'" placeholder="Win: D:\\\\projects\\\\app Mac: /Users/xxx/app" oninput="S.addDir=this.value"></div>'+
197
198
  '<div class="btn-row"><button class="btn btn-p" onclick="doAuthStart()">📡 发送授权请求</button></div>'+
198
199
  '</div></div>';
199
200
  }
200
201
 
201
202
  function doAuthStart(){
202
203
  var dir=(document.getElementById('iDir')?document.getElementById('iDir').value:'').trim();
203
- if(dir&&!/^[A-Za-z]:[\\\\\\/]|^\\//.test(dir)){toast('路径需为绝对路径或留空','err');return}
204
+ if(dir&&!/^[A-Za-z]:[\\\\\\/]|^\\/|^~\//.test(dir)){toast('路径需为绝对路径(D:\\xxx 或 /Users/xxx)或留空','err');return}
204
205
  S.addDir=dir;
205
206
  api('/api/auth/start',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({localDir:dir||''})}).then(function(r){
206
207
  if(!r.ok){toast(r.error||'授权请求失败','err');return}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ppdocs/mcp",
3
- "version": "3.2.8",
3
+ "version": "3.2.10",
4
4
  "description": "ppdocs MCP Server - Knowledge Graph for Claude",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",