Skip to content

Commit 3f8a1b5

Browse files
committed
feat: add support for private connection strings
1 parent 07ac0ee commit 3f8a1b5

File tree

3 files changed

+44
-7
lines changed

3 files changed

+44
-7
lines changed

src/common/atlas/cluster.ts

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1-
import type { ClusterDescription20240805, FlexClusterDescription20241113 } from "./openapi.js";
1+
import type {
2+
ClusterConnectionStrings,
3+
ClusterDescription20240805,
4+
FlexClusterDescription20241113,
5+
} from "./openapi.js";
26
import type { ApiClient } from "./apiClient.js";
37
import { LogId } from "../logger.js";
48
import { ConnectionString } from "mongodb-connection-string-url";
@@ -19,6 +23,7 @@ export interface Cluster {
1923
state?: "IDLE" | "CREATING" | "UPDATING" | "DELETING" | "REPAIRING";
2024
mongoDBVersion?: string;
2125
connectionString?: string;
26+
connectionStrings?: ClusterConnectionStrings;
2227
processIds?: Array<string>;
2328
}
2429

@@ -31,6 +36,7 @@ export function formatFlexCluster(cluster: FlexClusterDescription20241113): Clus
3136
state: cluster.stateName,
3237
mongoDBVersion: cluster.mongoDBVersion,
3338
connectionString,
39+
connectionStrings: cluster.connectionStrings,
3440
processIds: extractProcessIds(cluster.connectionStrings?.standard ?? ""),
3541
};
3642
}
@@ -74,10 +80,21 @@ export function formatCluster(cluster: ClusterDescription20240805): Cluster {
7480
state: cluster.stateName,
7581
mongoDBVersion: cluster.mongoDBVersion,
7682
connectionString,
83+
connectionStrings: cluster.connectionStrings,
7784
processIds: extractProcessIds(cluster.connectionStrings?.standard ?? ""),
7885
};
7986
}
8087

88+
export function getConnectionString(
89+
connectionStrings: ClusterConnectionStrings,
90+
connectionType: "standard" | "private"
91+
): string | undefined {
92+
if (connectionType === "standard") {
93+
return connectionStrings.standardSrv || connectionStrings.standard;
94+
}
95+
return connectionStrings.privateSrv || connectionStrings.private;
96+
}
97+
8198
export async function inspectCluster(apiClient: ApiClient, projectId: string, clusterName: string): Promise<Cluster> {
8299
try {
83100
const cluster = await apiClient.getCluster({

src/tools/args.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,12 @@ export const AtlasArgs = {
6868

6969
password: (): z.ZodString =>
7070
z.string().min(1, "Password is required").max(100, "Password must be 100 characters or less"),
71+
72+
connectionType: (): z.ZodDefault<z.ZodEnum<["standard", "private"]>> =>
73+
z
74+
.enum(["standard", "private"])
75+
.default("standard")
76+
.describe("Desired connection type (standard or private) to an Atlas cluster"),
7177
};
7278

7379
function toEJSON<T extends object | undefined>(value: T): T {

src/tools/atlas/connect/connectCluster.ts

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { ensureCurrentIpInAccessList } from "../../../common/atlas/accessListUti
88
import type { AtlasClusterConnectionInfo } from "../../../common/connectionManager.js";
99
import { getDefaultRoleFromConfig } from "../../../common/atlas/roles.js";
1010
import { AtlasArgs } from "../../args.js";
11+
import { getConnectionString } from "../../../common/atlas/cluster.js";
1112

1213
const addedIpAccessListMessage =
1314
"Note: Your current IP address has been added to the Atlas project's IP access list to enable secure connection.";
@@ -22,6 +23,7 @@ function sleep(ms: number): Promise<void> {
2223
export const ConnectClusterArgs = {
2324
projectId: AtlasArgs.projectId().describe("Atlas project ID"),
2425
clusterName: AtlasArgs.clusterName().describe("Atlas cluster name"),
26+
connectionType: AtlasArgs.connectionType().optional(),
2527
};
2628

2729
export class ConnectClusterTool extends AtlasToolBase {
@@ -69,12 +71,16 @@ export class ConnectClusterTool extends AtlasToolBase {
6971

7072
private async prepareClusterConnection(
7173
projectId: string,
72-
clusterName: string
74+
clusterName: string,
75+
connectionType: "standard" | "private"
7376
): Promise<{ connectionString: string; atlas: AtlasClusterConnectionInfo }> {
7477
const cluster = await inspectCluster(this.session.apiClient, projectId, clusterName);
75-
76-
if (!cluster.connectionString) {
77-
throw new Error("Connection string not available");
78+
if (cluster.connectionStrings === undefined) {
79+
throw new Error("Connection strings not available");
80+
}
81+
const connectionString = getConnectionString(cluster.connectionStrings, connectionType);
82+
if (connectionString === undefined) {
83+
throw new Error("Connection string not available for connection type: " + connectionType);
7884
}
7985

8086
const username = `mcpUser${Math.floor(Math.random() * 100000)}`;
@@ -200,7 +206,11 @@ export class ConnectClusterTool extends AtlasToolBase {
200206
});
201207
}
202208

203-
protected async execute({ projectId, clusterName }: ToolArgs<typeof this.argsShape>): Promise<CallToolResult> {
209+
protected async execute({
210+
projectId,
211+
clusterName,
212+
connectionType,
213+
}: ToolArgs<typeof this.argsShape>): Promise<CallToolResult> {
204214
const ipAccessListUpdated = await ensureCurrentIpInAccessList(this.session.apiClient, projectId);
205215
let createdUser = false;
206216

@@ -239,7 +249,11 @@ export class ConnectClusterTool extends AtlasToolBase {
239249
case "disconnected":
240250
default: {
241251
await this.session.disconnect();
242-
const { connectionString, atlas } = await this.prepareClusterConnection(projectId, clusterName);
252+
const { connectionString, atlas } = await this.prepareClusterConnection(
253+
projectId,
254+
clusterName,
255+
connectionType
256+
);
243257

244258
createdUser = true;
245259
// try to connect for about 5 minutes asynchronously

0 commit comments

Comments
 (0)