@blueking/bkui-knowledge 0.0.1-beta.12 → 0.0.1-beta.14

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.
@@ -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
- fs.writeFileSync(path.join(skillsDir, `${skillId}.md`), content, 'utf-8');
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
- // 尝试从 rootUri 或 workspaceFolders 获取项目路径
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
- if (!skillsSynced && mcpRootUri) {
379
+ // 如果没有获取到 mcpRootUri,回退到 cwd
380
+ if (!skillsSynced) {
329
381
  const projectRoot = getProjectRoot();
330
382
  const ideConfig = getIDEConfig();
331
- log(`[延迟同步] 工作目录: ${projectRoot}, IDE: ${ideConfig.name}`);
332
- syncSkills(projectRoot, ideConfig);
333
- skillsSynced = true;
383
+ if (projectRoot) {
384
+ log(`[延迟同步] 工作目录: ${projectRoot}, IDE: ${ideConfig.name}`);
385
+ syncSkills(projectRoot, ideConfig);
386
+ skillsSynced = true;
387
+ }
334
388
  }
335
389
 
336
390
  return {
@@ -700,5 +700,11 @@
700
700
  ]
701
701
  },
702
702
 
703
- "recommendedSkills": ["bkui-quick-start", "bkui-builder", "bkui-cheatsheet", "vue-best-practices", "code-review", "js-security-check"]
703
+ "recommendedSkills": [
704
+ "bkui-quick-start", "bkui-builder", "bkui-cheatsheet", "vue-best-practices",
705
+ "code-review", "js-security-check", "api-standard", "bk-security-redlines",
706
+ "bk-skill-creator", "bundle-optimization", "nodejs-security-check",
707
+ "permission-directive", "pinia-setup", "unit-testing", "virtual-list",
708
+ "vite-migration", "vue-composables", "web-security-guide"
709
+ ]
704
710
  }
package/package.json CHANGED
@@ -1,10 +1,11 @@
1
1
  {
2
2
  "name": "@blueking/bkui-knowledge",
3
- "version": "0.0.1-beta.12",
3
+ "version": "0.0.1-beta.14",
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/",