@ppdocs/mcp 3.2.18 → 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.
Files changed (2) hide show
  1. package/dist/cli.js +52 -39
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -89,10 +89,12 @@ function showHelp() {
89
89
  ppdocs MCP CLI
90
90
 
91
91
  Commands:
92
- init Initialize ppdocs config + install workflow templates
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 init -p myproject -k abc123xyz --codex
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
- await initProject(opts);
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; // Not a CLI command, run as MCP server
135
+ return false;
131
136
  }
132
- async function initProject(opts) {
133
- const cwd = process.cwd();
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
- if (fs.existsSync(ppdocsPath)) {
145
- const stat = fs.statSync(ppdocsPath);
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(ppdocsConfig, null, 2));
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;
@@ -179,7 +185,7 @@ async function initProject(opts) {
179
185
  }
180
186
  }
181
187
  // 自动检测并注册 MCP (如果已写入 Antigravity 配置,跳过 gemini CLI 注册避免冲突)
182
- const registered = autoRegisterMcp(apiUrl, opts.user, detectedIdes.includes('antigravity'));
188
+ const registered = autoRegisterMcp(detectedIdes.includes('antigravity'));
183
189
  // 如果没有检测到任何 AI CLI,并且也没有检测到配置文件夹,创建 .mcp.json 作为备用
184
190
  if (!registered && !hasIdeDir) {
185
191
  createMcpJson(cwd, apiUrl, opts.user);
@@ -276,31 +282,39 @@ function execSilent(cmd) {
276
282
  }
277
283
  catch { /* ignore */ }
278
284
  }
279
- /** 自动检测 AI CLI 并注册 MCP (注入环境变量实现启动即就绪) */
280
- function autoRegisterMcp(apiUrl, user, skipGemini = false) {
285
+ /** 自动检测 AI CLI 并注册全局 MCP (不注入 env,支持多项目通过 kg_init 切换) */
286
+ function autoRegisterMcp(skipGemini = false) {
281
287
  const detected = [];
282
288
  const serverName = 'ppdocs-kg';
283
- const envFlags = `-e PPDOCS_API_URL=${apiUrl} -e PPDOCS_USER=${user}`;
284
- // Claude CLI
289
+ const addCmd = `-- npx -y @ppdocs/mcp@latest`;
290
+ // Claude CLI (幂等:已注册则跳过)
285
291
  if (commandExists('claude')) {
286
292
  detected.push('Claude');
287
293
  try {
288
- console.log(`✅ Detected Claude CLI, registering MCP...`);
289
- // 先移除旧配置(可能无 env),再重新注册
290
- execSilent(`claude mcp remove ${serverName}`);
291
- execSync(`claude mcp add ${serverName} ${envFlags} -- npx -y @ppdocs/mcp@latest`, { stdio: 'inherit' });
294
+ const list = execSync(`claude mcp list`, { encoding: 'utf-8' });
295
+ if (list.includes(serverName)) {
296
+ console.log(`✅ Claude MCP already configured`);
297
+ }
298
+ else {
299
+ execSync(`claude mcp add ${serverName} ${addCmd}`, { stdio: 'inherit' });
300
+ }
292
301
  }
293
302
  catch {
294
- console.log(`⚠️ Claude MCP registration failed`);
303
+ try {
304
+ execSilent(`claude mcp remove ${serverName}`);
305
+ execSync(`claude mcp add ${serverName} ${addCmd}`, { stdio: 'inherit' });
306
+ }
307
+ catch {
308
+ console.log(`⚠️ Claude MCP registration failed`);
309
+ }
295
310
  }
296
311
  }
297
- // Codex CLI (OpenAI)
312
+ // Codex CLI
298
313
  if (commandExists('codex')) {
299
314
  detected.push('Codex');
300
315
  try {
301
- console.log(`✅ Detected Codex CLI, registering MCP...`);
302
316
  execSilent(`codex mcp remove ${serverName}`);
303
- execSync(`codex mcp add ${serverName} ${envFlags} -- npx -y @ppdocs/mcp@latest`, { stdio: 'inherit' });
317
+ execSync(`codex mcp add ${serverName} ${addCmd}`, { stdio: 'inherit' });
304
318
  }
305
319
  catch {
306
320
  console.log(`⚠️ Codex MCP registration failed`);
@@ -310,7 +324,6 @@ function autoRegisterMcp(apiUrl, user, skipGemini = false) {
310
324
  if (commandExists('gemini') && !skipGemini) {
311
325
  detected.push('Gemini');
312
326
  try {
313
- console.log(`✅ Detected Gemini CLI, registering MCP...`);
314
327
  execSilent(`gemini mcp remove ${serverName}`);
315
328
  execSync(`gemini mcp add ${serverName} "npx -y @ppdocs/mcp@latest"`, { stdio: 'inherit' });
316
329
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ppdocs/mcp",
3
- "version": "3.2.18",
3
+ "version": "3.2.19",
4
4
  "description": "ppdocs MCP Server - Knowledge Graph for Claude",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",