Skip to content

Commit 70077ef

Browse files
committed
feat: add connection config
1 parent f278e4f commit 70077ef

File tree

2 files changed

+58
-9
lines changed

2 files changed

+58
-9
lines changed

src/config.ts

Lines changed: 52 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,21 +4,34 @@ import argv from "yargs-parser";
44

55
import packageJson from "../package.json" with { type: "json" };
66
import fs from "fs";
7+
import { ReadConcernLevel, ReadPreferenceMode, W } from "mongodb";
78
const { localDataPath, configPath } = getLocalDataPath();
89

910
// If we decide to support non-string config options, we'll need to extend the mechanism for parsing
1011
// env variables.
11-
interface UserConfig extends Record<string, string | undefined> {
12+
interface UserConfig extends Record<string, unknown> {
1213
apiBaseUrl: string;
1314
clientId: string;
1415
stateFile: string;
1516
connectionString?: string;
17+
connectOptions: {
18+
readConcern: ReadConcernLevel;
19+
readPreference: ReadPreferenceMode;
20+
writeConcern: W;
21+
timeoutMS: number;
22+
};
1623
}
1724

1825
const defaults: UserConfig = {
1926
apiBaseUrl: "https://cloud.mongodb.com/",
2027
clientId: "0oabtxactgS3gHIR0297",
2128
stateFile: path.join(localDataPath, "state.json"),
29+
connectOptions: {
30+
readConcern: "local",
31+
readPreference: "secondaryPreferred",
32+
writeConcern: "majority",
33+
timeoutMS: 30_000,
34+
},
2235
};
2336

2437
const mergedUserConfig = {
@@ -66,21 +79,51 @@ function getLocalDataPath(): { localDataPath: string; configPath: string } {
6679
// are prefixed with `MDB_MCP_` and the keys match the UserConfig keys, but are converted
6780
// to SNAKE_UPPER_CASE.
6881
function getEnvConfig(): Partial<UserConfig> {
69-
const camelCaseToSNAKE_UPPER_CASE = (str: string): string => {
70-
return str.replace(/([a-z])([A-Z])/g, "$1_$2").toUpperCase();
71-
};
82+
function setValue(obj: Record<string, unknown>, path: string[], value: string): void {
83+
const currentField = path.shift()!;
84+
if (path.length === 0) {
85+
const numberValue = Number(value);
86+
if (!isNaN(numberValue)) {
87+
obj[currentField] = numberValue;
88+
return;
89+
}
90+
91+
const booleanValue = value.toLocaleLowerCase();
92+
if (booleanValue === "true" || booleanValue === "false") {
93+
obj[currentField] = booleanValue === "true";
94+
return;
95+
}
96+
97+
obj[currentField] = value;
98+
return;
99+
}
72100

73-
const result: Partial<UserConfig> = {};
74-
for (const key of Object.keys(defaults)) {
75-
const envVarName = `MDB_MCP_${camelCaseToSNAKE_UPPER_CASE(key)}`;
76-
if (process.env[envVarName]) {
77-
result[key] = process.env[envVarName];
101+
if (!obj[currentField]) {
102+
obj[currentField] = {};
78103
}
104+
105+
setValue(obj[currentField] as Record<string, unknown>, path, value);
106+
}
107+
108+
const result: Record<string, unknown> = {};
109+
for (const [key, value] of Object.entries(process.env).filter(
110+
([key, value]) => value !== undefined && key.startsWith("MDB_MCP_")
111+
)) {
112+
const fieldPath = key
113+
.replace("MDB_MCP_", "")
114+
.split(".")
115+
.map((part) => SNAKE_CASE_toCamelCase(part));
116+
117+
setValue(result, fieldPath, value!);
79118
}
80119

81120
return result;
82121
}
83122

123+
function SNAKE_CASE_toCamelCase(str: string): string {
124+
return str.toLowerCase().replace(/([-_][a-z])/g, (group) => group.toUpperCase().replace("_", ""));
125+
}
126+
84127
// Gets the config supplied by the user as a JSON file. The file is expected to be located in the local data path
85128
// and named `config.json`.
86129
function getFileConfig(): Partial<UserConfig> {

src/tools/mongodb/connect.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,12 @@ export class ConnectTool extends MongoDBToolBase {
6969
const provider = await NodeDriverServiceProvider.connect(connectionString, {
7070
productDocsLink: "https://docs.mongodb.com/todo-mcp",
7171
productName: "MongoDB MCP",
72+
readConcern: config.connectOptions.readConcern,
73+
readPreference: config.connectOptions.readPreference,
74+
writeConcern: {
75+
w: config.connectOptions.writeConcern,
76+
},
77+
timeoutMS: config.connectOptions.timeoutMS,
7278
});
7379

7480
this.state.serviceProvider = provider;

0 commit comments

Comments
 (0)