secondbrainos-mcp-server 1.3.0 → 1.4.1

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/build/index.js +108 -1
  2. package/package.json +1 -1
package/build/index.js CHANGED
@@ -7,6 +7,7 @@ import dotenv from "dotenv";
7
7
  import yaml from 'js-yaml';
8
8
  import fs from 'fs';
9
9
  import path from 'path';
10
+ import { homedir } from 'os';
10
11
  dotenv.config();
11
12
  function toSnakeCase(str) {
12
13
  return str
@@ -71,7 +72,8 @@ class SecondBrainOSServer {
71
72
  resources: {},
72
73
  tools: {},
73
74
  prompts: {}
74
- }
75
+ },
76
+ instructions: "SBOS provides tools for managing knowledge along with definitions for sub-agents and associated skills. For full server context, see the skills at ~/.claude/skills/secondbrainos/"
75
77
  });
76
78
  this.setupHandlers();
77
79
  this.setupErrorHandling();
@@ -562,11 +564,116 @@ class SecondBrainOSServer {
562
564
  this.cachedAgents = agents;
563
565
  return agents;
564
566
  }
567
+ /**
568
+ * Write Claude Code skill files to ~/.claude/skills/secondbrainos/
569
+ * Called on every server startup so skills stay in sync with SBOS.
570
+ */
571
+ async writeSkillFiles() {
572
+ const skillsBase = path.join(homedir(), '.claude', 'skills', 'secondbrainos');
573
+ // Helper to write a SKILL.md file
574
+ const writeSkill = (dir, content) => {
575
+ fs.mkdirSync(dir, { recursive: true });
576
+ fs.writeFileSync(path.join(dir, 'SKILL.md'), content, 'utf-8');
577
+ };
578
+ // 1. server-use — placeholder
579
+ writeSkill(path.join(skillsBase, 'server-use'), `---\nname: secondbrainos_server_use\ndescription: Second Brain OS server context\nuser-invocable: false\n---\n\nHello world.\n`);
580
+ // 2. tabs (agents)
581
+ if (this.getAIAgentsSchemaPath) {
582
+ try {
583
+ const agents = await this.fetchAndEnrichAgents();
584
+ for (const agent of agents) {
585
+ if (!agent.name || !agent.id)
586
+ continue;
587
+ const folderName = toSnakeCase(agent.name);
588
+ const agentDocument = {
589
+ agent_id: agent.id,
590
+ name: agent.name,
591
+ description: agent.description || '',
592
+ behaviour_and_instructions: agent.behaviour_and_instructions || '',
593
+ searchMyKnowledge_collection_id: agent.searchMyKnowledge_collection_id || '',
594
+ actions: agent.actions || [],
595
+ workflows: (agent.workflows || []).map((wf) => ({
596
+ id: wf.id,
597
+ name: wf.name,
598
+ prompts: (wf.prompts || []).map((p) => ({
599
+ id: p.id,
600
+ name: p.name,
601
+ order: p.order,
602
+ description: p.description
603
+ }))
604
+ }))
605
+ };
606
+ writeSkill(path.join(skillsBase, 'tabs', folderName), `---\nname: secondbrainos_agent_${folderName}\ndescription: "${agent.description || agent.name}"\nuser-invocable: false\n---\n\n${JSON.stringify(agentDocument, null, 2)}\n`);
607
+ }
608
+ }
609
+ catch (error) {
610
+ console.error('Failed to write agent skill files:', error);
611
+ }
612
+ }
613
+ // 3. workflows
614
+ if (this.runPromptChainPath) {
615
+ try {
616
+ const data = await this.callRunPromptChain('', '');
617
+ const workflows = data.workflows || [];
618
+ for (const wf of workflows) {
619
+ if (!wf.name || !wf.workflow_id)
620
+ continue;
621
+ const folderName = toSnakeCase(wf.name);
622
+ const workflowDetail = await this.callRunPromptChain('workflow', wf.workflow_id);
623
+ const promptIds = workflowDetail.prompt_id || [];
624
+ const promptResults = await Promise.all(promptIds.map(async (promptId) => {
625
+ try {
626
+ const promptData = await this.callRunPromptChain('prompt', promptId);
627
+ return {
628
+ id: promptId,
629
+ name: promptData.name,
630
+ order: promptData.order,
631
+ description: promptData.description || ''
632
+ };
633
+ }
634
+ catch {
635
+ return { id: promptId, name: '', order: 0, description: '' };
636
+ }
637
+ }));
638
+ const sortedPrompts = promptResults.sort((a, b) => (a.order || 0) - (b.order || 0));
639
+ const workflowDocument = {
640
+ skill_id: wf.workflow_id,
641
+ name: wf.name,
642
+ description: wf.description || '',
643
+ prompts: sortedPrompts
644
+ };
645
+ writeSkill(path.join(skillsBase, 'workflows', folderName), `---\nname: secondbrainos_skill_${folderName}\ndescription: "${wf.description || wf.name}"\nuser-invocable: false\n---\n\n${JSON.stringify(workflowDocument, null, 2)}\n`);
646
+ }
647
+ }
648
+ catch (error) {
649
+ console.error('Failed to write workflow skill files:', error);
650
+ }
651
+ }
652
+ // 4. knowledgebases
653
+ if (this.getAIAgentsSchemaPath) {
654
+ try {
655
+ const agents = await this.fetchAndEnrichAgents();
656
+ const collectionIds = agents
657
+ .map((a) => a.searchMyKnowledge_collection_id)
658
+ .filter((id) => id && id.length > 0);
659
+ if (collectionIds.length > 0) {
660
+ const kbDocument = { searchMyKnowledge_collection_ids: collectionIds };
661
+ writeSkill(path.join(skillsBase, 'knowledgebases'), `---\nname: secondbrainos_knowledge_bases\ndescription: Knowledge base collection IDs available to agents\nuser-invocable: false\n---\n\n${JSON.stringify(kbDocument, null, 2)}\n`);
662
+ }
663
+ }
664
+ catch (error) {
665
+ console.error('Failed to write knowledge bases skill file:', error);
666
+ }
667
+ }
668
+ console.error('Skill files written to ~/.claude/skills/secondbrainos/');
669
+ }
565
670
  setupErrorHandling() {
566
671
  // Error handling is now built into HttpLlm.execute
567
672
  // This method is kept for future error handling implementations
568
673
  }
569
674
  async run() {
675
+ // Write skill files before connecting so Claude Code sees them at session start
676
+ await this.writeSkillFiles().catch(err => console.error('Failed to write skill files:', err));
570
677
  const transport = new StdioServerTransport();
571
678
  await this.server.connect(transport);
572
679
  console.error("Second Brain OS MCP server running on stdio");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "secondbrainos-mcp-server",
3
- "version": "1.3.0",
3
+ "version": "1.4.1",
4
4
  "description": "Second Brain OS MCP Server for Claude Desktop",
5
5
  "type": "module",
6
6
  "main": "build/index.js",