Skip to content

Commit 213d234

Browse files
committed
chore: NodeDriverServiceProvider.connect blocks, breaking previous contract
NodeDriverServiceProvider.connect would return a Promise that was lazily connected. However, now, blocks until there is a ping from the server, forcing a connection. This would usually be fine, however, in OIDC it would mean blocking the whole MCP flow until the OIDC flow is connected. With the previous version, this was already handled, but now we need to split the logic a bit more to ensure that OIDC flows stay async.
1 parent bc39b6c commit 213d234

File tree

1 file changed

+34
-34
lines changed

1 file changed

+34
-34
lines changed

src/common/connectionManager.ts

Lines changed: 34 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ export interface ConnectionStateConnected extends ConnectionState {
3939

4040
export interface ConnectionStateConnecting extends ConnectionState {
4141
tag: "connecting";
42-
serviceProvider: NodeDriverServiceProvider;
42+
serviceProvider: Promise<NodeDriverServiceProvider>;
4343
oidcConnectionType: OIDCConnectionAuthType;
4444
oidcLoginUrl?: string;
4545
oidcUserCode?: string;
@@ -141,9 +141,10 @@ export class MCPConnectionManager extends ConnectionManager {
141141
await this.disconnect();
142142
}
143143

144-
let serviceProvider: NodeDriverServiceProvider;
144+
let serviceProvider: Promise<NodeDriverServiceProvider>;
145145
let connectionInfo: ConnectionInfo;
146146
let connectionStringAuthType: ConnectionStringAuthType = "scram";
147+
let isOidcConnection: boolean = false;
147148

148149
try {
149150
settings = { ...settings };
@@ -177,7 +178,8 @@ export class MCPConnectionManager extends ConnectionManager {
177178
connectionInfo
178179
);
179180

180-
serviceProvider = await NodeDriverServiceProvider.connect(
181+
isOidcConnection = connectionStringAuthType.startsWith("oidc");
182+
serviceProvider = NodeDriverServiceProvider.connect(
181183
connectionInfo.connectionString,
182184
{
183185
productDocsLink: "https://github.com/mongodb-js/mongodb-mcp-server/",
@@ -187,6 +189,16 @@ export class MCPConnectionManager extends ConnectionManager {
187189
undefined,
188190
this.bus
189191
);
192+
193+
if (isOidcConnection) {
194+
this.changeState("connection-request", {
195+
tag: "connecting",
196+
serviceProvider,
197+
connectedAtlasCluster: settings.atlas,
198+
connectionStringAuthType,
199+
oidcConnectionType: connectionStringAuthType as OIDCConnectionAuthType,
200+
});
201+
}
190202
} catch (error: unknown) {
191203
const errorReason = error instanceof Error ? error.message : `${error as string}`;
192204
this.changeState("connection-error", {
@@ -199,26 +211,16 @@ export class MCPConnectionManager extends ConnectionManager {
199211
}
200212

201213
try {
202-
if (connectionStringAuthType.startsWith("oidc")) {
203-
void this.pingAndForget(serviceProvider);
204-
205-
return this.changeState("connection-request", {
206-
tag: "connecting",
214+
if (!isOidcConnection) {
215+
return this.changeState("connection-success", {
216+
tag: "connected",
207217
connectedAtlasCluster: settings.atlas,
208-
serviceProvider,
218+
serviceProvider: await serviceProvider,
209219
connectionStringAuthType,
210-
oidcConnectionType: connectionStringAuthType as OIDCConnectionAuthType,
211220
});
221+
} else {
222+
return this.currentConnectionState;
212223
}
213-
214-
await serviceProvider?.runCommand?.("admin", { hello: 1 });
215-
216-
return this.changeState("connection-success", {
217-
tag: "connected",
218-
connectedAtlasCluster: settings.atlas,
219-
serviceProvider,
220-
connectionStringAuthType,
221-
});
222224
} catch (error: unknown) {
223225
const errorReason = error instanceof Error ? error.message : `${error as string}`;
224226
this.changeState("connection-error", {
@@ -238,7 +240,13 @@ export class MCPConnectionManager extends ConnectionManager {
238240

239241
if (this.currentConnectionState.tag === "connected" || this.currentConnectionState.tag === "connecting") {
240242
try {
241-
await this.currentConnectionState.serviceProvider?.close();
243+
if (this.currentConnectionState.tag === "connected") {
244+
await this.currentConnectionState.serviceProvider?.close();
245+
}
246+
if (this.currentConnectionState.tag === "connecting") {
247+
const serviceProvider = await this.currentConnectionState.serviceProvider;
248+
await serviceProvider.close();
249+
}
242250
} finally {
243251
this.changeState("connection-close", {
244252
tag: "disconnected",
@@ -258,12 +266,16 @@ export class MCPConnectionManager extends ConnectionManager {
258266
}
259267
}
260268

261-
private onOidcAuthSucceeded(): void {
269+
private async onOidcAuthSucceeded(): Promise<void> {
262270
if (
263271
this.currentConnectionState.tag === "connecting" &&
264272
this.currentConnectionState.connectionStringAuthType?.startsWith("oidc")
265273
) {
266-
this.changeState("connection-success", { ...this.currentConnectionState, tag: "connected" });
274+
this.changeState("connection-success", {
275+
...this.currentConnectionState,
276+
tag: "connected",
277+
serviceProvider: await this.currentConnectionState.serviceProvider,
278+
});
267279
}
268280

269281
this.logger.info({
@@ -330,18 +342,6 @@ export class MCPConnectionManager extends ConnectionManager {
330342
}
331343
}
332344

333-
private async pingAndForget(serviceProvider: NodeDriverServiceProvider): Promise<void> {
334-
try {
335-
await serviceProvider?.runCommand?.("admin", { hello: 1 });
336-
} catch (error: unknown) {
337-
this.logger.warning({
338-
id: LogId.oidcFlow,
339-
context: "pingAndForget",
340-
message: String(error),
341-
});
342-
}
343-
}
344-
345345
private async disconnectOnOidcError(error: unknown): Promise<void> {
346346
try {
347347
await this.disconnect();

0 commit comments

Comments
 (0)