@blueking/bkui-knowledge 0.0.1-beta.12 → 0.0.1-beta.13
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/bin/bkui-knowledge.js +62 -8
- package/package.json +3 -2
package/bin/bkui-knowledge.js
CHANGED
|
@@ -208,6 +208,35 @@ function scanSkillDir(dirPath, relativePath) {
|
|
|
208
208
|
return results;
|
|
209
209
|
}
|
|
210
210
|
|
|
211
|
+
/**
|
|
212
|
+
* 重写 SKILL.md 的 frontmatter 以符合 Claude Code 格式要求
|
|
213
|
+
* Claude Code 要求 name 字段必须是小写字母、数字和连字符
|
|
214
|
+
* @param {string} content - 原始内容
|
|
215
|
+
* @param {string} skillId - skill ID (用作 name)
|
|
216
|
+
* @param {object} skill - manifest 中的 skill 信息
|
|
217
|
+
* @returns {string} 重写后的内容
|
|
218
|
+
*/
|
|
219
|
+
function rewriteFrontmatterForClaudeCode(content, skillId, skill) {
|
|
220
|
+
// 解析 frontmatter
|
|
221
|
+
const frontmatterMatch = content.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);
|
|
222
|
+
if (!frontmatterMatch) {
|
|
223
|
+
// 没有 frontmatter,添加一个
|
|
224
|
+
return `---\nname: ${skillId}\ndescription: ${skill.description || skill.name}\n---\n\n${content}`;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
const frontmatter = frontmatterMatch[1];
|
|
228
|
+
const body = frontmatterMatch[2];
|
|
229
|
+
|
|
230
|
+
// 提取 description(从原始 frontmatter 或 skill 信息)
|
|
231
|
+
const descMatch = frontmatter.match(/^description:\s*(.+)$/m);
|
|
232
|
+
const description = descMatch ? descMatch[1].trim() : (skill.description || skill.name);
|
|
233
|
+
|
|
234
|
+
// 创建新的 Claude Code 兼容 frontmatter
|
|
235
|
+
const newFrontmatter = `---\nname: ${skillId}\ndescription: ${description}\n---`;
|
|
236
|
+
|
|
237
|
+
return `${newFrontmatter}\n${body}`;
|
|
238
|
+
}
|
|
239
|
+
|
|
211
240
|
/**
|
|
212
241
|
* 生成 skill 的可用资源列表
|
|
213
242
|
* @param {string} skillDir - skill 目录路径
|
|
@@ -267,6 +296,8 @@ function syncSkills(projectRoot, ideConfig) {
|
|
|
267
296
|
|
|
268
297
|
// 同步推荐的 skills
|
|
269
298
|
let count = 0;
|
|
299
|
+
const isClaudeCode = ideConfig.name === 'Claude Code';
|
|
300
|
+
|
|
270
301
|
for (const skillId of recommendedIds) {
|
|
271
302
|
const skill = manifest.skills.items.find(s => s.id === skillId);
|
|
272
303
|
if (!skill) continue;
|
|
@@ -282,7 +313,20 @@ function syncSkills(projectRoot, ideConfig) {
|
|
|
282
313
|
const resourcesList = generateResourcesList(skillDir, skillId);
|
|
283
314
|
content += resourcesList;
|
|
284
315
|
|
|
285
|
-
|
|
316
|
+
if (isClaudeCode) {
|
|
317
|
+
// Claude Code 要求每个 skill 在独立子目录,文件名为 SKILL.md
|
|
318
|
+
// 并且 name 字段必须是小写字母、数字和连字符
|
|
319
|
+
const skillSubDir = path.join(skillsDir, skillId);
|
|
320
|
+
fs.mkdirSync(skillSubDir, { recursive: true });
|
|
321
|
+
|
|
322
|
+
// 重写 frontmatter 以符合 Claude Code 格式要求
|
|
323
|
+
content = rewriteFrontmatterForClaudeCode(content, skillId, skill);
|
|
324
|
+
|
|
325
|
+
fs.writeFileSync(path.join(skillSubDir, 'SKILL.md'), content, 'utf-8');
|
|
326
|
+
} else {
|
|
327
|
+
// Cursor / CodeBuddy 直接放在 skills 目录
|
|
328
|
+
fs.writeFileSync(path.join(skillsDir, `${skillId}.md`), content, 'utf-8');
|
|
329
|
+
}
|
|
286
330
|
|
|
287
331
|
log(` ✓ ${skillId}`);
|
|
288
332
|
count++;
|
|
@@ -315,22 +359,32 @@ async function startMcpServer() {
|
|
|
315
359
|
// 从 initialize 请求中提取项目路径
|
|
316
360
|
const params = message.params || {};
|
|
317
361
|
|
|
318
|
-
//
|
|
362
|
+
// 打印 initialize 参数用于调试
|
|
363
|
+
log(`initialize params: ${JSON.stringify({ rootUri: params.rootUri, workspaceFolders: params.workspaceFolders, roots: params.roots })}`);
|
|
364
|
+
|
|
365
|
+
// 尝试从 rootUri 或 workspaceFolders 或 roots 获取项目路径
|
|
319
366
|
if (params.rootUri) {
|
|
320
367
|
mcpRootUri = uriToPath(params.rootUri);
|
|
321
|
-
log(`从 MCP initialize 获取项目路径: ${mcpRootUri}`);
|
|
368
|
+
log(`从 MCP initialize.rootUri 获取项目路径: ${mcpRootUri}`);
|
|
322
369
|
} else if (params.workspaceFolders && params.workspaceFolders.length > 0) {
|
|
323
370
|
mcpRootUri = uriToPath(params.workspaceFolders[0].uri);
|
|
324
|
-
log(`从 MCP workspaceFolders 获取项目路径: ${mcpRootUri}`);
|
|
371
|
+
log(`从 MCP initialize.workspaceFolders 获取项目路径: ${mcpRootUri}`);
|
|
372
|
+
} else if (params.roots && params.roots.length > 0) {
|
|
373
|
+
// Claude Code 使用 roots 字段
|
|
374
|
+
mcpRootUri = uriToPath(params.roots[0].uri);
|
|
375
|
+
log(`从 MCP initialize.roots 获取项目路径: ${mcpRootUri}`);
|
|
325
376
|
}
|
|
326
377
|
|
|
327
378
|
// 延迟同步 skills(在获取到项目路径后)
|
|
328
|
-
|
|
379
|
+
// 如果没有获取到 mcpRootUri,回退到 cwd
|
|
380
|
+
if (!skillsSynced) {
|
|
329
381
|
const projectRoot = getProjectRoot();
|
|
330
382
|
const ideConfig = getIDEConfig();
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
383
|
+
if (projectRoot) {
|
|
384
|
+
log(`[延迟同步] 工作目录: ${projectRoot}, IDE: ${ideConfig.name}`);
|
|
385
|
+
syncSkills(projectRoot, ideConfig);
|
|
386
|
+
skillsSynced = true;
|
|
387
|
+
}
|
|
334
388
|
}
|
|
335
389
|
|
|
336
390
|
return {
|
package/package.json
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@blueking/bkui-knowledge",
|
|
3
|
-
"version": "0.0.1-beta.
|
|
3
|
+
"version": "0.0.1-beta.13",
|
|
4
4
|
"description": "蓝鲸前端知识库 MCP 服务 - 自动同步 skills,支持 Cursor/CodeBuddy",
|
|
5
5
|
"main": "server/mcp-core.js",
|
|
6
6
|
"bin": {
|
|
7
|
-
"bkui-knowledge": "./bin/bkui-knowledge.js"
|
|
7
|
+
"bkui-knowledge": "./bin/bkui-knowledge.js",
|
|
8
|
+
"bkui-knowledge-mcp": "./bin/bkui-knowledge.js"
|
|
8
9
|
},
|
|
9
10
|
"files": [
|
|
10
11
|
"bin/",
|