secondbrainos-mcp-server 1.5.4 → 1.6.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/bin/cli.js CHANGED
@@ -362,42 +362,6 @@ async function main() {
362
362
  const cliPath = path.join(packageRoot, 'bin', 'cli.js');
363
363
  const claudeCodeConfigured = await configureClaudeCode(cliPath, nodePath);
364
364
 
365
- // Add SessionStart hook to global Claude Code settings
366
- if (claudeCodeConfigured) {
367
- try {
368
- const claudeSettingsPath = path.join(homedir(), '.claude', 'settings.json');
369
- let settings = {};
370
- try {
371
- settings = JSON.parse(await fs.readFile(claudeSettingsPath, 'utf8'));
372
- } catch { /* file may not exist yet */ }
373
-
374
- if (!settings.hooks) settings.hooks = {};
375
- if (!settings.hooks.SessionStart) settings.hooks.SessionStart = [];
376
-
377
- // Check if our hook already exists
378
- const skillFilePath = path.join(homedir(), '.claude', 'skills', 'secondbrainos', 'server-use', 'SKILL.md');
379
- const hookCommand = `cat "${skillFilePath}" 2>/dev/null || true`;
380
- const hasHook = settings.hooks.SessionStart.some(
381
- entry => entry.hooks && entry.hooks.some(h => h.command && h.command.includes('secondbrainos/server-use/SKILL.md'))
382
- );
383
-
384
- if (!hasHook) {
385
- settings.hooks.SessionStart.push({
386
- hooks: [
387
- {
388
- type: "command",
389
- command: hookCommand
390
- }
391
- ]
392
- });
393
- await fs.writeFile(claudeSettingsPath, JSON.stringify(settings, null, 2));
394
- console.log('SessionStart hook configured for SBOS context loading.');
395
- }
396
- } catch (error) {
397
- console.log(`Note: Could not configure SessionStart hook: ${error.message}`);
398
- }
399
- }
400
-
401
365
  console.log('\nInstallation successful!');
402
366
  console.log('\nClaude Desktop:');
403
367
  console.log('1. Completely quit Claude Desktop if it is running');
package/build/index.js CHANGED
@@ -15,12 +15,6 @@ function toSnakeCase(str) {
15
15
  .replace(/[^a-z0-9]+/g, '_')
16
16
  .replace(/^_+|_+$/g, '');
17
17
  }
18
- function toKebabCase(str) {
19
- return str
20
- .toLowerCase()
21
- .replace(/[^a-z0-9]+/g, '-')
22
- .replace(/^-+|-+$/g, '');
23
- }
24
18
  class SecondBrainOSServer {
25
19
  constructor(initialSchema) {
26
20
  this.originalSpec = initialSchema;
@@ -80,7 +74,7 @@ class SecondBrainOSServer {
80
74
  tools: {},
81
75
  prompts: {}
82
76
  },
83
- 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/"
77
+ instructions: "SBOS provides tools for managing knowledge along with definitions for sub-agents and associated skills. Run /secondbrainos:start_secondbrainos to load full SBOS context."
84
78
  });
85
79
  this.setupHandlers();
86
80
  this.setupErrorHandling();
@@ -253,6 +247,13 @@ class SecondBrainOSServer {
253
247
  console.error('Failed to fetch agents for prompts/list:', error);
254
248
  }
255
249
  }
250
+ // Add start_secondbrainos prompt — returns the server-use context document
251
+ prompts.push({
252
+ name: "start_secondbrainos",
253
+ title: "[Start] Second Brain OS",
254
+ description: "Load SBOS context: terminology, architecture, and available agents & skills index",
255
+ arguments: []
256
+ });
256
257
  // Add Knowledge Bases prompt (collects searchMyKnowledge_collection_ids from agents)
