@ppdocs/mcp 3.2.6 → 3.2.7
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 +6 -2
- package/dist/tools/init.d.ts +13 -0
- package/dist/tools/init.js +75 -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,14 @@
|
|
|
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 { registerInitTool } from './init.js';
|
|
10
12
|
import { registerStatusTool } from './kg_status.js';
|
|
11
13
|
import { registerDocTools } from './docs.js';
|
|
12
14
|
import { registerProjectTools } from './projects.js';
|
|
@@ -15,7 +17,9 @@ import { registerTaskTools } from './tasks.js';
|
|
|
15
17
|
import { registerFileTools } from './files.js';
|
|
16
18
|
import { registerDiscussionTools } from './discussion.js';
|
|
17
19
|
import { registerAnalyzerTools } from './analyzer.js';
|
|
18
|
-
export function registerTools(server, projectId, user) {
|
|
20
|
+
export function registerTools(server, projectId, user, onProjectChange) {
|
|
21
|
+
// 🔗 初始化 (kg_init — 运行时项目切换)
|
|
22
|
+
registerInitTool(server, projectId, onProjectChange || (() => { }));
|
|
19
23
|
// 📊 导航 (kg_status + kg_tree在docs中)
|
|
20
24
|
registerStatusTool(server, projectId);
|
|
21
25
|
// 📚 知识 (kg_doc + kg_tree + kg_projects + kg_rules)
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* kg_init 工具 — 项目上下文初始化
|
|
3
|
+
*
|
|
4
|
+
* 解决全局共用 MCP 进程时的多项目隔离问题:
|
|
5
|
+
* - 智能体调用 kg_init 传入 projectPath
|
|
6
|
+
* - MCP 从该路径读取 .ppdocs 配置
|
|
7
|
+
* - 重新初始化 HTTP Client 指向正确项目
|
|
8
|
+
* - 后续所有工具调用自动使用新的项目上下文
|
|
9
|
+
*/
|
|
10
|
+
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
11
|
+
/** 获取当前已初始化的 projectId */
|
|
12
|
+
export declare function getActiveProjectId(): string | null;
|
|
13
|
+
export declare function registerInitTool(server: McpServer, defaultProjectId: string, onProjectChange: (newProjectId: string, newApiUrl: string) => void): void;
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* kg_init 工具 — 项目上下文初始化
|
|
3
|
+
*
|
|
4
|
+
* 解决全局共用 MCP 进程时的多项目隔离问题:
|
|
5
|
+
* - 智能体调用 kg_init 传入 projectPath
|
|
6
|
+
* - MCP 从该路径读取 .ppdocs 配置
|
|
7
|
+
* - 重新初始化 HTTP Client 指向正确项目
|
|
8
|
+
* - 后续所有工具调用自动使用新的项目上下文
|
|
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
|
+
// 当前会话的项目上下文 (模块级单例)
|
|
16
|
+
let currentProjectId = null;
|
|
17
|
+
let currentApiUrl = null;
|
|
18
|
+
/** 获取当前已初始化的 projectId */
|
|
19
|
+
export function getActiveProjectId() {
|
|
20
|
+
return currentProjectId;
|
|
21
|
+
}
|
|
22
|
+
/** 尝试从指定目录读取 .ppdocs 配置 */
|
|
23
|
+
function readPpdocsFrom(dir) {
|
|
24
|
+
const configPath = path.join(dir, '.ppdocs');
|
|
25
|
+
if (!fs.existsSync(configPath))
|
|
26
|
+
return null;
|
|
27
|
+
try {
|
|
28
|
+
const c = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
|
|
29
|
+
if (!c.api || !c.projectId || !c.key)
|
|
30
|
+
return null;
|
|
31
|
+
return {
|
|
32
|
+
apiUrl: `${c.api}/api/${c.projectId}/${c.key}`,
|
|
33
|
+
projectId: c.projectId,
|
|
34
|
+
user: c.user || 'mcp-agent',
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
export function registerInitTool(server, defaultProjectId, onProjectChange) {
|
|
42
|
+
server.tool('kg_init', '🔗 项目上下文初始化 — 读取指定目录的 .ppdocs 配置,切换 MCP 连接到对应项目。首次对话建议调用。不传 projectPath 则使用当前工作目录', {
|
|
43
|
+
projectPath: z.string().optional().describe('项目根目录的绝对路径(含 .ppdocs 文件),不传则使用 cwd'),
|
|
44
|
+
}, async ({ projectPath }) => safeTool(async () => {
|
|
45
|
+
const targetDir = projectPath || process.cwd();
|
|
46
|
+
// 1. 尝试从目标目录读取 .ppdocs
|
|
47
|
+
const config = readPpdocsFrom(targetDir);
|
|
48
|
+
if (!config) {
|
|
49
|
+
return wrap(`❌ 未在 ${targetDir} 找到 .ppdocs 配置文件\n\n` +
|
|
50
|
+
`请先在项目目录中运行:\n` +
|
|
51
|
+
` npx @ppdocs/mcp init -p <projectId> -k <key>\n\n` +
|
|
52
|
+
`或通过 WebUI 绑定项目:\n` +
|
|
53
|
+
` npx @ppdocs/mcp webui`);
|
|
54
|
+
}
|
|
55
|
+
// 2. 检查是否需要切换
|
|
56
|
+
if (currentApiUrl === config.apiUrl) {
|
|
57
|
+
return wrap(`✅ 项目上下文已就绪 (无需切换)\n\n` +
|
|
58
|
+
`📂 项目: ${config.projectId}\n` +
|
|
59
|
+
`🔗 API: ${config.apiUrl.replace(/\/[^/]+$/, '/***')}\n` +
|
|
60
|
+
`👤 用户: ${config.user}`);
|
|
61
|
+
}
|
|
62
|
+
// 3. 重新初始化 HTTP Client
|
|
63
|
+
initClient(config.apiUrl);
|
|
64
|
+
currentProjectId = config.projectId;
|
|
65
|
+
currentApiUrl = config.apiUrl;
|
|
66
|
+
// 4. 通知主进程更新工具注册的 projectId
|
|
67
|
+
onProjectChange(config.projectId, config.apiUrl);
|
|
68
|
+
return wrap(`✅ 项目上下文已初始化\n\n` +
|
|
69
|
+
`📂 项目: ${config.projectId}\n` +
|
|
70
|
+
`📁 路径: ${targetDir}\n` +
|
|
71
|
+
`🔗 API: ${config.apiUrl.replace(/\/[^/]+$/, '/***')}\n` +
|
|
72
|
+
`👤 用户: ${config.user}\n\n` +
|
|
73
|
+
`所有后续工具调用将自动连接到此项目。`);
|
|
74
|
+
}));
|
|
75
|
+
}
|