@ppdocs/mcp 3.2.6 → 3.2.8
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/dist/config.d.ts +1 -1
- package/dist/config.js +2 -10
- package/dist/index.js +24 -12
- package/dist/storage/httpClient.js +3 -1
- package/dist/tools/index.d.ts +3 -2
- package/dist/tools/index.js +16 -9
- package/dist/tools/init.d.ts +12 -0
- package/dist/tools/init.js +72 -0
- package/dist/tools/kg_status.d.ts +2 -1
- package/dist/tools/kg_status.js +2 -2
- package/dist/tools/shared.d.ts +7 -0
- package/dist/tools/shared.js +4 -0
- package/package.json +1 -1
package/dist/config.d.ts
CHANGED
|
@@ -11,4 +11,4 @@ export interface PpdocsConfig {
|
|
|
11
11
|
export declare const PPDOCS_CONFIG_FILE = ".ppdocs";
|
|
12
12
|
/** 生成随机用户名 */
|
|
13
13
|
export declare function generateUser(): string;
|
|
14
|
-
export declare function loadConfig(): Promise<PpdocsConfig>;
|
|
14
|
+
export declare function loadConfig(): Promise<PpdocsConfig | null>;
|
package/dist/config.js
CHANGED
|
@@ -42,14 +42,6 @@ export async function loadConfig() {
|
|
|
42
42
|
const fileConfig = readPpdocsFile();
|
|
43
43
|
if (fileConfig)
|
|
44
44
|
return fileConfig;
|
|
45
|
-
// 无配置 →
|
|
46
|
-
|
|
47
|
-
console.error('');
|
|
48
|
-
console.error(' 请在 Agent WebUI 绑定此项目:');
|
|
49
|
-
console.error(' 1. 启动 Agent: npx @ppdocs/mcp webui');
|
|
50
|
-
console.error(' 2. 打开浏览器: http://localhost:20010');
|
|
51
|
-
console.error(' 3. 添加项目 → 选择本地目录和远程知识库 → 自动生成 .ppdocs');
|
|
52
|
-
console.error('');
|
|
53
|
-
console.error(' 或手动设置环境变量: PPDOCS_API_URL=http://host:port/api/projectId/key');
|
|
54
|
-
process.exit(1);
|
|
45
|
+
// 无配置 → 返回 null,由调用方决定行为 (MCP 模式下等待 kg_init)
|
|
46
|
+
return null;
|
|
55
47
|
}
|
package/dist/index.js
CHANGED
|
@@ -35,22 +35,34 @@ if (args.length > 0) {
|
|
|
35
35
|
// 运行 MCP 服务
|
|
36
36
|
async function main() {
|
|
37
37
|
const config = await loadConfig();
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
38
|
+
// 有配置 → 自动初始化 (环境变量 / .ppdocs)
|
|
39
|
+
if (config) {
|
|
40
|
+
initClient(config.apiUrl);
|
|
41
|
+
console.error(`ppdocs MCP v${VERSION} | project: ${config.projectId} | user: ${config.user}`);
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
console.error(`ppdocs MCP v${VERSION} | ⏳ 等待 kg_init 初始化项目上下文...`);
|
|
45
|
+
}
|
|
46
|
+
const projectId = config?.projectId || 'pending';
|
|
47
|
+
const user = config?.user || 'agent';
|
|
48
|
+
const server = new McpServer({ name: `ppdocs [${projectId}]`, version: VERSION }, { capabilities: { tools: {} } });
|
|
49
|
+
registerTools(server, projectId, user, (newProjectId, newApiUrl) => {
|
|
50
|
+
console.error(`[kg_init] 项目已切换: ${newProjectId}`);
|
|
51
|
+
});
|
|
41
52
|
const transport = new StdioServerTransport();
|
|
42
53
|
await server.connect(transport);
|
|
43
|
-
console.error(`ppdocs MCP v${VERSION} | project: ${config.projectId} | user: ${config.user}`);
|
|
44
54
|
// [M2 修复] beacon 变量提升到外部,支持优雅关闭
|
|
45
55
|
let beacon = null;
|
|
46
|
-
// 启动后台代码同步引擎 (Code Beacon)
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
56
|
+
// 启动后台代码同步引擎 (Code Beacon) — 仅在有配置时启动
|
|
57
|
+
if (config) {
|
|
58
|
+
try {
|
|
59
|
+
const { SyncBeacon } = await import('./sync/beacon.js');
|
|
60
|
+
beacon = new SyncBeacon(process.cwd(), config.projectId);
|
|
61
|
+
beacon.start();
|
|
62
|
+
}
|
|
63
|
+
catch (err) {
|
|
64
|
+
console.error(`[Code Beacon] Failed to start:`, err);
|
|
65
|
+
}
|
|
54
66
|
}
|
|
55
67
|
// 优雅关闭:进程退出时停止 watcher,防止上传截断
|
|
56
68
|
const shutdown = () => { beacon?.stop(); process.exit(0); };
|
|
@@ -517,7 +517,9 @@ export function initClient(apiUrl) {
|
|
|
517
517
|
}
|
|
518
518
|
export function getClient() {
|
|
519
519
|
if (!client) {
|
|
520
|
-
throw new Error('
|
|
520
|
+
throw new Error('❌ 项目未初始化!请先调用 kg_init 工具绑定项目上下文。\n\n' +
|
|
521
|
+
'用法: kg_init({ projectPath: "项目根目录绝对路径" })\n' +
|
|
522
|
+
'该目录下需存在 .ppdocs 配置文件。');
|
|
521
523
|
}
|
|
522
524
|
return client;
|
|
523
525
|
}
|
package/dist/tools/index.d.ts
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* MCP 工具注册入口
|
|
3
|
-
* 精简后:
|
|
3
|
+
* 精简后: 13 个工具, 6 个子模块
|
|
4
4
|
*
|
|
5
|
+
* 🔗 初始化: kg_init (1个)
|
|
5
6
|
* 📊 导航: kg_status, kg_tree (2个)
|
|
6
7
|
* 📚 知识: kg_doc, kg_projects, kg_rules (3个)
|
|
7
8
|
* 📝 工作流: kg_task, kg_files, kg_discuss (3个)
|
|
8
9
|
* 🔬 代码分析: code_scan, code_query, code_impact, code_context (4个)
|
|
9
10
|
*/
|
|
10
11
|
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
11
|
-
export declare function registerTools(server: McpServer, projectId: string, user: string): void;
|
|
12
|
+
export declare function registerTools(server: McpServer, projectId: string, user: string, onProjectChange?: (newProjectId: string, newApiUrl: string) => void): void;
|
package/dist/tools/index.js
CHANGED
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* MCP 工具注册入口
|
|
3
|
-
* 精简后:
|
|
3
|
+
* 精简后: 13 个工具, 6 个子模块
|
|
4
4
|
*
|
|
5
|
+
* 🔗 初始化: kg_init (1个)
|
|
5
6
|
* 📊 导航: kg_status, kg_tree (2个)
|
|
6
7
|
* 📚 知识: kg_doc, kg_projects, kg_rules (3个)
|
|
7
8
|
* 📝 工作流: kg_task, kg_files, kg_discuss (3个)
|
|
8
9
|
* 🔬 代码分析: code_scan, code_query, code_impact, code_context (4个)
|
|
9
10
|
*/
|
|
11
|
+
import { createContext } from './shared.js';
|
|
12
|
+
import { registerInitTool } from './init.js';
|
|
10
13
|
import { registerStatusTool } from './kg_status.js';
|
|
11
14
|
import { registerDocTools } from './docs.js';
|
|
12
15
|
import { registerProjectTools } from './projects.js';
|
|
@@ -15,17 +18,21 @@ import { registerTaskTools } from './tasks.js';
|
|
|
15
18
|
import { registerFileTools } from './files.js';
|
|
16
19
|
import { registerDiscussionTools } from './discussion.js';
|
|
17
20
|
import { registerAnalyzerTools } from './analyzer.js';
|
|
18
|
-
export function registerTools(server, projectId, user) {
|
|
21
|
+
export function registerTools(server, projectId, user, onProjectChange) {
|
|
22
|
+
// 创建共享可变上下文 — 所有工具捕获此对象引用
|
|
23
|
+
const ctx = createContext(projectId, user);
|
|
24
|
+
// 🔗 初始化 (kg_init — 运行时项目切换,更新 ctx)
|
|
25
|
+
registerInitTool(server, ctx, onProjectChange || (() => { }));
|
|
19
26
|
// 📊 导航 (kg_status + kg_tree在docs中)
|
|
20
|
-
registerStatusTool(server,
|
|
27
|
+
registerStatusTool(server, ctx);
|
|
21
28
|
// 📚 知识 (kg_doc + kg_tree + kg_projects + kg_rules)
|
|
22
|
-
registerDocTools(server, projectId);
|
|
23
|
-
registerProjectTools(server, projectId);
|
|
24
|
-
registerRuleTools(server, projectId);
|
|
29
|
+
registerDocTools(server, ctx.projectId);
|
|
30
|
+
registerProjectTools(server, ctx.projectId);
|
|
31
|
+
registerRuleTools(server, ctx.projectId);
|
|
25
32
|
// 📝 工作流 (kg_task + kg_files + kg_discuss)
|
|
26
|
-
registerTaskTools(server, projectId, user);
|
|
33
|
+
registerTaskTools(server, ctx.projectId, ctx.user);
|
|
27
34
|
registerFileTools(server);
|
|
28
|
-
registerDiscussionTools(server, projectId);
|
|
35
|
+
registerDiscussionTools(server, ctx.projectId);
|
|
29
36
|
// 🔬 代码分析 (不变)
|
|
30
|
-
registerAnalyzerTools(server, projectId);
|
|
37
|
+
registerAnalyzerTools(server, ctx.projectId);
|
|
31
38
|
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* kg_init 工具 — 项目上下文初始化
|
|
3
|
+
*
|
|
4
|
+
* 解决全局共用 MCP 进程时的多项目隔离问题:
|
|
5
|
+
* - 智能体调用 kg_init 传入 projectPath
|
|
6
|
+
* - MCP 从该路径读取 .ppdocs 配置
|
|
7
|
+
* - 重新初始化 HTTP Client 指向正确项目
|
|
8
|
+
* - 更新共享 McpContext,所有工具自动获取新 projectId
|
|
9
|
+
*/
|
|
10
|
+
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
11
|
+
import { type McpContext } from './shared.js';
|
|
12
|
+
export declare function registerInitTool(server: McpServer, ctx: McpContext, onProjectChange: (newProjectId: string, newApiUrl: string) => void): void;
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* kg_init 工具 — 项目上下文初始化
|
|
3
|
+
*
|
|
4
|
+
* 解决全局共用 MCP 进程时的多项目隔离问题:
|
|
5
|
+
* - 智能体调用 kg_init 传入 projectPath
|
|
6
|
+
* - MCP 从该路径读取 .ppdocs 配置
|
|
7
|
+
* - 重新初始化 HTTP Client 指向正确项目
|
|
8
|
+
* - 更新共享 McpContext,所有工具自动获取新 projectId
|
|
9
|
+
*/
|
|
10
|
+
import * as fs from 'fs';
|
|
11
|
+
import * as path from 'path';
|
|
12
|
+
import { z } from 'zod';
|
|
13
|
+
import { initClient } from '../storage/httpClient.js';
|
|
14
|
+
import { wrap, safeTool } from './shared.js';
|
|
15
|
+
// 当前会话的 API URL (用于幂等检查)
|
|
16
|
+
let currentApiUrl = null;
|
|
17
|
+
/** 尝试从指定目录读取 .ppdocs 配置 */
|
|
18
|
+
function readPpdocsFrom(dir) {
|
|
19
|
+
const configPath = path.join(dir, '.ppdocs');
|
|
20
|
+
if (!fs.existsSync(configPath))
|
|
21
|
+
return null;
|
|
22
|
+
try {
|
|
23
|
+
const c = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
|
|
24
|
+
if (!c.api || !c.projectId || !c.key)
|
|
25
|
+
return null;
|
|
26
|
+
return {
|
|
27
|
+
apiUrl: `${c.api}/api/${c.projectId}/${c.key}`,
|
|
28
|
+
projectId: c.projectId,
|
|
29
|
+
user: c.user || 'mcp-agent',
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
export function registerInitTool(server, ctx, onProjectChange) {
|
|
37
|
+
server.tool('kg_init', '🔗 项目上下文初始化 — 读取指定目录的 .ppdocs 配置,切换 MCP 连接到对应项目。首次对话必须调用。不传 projectPath 则使用当前工作目录', {
|
|
38
|
+
projectPath: z.string().optional().describe('项目根目录的绝对路径(含 .ppdocs 文件),不传则使用 cwd'),
|
|
39
|
+
}, async ({ projectPath }) => safeTool(async () => {
|
|
40
|
+
const targetDir = projectPath || process.cwd();
|
|
41
|
+
// 1. 尝试从目标目录读取 .ppdocs
|
|
42
|
+
const config = readPpdocsFrom(targetDir);
|
|
43
|
+
if (!config) {
|
|
44
|
+
return wrap(`❌ 未在 ${targetDir} 找到 .ppdocs 配置文件\n\n` +
|
|
45
|
+
`请先在项目目录中运行:\n` +
|
|
46
|
+
` npx @ppdocs/mcp init -p <projectId> -k <key>\n\n` +
|
|
47
|
+
`或通过 WebUI 绑定项目:\n` +
|
|
48
|
+
` npx @ppdocs/mcp webui`);
|
|
49
|
+
}
|
|
50
|
+
// 2. 幂等检查
|
|
51
|
+
if (currentApiUrl === config.apiUrl) {
|
|
52
|
+
return wrap(`✅ 项目上下文已就绪 (无需切换)\n\n` +
|
|
53
|
+
`📂 项目: ${config.projectId}\n` +
|
|
54
|
+
`🔗 API: ${config.apiUrl.replace(/\/[^/]+$/, '/***')}\n` +
|
|
55
|
+
`👤 用户: ${config.user}`);
|
|
56
|
+
}
|
|
57
|
+
// 3. 重新初始化 HTTP Client
|
|
58
|
+
initClient(config.apiUrl);
|
|
59
|
+
currentApiUrl = config.apiUrl;
|
|
60
|
+
// 4. 更新共享上下文 — 所有工具立刻获得新 projectId
|
|
61
|
+
ctx.projectId = config.projectId;
|
|
62
|
+
ctx.user = config.user;
|
|
63
|
+
// 5. 通知主进程
|
|
64
|
+
onProjectChange(config.projectId, config.apiUrl);
|
|
65
|
+
return wrap(`✅ 项目上下文已初始化\n\n` +
|
|
66
|
+
`📂 项目: ${config.projectId}\n` +
|
|
67
|
+
`📁 路径: ${targetDir}\n` +
|
|
68
|
+
`🔗 API: ${config.apiUrl.replace(/\/[^/]+$/, '/***')}\n` +
|
|
69
|
+
`👤 用户: ${config.user}\n\n` +
|
|
70
|
+
`所有后续工具调用将自动连接到此项目。`);
|
|
71
|
+
}));
|
|
72
|
+
}
|
|
@@ -2,4 +2,5 @@
|
|
|
2
2
|
* 📊 kg_status — 项目速览仪表盘 (新增)
|
|
3
3
|
*/
|
|
4
4
|
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
5
|
-
|
|
5
|
+
import { type McpContext } from './shared.js';
|
|
6
|
+
export declare function registerStatusTool(server: McpServer, ctx: McpContext): void;
|
package/dist/tools/kg_status.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import { getClient } from '../storage/httpClient.js';
|
|
5
5
|
import { wrap, safeTool } from './shared.js';
|
|
6
|
-
export function registerStatusTool(server,
|
|
6
|
+
export function registerStatusTool(server, ctx) {
|
|
7
7
|
const client = () => getClient();
|
|
8
8
|
server.tool('kg_status', '📊 项目速览仪表盘 — 一键了解项目健康。返回: 文档总数、目录数、活跃任务数、最近变更。每次对话开始建议首先调用', {}, async () => safeTool(async () => {
|
|
9
9
|
const [docs, activeTasks] = await Promise.all([
|
|
@@ -20,7 +20,7 @@ export function registerStatusTool(server, projectId) {
|
|
|
20
20
|
statusMap.set(s, (statusMap.get(s) || 0) + 1);
|
|
21
21
|
}
|
|
22
22
|
const lines = [
|
|
23
|
-
`📊 项目速览 [${projectId}]`,
|
|
23
|
+
`📊 项目速览 [${ctx.projectId}]`,
|
|
24
24
|
``,
|
|
25
25
|
`📄 文档: ${docCount} 个 | 📁 目录: ${dirCount} 个`,
|
|
26
26
|
`📝 活跃任务: ${activeTasks.length} 个`,
|
package/dist/tools/shared.d.ts
CHANGED
|
@@ -3,6 +3,13 @@
|
|
|
3
3
|
* 合并原 helpers.ts + 新增 safeTool / withCross 模式
|
|
4
4
|
*/
|
|
5
5
|
import type { DocData } from '../storage/types.js';
|
|
6
|
+
/** 运行时可变上下文 — 所有工具通过引用获取最新值 */
|
|
7
|
+
export interface McpContext {
|
|
8
|
+
projectId: string;
|
|
9
|
+
user: string;
|
|
10
|
+
}
|
|
11
|
+
/** 创建可变上下文对象 (工具闭包捕获此对象的引用,kg_init 更新其属性) */
|
|
12
|
+
export declare function createContext(projectId: string, user: string): McpContext;
|
|
6
13
|
export declare function wrap(text: string): {
|
|
7
14
|
content: {
|
|
8
15
|
type: "text";
|
package/dist/tools/shared.js
CHANGED
|
@@ -2,6 +2,10 @@
|
|
|
2
2
|
* MCP 工具共享模块
|
|
3
3
|
* 合并原 helpers.ts + 新增 safeTool / withCross 模式
|
|
4
4
|
*/
|
|
5
|
+
/** 创建可变上下文对象 (工具闭包捕获此对象的引用,kg_init 更新其属性) */
|
|
6
|
+
export function createContext(projectId, user) {
|
|
7
|
+
return { projectId, user };
|
|
8
|
+
}
|
|
5
9
|
// ==================== MCP 返回包装 ====================
|
|
6
10
|
export function wrap(text) {
|
|
7
11
|
return { content: [{ type: 'text', text }] };
|