secondbrainos-mcp-server 1.6.0 → 1.7.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/README.md +27 -14
- package/bin/cli.js +3 -5
- package/build/index.js +20 -59
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -25,8 +25,8 @@ secondbrainos-mcp USER_ID USER_SECRET
|
|
|
25
25
|
This will:
|
|
26
26
|
1. Verify your account credentials
|
|
27
27
|
2. Confirm you have access to the Claude MCP feature
|
|
28
|
-
3.
|
|
29
|
-
4. Configure
|
|
28
|
+
3. Store credentials securely at `~/.secondbrainos/credentials.json`
|
|
29
|
+
4. Configure Claude Desktop and Claude Code to use `serve` mode (credentials read from file, not embedded in config)
|
|
30
30
|
|
|
31
31
|
### Claude Code
|
|
32
32
|
|
|
@@ -52,16 +52,20 @@ The server uses `@samchon/openapi` library for robust OpenAPI handling, providin
|
|
|
52
52
|
- Support for complex parameters and nested objects
|
|
53
53
|
|
|
54
54
|
### Prompts
|
|
55
|
-
The server exposes
|
|
55
|
+
The server exposes four types of MCP prompts, available as slash commands (e.g. `/secondbrainos:agent_my_agent`):
|
|
56
|
+
|
|
57
|
+
#### Start (`start_secondbrainos`)
|
|
58
|
+
- Returns a context document with SBOS terminology, agent architecture, and an index of all available agents and skills with their slash commands
|
|
59
|
+
- Useful for orienting Claude at the start of a session
|
|
56
60
|
|
|
57
61
|
#### Skills (Workflows)
|
|
58
|
-
-
|
|
62
|
+
- Discovered via `runPromptChain` on first `ListPrompts` call, then cached for the session
|
|
59
63
|
- Each skill appears with a `[Skill]` prefix and returns a structured document with `skill_id`, `name`, `description`, and an ordered list of prompts (metadata only, no instructions)
|
|
60
64
|
- Supports an optional `user_input` argument to provide additional context
|
|
61
65
|
|
|
62
66
|
#### Agents
|
|
63
|
-
-
|
|
64
|
-
- Each agent appears with an `[Agent]` prefix and returns a structured document containing `agent_id`, `name`, `description`, `behaviour_and_instructions`, `searchMyKnowledge_collection_id`, `actions` (with id, name, description, body_parameters), and `workflows` (with
|
|
67
|
+
- Discovered via `getAIAgentsSchema` on first `ListPrompts` call, then cached for the session
|
|
68
|
+
- Each agent appears with an `[Agent]` prefix and returns a structured document containing `agent_id`, `name`, `description`, `behaviour_and_instructions`, `searchMyKnowledge_collection_id`, `actions` (with id, name, description, body_parameters), and `workflows` (with prompt order and description)
|
|
65
69
|
- Supports an optional `user_input` argument
|
|
66
70
|
|
|
67
71
|
#### Knowledge Bases
|
|
@@ -132,20 +136,29 @@ secondbrainos-mcp-server/
|
|
|
132
136
|
└── README.md # This file
|
|
133
137
|
```
|
|
134
138
|
|
|
135
|
-
##
|
|
139
|
+
## Credentials
|
|
136
140
|
|
|
137
|
-
The server
|
|
138
|
-
- `USER_ID`: Your Second Brain OS user ID
|
|
139
|
-
- `USER_SECRET`: Your Second Brain OS user secret
|
|
140
|
-
- `API_BASE_URL` (optional): Override the default API base URL
|
|
141
|
+
Credentials are stored securely at `~/.secondbrainos/credentials.json` (created during setup with mode `0o600`). The server reads from this file in `serve` mode. Environment variables `USER_ID`, `USER_SECRET`, and `API_BASE_URL` can override the stored credentials if set.
|
|
141
142
|
|
|
142
143
|
## How It Works
|
|
143
144
|
|
|
144
|
-
1. **Schema Fetching**: On startup, the server fetches your personalized OpenAPI schema from
|
|
145
|
+
1. **Schema Fetching**: On startup, the server fetches your personalized OpenAPI schema from `schema.secondbrainos.com`
|
|
145
146
|
2. **Schema Conversion**: The `@samchon/openapi` library converts the schema to an optimized format for LLM function calling
|
|
146
147
|
3. **MCP Tools**: Each API endpoint becomes an MCP tool that Claude can use
|
|
147
|
-
4. **MCP Prompts**:
|
|
148
|
-
5. **
|
|
148
|
+
4. **MCP Prompts**: On first `ListPrompts` call (automatic on session connect), the server fetches all agents via `getAIAgentsSchema` and all workflows via `runPromptChain`, caches them in memory, and exposes them as slash commands
|
|
149
|
+
5. **Slash Commands**: When a user runs a slash command (e.g. `/secondbrainos:agent_my_agent`), the server returns the full agent/skill definition from cache — no additional API calls, no credit cost
|
|
150
|
+
6. **Function Execution**: When Claude calls a tool, the server executes the corresponding API call via `api.secondbrainos.com` with proper authentication
|
|
151
|
+
7. **File Upload**: Local file paths in tool arguments are automatically uploaded to GCS via signed URL before the API call
|
|
152
|
+
|
|
153
|
+
### Credit Cost
|
|
154
|
+
|
|
155
|
+
| Event | Credits |
|
|
156
|
+
|-------|---------|
|
|
157
|
+
| Session init | n workflows + n agents |
|
|
158
|
+
| Slash commands | 0 (cached) |
|
|
159
|
+
| Tool calls | Billed per call via service router |
|
|
160
|
+
|
|
161
|
+
See [`docs/architecture.md`](docs/architecture.md) for detailed diagrams.
|
|
149
162
|
|
|
150
163
|
## Troubleshooting
|
|
151
164
|
|
package/bin/cli.js
CHANGED
|
@@ -332,13 +332,12 @@ async function main() {
|
|
|
332
332
|
const hadExistingSecondBrainOS = !!existingConfig.mcpServers.secondbrainos;
|
|
333
333
|
|
|
334
334
|
// Add or update the secondbrainos server configuration
|
|
335
|
+
// Uses serve mode which reads credentials from ~/.secondbrainos/credentials.json
|
|
336
|
+
const cliPath = path.join(packageRoot, 'bin', 'cli.js');
|
|
335
337
|
existingConfig.mcpServers.secondbrainos = {
|
|
336
338
|
command: nodePath,
|
|
337
|
-
args: [
|
|
339
|
+
args: [cliPath, 'serve'],
|
|
338
340
|
env: {
|
|
339
|
-
USER_ID,
|
|
340
|
-
USER_SECRET,
|
|
341
|
-
API_BASE_URL: 'https://api.secondbrainos.com',
|
|
342
341
|
NODE_PATH: getNodeModulesPath()
|
|
343
342
|
}
|
|
344
343
|
};
|
|
@@ -359,7 +358,6 @@ async function main() {
|
|
|
359
358
|
}
|
|
360
359
|
|
|
361
360
|
// Configure Claude Code
|
|
362
|
-
const cliPath = path.join(packageRoot, 'bin', 'cli.js');
|
|
363
361
|
const claudeCodeConfigured = await configureClaudeCode(cliPath, nodePath);
|
|
364
362
|
|
|
365
363
|
console.log('\nInstallation successful!');
|
package/build/index.js
CHANGED
|
@@ -5,9 +5,8 @@ import { OpenApi, HttpLlm } from "@samchon/openapi";
|
|
|
5
5
|
import axios from "axios";
|
|
6
6
|
import dotenv from "dotenv";
|
|
7
7
|
import yaml from 'js-yaml';
|
|
8
|
-
import fs from 'fs';
|
|
9
8
|
import path from 'path';
|
|
10
|
-
import
|
|
9
|
+
import fs from 'fs';
|
|
11
10
|
dotenv.config();
|
|
12
11
|
function toSnakeCase(str) {
|
|
13
12
|
return str
|
|
@@ -339,23 +338,14 @@ class SecondBrainOSServer {
|
|
|
339
338
|
if (agentId) {
|
|
340
339
|
return this.buildAgentPrompt(agentId, userInput);
|
|
341
340
|
}
|
|
342
|
-
// Otherwise treat as a workflow prompt
|
|
341
|
+
// Otherwise treat as a workflow prompt — use cached data
|
|
343
342
|
const workflowId = this.workflowNameToId.get(promptName) || promptName;
|
|
344
|
-
|
|
345
|
-
const
|
|
346
|
-
|
|
347
|
-
const prompts = workflowMeta?.prompts || [];
|
|
348
|
-
if (prompts.length === 0) {
|
|
343
|
+
const workflows = await this.fetchAndEnrichWorkflows();
|
|
344
|
+
const workflowMeta = workflows.find((wf) => wf.workflow_id === workflowId);
|
|
345
|
+
if (!workflowMeta || !workflowMeta.prompts || workflowMeta.prompts.length === 0) {
|
|
349
346
|
throw new McpError(ErrorCode.InvalidRequest, `No prompts found for workflow: ${workflowId}`);
|
|
350
347
|
}
|
|
351
|
-
const sortedPrompts = prompts
|
|
352
|
-
.map((p) => ({
|
|
353
|
-
id: p.prompt_id,
|
|
354
|
-
name: p.name || '',
|
|
355
|
-
order: p.order || 0,
|
|
356
|
-
description: p.description || ''
|
|
357
|
-
}))
|
|
358
|
-
.sort((a, b) => (a.order || 0) - (b.order || 0));
|
|
348
|
+
const sortedPrompts = workflowMeta.prompts;
|
|
359
349
|
const workflowDocument = {
|
|
360
350
|
skill_id: workflowId,
|
|
361
351
|
name: workflowMeta?.name || promptName,
|
|
@@ -435,15 +425,12 @@ class SecondBrainOSServer {
|
|
|
435
425
|
messages
|
|
436
426
|
};
|
|
437
427
|
}
|
|
438
|
-
async callRunPromptChain(
|
|
428
|
+
async callRunPromptChain() {
|
|
439
429
|
if (!this.runPromptChainPath) {
|
|
440
430
|
throw new McpError(ErrorCode.InternalError, 'runPromptChain service not available for this user');
|
|
441
431
|
}
|
|
442
432
|
const url = `${this.baseUrl}${this.runPromptChainPath}`;
|
|
443
|
-
const response = await axios.post(url, {
|
|
444
|
-
entity,
|
|
445
|
-
entity_id: entityId
|
|
446
|
-
}, {
|
|
433
|
+
const response = await axios.post(url, {}, {
|
|
447
434
|
headers: {
|
|
448
435
|
'Authorization': `Bearer ${this.userId}:${this.userSecret}`,
|
|
449
436
|
'Content-Type': 'application/json'
|
|
@@ -540,20 +527,10 @@ class SecondBrainOSServer {
|
|
|
540
527
|
async fetchAndEnrichAgents() {
|
|
541
528
|
if (this.cachedAgents)
|
|
542
529
|
return this.cachedAgents;
|
|
543
|
-
//
|
|
544
|
-
const
|
|
545
|
-
this.callGetAIAgentsSchema(),
|
|
546
|
-
this.fetchAndEnrichWorkflows()
|
|
547
|
-
]);
|
|
530
|
+
// Single API call — getAIAgentsSchema now returns prompt order/description
|
|
531
|
+
const agentData = await this.callGetAIAgentsSchema();
|
|
548
532
|
const agents = agentData.agents || [];
|
|
549
|
-
//
|
|
550
|
-
const promptLookup = new Map();
|
|
551
|
-
for (const wf of workflows) {
|
|
552
|
-
for (const p of wf.prompts || []) {
|
|
553
|
-
promptLookup.set(p.id, p);
|
|
554
|
-
}
|
|
555
|
-
}
|
|
556
|
-
// Enrich agent workflows using the lookup — no extra API calls
|
|
533
|
+
// Sort prompts within each workflow by order
|
|
557
534
|
for (const agent of agents) {
|
|
558
535
|
if (!agent.workflows)
|
|
559
536
|
continue;
|
|
@@ -561,16 +538,13 @@ class SecondBrainOSServer {
|
|
|
561
538
|
if (!workflow.prompts || workflow.prompts.length === 0)
|
|
562
539
|
continue;
|
|
563
540
|
workflow.prompts = workflow.prompts
|
|
564
|
-
.map((prompt) => {
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
};
|
|
572
|
-
})
|
|
573
|
-
.sort((a, b) => (a.order || 0) - (b.order || 0));
|
|
541
|
+
.map((prompt) => ({
|
|
542
|
+
id: prompt.id,
|
|
543
|
+
name: prompt.name || '',
|
|
544
|
+
order: prompt.order || 0,
|
|
545
|
+
description: prompt.description || ''
|
|
546
|
+
}))
|
|
547
|
+
.sort((a, b) => (Number(a.order) || 0) - (Number(b.order) || 0));
|
|
574
548
|
}
|
|
575
549
|
}
|
|
576
550
|
this.cachedAgents = agents;
|
|
@@ -580,7 +554,7 @@ class SecondBrainOSServer {
|
|
|
580
554
|
if (this.cachedWorkflows)
|
|
581
555
|
return this.cachedWorkflows;
|
|
582
556
|
// Single API call — now returns all workflows with prompt metadata
|
|
583
|
-
const data = await this.callRunPromptChain(
|
|
557
|
+
const data = await this.callRunPromptChain();
|
|
584
558
|
const workflows = (data.workflows || []).filter((wf) => wf.name && wf.workflow_id);
|
|
585
559
|
const enriched = workflows.map((wf) => ({
|
|
586
560
|
...wf,
|
|
@@ -596,20 +570,9 @@ class SecondBrainOSServer {
|
|
|
596
570
|
this.cachedWorkflows = enriched;
|
|
597
571
|
return enriched;
|
|
598
572
|
}
|
|
599
|
-
/**
|
|
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.
|
|
602
|
-
*/
|
|
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
573
|
/**
|
|
611
574
|
* Build the server-use context document content.
|
|
612
|
-
* Used by
|
|
575
|
+
* Used by the start_secondbrainos prompt.
|
|
613
576
|
*/
|
|
614
577
|
async buildServerUseContent() {
|
|
615
578
|
let agentIndex = '';
|
|
@@ -670,8 +633,6 @@ ${skillIndex || '_None configured_'}
|
|
|
670
633
|
// This method is kept for future error handling implementations
|
|
671
634
|
}
|
|
672
635
|
async run() {
|
|
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));
|
|
675
636
|
const transport = new StdioServerTransport();
|
|
676
637
|
await this.server.connect(transport);
|
|
677
638
|
console.error("Second Brain OS MCP server running on stdio");
|