@ppdocs/mcp 3.1.8 → 3.1.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.
package/dist/cli.d.ts CHANGED
@@ -3,3 +3,5 @@
3
3
  * 命令: init - 初始化项目配置 + 安装工作流模板 + 自动注册 MCP
4
4
  */
5
5
  export declare function runCli(args: string[]): boolean;
6
+ /** 安装项目模板文件 (供授权后自动配置调用) */
7
+ export declare function setupProjectFiles(cwd: string, apiUrl: string): void;
package/dist/cli.js CHANGED
@@ -181,8 +181,8 @@ async function initProject(opts) {
181
181
  installClaudeTemplates(cwd); // Default to Claude templates
182
182
  }
183
183
  }
184
- // 自动检测并注册 MCP
185
- const registered = autoRegisterMcp(apiUrl, opts.user);
184
+ // 自动检测并注册 MCP (如果已写入 Antigravity 配置,跳过 gemini CLI 注册避免冲突)
185
+ const registered = autoRegisterMcp(apiUrl, opts.user, detectedIdes.includes('antigravity'));
186
186
  // 如果没有检测到任何 AI CLI,并且也没有检测到配置文件夹,创建 .mcp.json 作为备用
187
187
  if (!registered && !hasIdeDir) {
188
188
  createMcpJson(cwd, apiUrl);
@@ -280,7 +280,7 @@ function execSilent(cmd) {
280
280
  catch { /* ignore */ }
281
281
  }
282
282
  /** 自动检测 AI CLI 并注册 MCP */
283
- function autoRegisterMcp(apiUrl, user) {
283
+ function autoRegisterMcp(apiUrl, user, skipGemini = false) {
284
284
  const detected = [];
285
285
  const serverName = 'ppdocs-kg';
286
286
  // 检测 Claude CLI (不传环境变量,MCP启动时读取.ppdocs)
@@ -324,7 +324,7 @@ function autoRegisterMcp(apiUrl, user) {
324
324
  }
325
325
  }
326
326
  // 检测 Gemini CLI
327
- if (commandExists('gemini')) {
327
+ if (commandExists('gemini') && !skipGemini) {
328
328
  detected.push('Gemini');
329
329
  try {
330
330
  console.log(`✅ Detected Gemini CLI, registering MCP...`);
@@ -344,33 +344,39 @@ function autoRegisterMcp(apiUrl, user) {
344
344
  return true;
345
345
  }
346
346
  /** 在指定路径创建或更新 mcp.json 配置 */
347
- function createMcpConfigAt(mcpPath, apiUrl) {
347
+ function createMcpConfigAt(mcpPath, apiUrl, options) {
348
348
  let mcpConfig = {};
349
349
  if (fs.existsSync(mcpPath)) {
350
350
  try {
351
351
  mcpConfig = JSON.parse(fs.readFileSync(mcpPath, 'utf-8'));
352
352
  }
353
353
  catch {
354
- // ignore parse error
354
+ // 解析失败时中止,避免清空已有配置
355
+ console.log(`⚠️ ${mcpPath} JSON格式无效,跳过MCP配置写入(请手动修复后重试)`);
356
+ return;
355
357
  }
356
358
  }
357
359
  // Windows 需要 cmd /c 包装才能执行 npx
358
360
  const isWindows = process.platform === 'win32';
359
361
  // 对于 Mac/Linux,IDE 可能没有用户的完整 PATH,导致找不到 npx
362
+ // 使用实际 PATH 值拼接,JSON 中的 $PATH 不会被展开
363
+ const macExtraPaths = '/usr/local/bin:/opt/homebrew/bin:/home/linuxbrew/.linuxbrew/bin';
364
+ const actualPath = `${process.env.PATH || '/usr/bin:/bin'}:${macExtraPaths}`;
360
365
  const ppdocsServer = isWindows
361
366
  ? {
362
367
  command: 'cmd',
363
368
  args: ['/c', 'npx', '-y', '@ppdocs/mcp@latest'],
364
- env: { "PPDOCS_API_URL": apiUrl }
369
+ ...(options?.noEnv ? {} : { env: { "PPDOCS_API_URL": apiUrl } })
365
370
  }
366
371
  : {
367
372
  command: 'npx',
368
373
  args: ['-y', '@ppdocs/mcp@latest'],
369
- env: {
370
- "PPDOCS_API_URL": apiUrl,
371
- // 强行注入常见路径,防止找不到 node/npx
372
- "PATH": "$PATH:/usr/local/bin:/opt/homebrew/bin:/home/linuxbrew/.linuxbrew/bin"
373
- }
374
+ ...(options?.noEnv ? { env: { "PATH": actualPath } } : {
375
+ env: {
376
+ "PPDOCS_API_URL": apiUrl,
377
+ "PATH": actualPath
378
+ }
379
+ })
374
380
  };
375
381
  mcpConfig.mcpServers = {
376
382
  ...(mcpConfig.mcpServers || {}),
@@ -522,8 +528,8 @@ function installCursorTemplates(cwd, apiUrl) {
522
528
  }
523
529
  /** 安装 Antigravity (Gemini IDE) 模板 */
524
530
  function installAntigravityTemplates(cwd, apiUrl) {
525
- // 1. 填充 .gemini/settings.json
526
- createMcpConfigAt(path.join(cwd, '.gemini', 'settings.json'), apiUrl);
531
+ // 1. 填充 .gemini/settings.json (noEnv: 依赖 .ppdocs 文件,不传 PPDOCS_API_URL 避免覆盖)
532
+ createMcpConfigAt(path.join(cwd, '.gemini', 'settings.json'), apiUrl, { noEnv: true });
527
533
  // 2. 生成 AGENTS.md
528
534
  generateAgentsMd(cwd);
529
535
  // 3. 安装斜杠命令 → .agents/workflows/ (Antigravity 的 slash command 机制)
@@ -587,3 +593,23 @@ function detectIDEs(cwd) {
587
593
  ides.push('kiro');
588
594
  return ides;
589
595
  }
596
+ /** 安装项目模板文件 (供授权后自动配置调用) */
597
+ export function setupProjectFiles(cwd, apiUrl) {
598
+ const detectedIdes = detectIDEs(cwd);
599
+ if (detectedIdes.includes('antigravity')) {
600
+ installAntigravityTemplates(cwd, apiUrl);
601
+ }
602
+ if (detectedIdes.includes('cursor')) {
603
+ installCursorTemplates(cwd, apiUrl);
604
+ }
605
+ if (detectedIdes.includes('kiro')) {
606
+ installKiroTemplates(cwd, apiUrl);
607
+ }
608
+ if (detectedIdes.includes('claude')) {
609
+ installClaudeTemplates(cwd);
610
+ }
611
+ // 如果没检测到任何 IDE,默认安装 Claude 模板
612
+ if (detectedIdes.length === 0) {
613
+ installClaudeTemplates(cwd);
614
+ }
615
+ }
package/dist/config.d.ts CHANGED
@@ -1,16 +1,22 @@
1
1
  /**
2
2
  * ppdocs MCP Config
3
- * 读取配置: 环境变量 > .ppdocs 文件
3
+ * 读取配置: 环境变量 > .ppdocs 文件 > 自动发现 > 授权请求
4
4
  */
5
5
  export interface PpdocsConfig {
6
6
  apiUrl: string;
7
7
  projectId: string;
8
8
  user: string;
9
+ source: 'env' | 'file' | 'discover' | 'auth';
10
+ /** 原始连接参数 (discover/auth 填充, 供持久化使用) */
11
+ connection?: {
12
+ host: string;
13
+ port: number;
14
+ password: string;
15
+ };
9
16
  }
10
- export declare const PPDOCS_DIR = ".ppdocs";
11
- /** 生成随机用户名 (8位字母数字) */
17
+ export declare const PPDOCS_CONFIG_FILE = ".ppdocs";
18
+ /** 生成随机用户名 */
12
19
  export declare function generateUser(): string;
13
- /**
14
- * 加载配置 (优先级: 环境变量 > .ppdocs 文件)
15
- */
16
- export declare function loadConfig(): PpdocsConfig;
20
+ /** 写入 .ppdocs 文件 (需 config.connection 存在) */
21
+ export declare function writePpdocsFile(config: PpdocsConfig): void;
22
+ export declare function loadConfig(): Promise<PpdocsConfig>;
package/dist/config.js CHANGED
@@ -1,72 +1,172 @@
1
1
  /**
2
2
  * ppdocs MCP Config
3
- * 读取配置: 环境变量 > .ppdocs 文件
3
+ * 读取配置: 环境变量 > .ppdocs 文件 > 自动发现 > 授权请求
4
4
  */
5
5
  import * as fs from 'fs';
6
6
  import * as path from 'path';
7
- export const PPDOCS_DIR = '.ppdocs';
8
- /** 生成随机用户名 (8位字母数字) */
7
+ import * as os from 'os';
8
+ export const PPDOCS_CONFIG_FILE = '.ppdocs';
9
+ /** 生成随机用户名 */
9
10
  export function generateUser() {
10
11
  const chars = 'abcdefghjkmnpqrstuvwxyz23456789';
11
12
  return Array.from({ length: 8 }, () => chars[Math.floor(Math.random() * chars.length)]).join('');
12
13
  }
13
- /**
14
- * 从 .ppdocs 文件读取配置
15
- */
14
+ // ============ 静态配置读取 ============
15
+ function readEnvConfig() {
16
+ const apiUrl = process.env.PPDOCS_API_URL;
17
+ if (!apiUrl)
18
+ return null;
19
+ const match = apiUrl.match(/\/api\/([^/]+)\/[^/]+\/?$/);
20
+ return { apiUrl, projectId: match?.[1] || 'unknown', user: process.env.PPDOCS_USER || generateUser(), source: 'env' };
21
+ }
16
22
  function readPpdocsFile() {
17
- const cwd = process.cwd();
18
- const configPath = path.join(cwd, '.ppdocs');
19
- if (!fs.existsSync(configPath)) {
23
+ const configPath = path.join(process.cwd(), '.ppdocs');
24
+ if (!fs.existsSync(configPath))
20
25
  return null;
21
- }
22
26
  try {
23
- const content = fs.readFileSync(configPath, 'utf-8');
24
- const config = JSON.parse(content);
25
- if (!config.api || !config.projectId || !config.key) {
27
+ const c = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
28
+ if (!c.api || !c.projectId || !c.key)
26
29
  return null;
30
+ return { apiUrl: `${c.api}/api/${c.projectId}/${c.key}`, projectId: c.projectId, user: c.user || generateUser(), source: 'file' };
31
+ }
32
+ catch {
33
+ return null;
34
+ }
35
+ }
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
+ }
27
47
  }
48
+ }
49
+ return null;
50
+ }
51
+ // ============ 自动发现 ============
52
+ async function autoDiscoverConfig(server) {
53
+ const cwd = process.cwd().replace(/\\/g, '/').toLowerCase();
54
+ try {
55
+ const res = await fetch(`${server.base}/api/projects`, { signal: AbortSignal.timeout(2000) });
56
+ if (!res.ok)
57
+ return null;
58
+ const { data: projects } = await res.json();
59
+ if (!Array.isArray(projects))
60
+ return null;
61
+ const match = projects.find((p) => p.projectPath && cwd.startsWith(p.projectPath.replace(/\\/g, '/').toLowerCase()));
62
+ if (!match)
63
+ return null;
64
+ const metaRes = await fetch(`${server.base}/api/projects/${match.id}/meta`, { signal: AbortSignal.timeout(2000) });
65
+ if (!metaRes.ok)
66
+ return null;
67
+ const { data: meta } = await metaRes.json();
68
+ if (!meta?.password)
69
+ return null;
70
+ console.error(`[AutoDiscovery] 匹配项目: ${match.name} (${match.id})`);
28
71
  return {
29
- apiUrl: `${config.api}/api/${config.projectId}/${config.key}`,
30
- projectId: config.projectId,
31
- user: config.user || generateUser(),
72
+ apiUrl: `${server.base}/api/${match.id}/${meta.password}`,
73
+ projectId: match.id,
74
+ user: `auto-${generateUser().slice(0, 4)}`,
75
+ source: 'discover',
76
+ connection: { host: server.host, port: server.port, password: meta.password },
32
77
  };
33
78
  }
34
79
  catch {
35
80
  return null;
36
81
  }
37
82
  }
38
- /**
39
- * 从环境变量读取配置
40
- */
41
- function readEnvConfig() {
42
- const apiUrl = process.env.PPDOCS_API_URL;
43
- if (!apiUrl)
83
+ // ============ 授权请求 ============
84
+ async function requestAuthConfig(server) {
85
+ try {
86
+ const reqRes = await fetch(`${server.base}/api/auth/request`, {
87
+ method: 'POST',
88
+ headers: { 'Content-Type': 'application/json' },
89
+ body: JSON.stringify({ cwd: process.cwd(), hostname: os.hostname() }),
90
+ });
91
+ if (!reqRes.ok)
92
+ return null;
93
+ const { data } = await reqRes.json();
94
+ if (!data?.requestId)
95
+ return null;
96
+ console.error(`[Auth] 等待桌面端授权... (请在 ppdocs 桌面端确认)`);
97
+ for (let i = 0; i < 150; i++) {
98
+ await new Promise(r => setTimeout(r, 2000));
99
+ const pollRes = await fetch(`${server.base}/api/auth/poll/${data.requestId}`, { signal: AbortSignal.timeout(3000) });
100
+ if (!pollRes.ok)
101
+ continue;
102
+ const { data: poll } = await pollRes.json();
103
+ if (poll?.status === 'approved' && poll.result) {
104
+ const r = poll.result;
105
+ console.error(`[Auth] 已授权: ${r.project_name} (${r.project_id})`);
106
+ return {
107
+ apiUrl: `http://${r.api_host}:${r.api_port}/api/${r.project_id}/${r.password}`,
108
+ projectId: r.project_id,
109
+ user: `auto-${generateUser().slice(0, 4)}`,
110
+ source: 'auth',
111
+ connection: { host: r.api_host, port: r.api_port, password: r.password },
112
+ };
113
+ }
114
+ if (poll?.status === 'rejected') {
115
+ console.error('[Auth] 授权被拒绝');
116
+ return null;
117
+ }
118
+ if (poll?.status === 'expired') {
119
+ console.error('[Auth] 授权超时');
120
+ return null;
121
+ }
122
+ }
123
+ console.error('[Auth] 轮询超时');
44
124
  return null;
45
- // URL 格式: http://localhost:20001/api/{projectId}/{password}
46
- const match = apiUrl.match(/\/api\/([^/]+)\/[^/]+\/?$/);
47
- const projectId = match?.[1] || 'unknown';
48
- const user = process.env.PPDOCS_USER || generateUser();
49
- return { apiUrl, projectId, user };
125
+ }
126
+ catch {
127
+ return null;
128
+ }
50
129
  }
51
- /**
52
- * 加载配置 (优先级: 环境变量 > .ppdocs 文件)
53
- */
54
- export function loadConfig() {
55
- // 1. 尝试环境变量
130
+ // ============ 持久化 ============
131
+ /** 写入 .ppdocs 文件 ( config.connection 存在) */
132
+ export function writePpdocsFile(config) {
133
+ if (!config.connection)
134
+ return;
135
+ const configPath = path.join(process.cwd(), '.ppdocs');
136
+ if (fs.existsSync(configPath))
137
+ return;
138
+ const { host, port, password } = config.connection;
139
+ fs.writeFileSync(configPath, JSON.stringify({
140
+ api: `http://${host}:${port}`,
141
+ projectId: config.projectId,
142
+ key: password,
143
+ user: config.user,
144
+ }, null, 2), 'utf-8');
145
+ console.error(`[Config] 已保存 .ppdocs`);
146
+ }
147
+ // ============ 入口 ============
148
+ export async function loadConfig() {
149
+ // 1. 环境变量
56
150
  const envConfig = readEnvConfig();
57
151
  if (envConfig)
58
152
  return envConfig;
59
- // 2. 尝试 .ppdocs 文件
153
+ // 2. .ppdocs 文件
60
154
  const fileConfig = readPpdocsFile();
61
155
  if (fileConfig)
62
156
  return fileConfig;
63
- // 3. 报错
157
+ // 3-4. 需要服务器 → 只扫一次
158
+ const server = await findLocalServer();
159
+ if (server) {
160
+ const discoverConfig = await autoDiscoverConfig(server);
161
+ if (discoverConfig)
162
+ return discoverConfig;
163
+ const authConfig = await requestAuthConfig(server);
164
+ if (authConfig)
165
+ return authConfig;
166
+ }
167
+ // 5. 全部失败
64
168
  console.error('ERROR: ppdocs config not found');
65
- console.error('');
66
- console.error('Option 1: Run init command in your project directory:');
67
- console.error(' npx @ppdocs/mcp init -p <projectId> -k <key>');
68
- console.error('');
69
- console.error('Option 2: Set environment variable:');
70
- console.error(' PPDOCS_API_URL=http://localhost:20001/api/{projectId}/{key}');
169
+ console.error(' Option 1: npx @ppdocs/mcp init -p <projectId> -k <key>');
170
+ console.error(' Option 2: Ensure ppdocs desktop app is running');
71
171
  process.exit(1);
72
172
  }
package/dist/index.js CHANGED
@@ -13,8 +13,8 @@ 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 } from './cli.js';
17
- import { loadConfig } from './config.js';
16
+ import { runCli, setupProjectFiles } from './cli.js';
17
+ import { loadConfig, writePpdocsFile } 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'));
@@ -26,7 +26,17 @@ if (args.length > 0 && runCli(args)) {
26
26
  }
27
27
  // 运行 MCP 服务
28
28
  async function main() {
29
- const config = loadConfig();
29
+ const config = await loadConfig();
30
+ // 自动持久化: 发现/授权后写入 .ppdocs + 安装模板
31
+ if ((config.source === 'discover' || 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
+ }
30
40
  initClient(config.apiUrl);
31
41
  const server = new McpServer({ name: `ppdocs [${config.projectId}]`, version: VERSION }, { capabilities: { tools: {} } });
32
42
  registerTools(server, config.projectId, config.user);
@@ -99,74 +99,4 @@ export declare class PpdocsApiClient {
99
99
  }
100
100
  export declare function initClient(apiUrl: string): void;
101
101
  export declare function getClient(): PpdocsApiClient;
102
- export declare function listDocs(_projectId: string): Promise<DocNode[]>;
103
- export declare function getDoc(_projectId: string, docPath: string): Promise<DocData | null>;
104
- export declare function createDoc(_projectId: string, docPath: string, doc: Partial<DocData>): Promise<DocData>;
105
- export declare function updateDoc(_projectId: string, docPath: string, updates: Partial<DocData>): Promise<DocData | null>;
106
- export declare function deleteDoc(_projectId: string, docPath: string): Promise<boolean>;
107
- export declare function searchDocs(_projectId: string, keywords: string[], limit?: number): Promise<DocSearchResult[]>;
108
- export declare function getDocsByStatus(_projectId: string, statusList: string[]): Promise<DocNode[]>;
109
- export declare function getTree(_projectId: string): Promise<TreeNode[]>;
110
- export declare function getRules(_projectId: string, ruleType: string): Promise<string[]>;
111
- export declare function saveRules(_projectId: string, ruleType: string, rules: string[]): Promise<boolean>;
112
- export declare function appendRules(_projectId: string, ruleType: string, newRules: string[]): Promise<{
113
- success: boolean;
114
- total: number;
115
- added: number;
116
- }>;
117
- export declare function getRulesMeta(): Promise<Record<string, RuleMeta>>;
118
- export declare function saveRulesMeta(meta: Record<string, RuleMeta>): Promise<boolean>;
119
- export declare function mergeRulesMeta(newMeta: Record<string, RuleMeta>): Promise<{
120
- success: boolean;
121
- total: number;
122
- }>;
123
- export declare function crossGetRulesMeta(target: string): Promise<Record<string, RuleMeta>>;
124
- export declare function getGlobalRulesMeta(): Promise<Record<string, RuleMeta>>;
125
- export declare function saveGlobalRulesMeta(meta: Record<string, RuleMeta>): Promise<boolean>;
126
- export declare function mergeGlobalRulesMeta(newMeta: Record<string, RuleMeta>): Promise<{
127
- success: boolean;
128
- total: number;
129
- }>;
130
- export declare function listTasks(_projectId: string, status?: 'active' | 'archived'): Promise<TaskSummary[]>;
131
- export declare function getTask(_projectId: string, taskId: string): Promise<Task | null>;
132
- export declare function createTask(_projectId: string, task: {
133
- title: string;
134
- description: string;
135
- goals: string[];
136
- }, creator: string): Promise<Task>;
137
- export declare function addTaskLog(_projectId: string, taskId: string, logType: TaskLogType, content: string): Promise<Task | null>;
138
- export declare function completeTask(_projectId: string, taskId: string, experience: TaskExperience): Promise<Task | null>;
139
- export declare function createProject(id: string, name: string, description?: string, projectPath?: string): Promise<{
140
- project: {
141
- id: string;
142
- name: string;
143
- };
144
- password: string;
145
- }>;
146
- export declare function crossListProjects(): Promise<{
147
- id: string;
148
- name: string;
149
- description: string;
150
- updatedAt: string;
151
- }[]>;
152
- export declare function crossGetDoc(target: string, docPath: string): Promise<DocData | null>;
153
- export declare function crossGetTree(target: string): Promise<TreeNode[]>;
154
- export declare function crossGetDocsByStatus(target: string, statusList: string[]): Promise<DocNode[]>;
155
- export declare function crossGetRules(target: string, ruleType: string): Promise<string[]>;
156
- export declare function listFiles(dir?: string): Promise<FileInfo[]>;
157
- export declare function readFile(filePath: string): Promise<string>;
158
- export declare function download(remotePath: string, localPath?: string): Promise<{
159
- localPath: string;
160
- fileCount: number;
161
- }>;
162
- export declare function crossListFiles(target: string, dir?: string): Promise<FileInfo[]>;
163
- export declare function crossReadFile(target: string, filePath: string): Promise<string>;
164
- export declare function crossDownload(target: string, remotePath: string, localPath?: string): Promise<{
165
- localPath: string;
166
- fileCount: number;
167
- }>;
168
- export declare function uploadFiles(localDir: string, remoteDir?: string): Promise<{
169
- fileCount: number;
170
- }>;
171
- export declare function clearFiles(): Promise<void>;
172
102
  export type { TreeNode };
@@ -492,131 +492,3 @@ export function getClient() {
492
492
  }
493
493
  return client;
494
494
  }
495
- // ============ 文档管理 ============
496
- export async function listDocs(_projectId) {
497
- return getClient().listDocs();
498
- }
499
- export async function getDoc(_projectId, docPath) {
500
- return getClient().getDoc(docPath);
501
- }
502
- export async function createDoc(_projectId, docPath, doc) {
503
- return getClient().createDoc(docPath, doc);
504
- }
505
- export async function updateDoc(_projectId, docPath, updates) {
506
- return getClient().updateDoc(docPath, updates);
507
- }
508
- export async function deleteDoc(_projectId, docPath) {
509
- return getClient().deleteDoc(docPath);
510
- }
511
- export async function searchDocs(_projectId, keywords, limit) {
512
- return getClient().searchDocs(keywords, limit);
513
- }
514
- export async function getDocsByStatus(_projectId, statusList) {
515
- return getClient().getDocsByStatus(statusList);
516
- }
517
- export async function getTree(_projectId) {
518
- return getClient().getTree();
519
- }
520
- // ============ 规则管理 ============
521
- export async function getRules(_projectId, ruleType) {
522
- return getClient().getRulesApi(ruleType);
523
- }
524
- export async function saveRules(_projectId, ruleType, rules) {
525
- return getClient().saveRulesApi(ruleType, rules);
526
- }
527
- export async function appendRules(_projectId, ruleType, newRules) {
528
- const existing = await getClient().getRulesApi(ruleType);
529
- const existingSet = new Set(existing.map(r => r.trim()));
530
- const toAdd = newRules.filter(r => !existingSet.has(r.trim()));
531
- const merged = [...existing, ...toAdd];
532
- const success = await getClient().saveRulesApi(ruleType, merged);
533
- return { success, total: merged.length, added: toAdd.length };
534
- }
535
- export async function getRulesMeta() {
536
- return getClient().getRulesMeta();
537
- }
538
- export async function saveRulesMeta(meta) {
539
- return getClient().saveRulesMeta(meta);
540
- }
541
- export async function mergeRulesMeta(newMeta) {
542
- const existing = await getClient().getRulesMeta();
543
- const merged = { ...existing, ...newMeta };
544
- const success = await getClient().saveRulesMeta(merged);
545
- return { success, total: Object.keys(merged).length };
546
- }
547
- export async function crossGetRulesMeta(target) {
548
- return getClient().crossGetRulesMeta(target);
549
- }
550
- export async function getGlobalRulesMeta() {
551
- return getClient().getGlobalRulesMeta();
552
- }
553
- export async function saveGlobalRulesMeta(meta) {
554
- return getClient().saveGlobalRulesMeta(meta);
555
- }
556
- export async function mergeGlobalRulesMeta(newMeta) {
557
- const existing = await getClient().getGlobalRulesMeta();
558
- const merged = { ...existing, ...newMeta };
559
- const success = await getClient().saveGlobalRulesMeta(merged);
560
- return { success, total: Object.keys(merged).length };
561
- }
562
- // ============ 任务管理 ============
563
- export async function listTasks(_projectId, status) {
564
- return getClient().listTasks(status);
565
- }
566
- export async function getTask(_projectId, taskId) {
567
- return getClient().getTask(taskId);
568
- }
569
- export async function createTask(_projectId, task, creator) {
570
- return getClient().createTask(task, creator);
571
- }
572
- export async function addTaskLog(_projectId, taskId, logType, content) {
573
- return getClient().addTaskLog(taskId, logType, content);
574
- }
575
- export async function completeTask(_projectId, taskId, experience) {
576
- return getClient().completeTask(taskId, experience);
577
- }
578
- // ============ 项目管理 ============
579
- export async function createProject(id, name, description, projectPath) {
580
- return getClient().createProject(id, name, description, projectPath);
581
- }
582
- // ============ 跨项目只读访问 ============
583
- export async function crossListProjects() {
584
- return getClient().crossListProjects();
585
- }
586
- export async function crossGetDoc(target, docPath) {
587
- return getClient().crossGetDoc(target, docPath);
588
- }
589
- export async function crossGetTree(target) {
590
- return getClient().crossGetTree(target);
591
- }
592
- export async function crossGetDocsByStatus(target, statusList) {
593
- return getClient().crossGetDocsByStatus(target, statusList);
594
- }
595
- export async function crossGetRules(target, ruleType) {
596
- return getClient().crossGetRules(target, ruleType);
597
- }
598
- // ============ 项目文件访问 ============
599
- export async function listFiles(dir) {
600
- return getClient().listFiles(dir);
601
- }
602
- export async function readFile(filePath) {
603
- return getClient().readFile(filePath);
604
- }
605
- export async function download(remotePath, localPath) {
606
- return getClient().download(remotePath, localPath);
607
- }
608
- export async function crossListFiles(target, dir) {
609
- return getClient().crossListFiles(target, dir);
610
- }
611
- export async function crossReadFile(target, filePath) {
612
- return getClient().crossReadFile(target, filePath);
613
- }
614
- export async function crossDownload(target, remotePath, localPath) {
615
- return getClient().crossDownload(target, remotePath, localPath);
616
- }
617
- export async function uploadFiles(localDir, remoteDir) {
618
- return getClient().uploadFiles(localDir, remoteDir);
619
- }
620
- export async function clearFiles() {
621
- return getClient().clearFiles();
622
- }
@@ -0,0 +1,7 @@
1
+ /**
2
+ * 文档管理工具 (7个)
3
+ * kg_create_node, kg_delete_node, kg_update_node, kg_read_node,
4
+ * kg_get_tree, kg_get_docs_by_status, kg_copy_node
5
+ */
6
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
7
+ export declare function registerDocTools(server: McpServer, projectId: string): void;