Skip to content

Commit 795858a

Browse files
authored
fix: tweak the connect tool to prefer preconfigured connection string (#88)
1 parent 8da49a1 commit 795858a

File tree

4 files changed

+85
-29
lines changed

4 files changed

+85
-29
lines changed

src/server.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { AtlasTools } from "./tools/atlas/tools.js";
55
import { MongoDbTools } from "./tools/mongodb/tools.js";
66
import logger, { initializeLogger } from "./logger.js";
77
import { mongoLogId } from "mongodb-log-writer";
8+
import config from "./config.js";
89

910
export class Server {
1011
public readonly session: Session;
@@ -19,6 +20,7 @@ export class Server {
1920
this.mcpServer.server.registerCapabilities({ logging: {} });
2021

2122
this.registerTools();
23+
this.registerResources();
2224

2325
await initializeLogger(this.mcpServer);
2426

@@ -37,4 +39,26 @@ export class Server {
3739
new tool(this.session).register(this.mcpServer);
3840
}
3941
}
42+
43+
private registerResources() {
44+
if (config.connectionString) {
45+
this.mcpServer.resource(
46+
"connection-string",
47+
"config://connection-string",
48+
{
49+
description: "Preconfigured connection string that will be used as a default in the `connect` tool",
50+
},
51+
(uri) => {
52+
return {
53+
contents: [
54+
{
55+
text: `Preconfigured connection string: ${config.connectionString}`,
56+
uri: uri.href,
57+
},
58+
],
59+
};
60+
}
61+
);
62+
}
63+
}
4064
}

src/tools/mongodb/metadata/connect.ts

Lines changed: 27 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -9,38 +9,46 @@ export class ConnectTool extends MongoDBToolBase {
99
protected name = "connect";
1010
protected description = "Connect to a MongoDB instance";
1111
protected argsShape = {
12-
connectionStringOrClusterName: z
13-
.string()
12+
options: z
13+
.array(
14+
z
15+
.union([
16+
z.object({
17+
connectionString: z
18+
.string()
19+
.describe("MongoDB connection string (in the mongodb:// or mongodb+srv:// format)"),
20+
}),
21+
z.object({
22+
clusterName: z.string().describe("MongoDB cluster name"),
23+
}),
24+
])
25+
.optional()
26+
)
1427
.optional()
15-
.describe("MongoDB connection string (in the mongodb:// or mongodb+srv:// format) or cluster name"),
28+
.describe(
29+
"Options for connecting to MongoDB. If not provided, the connection string from the config://connection-string resource will be used. If the user hasn't specified Atlas cluster name or a connection string explicitly and the `config://connection-string` resource is present, always invoke this with no arguments."
30+
),
1631
};
1732

1833
protected operationType: OperationType = "metadata";
1934

20-
protected async execute({
21-
connectionStringOrClusterName,
22-
}: ToolArgs<typeof this.argsShape>): Promise<CallToolResult> {
23-
connectionStringOrClusterName ??= config.connectionString;
24-
if (!connectionStringOrClusterName) {
35+
protected async execute({ options: optionsArr }: ToolArgs<typeof this.argsShape>): Promise<CallToolResult> {
36+
const options = optionsArr?.[0];
37+
let connectionString: string;
38+
if (!options && !config.connectionString) {
2539
return {
2640
content: [
2741
{ type: "text", text: "No connection details provided." },
2842
{ type: "text", text: "Please provide either a connection string or a cluster name" },
29-
{
30-
type: "text",
31-
text: "Alternatively, you can use the default deployment at mongodb://localhost:27017",
32-
},
3343
],
3444
};
3545
}
3646

37-
let connectionString: string;
38-
39-
if (
40-
connectionStringOrClusterName.startsWith("mongodb://") ||
41-
connectionStringOrClusterName.startsWith("mongodb+srv://")
42-
) {
43-
connectionString = connectionStringOrClusterName;
47+
if (!options) {
48+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
49+
connectionString = config.connectionString!;
50+
} else if ("connectionString" in options) {
51+
connectionString = options.connectionString;
4452
} else {
4553
// TODO: https://github.com/mongodb-js/mongodb-mcp-server/issues/19
4654
// We don't support connecting via cluster name since we'd need to obtain the user credentials

tests/integration/helpers.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ export function setupIntegrationTest(): {
148148
connectMcpClient: async () => {
149149
await getMcpClient().callTool({
150150
name: "connect",
151-
arguments: { connectionStringOrClusterName: getConnectionString() },
151+
arguments: { options: [{ connectionString: getConnectionString() }] },
152152
});
153153
},
154154
randomDbName: () => randomDbName,

tests/integration/tools/mongodb/metadata/connect.test.ts

Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,10 @@ describe("Connect tool", () => {
1313

1414
validateParameters(connectTool, [
1515
{
16-
name: "connectionStringOrClusterName",
17-
description: "MongoDB connection string (in the mongodb:// or mongodb+srv:// format) or cluster name",
18-
type: "string",
16+
name: "options",
17+
description:
18+
"Options for connecting to MongoDB. If not provided, the connection string from the config://connection-string resource will be used. If the user hasn't specified Atlas cluster name or a connection string explicitly and the `config://connection-string` resource is present, always invoke this with no arguments.",
19+
type: "array",
1920
required: false,
2021
},
2122
]);
@@ -27,15 +28,20 @@ describe("Connect tool", () => {
2728
const response = await integration.mcpClient().callTool({ name: "connect", arguments: {} });
2829
const content = getResponseContent(response.content);
2930
expect(content).toContain("No connection details provided");
30-
expect(content).toContain("mongodb://localhost:27017");
3131
});
3232
});
3333

3434
describe("with connection string", () => {
3535
it("connects to the database", async () => {
3636
const response = await integration.mcpClient().callTool({
3737
name: "connect",
38-
arguments: { connectionStringOrClusterName: integration.connectionString() },
38+
arguments: {
39+
options: [
40+
{
41+
connectionString: integration.connectionString(),
42+
},
43+
],
44+
},
3945
});
4046
const content = getResponseContent(response.content);
4147
expect(content).toContain("Successfully connected");
@@ -47,7 +53,7 @@ describe("Connect tool", () => {
4753
it("returns error message", async () => {
4854
const response = await integration.mcpClient().callTool({
4955
name: "connect",
50-
arguments: { connectionStringOrClusterName: "mongodb://localhost:12345" },
56+
arguments: { options: [{ connectionString: "mongodb://localhost:12345" }] },
5157
});
5258
const content = getResponseContent(response.content);
5359
expect(content).toContain("Error running connect");
@@ -74,7 +80,13 @@ describe("Connect tool", () => {
7480
const newConnectionString = `${integration.connectionString()}?appName=foo-bar`;
7581
const response = await integration.mcpClient().callTool({
7682
name: "connect",
77-
arguments: { connectionStringOrClusterName: newConnectionString },
83+
arguments: {
84+
options: [
85+
{
86+
connectionString: newConnectionString,
87+
},
88+
],
89+
},
7890
});
7991
const content = getResponseContent(response.content);
8092
expect(content).toContain("Successfully connected");
@@ -85,7 +97,13 @@ describe("Connect tool", () => {
8597
it("suggests the config connection string if set", async () => {
8698
const response = await integration.mcpClient().callTool({
8799
name: "connect",
88-
arguments: { connectionStringOrClusterName: "mongodb://localhost:12345" },
100+
arguments: {
101+
options: [
102+
{
103+
connectionString: "mongodb://localhost:12345",
104+
},
105+
],
106+
},
89107
});
90108
const content = getResponseContent(response.content);
91109
expect(content).toContain("Failed to connect to MongoDB at 'mongodb://localhost:12345'");
@@ -98,7 +116,13 @@ describe("Connect tool", () => {
98116
config.connectionString = "mongodb://localhost:12345";
99117
const response = await integration.mcpClient().callTool({
100118
name: "connect",
101-
arguments: { connectionStringOrClusterName: "mongodb://localhost:12345" },
119+
arguments: {
120+
options: [
121+
{
122+
connectionString: "mongodb://localhost:12345",
123+
},
124+
],
125+
},
102126
});
103127

104128
const content = getResponseContent(response.content);

0 commit comments

Comments
 (0)