@ppdocs/mcp 3.2.2 → 3.2.4

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/cli.d.ts CHANGED
@@ -2,6 +2,6 @@
2
2
  * ppdocs MCP CLI
3
3
  * 命令: init - 初始化项目配置 + 安装工作流模板 + 自动注册 MCP
4
4
  */
5
- export declare function runCli(args: string[]): boolean;
5
+ export declare function runCli(args: string[]): Promise<'exit' | 'keep-alive' | false>;
6
6
  /** 安装项目模板文件 (供授权后自动配置调用) */
7
7
  export declare function setupProjectFiles(cwd: string, apiUrl: string): void;
package/dist/cli.js CHANGED
@@ -112,7 +112,7 @@ Example:
112
112
  npx @ppdocs/mcp init -p myproject -k abc123xyz --sync shared-rules
113
113
  `);
114
114
  }
115
- export function runCli(args) {
115
+ export async function runCli(args) {
116
116
  const cmd = args[0];
117
117
  if (cmd === 'init') {
118
118
  const opts = parseArgs(args.slice(1));
@@ -121,23 +121,17 @@ export function runCli(args) {
121
121
  showHelp();
122
122
  process.exit(1);
123
123
  }
124
- initProject(opts).catch(e => {
125
- console.error(`❌ Init failed: ${e}`);
126
- process.exit(1);
127
- });
128
- return true;
124
+ await initProject(opts);
125
+ return 'exit';
129
126
  }
130
127
  if (cmd === 'agent' || cmd === 'webui') {
131
- // 动态导入 Agent 入口 (Web UI + 多项目管理)
132
- import('./agent.js').catch(e => {
133
- console.error(`❌ Agent failed: ${e}`);
134
- process.exit(1);
135
- });
136
- return true;
128
+ // 动态导入 Agent 入口 (Web UI + 多项目管理) — 长驻进程,不退出
129
+ await import('./agent.js');
130
+ return 'keep-alive';
137
131
  }
138
132
  if (cmd === '--help' || cmd === '-h' || cmd === 'help') {
139
133
  showHelp();
140
- return true;
134
+ return 'exit';
141
135
  }
142
136
  return false; // Not a CLI command, run as MCP server
143
137
  }
package/dist/config.d.ts CHANGED
@@ -1,22 +1,14 @@
1
1
  /**
2
2
  * ppdocs MCP Config
3
- * 读取配置: 环境变量 > .ppdocs 文件 > 自动发现 > 授权请求
3
+ * 读取配置: 环境变量 > .ppdocs 文件 > 提示去 Agent WebUI 绑定
4
4
  */
5
5
  export interface PpdocsConfig {
6
6
  apiUrl: string;
7
7
  projectId: string;
8
8
  user: string;
9
- source: 'env' | 'file' | 'auth';
10
- /** 原始连接参数 (discover/auth 填充, 供持久化使用) */
11
- connection?: {
12
- host: string;
13
- port: number;
14
- password: string;
15
- };
9
+ source: 'env' | 'file';
16
10
  }
17
11
  export declare const PPDOCS_CONFIG_FILE = ".ppdocs";
18
12
  /** 生成随机用户名 */
19
13
  export declare function generateUser(): string;
20
- /** 写入 .ppdocs 文件 (需 config.connection 存在) */
21
- export declare function writePpdocsFile(config: PpdocsConfig): void;
22
14
  export declare function loadConfig(): Promise<PpdocsConfig>;
package/dist/config.js CHANGED
@@ -1,17 +1,16 @@
1
1
  /**
2
2
  * ppdocs MCP Config
3
- * 读取配置: 环境变量 > .ppdocs 文件 > 自动发现 > 授权请求
3
+ * 读取配置: 环境变量 > .ppdocs 文件 > 提示去 Agent WebUI 绑定
4
4
  */
5
5
  import * as fs from 'fs';
6
6
  import * as path from 'path';
7
- import * as os from 'os';
8
7
  export const PPDOCS_CONFIG_FILE = '.ppdocs';
9
8
  /** 生成随机用户名 */
10
9
  export function generateUser() {
11
10
  const chars = 'abcdefghjkmnpqrstuvwxyz23456789';
12
11
  return Array.from({ length: 8 }, () => chars[Math.floor(Math.random() * chars.length)]).join('');
13
12
  }
14
- // ============ 静态配置读取 ============
13
+ // ============ 配置读取 ============
15
14
  function readEnvConfig() {
16
15
  const apiUrl = process.env.PPDOCS_API_URL;
17
16
  if (!apiUrl)
@@ -33,104 +32,24 @@ function readPpdocsFile() {
33
32
  return null;
34
33
  }
35
34
  }
36
- async function findLocalServer() {
37
- for (const host of ['localhost', '127.0.0.1', '10.0.0.176']) {
38
- for (const port of [20001]) {
39
- try {
40
- const res = await fetch(`http://${host}:${port}/health`, { signal: AbortSignal.timeout(2000) });
41
- if (res.ok)
42
- return { host, port, base: `http://${host}:${port}` };
43
- }
44
- catch {
45
- continue;
46
- }
47
- }
48
- }
49
- return null;
50
- }
51
- // ============ 授权请求 ============
52
- async function requestAuthConfig(server) {
53
- try {
54
- const reqRes = await fetch(`${server.base}/api/auth/request`, {
55
- method: 'POST',
56
- headers: { 'Content-Type': 'application/json' },
57
- body: JSON.stringify({ cwd: process.cwd(), hostname: os.hostname() }),
58
- });
59
- if (!reqRes.ok)
60
- return null;
61
- const { data } = await reqRes.json();
62
- if (!data?.requestId)
63
- return null;
64
- console.error(`[Auth] 等待桌面端授权... (请在 ppdocs 桌面端确认)`);
65
- for (let i = 0; i < 150; i++) {
66
- await new Promise(r => setTimeout(r, 2000));
67
- const pollRes = await fetch(`${server.base}/api/auth/poll/${data.requestId}`, { signal: AbortSignal.timeout(3000) });
68
- if (!pollRes.ok)
69
- continue;
70
- const { data: poll } = await pollRes.json();
71
- if (poll?.status === 'approved' && poll.result) {
72
- const r = poll.result;
73
- console.error(`[Auth] 已授权: ${r.project_name} (${r.project_id})`);
74
- return {
75
- apiUrl: `http://${r.api_host}:${r.api_port}/api/${r.project_id}/${r.password}`,
76
- projectId: r.project_id,
77
- user: `auto-${generateUser().slice(0, 4)}`,
78
- source: 'auth',
79
- connection: { host: r.api_host, port: r.api_port, password: r.password },
80
- };
81
- }
82
- if (poll?.status === 'rejected') {
83
- console.error('[Auth] 授权被拒绝');
84
- return null;
85
- }
86
- if (poll?.status === 'expired') {
87
- console.error('[Auth] 授权超时');
88
- return null;
89
- }
90
- }
91
- console.error('[Auth] 轮询超时');
92
- return null;
93
- }
94
- catch {
95
- return null;
96
- }
97
- }
98
- // ============ 持久化 ============
99
- /** 写入 .ppdocs 文件 (需 config.connection 存在) */
100
- export function writePpdocsFile(config) {
101
- if (!config.connection)
102
- return;
103
- const configPath = path.join(process.cwd(), '.ppdocs');
104
- if (fs.existsSync(configPath))
105
- return;
106
- const { host, port, password } = config.connection;
107
- fs.writeFileSync(configPath, JSON.stringify({
108
- api: `http://${host}:${port}`,
109
- projectId: config.projectId,
110
- key: password,
111
- user: config.user,
112
- }, null, 2), 'utf-8');
113
- console.error(`[Config] 已保存 .ppdocs`);
114
- }
115
35
  // ============ 入口 ============
