secondbrainos-mcp-server 1.4.7 → 1.4.9
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 +35 -78
- package/package.json +1 -1
package/build/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
2
2
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
3
3
|
import { ListResourcesRequestSchema, ReadResourceRequestSchema, ListToolsRequestSchema, CallToolRequestSchema, ListPromptsRequestSchema, GetPromptRequestSchema, ErrorCode, McpError } from "@modelcontextprotocol/sdk/types.js";
|
|
4
|
-
import { OpenApi, HttpLlm
|
|
4
|
+
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';
|
|
@@ -142,97 +142,52 @@ class SecondBrainOSServer {
|
|
|
142
142
|
try {
|
|
143
143
|
// Intercept file_path arguments: upload local files to GCS
|
|
144
144
|
const processedArgs = await this.interceptFilePathArgs((request.params.arguments || {}));
|
|
145
|
-
// Use HttpLlm.
|
|
146
|
-
|
|
145
|
+
// Use HttpLlm.propagate to get full response (status + body)
|
|
146
|
+
// instead of HttpLlm.execute which throws HttpError and loses
|
|
147
|
+
// the response body (Error constructor coerces objects to "[object Object]")
|
|
148
|
+
const response = await HttpLlm.propagate({
|
|
147
149
|
connection: {
|
|
148
150
|
host: this.baseUrl,
|
|
149
151
|
headers: {
|
|
150
152
|
'Authorization': `Bearer ${this.userId}:${this.userSecret}`
|
|
151
153
|
}
|
|
152
154
|
},
|
|
153
|
-
application: this.application,
|
|
155
|
+
application: this.application,
|
|
154
156
|
function: func,
|
|
155
157
|
input: processedArgs
|
|
156
158
|
});
|
|
157
|
-
return
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
}
|
|
162
|
-
};
|
|
163
|
-
}
|
|
164
|
-
catch (error) {
|
|
165
|
-
// HttpError from @samchon/openapi — its constructor passes the
|
|
166
|
-
// parsed response body (an object) to super(), so Error coerces it
|
|
167
|
-
// to "[object Object]" and the original detail is lost.
|
|
168
|
-
// We can only rely on error.status for meaningful messages.
|
|
169
|
-
if (error instanceof HttpError) {
|
|
170
|
-
let mcpError;
|
|
171
|
-
switch (error.status) {
|
|
172
|
-
case 401:
|
|
173
|
-
mcpError = 'Authentication failed: Invalid or expired credentials';
|
|
174
|
-
break;
|
|
175
|
-
case 400:
|
|
176
|
-
mcpError = `Bad request (${error.method} ${error.path})`;
|
|
177
|
-
break;
|
|
178
|
-
case 403:
|
|
179
|
-
mcpError = `Insufficient credits or permissions (${error.method} ${error.path})`;
|
|
180
|
-
break;
|
|
181
|
-
case 404:
|
|
182
|
-
mcpError = `Service or resource not found (${error.method} ${error.path})`;
|
|
183
|
-
break;
|
|
184
|
-
default:
|
|
185
|
-
mcpError = `Error ${error.status} (${error.method} ${error.path})`;
|
|
186
|
-
}
|
|
187
|
-
return {
|
|
188
|
-
content: [{
|
|
189
|
-
type: 'text',
|
|
190
|
-
text: mcpError
|
|
191
|
-
}],
|
|
192
|
-
isError: true
|
|
193
|
-
};
|
|
194
|
-
}
|
|
195
|
-
else if (axios.isAxiosError(error)) {
|
|
196
|
-
const status = error.response?.status;
|
|
197
|
-
const rawError = error.response?.data?.error || error.response?.data?.message || error.message;
|
|
198
|
-
const errorMessage = typeof rawError === 'object' ? JSON.stringify(rawError) : rawError;
|
|
199
|
-
let mcpError;
|
|
200
|
-
switch (status) {
|
|
201
|
-
case 401:
|
|
202
|
-
mcpError = 'Authentication failed: Invalid or expired credentials';
|
|
203
|
-
break;
|
|
204
|
-
case 400:
|
|
205
|
-
mcpError = `Bad request: ${errorMessage}`;
|
|
206
|
-
break;
|
|
207
|
-
case 403:
|
|
208
|
-
mcpError = 'Insufficient credits or permissions';
|
|
209
|
-
break;
|
|
210
|
-
case 404:
|
|
211
|
-
mcpError = 'Service or resource not found';
|
|
212
|
-
break;
|
|
213
|
-
default:
|
|
214
|
-
mcpError = `Error calling function: ${errorMessage}`;
|
|
215
|
-
}
|
|
216
|
-
return {
|
|
217
|
-
content: [{
|
|
218
|
-
type: 'text',
|
|
219
|
-
text: mcpError
|
|
220
|
-
}],
|
|
221
|
-
isError: true
|
|
222
|
-
};
|
|
223
|
-
}
|
|
224
|
-
else {
|
|
225
|
-
const msg = error instanceof Error
|
|
226
|
-
? error.message
|
|
227
|
-
: (typeof error === 'object' ? JSON.stringify(error) : String(error));
|
|
159
|
+
// Non-success status — return the full error body
|
|
160
|
+
if (response.status !== 200 && response.status !== 201) {
|
|
161
|
+
const detail = typeof response.body === 'object'
|
|
162
|
+
? JSON.stringify(response.body)
|
|
163
|
+
: String(response.body ?? `HTTP ${response.status}`);
|
|
228
164
|
return {
|
|
229
165
|
content: [{
|
|
230
166
|
type: 'text',
|
|
231
|
-
text:
|
|
167
|
+
text: detail
|
|
232
168
|
}],
|
|
233
169
|
isError: true
|
|
234
170
|
};
|
|
235
171
|
}
|
|
172
|
+
return {
|
|
173
|
+
content: [{
|
|
174
|
+
type: 'text',
|
|
175
|
+
text: JSON.stringify(response.body, null, 2)
|
|
176
|
+
}]
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
catch (error) {
|
|
180
|
+
// Connection failures or unexpected errors
|
|
181
|
+
const msg = error instanceof Error
|
|
182
|
+
? error.message
|
|
183
|
+
: (typeof error === 'object' ? JSON.stringify(error) : String(error));
|
|
184
|
+
return {
|
|
185
|
+
content: [{
|
|
186
|
+
type: 'text',
|
|
187
|
+
text: `Error calling function: ${msg}`
|
|
188
|
+
}],
|
|
189
|
+
isError: true
|
|
190
|
+
};
|
|
236
191
|
}
|
|
237
192
|
});
|
|
238
193
|
// List available prompts (user's workflows + agents)
|
|
@@ -720,11 +675,13 @@ class SecondBrainOSServer {
|
|
|
720
675
|
// This method is kept for future error handling implementations
|
|
721
676
|
}
|
|
722
677
|
async run() {
|
|
723
|
-
// Write skill files before connecting so Claude Code sees them at session start
|
|
724
|
-
await this.writeSkillFiles().catch(err => console.error('Failed to write skill files:', err));
|
|
725
678
|
const transport = new StdioServerTransport();
|
|
726
679
|
await this.server.connect(transport);
|
|
727
680
|
console.error("Second Brain OS MCP server running on stdio");
|
|
681
|
+
// Write skill files AFTER connecting so the MCP handshake completes
|
|
682
|
+
// within Claude Code's 30s timeout. Skill files are written in the
|
|
683
|
+
// background — they'll be available for subsequent conversations.
|
|
684
|
+
this.writeSkillFiles().catch(err => console.error('Failed to write skill files:', err));
|
|
728
685
|
}
|
|
729
686
|
}
|
|
730
687
|
SecondBrainOSServer.ALLOWED_EXTENSIONS = ['.txt', '.md'];
|