secondbrainos-mcp-server 1.1.0 → 1.2.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 +194 -48
- package/package.json +1 -1
package/build/index.js
CHANGED
|
@@ -30,19 +30,24 @@ class SecondBrainOSServer {
|
|
|
30
30
|
this.functionMap.set(operation.operationId, func);
|
|
31
31
|
}
|
|
32
32
|
});
|
|
33
|
-
// Initialize
|
|
33
|
+
// Initialize maps and cache
|
|
34
34
|
this.workflowNameToId = new Map();
|
|
35
|
-
|
|
35
|
+
this.agentNameToId = new Map();
|
|
36
|
+
this.cachedAgents = null;
|
|
37
|
+
// Discover service paths from the OpenAPI schema
|
|
36
38
|
this.runPromptChainPath = null;
|
|
39
|
+
this.getAIAgentsSchemaPath = null;
|
|
37
40
|
if (initialSchema.paths) {
|
|
38
41
|
for (const [path, pathItem] of Object.entries(initialSchema.paths)) {
|
|
39
42
|
for (const operation of Object.values(pathItem)) {
|
|
40
43
|
if (operation.operationId === 'runPromptChain') {
|
|
41
44
|
this.runPromptChainPath = path;
|
|
42
|
-
|
|
45
|
+
}
|
|
46
|
+
if (operation.operationId === 'getAIAgentsSchema') {
|
|
47
|
+
this.getAIAgentsSchemaPath = path;
|
|
43
48
|
}
|
|
44
49
|
}
|
|
45
|
-
if (this.runPromptChainPath)
|
|
50
|
+
if (this.runPromptChainPath && this.getAIAgentsSchemaPath)
|
|
46
51
|
break;
|
|
47
52
|
}
|
|
48
53
|
}
|
|
@@ -181,66 +186,112 @@ class SecondBrainOSServer {
|
|
|
181
186
|
throw error;
|
|
182
187
|
}
|
|
183
188
|
});
|
|
184
|
-
// List available prompts (user's workflows)
|
|
189
|
+
// List available prompts (user's workflows + agents)
|
|
185
190
|
this.server.setRequestHandler(ListPromptsRequestSchema, async () => {
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
191
|
+
const prompts = [];
|
|
192
|
+
// Fetch workflows as prompts
|
|
193
|
+
if (this.runPromptChainPath) {
|
|
194
|
+
try {
|
|
195
|
+
const data = await this.callRunPromptChain('', '');
|
|
196
|
+
const workflows = data.workflows || [];
|
|
197
|
+
this.workflowNameToId.clear();
|
|
198
|
+
for (const wf of workflows) {
|
|
199
|
+
if (wf.name && wf.workflow_id) {
|
|
200
|
+
this.workflowNameToId.set(wf.name, wf.workflow_id);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
for (const wf of workflows) {
|
|
204
|
+
prompts.push({
|
|
205
|
+
name: wf.name || wf.workflow_id,
|
|
206
|
+
description: wf.description || wf.name,
|
|
207
|
+
arguments: [
|
|
208
|
+
{
|
|
209
|
+
name: "user_input",
|
|
210
|
+
description: "Optional context or input to guide the workflow execution",
|
|
211
|
+
required: false
|
|
212
|
+
}
|
|
213
|
+
]
|
|
214
|
+
});
|
|
197
215
|
}
|
|
198
216
|
}
|
|
199
|
-
|
|
200
|
-
prompts:
|
|
201
|
-
|
|
202
|
-
description: wf.description || wf.name,
|
|
203
|
-
arguments: [
|
|
204
|
-
{
|
|
205
|
-
name: "user_input",
|
|
206
|
-
description: "Optional context or input to guide the workflow execution",
|
|
207
|
-
required: false
|
|
208
|
-
}
|
|
209
|
-
]
|
|
210
|
-
}))
|
|
211
|
-
};
|
|
217
|
+
catch (error) {
|
|
218
|
+
console.error('Failed to fetch workflows for prompts/list:', error);
|
|
219
|
+
}
|
|
212
220
|
}
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
221
|
+
// Fetch agents as prompts
|
|
222
|
+
if (this.getAIAgentsSchemaPath) {
|
|
223
|
+
try {
|
|
224
|
+
const agents = await this.fetchAndEnrichAgents();
|
|
225
|
+
this.agentNameToId.clear();
|
|
226
|
+
for (const agent of agents) {
|
|
227
|
+
if (agent.name && agent.id) {
|
|
228
|
+
const agentPromptName = `[Agent] ${agent.name}`;
|
|
229
|
+
this.agentNameToId.set(agentPromptName, agent.id);
|
|
230
|
+
prompts.push({
|
|
231
|
+
name: agentPromptName,
|
|
232
|
+
description: agent.description || agent.name,
|
|
233
|
+
arguments: [
|
|
234
|
+
{
|
|
235
|
+
name: "user_input",
|
|
236
|
+
description: "Optional context or input to guide the agent",
|
|
237
|
+
required: false
|
|
238
|
+
}
|
|
239
|
+
]
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
catch (error) {
|
|
245
|
+
console.error('Failed to fetch agents for prompts/list:', error);
|
|
246
|
+
}
|
|
216
247
|
}
|
|
248
|
+
return { prompts };
|
|
217
249
|
});
|
|
218
|
-
// Get a specific prompt (workflow
|
|
250
|
+
// Get a specific prompt (workflow prompt chain or agent document)
|
|
219
251
|
this.server.setRequestHandler(GetPromptRequestSchema, async (request) => {
|
|
220
252
|
const promptName = request.params.name;
|
|
221
|
-
const workflowId = this.workflowNameToId.get(promptName) || promptName;
|
|
222
253
|
const userInput = request.params.arguments?.user_input;
|
|
223
|
-
//
|
|
224
|
-
const
|
|
225
|
-
|
|
254
|
+
// Check if this is an agent prompt
|
|
255
|
+
const agentId = this.agentNameToId.get(promptName);
|
|
256
|
+
if (agentId) {
|
|
257
|
+
return this.buildAgentPrompt(agentId, userInput);
|
|
258
|
+
}
|
|
259
|
+
// Otherwise treat as a workflow prompt
|
|
260
|
+
const workflowId = this.workflowNameToId.get(promptName) || promptName;
|
|
261
|
+
// Fetch workflow metadata from the workflows list
|
|
262
|
+
const workflowsData = await this.callRunPromptChain('', '');
|
|
263
|
+
const workflowMeta = (workflowsData.workflows || []).find((wf) => wf.workflow_id === workflowId);
|
|
264
|
+
const workflowDetail = await this.callRunPromptChain('workflow', workflowId);
|
|
265
|
+
const promptIds = workflowDetail.prompt_id || [];
|
|
226
266
|
if (promptIds.length === 0) {
|
|
227
267
|
throw new McpError(ErrorCode.InvalidRequest, `No prompts found for workflow: ${workflowId}`);
|
|
228
268
|
}
|
|
229
|
-
// Fetch
|
|
230
|
-
const promptResults = await Promise.all(promptIds.map((promptId) =>
|
|
231
|
-
|
|
269
|
+
// Fetch prompt metadata (no instructions)
|
|
270
|
+
const promptResults = await Promise.all(promptIds.map(async (promptId) => {
|
|
271
|
+
const promptData = await this.callRunPromptChain('prompt', promptId);
|
|
272
|
+
return {
|
|
273
|
+
id: promptId,
|
|
274
|
+
name: promptData.name,
|
|
275
|
+
order: promptData.order,
|
|
276
|
+
description: promptData.description || ''
|
|
277
|
+
};
|
|
278
|
+
}));
|
|
232
279
|
const sortedPrompts = promptResults.sort((a, b) => (a.order || 0) - (b.order || 0));
|
|
233
|
-
const
|
|
234
|
-
|
|
235
|
-
|
|
280
|
+
const workflowDocument = {
|
|
281
|
+
workflow_id: workflowId,
|
|
282
|
+
name: workflowMeta?.name || promptName,
|
|
283
|
+
description: workflowMeta?.description || '',
|
|
284
|
+
prompts: sortedPrompts
|
|
285
|
+
};
|
|
286
|
+
const messages = [
|
|
287
|
+
{
|
|
236
288
|
role: "user",
|
|
237
289
|
content: {
|
|
238
290
|
type: "text",
|
|
239
|
-
text:
|
|
291
|
+
text: JSON.stringify(workflowDocument, null, 2)
|
|
240
292
|
}
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
// If user provided input, append it as the final message
|
|
293
|
+
}
|
|
294
|
+
];
|
|
244
295
|
if (userInput) {
|
|
245
296
|
messages.push({
|
|
246
297
|
role: "user",
|
|
@@ -251,11 +302,58 @@ class SecondBrainOSServer {
|
|
|
251
302
|
});
|
|
252
303
|
}
|
|
253
304
|
return {
|
|
254
|
-
description: `Workflow
|
|
305
|
+
description: `Workflow: ${workflowDocument.name} (${sortedPrompts.length} prompts)`,
|
|
255
306
|
messages
|
|
256
307
|
};
|
|
257
308
|
});
|
|
258
309
|
}
|
|
310
|
+
async buildAgentPrompt(agentId, userInput) {
|
|
311
|
+
const agents = await this.fetchAndEnrichAgents();
|
|
312
|
+
const agent = agents.find((a) => a.id === agentId);
|
|
313
|
+
if (!agent) {
|
|
314
|
+
throw new McpError(ErrorCode.InvalidRequest, `Agent not found: ${agentId}`);
|
|
315
|
+
}
|
|
316
|
+
// Build the agent document as a structured JSON object
|
|
317
|
+
const agentDocument = {
|
|
318
|
+
name: agent.name,
|
|
319
|
+
description: agent.description || '',
|
|
320
|
+
behaviour_and_instructions: agent.behaviour_and_instructions || '',
|
|
321
|
+
actions: agent.actions || [],
|
|
322
|
+
workflows: (agent.workflows || []).map((wf) => ({
|
|
323
|
+
id: wf.id,
|
|
324
|
+
name: wf.name,
|
|
325
|
+
prompts: (wf.prompts || []).map((p) => ({
|
|
326
|
+
id: p.id,
|
|
327
|
+
name: p.name,
|
|
328
|
+
order: p.order,
|
|
329
|
+
description: p.description
|
|
330
|
+
}))
|
|
331
|
+
}))
|
|
332
|
+
};
|
|
333
|
+
const messages = [
|
|
334
|
+
{
|
|
335
|
+
role: "user",
|
|
336
|
+
content: {
|
|
337
|
+
type: "text",
|
|
338
|
+
text: JSON.stringify(agentDocument, null, 2)
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
];
|
|
342
|
+
if (userInput) {
|
|
343
|
+
messages.push({
|
|
344
|
+
role: "user",
|
|
345
|
+
content: {
|
|
346
|
+
type: "text",
|
|
347
|
+
text: userInput
|
|
348
|
+
}
|
|
349
|
+
});
|
|
350
|
+
}
|
|
351
|
+
const skillCount = agentDocument.workflows.length;
|
|
352
|
+
return {
|
|
353
|
+
description: `Agent: ${agent.name} (${skillCount} skill${skillCount !== 1 ? 's' : ''})`,
|
|
354
|
+
messages
|
|
355
|
+
};
|
|
356
|
+
}
|
|
259
357
|
async callRunPromptChain(entity, entityId) {
|
|
260
358
|
if (!this.runPromptChainPath) {
|
|
261
359
|
throw new McpError(ErrorCode.InternalError, 'runPromptChain service not available for this user');
|
|
@@ -272,6 +370,54 @@ class SecondBrainOSServer {
|
|
|
272
370
|
});
|
|
273
371
|
return response.data;
|
|
274
372
|
}
|
|
373
|
+
async callGetAIAgentsSchema() {
|
|
374
|
+
if (!this.getAIAgentsSchemaPath) {
|
|
375
|
+
throw new McpError(ErrorCode.InternalError, 'getAIAgentsSchema service not available for this user');
|
|
376
|
+
}
|
|
377
|
+
const url = `${this.baseUrl}${this.getAIAgentsSchemaPath}`;
|
|
378
|
+
const response = await axios.post(url, {
|
|
379
|
+
include_sensitive_config: true
|
|
380
|
+
}, {
|
|
381
|
+
headers: {
|
|
382
|
+
'Authorization': `Bearer ${this.userId}:${this.userSecret}`,
|
|
383
|
+
'Content-Type': 'application/json'
|
|
384
|
+
}
|
|
385
|
+
});
|
|
386
|
+
return response.data;
|
|
387
|
+
}
|
|
388
|
+
async fetchAndEnrichAgents() {
|
|
389
|
+
if (this.cachedAgents)
|
|
390
|
+
return this.cachedAgents;
|
|
391
|
+
const data = await this.callGetAIAgentsSchema();
|
|
392
|
+
const agents = data.agents || [];
|
|
393
|
+
// Enrich each agent's workflows with full prompt details
|
|
394
|
+
for (const agent of agents) {
|
|
395
|
+
if (!agent.workflows)
|
|
396
|
+
continue;
|
|
397
|
+
for (const workflow of agent.workflows) {
|
|
398
|
+
if (!workflow.prompts || workflow.prompts.length === 0)
|
|
399
|
+
continue;
|
|
400
|
+
// Fetch prompt metadata (name, order, description) — no instructions
|
|
401
|
+
const enrichedPrompts = await Promise.all(workflow.prompts.map(async (prompt) => {
|
|
402
|
+
try {
|
|
403
|
+
const promptData = await this.callRunPromptChain('prompt', prompt.id);
|
|
404
|
+
return {
|
|
405
|
+
id: prompt.id,
|
|
406
|
+
name: promptData.name || prompt.name,
|
|
407
|
+
order: promptData.order,
|
|
408
|
+
description: promptData.description || ''
|
|
409
|
+
};
|
|
410
|
+
}
|
|
411
|
+
catch {
|
|
412
|
+
return { id: prompt.id, name: prompt.name, order: 0, description: '' };
|
|
413
|
+
}
|
|
414
|
+
}));
|
|
415
|
+
workflow.prompts = enrichedPrompts.sort((a, b) => (a.order || 0) - (b.order || 0));
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
this.cachedAgents = agents;
|
|
419
|
+
return agents;
|
|
420
|
+
}
|
|
275
421
|
setupErrorHandling() {
|
|
276
422
|
// Error handling is now built into HttpLlm.execute
|
|
277
423
|
// This method is kept for future error handling implementations
|