From 34a7296bb531b2f580a7280e64320039b84a1928 Mon Sep 17 00:00:00 2001 From: Kevin Mas Ruiz Date: Thu, 4 Sep 2025 08:49:16 +0200 Subject: [PATCH 1/5] chore: support for multiple hosts urls #327 --- src/common/config.ts | 6 ++++++ tests/unit/common/config.test.ts | 14 ++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/src/common/config.ts b/src/common/config.ts index 4bc02efe..f95525a7 100644 --- a/src/common/config.ts +++ b/src/common/config.ts @@ -191,6 +191,12 @@ function parseEnvConfig(env: Record): Partial { return; } if (path.length === 0) { + // MongoDB URLs must not be preprocessed + if (value.startsWith("mongodb://") || value.startsWith("mongodb+srv://")) { + obj[currentField] = value; + return; + } + const numberValue = Number(value); if (!isNaN(numberValue)) { obj[currentField] = numberValue; diff --git a/tests/unit/common/config.test.ts b/tests/unit/common/config.test.ts index 789febff..e31d474d 100644 --- a/tests/unit/common/config.test.ts +++ b/tests/unit/common/config.test.ts @@ -5,6 +5,20 @@ import type { CliOptions } from "@mongosh/arg-parser"; describe("config", () => { describe("env var parsing", () => { + describe("mongodb urls", () => { + it("should not try to parse a multiple-host urls", () => { + const actual = setupUserConfig({ + env: { + MDB_MCP_CONNECTION_STRING: "mongodb://user:password@host1,host2,host3/", + }, + cli: [], + defaults: defaultUserConfig, + }); + + expect(actual.connectionString).toEqual("mongodb://user:password@host1,host2,host3/"); + }); + }); + describe("string cases", () => { const testCases = [ { envVar: "MDB_MCP_API_BASE_URL", property: "apiBaseUrl", value: "http://test.com" }, From 42d435f6a6c92de23aa285413343b042a1f2bb9c Mon Sep 17 00:00:00 2001 From: Kevin Mas Ruiz Date: Thu, 4 Sep 2025 08:57:33 +0200 Subject: [PATCH 2/5] chore: check that the value is a string _just in case_. Environment variables are always strings, but we will add this check in case we receive something that is not process.env. --- src/common/config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/config.ts b/src/common/config.ts index f95525a7..ffbe25e0 100644 --- a/src/common/config.ts +++ b/src/common/config.ts @@ -192,7 +192,7 @@ function parseEnvConfig(env: Record): Partial { } if (path.length === 0) { // MongoDB URLs must not be preprocessed - if (value.startsWith("mongodb://") || value.startsWith("mongodb+srv://")) { + if (typeof value === "string" && (value.startsWith("mongodb://") || value.startsWith("mongodb+srv://"))) { obj[currentField] = value; return; } From f7dd0e7ab77c67c9b2e8ed10cf3340f24ee97d29 Mon Sep 17 00:00:00 2001 From: Kevin Mas Ruiz Date: Thu, 4 Sep 2025 09:01:01 +0200 Subject: [PATCH 3/5] chore: add a test for CLI parsing to avoid regressions CLI parsing doesn't have that issue but, in case we refactor add a test to ensure we don't regress here. --- tests/unit/common/config.test.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tests/unit/common/config.test.ts b/tests/unit/common/config.test.ts index e31d474d..0a6ae5f1 100644 --- a/tests/unit/common/config.test.ts +++ b/tests/unit/common/config.test.ts @@ -74,6 +74,16 @@ describe("config", () => { }); describe("cli parsing", () => { + it("should not try to parse a multiple-host urls", () => { + const actual = setupUserConfig({ + cli: ["myself", "--", "--connectionString", "mongodb://user:password@host1,host2,host3/"], + env: {}, + defaults: defaultUserConfig, + }); + + expect(actual.connectionString).toEqual("mongodb://user:password@host1,host2,host3/"); + }); + describe("string use cases", () => { const testCases = [ { From 73e57bd57a514b2331e7ed769cb8de998e605f81 Mon Sep 17 00:00:00 2001 From: Kevin Mas Ruiz Date: Thu, 4 Sep 2025 12:30:32 +0200 Subject: [PATCH 4/5] chore: use a dictionary of flags with urls instead --- src/common/config.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/common/config.ts b/src/common/config.ts index ffbe25e0..bf69c497 100644 --- a/src/common/config.ts +++ b/src/common/config.ts @@ -87,7 +87,7 @@ const OPTIONS = { "greedy-arrays": true, "short-option-groups": false, }, -}; +} as const; function isConnectionSpecifier(arg: string | undefined): boolean { return ( @@ -185,14 +185,15 @@ function getExportsPath(): string { // are prefixed with `MDB_MCP_` and the keys match the UserConfig keys, but are converted // to SNAKE_UPPER_CASE. function parseEnvConfig(env: Record): Partial { + const CONFIG_WITH_URLS: Set = new Set<(typeof OPTIONS)["string"][number]>(["connectionString"]); + function setValue(obj: Record, path: string[], value: string): void { const currentField = path.shift(); if (!currentField) { return; } if (path.length === 0) { - // MongoDB URLs must not be preprocessed - if (typeof value === "string" && (value.startsWith("mongodb://") || value.startsWith("mongodb+srv://"))) { + if (CONFIG_WITH_URLS.has(currentField)) { obj[currentField] = value; return; } From f2b301a322c1eefbcae48429d5992153e7952dd9 Mon Sep 17 00:00:00 2001 From: Kevin Mas Ruiz Date: Thu, 4 Sep 2025 12:36:01 +0200 Subject: [PATCH 5/5] chore: fix linter warnings --- src/common/config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/config.ts b/src/common/config.ts index 04d1a532..9fa78ec0 100644 --- a/src/common/config.ts +++ b/src/common/config.ts @@ -256,7 +256,7 @@ function SNAKE_CASE_toCamelCase(str: string): string { // whatever is in mongosh. function parseCliConfig(args: string[]): CliOptions { const programArgs = args.slice(2); - const parsed = argv(programArgs, OPTIONS) as unknown as CliOptions & + const parsed = argv(programArgs, OPTIONS as unknown as argv.Options) as unknown as CliOptions & UserConfig & { _?: string[]; };