@ppdocs/mcp 2.5.1 → 2.6.0
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 +120 -37
- package/package.json +1 -1
- package/templates/settings-hooks.json +1 -1
package/dist/cli.d.ts
CHANGED
package/dist/cli.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* ppdocs MCP CLI
|
|
3
|
-
* 命令: init - 初始化项目配置 + 安装工作流模板
|
|
3
|
+
* 命令: init - 初始化项目配置 + 安装工作流模板 + 自动注册 MCP
|
|
4
4
|
*/
|
|
5
5
|
import * as fs from 'fs';
|
|
6
6
|
import * as path from 'path';
|
|
7
7
|
import { fileURLToPath } from 'url';
|
|
8
|
+
import { execSync } from 'child_process';
|
|
8
9
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
9
10
|
const TEMPLATES_DIR = path.join(__dirname, '..', 'templates');
|
|
10
11
|
/** 生成随机用户名 (8位字母数字) */
|
|
@@ -84,6 +85,7 @@ export function runCli(args) {
|
|
|
84
85
|
}
|
|
85
86
|
function initProject(opts) {
|
|
86
87
|
const cwd = process.cwd();
|
|
88
|
+
const apiUrl = `http://${opts.api}:${opts.port}/api/${opts.project}/${opts.key}`;
|
|
87
89
|
// Create .ppdocs config
|
|
88
90
|
const ppdocsConfig = {
|
|
89
91
|
api: `http://${opts.api}:${opts.port}`,
|
|
@@ -94,7 +96,85 @@ function initProject(opts) {
|
|
|
94
96
|
const ppdocsPath = path.join(cwd, '.ppdocs');
|
|
95
97
|
fs.writeFileSync(ppdocsPath, JSON.stringify(ppdocsConfig, null, 2));
|
|
96
98
|
console.log(`✅ Created ${ppdocsPath}`);
|
|
97
|
-
//
|
|
99
|
+
// Install workflow templates
|
|
100
|
+
if (opts.codex) {
|
|
101
|
+
installCodexTemplates(cwd);
|
|
102
|
+
}
|
|
103
|
+
else {
|
|
104
|
+
installClaudeTemplates(cwd);
|
|
105
|
+
}
|
|
106
|
+
// 自动检测并注册 MCP
|
|
107
|
+
const registered = autoRegisterMcp(apiUrl, opts.user);
|
|
108
|
+
// 如果没有检测到任何 AI CLI,创建 .mcp.json 作为备用
|
|
109
|
+
if (!registered) {
|
|
110
|
+
createMcpJson(cwd);
|
|
111
|
+
}
|
|
112
|
+
console.log(`
|
|
113
|
+
🎉 Done! ppdocs MCP configured for project: ${opts.project}
|
|
114
|
+
User: ${opts.user}
|
|
115
|
+
|
|
116
|
+
Restart your AI tool to use ppdocs knowledge graph.
|
|
117
|
+
`);
|
|
118
|
+
}
|
|
119
|
+
/** 检测命令是否存在 */
|
|
120
|
+
function commandExists(cmd) {
|
|
121
|
+
try {
|
|
122
|
+
const checkCmd = process.platform === 'win32' ? `where ${cmd}` : `which ${cmd}`;
|
|
123
|
+
execSync(checkCmd, { stdio: 'ignore' });
|
|
124
|
+
return true;
|
|
125
|
+
}
|
|
126
|
+
catch {
|
|
127
|
+
return false;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
/** 自动检测 AI CLI 并注册 MCP */
|
|
131
|
+
function autoRegisterMcp(apiUrl, user) {
|
|
132
|
+
const detected = [];
|
|
133
|
+
// 检测 Claude CLI
|
|
134
|
+
if (commandExists('claude')) {
|
|
135
|
+
detected.push('Claude');
|
|
136
|
+
try {
|
|
137
|
+
const cmd = `claude mcp add ppdocs-kg -e PPDOCS_API_URL=${apiUrl} -e PPDOCS_USER=${user} -- npx -y @ppdocs/mcp`;
|
|
138
|
+
console.log(`✅ Detected Claude CLI, registering MCP...`);
|
|
139
|
+
execSync(cmd, { stdio: 'inherit' });
|
|
140
|
+
}
|
|
141
|
+
catch (e) {
|
|
142
|
+
console.log(`⚠️ Claude MCP registration failed: ${e}`);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
// 检测 Codex CLI (OpenAI)
|
|
146
|
+
if (commandExists('codex')) {
|
|
147
|
+
detected.push('Codex');
|
|
148
|
+
try {
|
|
149
|
+
const cmd = `codex mcp add ppdocs-kg -e PPDOCS_API_URL=${apiUrl} -e PPDOCS_USER=${user} -- npx -y @ppdocs/mcp`;
|
|
150
|
+
console.log(`✅ Detected Codex CLI, registering MCP...`);
|
|
151
|
+
execSync(cmd, { stdio: 'inherit' });
|
|
152
|
+
}
|
|
153
|
+
catch (e) {
|
|
154
|
+
console.log(`⚠️ Codex MCP registration failed: ${e}`);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
// 检测 Gemini CLI
|
|
158
|
+
if (commandExists('gemini')) {
|
|
159
|
+
detected.push('Gemini');
|
|
160
|
+
try {
|
|
161
|
+
const cmd = `gemini mcp add ppdocs-kg -e PPDOCS_API_URL=${apiUrl} -e PPDOCS_USER=${user} -- npx -y @ppdocs/mcp`;
|
|
162
|
+
console.log(`✅ Detected Gemini CLI, registering MCP...`);
|
|
163
|
+
execSync(cmd, { stdio: 'inherit' });
|
|
164
|
+
}
|
|
165
|
+
catch (e) {
|
|
166
|
+
console.log(`⚠️ Gemini MCP registration failed: ${e}`);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
if (detected.length === 0) {
|
|
170
|
+
console.log(`ℹ️ No AI CLI detected (claude/codex/gemini), creating .mcp.json for manual config`);
|
|
171
|
+
return false;
|
|
172
|
+
}
|
|
173
|
+
console.log(`✅ Registered MCP for: ${detected.join(', ')}`);
|
|
174
|
+
return true;
|
|
175
|
+
}
|
|
176
|
+
/** 创建 .mcp.json (手动配置备用) */
|
|
177
|
+
function createMcpJson(cwd) {
|
|
98
178
|
const mcpPath = path.join(cwd, '.mcp.json');
|
|
99
179
|
let mcpConfig = {};
|
|
100
180
|
if (fs.existsSync(mcpPath)) {
|
|
@@ -105,28 +185,17 @@ function initProject(opts) {
|
|
|
105
185
|
// ignore parse error
|
|
106
186
|
}
|
|
107
187
|
}
|
|
188
|
+
// Windows 需要 cmd /c 包装才能执行 npx
|
|
189
|
+
const isWindows = process.platform === 'win32';
|
|
190
|
+
const ppdocsServer = isWindows
|
|
191
|
+
? { command: 'cmd', args: ['/c', 'npx', '@ppdocs/mcp'] }
|
|
192
|
+
: { command: 'npx', args: ['@ppdocs/mcp'] };
|
|
108
193
|
mcpConfig.mcpServers = {
|
|
109
194
|
...(mcpConfig.mcpServers || {}),
|
|
110
|
-
ppdocs:
|
|
111
|
-
command: 'npx',
|
|
112
|
-
args: ['@ppdocs/mcp'],
|
|
113
|
-
},
|
|
195
|
+
ppdocs: ppdocsServer,
|
|
114
196
|
};
|
|
115
197
|
fs.writeFileSync(mcpPath, JSON.stringify(mcpConfig, null, 2));
|
|
116
198
|
console.log(`✅ Created ${mcpPath}`);
|
|
117
|
-
// Install workflow templates
|
|
118
|
-
if (opts.codex) {
|
|
119
|
-
installCodexTemplates(cwd);
|
|
120
|
-
}
|
|
121
|
-
else {
|
|
122
|
-
installClaudeTemplates(cwd);
|
|
123
|
-
}
|
|
124
|
-
console.log(`
|
|
125
|
-
🎉 Done! ppdocs MCP configured for project: ${opts.project}
|
|
126
|
-
User: ${opts.user}
|
|
127
|
-
|
|
128
|
-
Restart Claude Code to use ppdocs knowledge graph.
|
|
129
|
-
`);
|
|
130
199
|
}
|
|
131
200
|
/** 递归复制目录 */
|
|
132
201
|
function copyDirRecursive(src, dest) {
|
|
@@ -144,6 +213,23 @@ function copyDirRecursive(src, dest) {
|
|
|
144
213
|
}
|
|
145
214
|
}
|
|
146
215
|
}
|
|
216
|
+
/** 生成跨平台的 hooks 配置 */
|
|
217
|
+
function generateHooksConfig() {
|
|
218
|
+
const isWindows = process.platform === 'win32';
|
|
219
|
+
const command = isWindows
|
|
220
|
+
? 'type ".claude\\hooks\\SystemPrompt.md"'
|
|
221
|
+
: 'cat ".claude/hooks/SystemPrompt.md"';
|
|
222
|
+
return {
|
|
223
|
+
hooks: {
|
|
224
|
+
UserPromptSubmit: [
|
|
225
|
+
{
|
|
226
|
+
matcher: '*',
|
|
227
|
+
hooks: [{ type: 'command', command }]
|
|
228
|
+
}
|
|
229
|
+
]
|
|
230
|
+
}
|
|
231
|
+
};
|
|
232
|
+
}
|
|
147
233
|
/** 安装 Claude Code 模板 */
|
|
148
234
|
function installClaudeTemplates(cwd) {
|
|
149
235
|
const claudeDir = path.join(cwd, '.claude');
|
|
@@ -161,26 +247,23 @@ function installClaudeTemplates(cwd) {
|
|
|
161
247
|
copyDirRecursive(srcHooks, destHooks);
|
|
162
248
|
console.log(`✅ Installed .claude/hooks/`);
|
|
163
249
|
}
|
|
164
|
-
// 3.
|
|
165
|
-
const settingsHooksPath = path.join(TEMPLATES_DIR, 'settings-hooks.json');
|
|
250
|
+
// 3. 生成跨平台 hooks 配置并合并到 settings.local.json
|
|
166
251
|
const settingsLocalPath = path.join(claudeDir, 'settings.local.json');
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
catch { /* ignore */ }
|
|
174
|
-
}
|
|
175
|
-
const hooksConfig = JSON.parse(fs.readFileSync(settingsHooksPath, 'utf-8'));
|
|
176
|
-
const mergedSettings = {
|
|
177
|
-
...existingSettings,
|
|
178
|
-
hooks: hooksConfig.hooks
|
|
179
|
-
};
|
|
180
|
-
fs.mkdirSync(claudeDir, { recursive: true });
|
|
181
|
-
fs.writeFileSync(settingsLocalPath, JSON.stringify(mergedSettings, null, 2));
|
|
182
|
-
console.log(`✅ Configured .claude/settings.local.json hooks`);
|
|
252
|
+
let existingSettings = {};
|
|
253
|
+
if (fs.existsSync(settingsLocalPath)) {
|
|
254
|
+
try {
|
|
255
|
+
existingSettings = JSON.parse(fs.readFileSync(settingsLocalPath, 'utf-8'));
|
|
256
|
+
}
|
|
257
|
+
catch { /* ignore */ }
|
|
183
258
|
}
|
|
259
|
+
const hooksConfig = generateHooksConfig();
|
|
260
|
+
const mergedSettings = {
|
|
261
|
+
...existingSettings,
|
|
262
|
+
...hooksConfig
|
|
263
|
+
};
|
|
264
|
+
fs.mkdirSync(claudeDir, { recursive: true });
|
|
265
|
+
fs.writeFileSync(settingsLocalPath, JSON.stringify(mergedSettings, null, 2));
|
|
266
|
+
console.log(`✅ Configured .claude/settings.local.json hooks (${process.platform})`);
|
|
184
267
|
}
|
|
185
268
|
/** 安装 Codex 模板 (生成 AGENTS.md) */
|
|
186
269
|
function installCodexTemplates(cwd) {
|
package/package.json
CHANGED