secondbrainos-mcp-server 1.4.3 → 1.4.5

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 +57 -49
  2. package/package.json +1 -1
package/build/index.js CHANGED
@@ -43,6 +43,7 @@ class SecondBrainOSServer {
43
43
  this.workflowNameToId = new Map();
44
44
  this.agentNameToId = new Map();
45
45
  this.cachedAgents = null;
46
+ this.cachedWorkflows = null;
46
47
  // Discover service paths from the OpenAPI schema
47
48
  this.runPromptChainPath = null;
48
49
  this.getAIAgentsSchemaPath = null;
@@ -164,7 +165,8 @@ class SecondBrainOSServer {
164
165
  // Better error handling with HttpLlm
165
166
  if (axios.isAxiosError(error)) {
166
167
  const status = error.response?.status;
167
- const errorMessage = error.response?.data?.error || error.message;
168
+ const rawError = error.response?.data?.error || error.response?.data?.message || error.message;
169
+ const errorMessage = typeof rawError === 'object' ? JSON.stringify(rawError) : rawError;
168
170
  let mcpError;
169
171
  switch (status) {
170
172
  case 401:
@@ -205,24 +207,17 @@ class SecondBrainOSServer {
205
207
  // List available prompts (user's workflows + agents)
206
208
  this.server.setRequestHandler(ListPromptsRequestSchema, async () => {
207
209
  const prompts = [];
208
- // Fetch workflows as prompts
210
+ // Fetch workflows as prompts (uses cached enriched data)
209
211
  if (this.runPromptChainPath) {
210
212
  try {
211
- const data = await this.callRunPromptChain('', '');
212
- const workflows = data.workflows || [];
213
+ const workflows = await this.fetchAndEnrichWorkflows();
213
214
  this.workflowNameToId.clear();
214
215
  for (const wf of workflows) {
215
- if (wf.name && wf.workflow_id) {
216
- const snakeName = `skill_${toSnakeCase(wf.name)}`;
217
- this.workflowNameToId.set(snakeName, wf.workflow_id);
218
- }
219
- }
220
- for (const wf of workflows) {
221
- const skillName = wf.name || wf.workflow_id;
222
- const snakeName = `skill_${toSnakeCase(skillName)}`;
216
+ const snakeName = `skill_${toSnakeCase(wf.name)}`;
217
+ this.workflowNameToId.set(snakeName, wf.workflow_id);
223
218
  prompts.push({
224
219
  name: snakeName,
225
- title: `[Skill] ${skillName}`,
220
+ title: `[Skill] ${wf.name}`,
226
221
  description: wf.description || wf.name,
227
222
  arguments: [
228
223
  {
@@ -570,6 +565,42 @@ class SecondBrainOSServer {
570
565
  this.cachedAgents = agents;
571
566
  return agents;
572
567
  }
568
+ async fetchAndEnrichWorkflows() {
569
+ if (this.cachedWorkflows)
570
+ return this.cachedWorkflows;
571
+ const data = await this.callRunPromptChain('', '');
572
+ const workflows = (data.workflows || []).filter((wf) => wf.name && wf.workflow_id);
573
+ const enriched = await Promise.all(workflows.map(async (wf) => {
574
+ try {
575
+ const workflowDetail = await this.callRunPromptChain('workflow', wf.workflow_id);
576
+ const promptIds = workflowDetail.prompt_id || [];
577
+ const promptResults = await Promise.all(promptIds.map(async (promptId) => {
578
+ try {
579
+ const promptData = await this.callRunPromptChain('prompt', promptId);
580
+ return {
581
+ id: promptId,
582
+ name: promptData.name,
583
+ order: promptData.order,
584
+ description: promptData.description || ''
585
+ };
586
+ }
587
+ catch {
588
+ return { id: promptId, name: '', order: 0, description: '' };
589
+ }
590
+ }));
591
+ return {
592
+ ...wf,
593
+ prompts: promptResults.sort((a, b) => (a.order || 0) - (b.order || 0))
594
+ };
595
+ }
596
+ catch (error) {
597
+ console.error(`Failed to enrich workflow "${wf.name}":`, error);
598
+ return { ...wf, prompts: [] };
599
+ }
600
+ }));
601
+ this.cachedWorkflows = enriched;
602
+ return enriched;
603
+ }
573
604
  /**
574
605
  * Write Claude Code skill files to ~/.claude/skills/secondbrainos/
575
606
  * Called on every server startup so skills stay in sync with SBOS.
@@ -616,46 +647,23 @@ class SecondBrainOSServer {
616
647
  console.error('Failed to write agent skill files:', error);
617
648
  }
618
649
  }
619
- // 3. workflows (parallelized each workflow fetched concurrently)
650
+ // 3. workflows (uses cached enriched data)
620
651
  if (this.runPromptChainPath) {
621
652
  try {
622
- const data = await this.callRunPromptChain('', '');
623
- const workflows = (data.workflows || []).filter((wf) => wf.name && wf.workflow_id);
624
- await Promise.all(workflows.map(async (wf) => {
625
- try {
626
- const folderName = toSnakeCase(wf.name);
627
- const workflowDetail = await this.callRunPromptChain('workflow', wf.workflow_id);
628
- const promptIds = workflowDetail.prompt_id || [];
629
- const promptResults = await Promise.all(promptIds.map(async (promptId) => {
630
- try {
631
- const promptData = await this.callRunPromptChain('prompt', promptId);
632
- return {
633
- id: promptId,
634
- name: promptData.name,
635
- order: promptData.order,
636
- description: promptData.description || ''
637
- };
638
- }
639
- catch {
640
- return { id: promptId, name: '', order: 0, description: '' };
641
- }
642
- }));
643
- const sortedPrompts = promptResults.sort((a, b) => (a.order || 0) - (b.order || 0));
644
- const workflowDocument = {
645
- skill_id: wf.workflow_id,
646
- name: wf.name,
647
- description: wf.description || '',
648
- prompts: sortedPrompts
649
- };
650
- 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`);
651
- }
652
- catch (error) {
653
- console.error(`Failed to write skill file for workflow "${wf.name}":`, error);
654
- }
655
- }));
653
+ const workflows = await this.fetchAndEnrichWorkflows();
654
+ for (const wf of workflows) {
655
+ const folderName = toSnakeCase(wf.name);
656
+ const workflowDocument = {
657
+ skill_id: wf.workflow_id,
658
+ name: wf.name,
659
+ description: wf.description || '',
660
+ prompts: wf.prompts
661
+ };
662
+ 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`);
663
+ }
656
664
  }
657
665
  catch (error) {
658
- console.error('Failed to fetch workflows for skill files:', error);
666
+ console.error('Failed to write workflow skill files:', error);
659
667
  }
660
668
  }
661
669
  // 4. knowledgebases
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "secondbrainos-mcp-server",
3
- "version": "1.4.3",
3
+ "version": "1.4.5",
4
4
  "description": "Second Brain OS MCP Server for Claude Desktop",
5
5
  "type": "module",
6
6
  "main": "build/index.js",