secondbrainos-mcp-server 1.3.0 → 1.4.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/build/index.js +106 -0
- 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
|
|
@@ -562,6 +563,109 @@ class SecondBrainOSServer {
|
|
|
562
563
|
this.cachedAgents = agents;
|
|
563
564
|
return agents;
|
|
564
565
|
}
|
|
566
|
+
/**
|
|
567
|
+
* Write Claude Code skill files to ~/.claude/skills/secondbrainos/
|
|
568
|
+
* Called on every server startup so skills stay in sync with SBOS.
|
|
569
|
+
*/
|
|
570
|
+
async writeSkillFiles() {
|
|
571
|
+
const skillsBase = path.join(homedir(), '.claude', 'skills', 'secondbrainos');
|
|
572
|
+
// Helper to write a SKILL.md file
|
|
573
|
+
const writeSkill = (dir, content) => {
|
|
574
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
575
|
+
fs.writeFileSync(path.join(dir, 'SKILL.md'), content, 'utf-8');
|
|
576
|
+
};
|
|
577
|
+
// 1. server-use — placeholder
|
|
578
|
+
writeSkill(path.join(skillsBase, 'server-use'), `---\nname: secondbrainos_server_use\ndescription: Second Brain OS server context\nuser-invocable: false\n---\n\nHello world.\n`);
|
|
579
|
+
// 2. tabs (agents)
|
|
580
|
+
if (this.getAIAgentsSchemaPath) {
|
|
581
|
+
try {
|
|
582
|
+
const agents = await this.fetchAndEnrichAgents();
|
|
583
|
+
for (const agent of agents) {
|
|
584
|
+
if (!agent.name || !agent.id)
|
|
585
|
+
continue;
|
|
586
|
+
const folderName = toSnakeCase(agent.name);
|
|
587
|
+
const agentDocument = {
|
|
588
|
+
agent_id: agent.id,
|
|
589
|
+
name: agent.name,
|
|
590
|
+
description: agent.description || '',
|
|
591
|
+
behaviour_and_instructions: agent.behaviour_and_instructions || '',
|
|
592
|
+
searchMyKnowledge_collection_id: agent.searchMyKnowledge_collection_id || '',
|
|
593
|
+
actions: agent.actions || [],
|
|
594
|
+
workflows: (agent.workflows || []).map((wf) => ({
|
|
595
|
+
id: wf.id,
|
|
596
|
+
name: wf.name,
|
|
597
|
+
prompts: (wf.prompts || []).map((p) => ({
|
|
598
|
+
id: p.id,
|
|
599
|
+
name: p.name,
|
|
600
|
+
order: p.order,
|
|
601
|
+
description: p.description
|
|
602
|
+
}))
|
|
603
|
+
}))
|
|
604
|
+
};
|
|
605
|
+
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`);
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
catch (error) {
|
|
609
|
+
console.error('Failed to write agent skill files:', error);
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
// 3. workflows
|
|
613
|
+
if (this.runPromptChainPath) {
|
|
614
|
+
try {
|
|
615
|
+
const data = await this.callRunPromptChain('', '');
|
|
616
|
+
const workflows = data.workflows || [];
|
|
617
|
+
for (const wf of workflows) {
|
|
618
|
+
if (!wf.name || !wf.workflow_id)
|
|
619
|
+
continue;
|
|
620
|
+
const folderName = toSnakeCase(wf.name);
|
|
621
|
+
const workflowDetail = await this.callRunPromptChain('workflow', wf.workflow_id);
|
|
622
|
+
const promptIds = workflowDetail.prompt_id || [];
|
|
623
|
+
const promptResults = await Promise.all(promptIds.map(async (promptId) => {
|
|
624
|
+
try {
|
|
625
|
+
const promptData = await this.callRunPromptChain('prompt', promptId);
|
|
626
|
+
return {
|
|
627
|
+
id: promptId,
|
|
628
|
+
name: promptData.name,
|
|
629
|
+
order: promptData.order,
|
|
630
|
+
description: promptData.description || ''
|
|
631
|
+
};
|
|
632
|
+
}
|
|
633
|
+
catch {
|
|
634
|
+
return { id: promptId, name: '', order: 0, description: '' };
|
|
635
|
+
}
|
|
636
|
+
}));
|
|
637
|
+
const sortedPrompts = promptResults.sort((a, b) => (a.order || 0) - (b.order || 0));
|
|
638
|
+
const workflowDocument = {
|
|
639
|
+
skill_id: wf.workflow_id,
|
|
640
|
+
name: wf.name,
|
|
641
|
+
description: wf.description || '',
|
|
642
|
+
prompts: sortedPrompts
|
|
643
|
+
};
|
|
644
|
+
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`);
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
catch (error) {
|
|
648
|
+
console.error('Failed to write workflow skill files:', error);
|
|
649
|
+
}
|
|
650
|
+
}
|
|
651
|
+
// 4. knowledgebases
|
|
652
|
+
if (this.getAIAgentsSchemaPath) {
|
|
653
|
+
try {
|
|
654
|
+
const agents = await this.fetchAndEnrichAgents();
|
|
655
|
+
const collectionIds = agents
|
|
656
|
+
.map((a) => a.searchMyKnowledge_collection_id)
|
|
657
|
+
.filter((id) => id && id.length > 0);
|
|
658
|
+
if (collectionIds.length > 0) {
|
|
659
|
+
const kbDocument = { searchMyKnowledge_collection_ids: collectionIds };
|
|
660
|
+
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`);
|
|
661
|
+
}
|
|
662
|
+
}
|
|
663
|
+
catch (error) {
|
|
664
|
+
console.error('Failed to write knowledge bases skill file:', error);
|
|
665
|
+
}
|
|
666
|
+
}
|
|
667
|
+
console.error('Skill files written to ~/.claude/skills/secondbrainos/');
|
|
668
|
+
}
|
|
565
669
|
setupErrorHandling() {
|
|
566
670
|
// Error handling is now built into HttpLlm.execute
|
|
567
671
|
// This method is kept for future error handling implementations
|
|
@@ -570,6 +674,8 @@ class SecondBrainOSServer {
|
|
|
570
674
|
const transport = new StdioServerTransport();
|
|
571
675
|
await this.server.connect(transport);
|
|
572
676
|
console.error("Second Brain OS MCP server running on stdio");
|
|
677
|
+
// Write skill files in the background (non-blocking)
|
|
678
|
+
this.writeSkillFiles().catch(err => console.error('Failed to write skill files:', err));
|
|
573
679
|
}
|
|
574
680
|
}
|
|
575
681
|
SecondBrainOSServer.ALLOWED_EXTENSIONS = ['.txt', '.md'];
|