116
36
  export async function loadConfig() {
117
37
  // 1. 环境变量
118
38
  const envConfig = readEnvConfig();
119
39
  if (envConfig)
120
40
  return envConfig;
121
- // 2. .ppdocs 文件
41
+ // 2. .ppdocs 文件 (由 Agent WebUI 绑定时自动生成)
122
42
  const fileConfig = readPpdocsFile();
123
43
  if (fileConfig)
124
44
  return fileConfig;
125
- // 3. 扫描本地服务器 请求桌面端授权
126
- const server = await findLocalServer();
127
- if (server) {
128
- const authConfig = await requestAuthConfig(server);
129
- if (authConfig)
130
- return authConfig;
131
- }
132
- // 全部失败
133
- console.error('ERROR: ppdocs 配置未找到');
134
- console.error(' 请确保 ppdocs 桌面端正在运行,或手动配置 PPDOCS_API_URL 环境变量');
45
+ // 无配置提示用户去 Agent WebUI 绑定
46
+ console.error('ERROR: 未找到 .ppdocs 配置');
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');
135
54
  process.exit(1);
136
55
  }
package/dist/index.js CHANGED
@@ -13,30 +13,28 @@ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
13
13
  import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
14
14
  import { registerTools } from './tools/index.js';
15
15
  import { initClient } from './storage/httpClient.js';
