secondbrainos-mcp-server 1.2.3 → 1.2.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.
- package/README.md +30 -10
- package/bin/cli.js +137 -29
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
# Second Brain OS MCP Server
|
|
2
2
|
|
|
3
|
-
This package provides a Model Context Protocol (MCP) server for integrating Second Brain OS with Claude Desktop.
|
|
3
|
+
This package provides a Model Context Protocol (MCP) server for integrating Second Brain OS with Claude Desktop and Claude Code.
|
|
4
4
|
|
|
5
5
|
## Prerequisites
|
|
6
6
|
|
|
7
7
|
- Node.js v16 or higher
|
|
8
|
-
- Claude Desktop application
|
|
8
|
+
- Claude Desktop application and/or Claude Code CLI
|
|
9
9
|
- A valid Second Brain OS account with the Claude MCP feature enabled
|
|
10
10
|
|
|
11
11
|
## Installation
|
|
@@ -28,6 +28,16 @@ This will:
|
|
|
28
28
|
3. Create the necessary configuration files for Claude Desktop
|
|
29
29
|
4. Configure the server to dynamically fetch your available API endpoints
|
|
30
30
|
|
|
31
|
+
### Claude Code
|
|
32
|
+
|
|
33
|
+
To add the server to Claude Code:
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
claude mcp add secondbrainos-mcp-server -- npx secondbrainos-mcp-server
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Or add it to your project's `.mcp.json` file.
|
|
40
|
+
|
|
31
41
|
## Features
|
|
32
42
|
|
|
33
43
|
### Enhanced OpenAPI Support
|
|
@@ -41,13 +51,23 @@ The server uses `@samchon/openapi` library for robust OpenAPI handling, providin
|
|
|
41
51
|
- Automatic request formatting based on OpenAPI specifications
|
|
42
52
|
- Support for complex parameters and nested objects
|
|
43
53
|
|
|
44
|
-
### Prompts
|
|
45
|
-
The server exposes
|
|
54
|
+
### Prompts
|
|
55
|
+
The server exposes three types of MCP prompts, available in the client's attach menu:
|
|
56
|
+
|
|
57
|
+
#### Skills (Workflows)
|
|
46
58
|
- Automatically discovers your workflows via the `runPromptChain` service
|
|
47
|
-
- Each
|
|
48
|
-
- Selecting a prompt fetches the full prompt chain (ordered instructions) and injects them into the conversation
|
|
59
|
+
- 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)
|
|
49
60
|
- Supports an optional `user_input` argument to provide additional context
|
|
50
61
|
|
|
62
|
+
#### Agents
|
|
63
|
+
- Discovers your AI agents via the `getAIAgentsSchema` service
|
|
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 enriched prompt metadata)
|
|
65
|
+
- Supports an optional `user_input` argument
|
|
66
|
+
|
|
67
|
+
#### Knowledge Bases
|
|
68
|
+
- Aggregates all `searchMyKnowledge_collection_id` values from your agents
|
|
69
|
+
- Appears as a single `[Knowledge Bases]` prompt returning an array of collection IDs
|
|
70
|
+
|
|
51
71
|
### Better Error Handling
|
|
52
72
|
- Detailed error messages for debugging
|
|
53
73
|
- Proper handling of authentication failures, bad requests, and service errors
|
|
@@ -124,14 +144,14 @@ The server requires the following environment variables:
|
|
|
124
144
|
1. **Schema Fetching**: On startup, the server fetches your personalized OpenAPI schema from Second Brain OS
|
|
125
145
|
2. **Schema Conversion**: The `@samchon/openapi` library converts the schema to an optimized format for LLM function calling
|
|
126
146
|
3. **MCP Tools**: Each API endpoint becomes an MCP tool that Claude can use
|
|
127
|
-
4. **MCP Prompts**:
|
|
147
|
+
4. **MCP Prompts**: Your skills (workflows), AI agents, and knowledge bases are exposed as selectable prompts in the client UI
|
|
128
148
|
5. **Function Execution**: When Claude calls a tool, the server executes the corresponding API call with proper authentication
|
|
129
149
|
|
|
130
150
|
## Troubleshooting
|
|
131
151
|
|
|
132
|
-
###
|
|
133
|
-
1.
|
|
134
|
-
2.
|
|
152
|
+
### Client doesn't see the server
|
|
153
|
+
1. **Claude Desktop**: Ensure it's completely quit before running setup. Check the configuration file was created at the correct location.
|
|
154
|
+
2. **Claude Code**: Run `claude mcp add` or check your `.mcp.json` configuration.
|
|
135
155
|
3. Review the logs at the platform-specific location mentioned during setup
|
|
136
156
|
|
|
137
157
|
### Authentication errors
|
package/bin/cli.js
CHANGED
|
@@ -129,13 +129,103 @@ async function readExistingConfig(configPath) {
|
|
|
129
129
|
}
|
|
130
130
|
}
|
|
131
131
|
|
|
132
|
+
/**
|
|
133
|
+
* Get the credentials file path
|
|
134
|
+
*/
|
|
135
|
+
function getCredentialsPath() {
|
|
136
|
+
return path.join(homedir(), '.secondbrainos', 'credentials.json');
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Store credentials to ~/.secondbrainos/credentials.json
|
|
141
|
+
*/
|
|
142
|
+
async function storeCredentials(USER_ID, USER_SECRET) {
|
|
143
|
+
const credDir = path.join(homedir(), '.secondbrainos');
|
|
144
|
+
await fs.mkdir(credDir, { recursive: true });
|
|
145
|
+
await fs.writeFile(
|
|
146
|
+
getCredentialsPath(),
|
|
147
|
+
JSON.stringify({ USER_ID, USER_SECRET, API_BASE_URL: 'https://api.secondbrainos.com' }, null, 2),
|
|
148
|
+
{ mode: 0o600 }
|
|
149
|
+
);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Configure Claude Code via `claude mcp add`
|
|
154
|
+
*/
|
|
155
|
+
async function configureClaudeCode(serverPath, nodePath) {
|
|
156
|
+
try {
|
|
157
|
+
const { stdout } = await execAsync('which claude').catch(() => ({ stdout: '' }));
|
|
158
|
+
if (!stdout.trim()) {
|
|
159
|
+
console.log('\nClaude Code CLI not found — skipping Claude Code configuration.');
|
|
160
|
+
console.log('To set up Claude Code later, install it and run this setup again.');
|
|
161
|
+
return false;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// Remove existing config first (ignore errors if it doesn't exist)
|
|
165
|
+
await execAsync('claude mcp remove secondbrainos -s user').catch(() => {});
|
|
166
|
+
|
|
167
|
+
// Add the server with serve subcommand
|
|
168
|
+
await execAsync(`claude mcp add secondbrainos -s user -- ${nodePath} ${serverPath} serve`);
|
|
169
|
+
console.log('Claude Code configured successfully!');
|
|
170
|
+
return true;
|
|
171
|
+
} catch (error) {
|
|
172
|
+
console.log(`\nClaude Code auto-configuration failed: ${error.message}`);
|
|
173
|
+
console.log('You can manually configure it by running:');
|
|
174
|
+
console.log(` claude mcp add secondbrainos -s user -- ${nodePath} ${serverPath} serve`);
|
|
175
|
+
return false;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Run the MCP server (serve mode)
|
|
181
|
+
*/
|
|
182
|
+
async function serve() {
|
|
183
|
+
// Load credentials from stored file, with env var override
|
|
184
|
+
let USER_ID = process.env.USER_ID;
|
|
185
|
+
let USER_SECRET = process.env.USER_SECRET;
|
|
186
|
+
let API_BASE_URL = process.env.API_BASE_URL;
|
|
187
|
+
|
|
188
|
+
if (!USER_ID || !USER_SECRET) {
|
|
189
|
+
try {
|
|
190
|
+
const creds = JSON.parse(await fs.readFile(getCredentialsPath(), 'utf8'));
|
|
191
|
+
USER_ID = USER_ID || creds.USER_ID;
|
|
192
|
+
USER_SECRET = USER_SECRET || creds.USER_SECRET;
|
|
193
|
+
API_BASE_URL = API_BASE_URL || creds.API_BASE_URL;
|
|
194
|
+
} catch {
|
|
195
|
+
console.error('Error: No credentials found. Run setup first:');
|
|
196
|
+
console.error(' npx secondbrainos-mcp-server USER_ID USER_SECRET');
|
|
197
|
+
process.exit(1);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
if (!USER_ID || !USER_SECRET) {
|
|
202
|
+
console.error('Error: Missing USER_ID or USER_SECRET.');
|
|
203
|
+
process.exit(1);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
// Set env vars for the server process
|
|
207
|
+
process.env.USER_ID = USER_ID;
|
|
208
|
+
process.env.USER_SECRET = USER_SECRET;
|
|
209
|
+
process.env.API_BASE_URL = API_BASE_URL || 'https://api.secondbrainos.com';
|
|
210
|
+
|
|
211
|
+
// Import and run the server
|
|
212
|
+
const packageRoot = path.resolve(__dirname, '..');
|
|
213
|
+
const serverModule = path.join(packageRoot, 'build', 'index.js');
|
|
214
|
+
await import(serverModule);
|
|
215
|
+
}
|
|
216
|
+
|
|
132
217
|
async function main() {
|
|
133
218
|
try {
|
|
134
219
|
// Get command line arguments
|
|
135
220
|
const args = process.argv.slice(2);
|
|
136
|
-
|
|
221
|
+
|
|
222
|
+
// Handle serve subcommand
|
|
223
|
+
if (args.length === 1 && args[0] === 'serve') {
|
|
224
|
+
return await serve();
|
|
225
|
+
}
|
|
226
|
+
|
|
137
227
|
let USER_ID, USER_SECRET;
|
|
138
|
-
|
|
228
|
+
|
|
139
229
|
if (args.length === 1 && args[0].includes(':')) {
|
|
140
230
|
// Handle the combined format USER_ID:USER_SECRET
|
|
141
231
|
[USER_ID, USER_SECRET] = args[0].split(':');
|
|
@@ -145,70 +235,79 @@ async function main() {
|
|
|
145
235
|
} else {
|
|
146
236
|
console.error('Usage: secondbrainos-mcp USER_ID:USER_SECRET');
|
|
147
237
|
console.error(' or: secondbrainos-mcp USER_ID USER_SECRET');
|
|
238
|
+
console.error(' or: secondbrainos-mcp serve');
|
|
148
239
|
process.exit(1);
|
|
149
240
|
}
|
|
150
|
-
|
|
241
|
+
|
|
151
242
|
// Validate that we have both values
|
|
152
243
|
if (!USER_ID || !USER_SECRET) {
|
|
153
244
|
console.error('Error: Both USER_ID and USER_SECRET are required');
|
|
154
245
|
process.exit(1);
|
|
155
246
|
}
|
|
156
|
-
|
|
247
|
+
|
|
157
248
|
console.log('Verifying user credentials...');
|
|
158
|
-
|
|
249
|
+
|
|
159
250
|
// Verify user with the cloud function
|
|
160
251
|
try {
|
|
161
252
|
const verificationUrl = 'https://us-central1-second-brain-os.cloudfunctions.net/gcf-sbos-verifyuserdatapublic';
|
|
162
253
|
const response = await axios.post(verificationUrl, {
|
|
163
254
|
"x-user-api-key": `Bearer ${USER_ID}:${USER_SECRET}`
|
|
164
255
|
});
|
|
165
|
-
|
|
256
|
+
|
|
166
257
|
const { exists, email, features } = response.data;
|
|
167
|
-
|
|
258
|
+
|
|
168
259
|
if (!exists || exists !== 1) {
|
|
169
260
|
console.error('Error: User does not exist.');
|
|
170
261
|
process.exit(1);
|
|
171
262
|
}
|
|
172
|
-
|
|
263
|
+
|
|
173
264
|
if (!email) {
|
|
174
265
|
console.error('Error: User email not found.');
|
|
175
266
|
process.exit(1);
|
|
176
267
|
}
|
|
177
|
-
|
|
268
|
+
|
|
178
269
|
// Check if claudemcp feature is enabled
|
|
179
270
|
if (!features || typeof features !== 'string') {
|
|
180
271
|
console.error('Error: User features not found.');
|
|
181
272
|
process.exit(1);
|
|
182
273
|
}
|
|
183
|
-
|
|
274
|
+
|
|
184
275
|
const featuresList = features.toLowerCase().split(',').map(f => f.trim().replace(/\s+/g, ''));
|
|
185
276
|
if (!featuresList.includes('claudemcp')) {
|
|
186
277
|
console.error('Error: Claude MCP feature not enabled for this user.');
|
|
187
278
|
process.exit(1);
|
|
188
279
|
}
|
|
189
|
-
|
|
280
|
+
|
|
190
281
|
console.log('User verified successfully!');
|
|
191
|
-
|
|
282
|
+
|
|
192
283
|
} catch (error) {
|
|
193
284
|
console.error('Error verifying user:', error.message);
|
|
194
285
|
process.exit(1);
|
|
195
286
|
}
|
|
196
|
-
|
|
197
|
-
//
|
|
287
|
+
|
|
288
|
+
// Store credentials locally
|
|
289
|
+
try {
|
|
290
|
+
await storeCredentials(USER_ID, USER_SECRET);
|
|
291
|
+
console.log(`Credentials stored at: ${getCredentialsPath()}`);
|
|
292
|
+
} catch (error) {
|
|
293
|
+
console.error('Warning: Could not store credentials:', error.message);
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
// Configure Claude Desktop
|
|
198
297
|
const claudeConfigDir = getClaudeConfigPath();
|
|
199
298
|
const claudeConfigFile = path.join(claudeConfigDir, 'claude_desktop_config.json');
|
|
200
|
-
|
|
299
|
+
|
|
201
300
|
try {
|
|
202
301
|
await fs.mkdir(claudeConfigDir, { recursive: true });
|
|
203
302
|
} catch (error) {
|
|
204
303
|
console.error('Error creating config directory:', error);
|
|
205
304
|
process.exit(1);
|
|
206
305
|
}
|
|
207
|
-
|
|
306
|
+
|
|
208
307
|
// Get the absolute path to the installed package's index.js file
|
|
209
308
|
const packageRoot = path.resolve(__dirname, '..');
|
|
210
309
|
const serverPath = path.join(packageRoot, 'build', 'index.js');
|
|
211
|
-
|
|
310
|
+
|
|
212
311
|
// Check if serverPath exists
|
|
213
312
|
try {
|
|
214
313
|
await fs.access(serverPath);
|
|
@@ -217,21 +316,21 @@ async function main() {
|
|
|
217
316
|
console.error('This might be due to an incomplete installation. Try reinstalling the package with: npm install -g secondbrainos-mcp-server');
|
|
218
317
|
process.exit(1);
|
|
219
318
|
}
|
|
220
|
-
|
|
319
|
+
|
|
221
320
|
// Find Node.js executable
|
|
222
321
|
const nodePath = await findNodeExecutable();
|
|
223
|
-
|
|
322
|
+
|
|
224
323
|
// Read existing configuration
|
|
225
324
|
const existingConfig = await readExistingConfig(claudeConfigFile);
|
|
226
|
-
|
|
325
|
+
|
|
227
326
|
// Ensure mcpServers object exists
|
|
228
327
|
if (!existingConfig.mcpServers) {
|
|
229
328
|
existingConfig.mcpServers = {};
|
|
230
329
|
}
|
|
231
|
-
|
|
330
|
+
|
|
232
331
|
// Check if secondbrainos already exists
|
|
233
332
|
const hadExistingSecondBrainOS = !!existingConfig.mcpServers.secondbrainos;
|
|
234
|
-
|
|
333
|
+
|
|
235
334
|
// Add or update the secondbrainos server configuration
|
|
236
335
|
existingConfig.mcpServers.secondbrainos = {
|
|
237
336
|
command: nodePath,
|
|
@@ -243,30 +342,39 @@ async function main() {
|
|
|
243
342
|
NODE_PATH: getNodeModulesPath()
|
|
244
343
|
}
|
|
245
344
|
};
|
|
246
|
-
|
|
345
|
+
|
|
247
346
|
try {
|
|
248
347
|
// Write the updated configuration back
|
|
249
348
|
await fs.writeFile(claudeConfigFile, JSON.stringify(existingConfig, null, 2));
|
|
250
|
-
console.log(`
|
|
251
|
-
|
|
349
|
+
console.log(`Claude Desktop configuration ${hadExistingSecondBrainOS ? 'updated' : 'created'} at: ${claudeConfigFile}`);
|
|
350
|
+
|
|
252
351
|
// Show summary of configured servers
|
|
253
352
|
const serverCount = Object.keys(existingConfig.mcpServers).length;
|
|
254
353
|
console.log(`\nTotal MCP servers configured: ${serverCount}`);
|
|
255
354
|
console.log('Configured servers:', Object.keys(existingConfig.mcpServers).join(', '));
|
|
256
|
-
|
|
355
|
+
|
|
257
356
|
} catch (error) {
|
|
258
357
|
console.error('Error writing configuration file:', error);
|
|
259
358
|
process.exit(1);
|
|
260
359
|
}
|
|
261
|
-
|
|
360
|
+
|
|
361
|
+
// Configure Claude Code
|
|
362
|
+
const cliPath = path.join(packageRoot, 'bin', 'cli.js');
|
|
363
|
+
const claudeCodeConfigured = await configureClaudeCode(cliPath, nodePath);
|
|
364
|
+
|
|
262
365
|
console.log('\nInstallation successful!');
|
|
263
|
-
console.log('\
|
|
366
|
+
console.log('\nClaude Desktop:');
|
|
264
367
|
console.log('1. Completely quit Claude Desktop if it is running');
|
|
265
368
|
console.log('2. Restart Claude Desktop');
|
|
266
369
|
console.log('3. In the Chat Input inside Claude (i.e where you type your messages), you will now see a "🔨" icon which contains all the tools you have access to');
|
|
370
|
+
if (claudeCodeConfigured) {
|
|
371
|
+
console.log('\nClaude Code:');
|
|
372
|
+
console.log('1. Restart Claude Code if it is running');
|
|
373
|
+
console.log('2. Your Second Brain OS tools will be available automatically');
|
|
374
|
+
}
|
|
267
375
|
console.log('\nIf you encounter issues, check the logs:');
|
|
268
376
|
console.log(`${getLogPath()}`);
|
|
269
|
-
|
|
377
|
+
|
|
270
378
|
} catch (error) {
|
|
271
379
|
console.error('Unexpected error:', error);
|
|
272
380
|
process.exit(1);
|