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.
- package/build/index.js +108 -1
- 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");
|