16
- import { runCli, setupProjectFiles } from './cli.js';
17
- import { loadConfig, writePpdocsFile } from './config.js';
16
+ import { runCli } from './cli.js';
17
+ import { loadConfig } from './config.js';
18
18
  // 从 package.json 读取版本号
19
19
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
20
20
  const pkg = JSON.parse(fs.readFileSync(path.join(__dirname, '..', 'package.json'), 'utf-8'));
21
21
  const VERSION = pkg.version;
22
22
  // 检查是否为 CLI 命令
23
23
  const args = process.argv.slice(2);
24
- if (args.length > 0 && runCli(args)) {
25
- process.exit(0);
24
+ if (args.length > 0) {
25
+ const result = await runCli(args);
26
+ if (result === 'exit')
27
+ process.exit(0);
28
+ if (result === 'keep-alive') {
29
+ // agent/webui 长驻模式,不继续执行 MCP Server
30
+ // @ts-ignore: 阻止后续 main() 执行
31
+ await new Promise(() => { }); // 永不 resolve,进程由 agent.ts 的 HTTP 服务保活
32
+ }
33
+ // result === false → 继续作为 MCP Server
26
34
  }
27
35
  // 运行 MCP 服务
28
36
  async function main() {
29
37
  const config = await loadConfig();
30
- // 自动持久化: 发现/授权后写入 .ppdocs + 安装模板
31
- if (config.source === 'auth' && config.connection) {
32
- try {
33
- writePpdocsFile(config);
34
- setupProjectFiles(process.cwd(), config.apiUrl);
35
- }
36
- catch (e) {
37
- console.error('[AutoSetup] 自动配置失败:', e);
38
- }
39
- }
40
38
  initClient(config.apiUrl);
41
39
  const server = new McpServer({ name: `ppdocs [${config.projectId}]`, version: VERSION }, { capabilities: { tools: {} } });
42
40
  registerTools(server, config.projectId, config.user);
@@ -39,6 +39,25 @@ export function saveAgentConfig(config) {
39
39
  fs.mkdirSync(CONFIG_DIR, { recursive: true });
40
40
  fs.writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2));
41
41
  }
42
+ /** 写入 .ppdocs 到项目目录,供 MCP 直接读取 */
43
+ function writePpdocsToProject(binding, host, port) {
44
+ if (!binding.localDir || !binding.remote.password)
45
+ return;
46
+ const configPath = path.join(binding.localDir, '.ppdocs');
47
+ const content = {
48
+ api: `http://${host}:${port}`,
49
+ projectId: binding.remote.id,
50
+ key: binding.remote.password,
51
+ user: `agent-${binding.localName.slice(0, 8)}`,
52
+ };
53
+ try {
54
+ fs.writeFileSync(configPath, JSON.stringify(content, null, 2), 'utf-8');
55
+ console.log(`[Config] 已写入 ${configPath}`);
56
+ }
57
+ catch (e) {
58
+ console.error(`[Config] 写入 .ppdocs 失败: ${e}`);
59
+ }
60
+ }
42
61
  const state = {
43
62
  hostConnected: false,
44
63
  projectStatus: new Map(),
@@ -233,6 +252,8 @@ export function startWebServer(webPort) {
233
252
  };
234
253
  config.projects.push(binding);
235
254
  saveAgentConfig(config);
255
+ // 写入 .ppdocs 到项目目录,供 MCP 直接读取
256
+ writePpdocsToProject(binding, config.host, config.port);
236
257
  // 通知 Agent 主进程启动同步
237
258
  if (state.onBind)
238
259
  state.onBind(binding);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ppdocs/mcp",
3
- "version": "3.2.2",
3
+ "version": "3.2.4",
4
4
  "description": "ppdocs MCP Server - Knowledge Graph for Claude",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",