Skip to content

Commit 778cbab

Browse files
fix(mcp): initialize SDK lazily to avoid failing the connection on init errors
1 parent ffbde42 commit 778cbab

File tree

3 files changed

+63
-36
lines changed

3 files changed

+63
-36
lines changed

packages/mcp-server/src/http.ts

Lines changed: 10 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -24,28 +24,17 @@ const newServer = async ({
2424
const stainlessApiKey = getStainlessApiKey(req, mcpOptions);
2525
const server = await newMcpServer(stainlessApiKey);
2626

27-
try {
28-
const authOptions = parseClientAuthHeaders(req, false);
27+
const authOptions = parseClientAuthHeaders(req, false);
2928

30-
await initMcpServer({
31-
server: server,
32-
mcpOptions: mcpOptions,
33-
clientOptions: {
34-
...clientOptions,
35-
...authOptions,
36-
},
37-
stainlessApiKey: stainlessApiKey,
38-
});
39-
} catch (error) {
40-
res.status(401).json({
41-
jsonrpc: '2.0',
42-
error: {
43-
code: -32000,
44-
message: `Unauthorized: ${error instanceof Error ? error.message : error}`,
45-
},
46-
});
47-
return null;
48-
}
29+
await initMcpServer({
30+
server: server,
31+
mcpOptions: mcpOptions,
32+
clientOptions: {
33+
...clientOptions,
34+
...authOptions,
35+
},
36+
stainlessApiKey: stainlessApiKey,
37+
});
4938

5039
return server;
5140
};

packages/mcp-server/src/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ async function main() {
2424
await launchStreamableHTTPServer({
2525
mcpOptions: options,
2626
debug: options.debug,
27-
port: options.port ?? options.socket,
27+
port: options.socket ?? options.port,
2828
});
2929
break;
3030
}

packages/mcp-server/src/server.ts

Lines changed: 52 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -56,15 +56,33 @@ export async function initMcpServer(params: {
5656
error: logAtLevel('error'),
5757
};
5858

59-
let client = new Dedalus({
60-
...{ environment: (readEnv('DEDALUS_ENVIRONMENT') || undefined) as any },
61-
logger,
62-
...params.clientOptions,
63-
defaultHeaders: {
64-
...params.clientOptions?.defaultHeaders,
65-
'X-Stainless-MCP': 'true',
66-
},
67-
});
59+
let _client: Dedalus | undefined;
60+
let _clientError: Error | undefined;
61+
let _logLevel: 'debug' | 'info' | 'warn' | 'error' | 'off' | undefined;
62+
63+
const getClient = (): Dedalus => {
64+
if (_clientError) throw _clientError;
65+
if (!_client) {
66+
try {
67+
_client = new Dedalus({
68+
...{ environment: (readEnv('DEDALUS_ENVIRONMENT') || undefined) as any },
69+
logger,
70+
...params.clientOptions,
71+
defaultHeaders: {
72+
...params.clientOptions?.defaultHeaders,
73+
'X-Stainless-MCP': 'true',
74+
},
75+
});
76+
if (_logLevel) {
77+
_client = _client.withOptions({ logLevel: _logLevel });
78+
}
79+
} catch (e) {
80+
_clientError = e instanceof Error ? e : new Error(String(e));
81+
throw _clientError;
82+
}
83+
}
84+
return _client;
85+
};
6886

6987
const providedTools = selectTools(params.mcpOptions);
7088
const toolMap = Object.fromEntries(providedTools.map((mcpTool) => [mcpTool.tool.name, mcpTool]));
@@ -82,6 +100,21 @@ export async function initMcpServer(params: {
82100
throw new Error(`Unknown tool: ${name}`);
83101
}
84102

103+
let client: Dedalus;
104+
try {
105+
client = getClient();
106+
} catch (error) {
107+
return {
108+
content: [
109+
{
110+
type: 'text' as const,
111+
text: `Failed to initialize client: ${error instanceof Error ? error.message : String(error)}`,
112+
},
113+
],
114+
isError: true,
115+
};
116+
}
117+
85118
return executeHandler({
86119
handler: mcpTool.handler,
87120
reqContext: {
@@ -94,24 +127,29 @@ export async function initMcpServer(params: {
94127

95128
server.setRequestHandler(SetLevelRequestSchema, async (request) => {
96129
const { level } = request.params;
130+
let logLevel: 'debug' | 'info' | 'warn' | 'error' | 'off';
97131
switch (level) {
98132
case 'debug':
99-
client = client.withOptions({ logLevel: 'debug' });
133+
logLevel = 'debug';
100134
break;
101135
case 'info':
102-
client = client.withOptions({ logLevel: 'info' });
136+
logLevel = 'info';
103137
break;
104138
case 'notice':
105139
case 'warning':
106-
client = client.withOptions({ logLevel: 'warn' });
140+
logLevel = 'warn';
107141
break;
108142
case 'error':
109-
client = client.withOptions({ logLevel: 'error' });
143+
logLevel = 'error';
110144
break;
111145
default:
112-
client = client.withOptions({ logLevel: 'off' });
146+
logLevel = 'off';
113147
break;
114148
}
149+
_logLevel = logLevel;
150+
if (_client) {
151+
_client = _client.withOptions({ logLevel });
152+
}
115153
return {};
116154
});
117155
}

0 commit comments

Comments
 (0)