257
258
  if (this.getAIAgentsSchemaPath) {
258
259
  try {
@@ -285,6 +286,22 @@ class SecondBrainOSServer {
285
286
  this.server.setRequestHandler(GetPromptRequestSchema, async (request) => {
286
287
  const promptName = request.params.name;
287
288
  const userInput = request.params.arguments?.user_input;
289
+ // Check if this is the start_secondbrainos prompt
290
+ if (promptName === "start_secondbrainos") {
291
+ const content = await this.buildServerUseContent();
292
+ return {
293
+ description: "Second Brain OS — Server Context",
294
+ messages: [
295
+ {
296
+ role: "user",
297
+ content: {
298
+ type: "text",
299
+ text: content
300
+ }
301
+ }
302
+ ]
303
+ };
304
+ }
288
305
  // Check if this is the Knowledge Bases prompt
289
306
  if (promptName === "knowledge_bases") {
290
307
  const agents = await this.fetchAndEnrichAgents();
@@ -580,25 +597,28 @@ class SecondBrainOSServer {
580
597
  return enriched;
581
598
  }
582
599
  /**
583
- * Write Claude Code skill files to ~/.claude/skills/secondbrainos/
584
- * Called on every server startup so skills stay in sync with SBOS.
600
+ * Write the server-use skill file to ~/.claude/skills/secondbrainos/
601
+ * Called on every server startup so the context index stays in sync with SBOS.
585
602
  */
586
- async writeSkillFiles() {
587
- const skillsBase = path.join(homedir(), '.claude', 'skills', 'secondbrainos');
588
- // Helper to write a SKILL.md file
589
- const writeSkill = (dir, content) => {
590
- fs.mkdirSync(dir, { recursive: true });
591
- fs.writeFileSync(path.join(dir, 'SKILL.md'), content, 'utf-8');
592
- };
593
- // 1. server-use — context document for Claude Code sessions
594
- // Gather agent and workflow names for the index
603
+ async writeServerUseSkillFile() {
604
+ const serverUseContent = await this.buildServerUseContent();
605
+ const dir = path.join(homedir(), '.claude', 'skills', 'secondbrainos', 'server-use');
606
+ fs.mkdirSync(dir, { recursive: true });
607
+ fs.writeFileSync(path.join(dir, 'SKILL.md'), serverUseContent, 'utf-8');
608
+ console.error('Server-use skill file written to ~/.claude/skills/secondbrainos/server-use/');
609
+ }
610
+ /**
611
+ * Build the server-use context document content.
612
+ * Used by both writeServerUseSkillFile and the start_secondbrainos prompt.
613
+ */
614
+ async buildServerUseContent() {
595
615
  let agentIndex = '';
596
616
  let skillIndex = '';
597
617
  try {
598
618
  const agents = await this.fetchAndEnrichAgents();
599
619
  agentIndex = agents
600
620
  .filter((a) => a.name && a.id)
601
- .map((a) => `- ${a.name} → \`/secondbrainos:agent_${toSnakeCase(a.name)}\``)
621
+ .map((a) => `- ${a.name} (id: ${a.id}) → \`/secondbrainos:agent_${toSnakeCase(a.name)}\`${a.description ? `\n ${a.description}` : ''}`)
602
622
  .join('\n');
603
623
  }
604
624
  catch { /* skip if unavailable */ }
@@ -606,11 +626,11 @@ class SecondBrainOSServer {
606
626
  const workflows = await this.fetchAndEnrichWorkflows();
607
627
  skillIndex = workflows
608
628
  .filter((wf) => wf.name)
609
- .map((wf) => `- ${wf.name} → \`/secondbrainos:skill_${toSnakeCase(wf.name)}\``)
629
+ .map((wf) => `- ${wf.name} (id: ${wf.workflow_id}) → \`/secondbrainos:skill_${toSnakeCase(wf.name)}\`${wf.description ? `\n ${wf.description}` : ''}`)
610
630
  .join('\n');
611
631
  }
612
632
  catch { /* skip if unavailable */ }
613
- const serverUseContent = `---
633
+ return `---
614
634
  name: server-use
615
635
  description: Second Brain OS server context — terminology, architecture, and available agents/skills index
616
636
  user-invocable: false
@@ -630,14 +650,13 @@ An agent definition combines:
630
650
  2. **Services (Tools)** — the MCP tools the agent can use
631
651
  3. **Workflows (Skills)** — the prompt chains the agent follows
632
652
 
633
- This means you can spin up sub-agents from an agent's skill definitions (see \`~/.claude/skills/secondbrainos/tabs/\`).
653
+ ## Loading Agent & Skill Details
654
+ - To get full agent definitions (behaviour, knowledge, actions, workflows): use the \`getAIAgentsSchema\` tool
655
+ - To get full skill/workflow details and run prompt chains: use the \`runPromptChain\` tool
634
656
 
635
657
  ## Accessing Agents & Skills
636
- - Skill files live at \`~/.claude/skills/secondbrainos/\` (tabs/, workflows/, knowledge-bases/)
637
- - All skill files are set to \`user-invocable: false\` to avoid duplicating slash commands already available via MCP prompts
638
658
  - **Users** invoke agents or skills via slash commands (e.g. \`/secondbrainos:agent_...\` or \`/secondbrainos:skill_...\`)
639
659
  - **Users** cannot invoke MCP tools directly via slash commands — they must ask you to load and call the relevant tool
640
- - When using an agent with sub-agents, load the necessary skills at the start of the conversation by reading the agent's skill files
641
660
 
642
661
  ## Available Agents
643
662
  ${agentIndex || '_None configured_'}
@@ -645,85 +664,14 @@ ${agentIndex || '_None configured_'}
645
664
  ## Available Skills
646
665
  ${skillIndex || '_None configured_'}
647
666
  `;
648
- writeSkill(path.join(skillsBase, 'server-use'), serverUseContent);
649
- // 2. tabs (agents)
650
- if (this.getAIAgentsSchemaPath) {
651
- try {
652
- const agents = await this.fetchAndEnrichAgents();
653
- for (const agent of agents) {
654
- if (!agent.name || !agent.id)
655
- continue;
656
- const folderName = toKebabCase(agent.name);
657
- const agentDocument = {
658
- agent_id: agent.id,
659
- name: agent.name,
660
- description: agent.description || '',
661
- behaviour_and_instructions: agent.behaviour_and_instructions || '',
662
- searchMyKnowledge_collection_id: agent.searchMyKnowledge_collection_id || '',
663
- actions: agent.actions || [],
664
- workflows: (agent.workflows || []).map((wf) => ({
665
- id: wf.id,
666
- name: wf.name,
667
- prompts: (wf.prompts || []).map((p) => ({
668
- id: p.id,
669
- name: p.name,
670
- order: p.order,
671
- description: p.description
672
- }))
673
- }))
674
- };
675
- writeSkill(path.join(skillsBase, 'tabs', folderName), `---\nname: ${folderName}\ndescription: "${agent.description || agent.name}"\nuser-invocable: false\n---\n\n${JSON.stringify(agentDocument, null, 2)}\n`);
676
- }
677
- }
678
- catch (error) {
679
- console.error('Failed to write agent skill files:', error);
680
- }
681
- }
682
- // 3. workflows (uses cached enriched data)
683
- if (this.runPromptChainPath) {
684
- try {
685
- const workflows = await this.fetchAndEnrichWorkflows();
686
- for (const wf of workflows) {
687
- const folderName = toKebabCase(wf.name);
688
- const workflowDocument = {
689
- skill_id: wf.workflow_id,
690
- name: wf.name,
691
- description: wf.description || '',
692
- prompts: wf.prompts
693
- };
694
- writeSkill(path.join(skillsBase, 'workflows', folderName), `---\nname: ${folderName}\ndescription: "${wf.description || wf.name}"\nuser-invocable: false\n---\n\n${JSON.stringify(workflowDocument, null, 2)}\n`);
695
- }
696
- }
697
- catch (error) {
698
- console.error('Failed to write workflow skill files:', error);
699
- }
700
- }
701
- // 4. knowledgebases
702
- if (this.getAIAgentsSchemaPath) {
703
- try {
704
- const agents = await this.fetchAndEnrichAgents();
705
- const collectionIds = agents
706
- .map((a) => a.searchMyKnowledge_collection_id)
707
- .filter((id) => id && id.length > 0);
708
- if (collectionIds.length > 0) {
709
- const kbDocument = { searchMyKnowledge_collection_ids: collectionIds };
710
- writeSkill(path.join(skillsBase, 'knowledge-bases'), `---\nname: knowledge-bases\ndescription: Knowledge base collection IDs available to agents\nuser-invocable: false\n---\n\n${JSON.stringify(kbDocument, null, 2)}\n`);
711
- }
712
- }
713
- catch (error) {
714
- console.error('Failed to write knowledge bases skill file:', error);
715
- }
716
- }
717
- console.error('Skill files written to ~/.claude/skills/secondbrainos/');
718
667
  }
719
668
  setupErrorHandling() {
720
669
  // Error handling is now built into HttpLlm.execute
721
670
  // This method is kept for future error handling implementations
722
671
  }
723
672
  async run() {
724
- // Write skill files before connecting so Claude Code sees them at session start.
725
- // This is fast now (~2-3s) since enrichment uses single API calls.
726
- await this.writeSkillFiles().catch(err => console.error('Failed to write skill files:', err));
673
+ // Write server-use skill file before connecting so Claude Code sees it at session start.
674
+ await this.writeServerUseSkillFile().catch(err => console.error('Failed to write server-use skill file:', err));
727
675
  const transport = new StdioServerTransport();
728
676
  await this.server.connect(transport);
729
677
  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.5.4",
3
+ "version": "1.6.0",
4
4
  "description": "Second Brain OS MCP Server for Claude Desktop",
5
5
  "type": "module",
6
6
  "main": "build/index.js",