@ppdocs/mcp 3.2.17 → 3.2.19
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 +1 -1
- package/dist/cli.js +79 -85
- package/package.json +1 -1
package/dist/cli.d.ts
CHANGED
|
@@ -4,4 +4,4 @@
|
|
|
4
4
|
*/
|
|
5
5
|
export declare function runCli(args: string[]): Promise<boolean>;
|
|
6
6
|
/** 安装项目模板文件 (供授权后自动配置调用) */
|
|
7
|
-
export declare function setupProjectFiles(cwd: string, apiUrl: string): void;
|
|
7
|
+
export declare function setupProjectFiles(cwd: string, apiUrl: string, user?: string): void;
|
package/dist/cli.js
CHANGED
|
@@ -89,10 +89,12 @@ function showHelp() {
|
|
|
89
89
|
ppdocs MCP CLI
|
|
90
90
|
|
|
91
91
|
Commands:
|
|
92
|
-
init
|
|
92
|
+
init Full setup: .ppdocs + templates + MCP registration
|
|
93
|
+
bind Lightweight: only create .ppdocs (for adding projects to existing MCP)
|
|
93
94
|
|
|
94
95
|
Usage:
|
|
95
96
|
npx @ppdocs/mcp init -p <projectId> -k <key> [options]
|
|
97
|
+
npx @ppdocs/mcp bind -p <projectId> -k <key> [options]
|
|
96
98
|
|
|
97
99
|
Options:
|
|
98
100
|
-p, --project Project ID (required)
|
|
@@ -105,51 +107,55 @@ Options:
|
|
|
105
107
|
--sync <id> Sync knowledge base docs from a source project to ./docs/ppdocs/
|
|
106
108
|
|
|
107
109
|
Example:
|
|
108
|
-
npx @ppdocs/mcp init -p myproject -k abc123xyz
|
|
109
|
-
npx @ppdocs/mcp
|
|
110
|
-
npx @ppdocs/mcp init -p myproject -k abc123xyz --from _templates
|
|
111
|
-
npx @ppdocs/mcp init -p myproject -k abc123xyz --sync shared-rules
|
|
110
|
+
npx @ppdocs/mcp init -p myproject -k abc123xyz --api 192.168.1.100
|
|
111
|
+
npx @ppdocs/mcp bind -p myproject -k abc123xyz --api 192.168.1.100
|
|
112
112
|
`);
|
|
113
113
|
}
|
|
114
114
|
export async function runCli(args) {
|
|
115
115
|
const cmd = args[0];
|
|
116
|
-
if (cmd === 'init') {
|
|
116
|
+
if (cmd === 'init' || cmd === 'bind') {
|
|
117
117
|
const opts = parseArgs(args.slice(1));
|
|
118
118
|
if (!opts) {
|
|
119
119
|
console.error('Error: -p (project) and -k (key) are required\n');
|
|
120
120
|
showHelp();
|
|
121
121
|
process.exit(1);
|
|
122
122
|
}
|
|
123
|
-
|
|
123
|
+
if (cmd === 'bind') {
|
|
124
|
+
bindProject(opts);
|
|
125
|
+
}
|
|
126
|
+
else {
|
|
127
|
+
await initProject(opts);
|
|
128
|
+
}
|
|
124
129
|
return true;
|
|
125
130
|
}
|
|
126
131
|
if (cmd === '--help' || cmd === '-h' || cmd === 'help') {
|
|
127
132
|
showHelp();
|
|
128
133
|
return true;
|
|
129
134
|
}
|
|
130
|
-
return false;
|
|
135
|
+
return false;
|
|
131
136
|
}
|
|
132
|
-
|
|
133
|
-
|
|
137
|
+
/** 轻量绑定: 仅创建 .ppdocs, 不注册 MCP 不安装模板 */
|
|
138
|
+
function bindProject(opts) {
|
|
139
|
+
writePpdocsConfig(process.cwd(), opts);
|
|
140
|
+
console.log(`\n🔗 Project bound: ${opts.project}\n AI will auto-connect via kg_init when opening this directory.\n`);
|
|
141
|
+
}
|
|
142
|
+
/** 写入 .ppdocs 配置文件 (init + bind 复用) */
|
|
143
|
+
function writePpdocsConfig(cwd, opts) {
|
|
134
144
|
const apiUrl = `http://${opts.api}:${opts.port}/api/${opts.project}/${opts.key}`;
|
|
135
|
-
// Create .ppdocs config
|
|
136
|
-
const ppdocsConfig = {
|
|
137
|
-
api: `http://${opts.api}:${opts.port}`,
|
|
138
|
-
projectId: opts.project,
|
|
139
|
-
key: opts.key,
|
|
140
|
-
user: opts.user,
|
|
141
|
-
};
|
|
142
145
|
const ppdocsPath = path.join(cwd, '.ppdocs');
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
if (stat.isDirectory()) {
|
|
147
|
-
fs.rmSync(ppdocsPath, { recursive: true });
|
|
148
|
-
console.log(`⚠️ Removed existing .ppdocs directory`);
|
|
149
|
-
}
|
|
146
|
+
if (fs.existsSync(ppdocsPath) && fs.statSync(ppdocsPath).isDirectory()) {
|
|
147
|
+
fs.rmSync(ppdocsPath, { recursive: true });
|
|
148
|
+
console.log(`⚠️ Removed existing .ppdocs directory`);
|
|
150
149
|
}
|
|
151
|
-
fs.writeFileSync(ppdocsPath, JSON.stringify(
|
|
150
|
+
fs.writeFileSync(ppdocsPath, JSON.stringify({
|
|
151
|
+
api: `http://${opts.api}:${opts.port}`, projectId: opts.project, key: opts.key, user: opts.user,
|
|
152
|
+
}, null, 2));
|
|
152
153
|
console.log(`✅ Created ${ppdocsPath}`);
|
|
154
|
+
return apiUrl;
|
|
155
|
+
}
|
|
156
|
+
async function initProject(opts) {
|
|
157
|
+
const cwd = process.cwd();
|
|
158
|
+
const apiUrl = writePpdocsConfig(cwd, opts);
|
|
153
159
|
// Install workflow templates based on IDE detection
|
|
154
160
|
const detectedIdes = detectIDEs(cwd);
|
|
155
161
|
let hasIdeDir = false;
|
|
@@ -158,15 +164,15 @@ async function initProject(opts) {
|
|
|
158
164
|
hasIdeDir = true;
|
|
159
165
|
}
|
|
160
166
|
if (detectedIdes.includes('cursor')) {
|
|
161
|
-
installCursorTemplates(cwd, apiUrl);
|
|
167
|
+
installCursorTemplates(cwd, apiUrl, opts.user);
|
|
162
168
|
hasIdeDir = true;
|
|
163
169
|
}
|
|
164
170
|
if (detectedIdes.includes('antigravity')) {
|
|
165
|
-
installAntigravityTemplates(cwd, apiUrl);
|
|
171
|
+
installAntigravityTemplates(cwd, apiUrl, opts.user);
|
|
166
172
|
hasIdeDir = true;
|
|
167
173
|
}
|
|
168
174
|
if (detectedIdes.includes('kiro')) {
|
|
169
|
-
installKiroTemplates(cwd, apiUrl);
|
|
175
|
+
installKiroTemplates(cwd, apiUrl, opts.user);
|
|
170
176
|
hasIdeDir = true;
|
|
171
177
|
}
|
|
172
178
|
// Fallback behavior: if no specific IDE config directories found
|
|
@@ -179,10 +185,10 @@ async function initProject(opts) {
|
|
|
179
185
|
}
|
|
180
186
|
}
|
|
181
187
|
// 自动检测并注册 MCP (如果已写入 Antigravity 配置,跳过 gemini CLI 注册避免冲突)
|
|
182
|
-
const registered = autoRegisterMcp(
|
|
188
|
+
const registered = autoRegisterMcp(detectedIdes.includes('antigravity'));
|
|
183
189
|
// 如果没有检测到任何 AI CLI,并且也没有检测到配置文件夹,创建 .mcp.json 作为备用
|
|
184
190
|
if (!registered && !hasIdeDir) {
|
|
185
|
-
createMcpJson(cwd, apiUrl);
|
|
191
|
+
createMcpJson(cwd, apiUrl, opts.user);
|
|
186
192
|
}
|
|
187
193
|
// --from: 从模板项目拉取 IDE 配置文件
|
|
188
194
|
if (opts.from) {
|
|
@@ -276,61 +282,53 @@ function execSilent(cmd) {
|
|
|
276
282
|
}
|
|
277
283
|
catch { /* ignore */ }
|
|
278
284
|
}
|
|
279
|
-
/** 自动检测 AI CLI
|
|
280
|
-
function autoRegisterMcp(
|
|
285
|
+
/** 自动检测 AI CLI 并注册全局 MCP (不注入 env,支持多项目通过 kg_init 切换) */
|
|
286
|
+
function autoRegisterMcp(skipGemini = false) {
|
|
281
287
|
const detected = [];
|
|
282
288
|
const serverName = 'ppdocs-kg';
|
|
283
|
-
|
|
289
|
+
const addCmd = `-- npx -y @ppdocs/mcp@latest`;
|
|
290
|
+
// Claude CLI (幂等:已注册则跳过)
|
|
284
291
|
if (commandExists('claude')) {
|
|
285
292
|
detected.push('Claude');
|
|
286
293
|
try {
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
const checkResult = execSync(`claude mcp list`, { encoding: 'utf-8' });
|
|
290
|
-
if (checkResult.includes(serverName)) {
|
|
294
|
+
const list = execSync(`claude mcp list`, { encoding: 'utf-8' });
|
|
295
|
+
if (list.includes(serverName)) {
|
|
291
296
|
console.log(`✅ Claude MCP already configured`);
|
|
292
297
|
}
|
|
293
298
|
else {
|
|
294
|
-
|
|
295
|
-
execSync(cmd, { stdio: 'inherit' });
|
|
299
|
+
execSync(`claude mcp add ${serverName} ${addCmd}`, { stdio: 'inherit' });
|
|
296
300
|
}
|
|
297
301
|
}
|
|
298
|
-
catch
|
|
299
|
-
// 如果 list 失败,尝试添加
|
|
302
|
+
catch {
|
|
300
303
|
try {
|
|
301
304
|
execSilent(`claude mcp remove ${serverName}`);
|
|
302
|
-
|
|
303
|
-
execSync(cmd, { stdio: 'inherit' });
|
|
305
|
+
execSync(`claude mcp add ${serverName} ${addCmd}`, { stdio: 'inherit' });
|
|
304
306
|
}
|
|
305
307
|
catch {
|
|
306
308
|
console.log(`⚠️ Claude MCP registration failed`);
|
|
307
309
|
}
|
|
308
310
|
}
|
|
309
311
|
}
|
|
310
|
-
//
|
|
312
|
+
// Codex CLI
|
|
311
313
|
if (commandExists('codex')) {
|
|
312
314
|
detected.push('Codex');
|
|
313
315
|
try {
|
|
314
|
-
console.log(`✅ Detected Codex CLI, registering MCP...`);
|
|
315
316
|
execSilent(`codex mcp remove ${serverName}`);
|
|
316
|
-
|
|
317
|
-
execSync(cmd, { stdio: 'inherit' });
|
|
317
|
+
execSync(`codex mcp add ${serverName} ${addCmd}`, { stdio: 'inherit' });
|
|
318
318
|
}
|
|
319
|
-
catch
|
|
320
|
-
console.log(`⚠️ Codex MCP registration failed
|
|
319
|
+
catch {
|
|
320
|
+
console.log(`⚠️ Codex MCP registration failed`);
|
|
321
321
|
}
|
|
322
322
|
}
|
|
323
|
-
//
|
|
323
|
+
// Gemini CLI
|
|
324
324
|
if (commandExists('gemini') && !skipGemini) {
|
|
325
325
|
detected.push('Gemini');
|
|
326
326
|
try {
|
|
327
|
-
console.log(`✅ Detected Gemini CLI, registering MCP...`);
|
|
328
327
|
execSilent(`gemini mcp remove ${serverName}`);
|
|
329
|
-
|
|
330
|
-
execSync(cmd, { stdio: 'inherit' });
|
|
328
|
+
execSync(`gemini mcp add ${serverName} "npx -y @ppdocs/mcp@latest"`, { stdio: 'inherit' });
|
|
331
329
|
}
|
|
332
|
-
catch
|
|
333
|
-
console.log(`⚠️ Gemini MCP registration failed
|
|
330
|
+
catch {
|
|
331
|
+
console.log(`⚠️ Gemini MCP registration failed`);
|
|
334
332
|
}
|
|
335
333
|
}
|
|
336
334
|
if (detected.length === 0) {
|
|
@@ -340,34 +338,33 @@ function autoRegisterMcp(apiUrl, user, skipGemini = false) {
|
|
|
340
338
|
console.log(`✅ Registered MCP for: ${detected.join(', ')}`);
|
|
341
339
|
return true;
|
|
342
340
|
}
|
|
343
|
-
/** 在指定路径创建或更新 mcp.json
|
|
344
|
-
function createMcpConfigAt(mcpPath,
|
|
341
|
+
/** 在指定路径创建或更新 mcp.json 配置,注入 PPDOCS_API_URL 环境变量实现启动即就绪 */
|
|
342
|
+
function createMcpConfigAt(mcpPath, apiUrl, options) {
|
|
345
343
|
let mcpConfig = {};
|
|
346
344
|
if (fs.existsSync(mcpPath)) {
|
|
347
345
|
try {
|
|
348
346
|
mcpConfig = JSON.parse(fs.readFileSync(mcpPath, 'utf-8'));
|
|
349
347
|
}
|
|
350
348
|
catch {
|
|
351
|
-
// 解析失败时中止,避免清空已有配置
|
|
352
349
|
console.log(`⚠️ ${mcpPath} JSON格式无效,跳过MCP配置写入(请手动修复后重试)`);
|
|
353
350
|
return;
|
|
354
351
|
}
|
|
355
352
|
}
|
|
356
|
-
// Windows 需要 cmd /c 包装才能执行 npx
|
|
357
353
|
const isWindows = process.platform === 'win32';
|
|
358
|
-
// 对于 Mac/Linux,IDE 可能没有用户的完整 PATH,导致找不到 npx
|
|
359
354
|
const macExtraPaths = '/usr/local/bin:/opt/homebrew/bin:/home/linuxbrew/.linuxbrew/bin';
|
|
360
355
|
const actualPath = `${process.env.PATH || '/usr/bin:/bin'}:${macExtraPaths}`;
|
|
356
|
+
// 构建 env: 非 Windows 补 PATH + 注入项目绑定变量
|
|
357
|
+
const env = {};
|
|
358
|
+
if (!isWindows)
|
|
359
|
+
env.PATH = actualPath;
|
|
360
|
+
if (!options?.noEnv) {
|
|
361
|
+
env.PPDOCS_API_URL = apiUrl;
|
|
362
|
+
if (options?.user)
|
|
363
|
+
env.PPDOCS_USER = options.user;
|
|
364
|
+
}
|
|
361
365
|
const ppdocsServer = isWindows
|
|
362
|
-
? {
|
|
363
|
-
|
|
364
|
-
args: ['/c', 'npx', '-y', '@ppdocs/mcp@latest'],
|
|
365
|
-
}
|
|
366
|
-
: {
|
|
367
|
-
command: 'npx',
|
|
368
|
-
args: ['-y', '@ppdocs/mcp@latest'],
|
|
369
|
-
env: { "PATH": actualPath }
|
|
370
|
-
};
|
|
366
|
+
? { command: 'cmd', args: ['/c', 'npx', '-y', '@ppdocs/mcp@latest'], ...(Object.keys(env).length > 0 && { env }) }
|
|
367
|
+
: { command: 'npx', args: ['-y', '@ppdocs/mcp@latest'], env };
|
|
371
368
|
mcpConfig.mcpServers = {
|
|
372
369
|
...(mcpConfig.mcpServers || {}),
|
|
373
370
|
"ppdocs-kg": ppdocsServer,
|
|
@@ -381,8 +378,8 @@ function createMcpConfigAt(mcpPath, _apiUrl, _options) {
|
|
|
381
378
|
console.log(`✅ Configured MCP in ${mcpPath}`);
|
|
382
379
|
}
|
|
383
380
|
/** 创建 .mcp.json (手动配置备用) */
|
|
384
|
-
function createMcpJson(cwd, apiUrl) {
|
|
385
|
-
createMcpConfigAt(path.join(cwd, '.mcp.json'), apiUrl);
|
|
381
|
+
function createMcpJson(cwd, apiUrl, user) {
|
|
382
|
+
createMcpConfigAt(path.join(cwd, '.mcp.json'), apiUrl, { user });
|
|
386
383
|
}
|
|
387
384
|
/** 递归复制目录 */
|
|
388
385
|
function copyDirRecursive(src, dest) {
|
|
@@ -505,9 +502,8 @@ function generateAgentsMd(cwd) {
|
|
|
505
502
|
}
|
|
506
503
|
}
|
|
507
504
|
/** 安装 Cursor 模板 */
|
|
508
|
-
function installCursorTemplates(cwd, apiUrl) {
|
|
509
|
-
|
|
510
|
-
createMcpConfigAt(path.join(cwd, '.cursor', 'mcp.json'), apiUrl);
|
|
505
|
+
function installCursorTemplates(cwd, apiUrl, user) {
|
|
506
|
+
createMcpConfigAt(path.join(cwd, '.cursor', 'mcp.json'), apiUrl, { user });
|
|
511
507
|
// 2. 生成 .cursorrules 提示词
|
|
512
508
|
const srcRules = path.join(TEMPLATES_DIR, 'cursorrules.md');
|
|
513
509
|
const destRules = path.join(cwd, '.cursorrules');
|
|
@@ -517,9 +513,9 @@ function installCursorTemplates(cwd, apiUrl) {
|
|
|
517
513
|
}
|
|
518
514
|
}
|
|
519
515
|
/** 安装 Antigravity (Gemini IDE) 模板 */
|
|
520
|
-
function installAntigravityTemplates(cwd, apiUrl) {
|
|
521
|
-
//
|
|
522
|
-
createMcpConfigAt(path.join(cwd, '.gemini', 'settings.json'), apiUrl, { noEnv: true });
|
|
516
|
+
function installAntigravityTemplates(cwd, apiUrl, user) {
|
|
517
|
+
// Antigravity 由 gemini CLI 注册 env,文件配置不注入避免冲突
|
|
518
|
+
createMcpConfigAt(path.join(cwd, '.gemini', 'settings.json'), apiUrl, { noEnv: true, user });
|
|
523
519
|
// 2. 生成 AGENTS.md
|
|
524
520
|
generateAgentsMd(cwd);
|
|
525
521
|
// 3. 安装斜杠命令 → 全局目录 ~/.gemini/antigravity/global_workflows/
|
|
@@ -575,9 +571,8 @@ function installAntigravityTemplates(cwd, apiUrl) {
|
|
|
575
571
|
}
|
|
576
572
|
}
|
|
577
573
|
/** 安装 Kiro 模板 */
|
|
578
|
-
function installKiroTemplates(cwd, apiUrl) {
|
|
579
|
-
|
|
580
|
-
createMcpConfigAt(path.join(cwd, '.kiro', 'settings', 'mcp.json'), apiUrl);
|
|
574
|
+
function installKiroTemplates(cwd, apiUrl, user) {
|
|
575
|
+
createMcpConfigAt(path.join(cwd, '.kiro', 'settings', 'mcp.json'), apiUrl, { user });
|
|
581
576
|
// 2. 生成 Kiro Agent 规则
|
|
582
577
|
const kiroRulesDir = path.join(cwd, '.kiro', 'rules');
|
|
583
578
|
if (!fs.existsSync(kiroRulesDir)) {
|
|
@@ -604,21 +599,20 @@ function detectIDEs(cwd) {
|
|
|
604
599
|
return ides;
|
|
605
600
|
}
|
|
606
601
|
/** 安装项目模板文件 (供授权后自动配置调用) */
|
|
607
|
-
export function setupProjectFiles(cwd, apiUrl) {
|
|
602
|
+
export function setupProjectFiles(cwd, apiUrl, user) {
|
|
608
603
|
const detectedIdes = detectIDEs(cwd);
|
|
609
604
|
if (detectedIdes.includes('antigravity')) {
|
|
610
|
-
installAntigravityTemplates(cwd, apiUrl);
|
|
605
|
+
installAntigravityTemplates(cwd, apiUrl, user);
|
|
611
606
|
}
|
|
612
607
|
if (detectedIdes.includes('cursor')) {
|
|
613
|
-
installCursorTemplates(cwd, apiUrl);
|
|
608
|
+
installCursorTemplates(cwd, apiUrl, user);
|
|
614
609
|
}
|
|
615
610
|
if (detectedIdes.includes('kiro')) {
|
|
616
|
-
installKiroTemplates(cwd, apiUrl);
|
|
611
|
+
installKiroTemplates(cwd, apiUrl, user);
|
|
617
612
|
}
|
|
618
613
|
if (detectedIdes.includes('claude')) {
|
|
619
614
|
installClaudeTemplates(cwd);
|
|
620
615
|
}
|
|
621
|
-
// 如果没检测到任何 IDE,默认安装 Claude 模板
|
|
622
616
|
if (detectedIdes.length === 0) {
|
|
623
617
|
installClaudeTemplates(cwd);
|
|
624
618
|
}
|