Skip to content

Commit baf9bbe

Browse files
committed
chore: adjust override behavior
1 parent 389eabd commit baf9bbe

File tree

3 files changed

+53
-15
lines changed

3 files changed

+53
-15
lines changed

src/common/config/configUtils.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -113,11 +113,10 @@ export function commaSeparatedToArray<T extends string[]>(str: string | string[]
113113
*/
114114
export function parseBoolean(val: unknown): unknown {
115115
if (typeof val === "string") {
116-
const lower = val.toLowerCase().trim();
117-
if (lower === "false") {
116+
if (val === "false") {
118117
return false;
119118
}
120-
if (lower === "true") {
119+
if (val === "true") {
121120
return true;
122121
}
123122
throw new Error(`Invalid boolean value: ${val}`);
@@ -134,7 +133,10 @@ export function parseBoolean(val: unknown): unknown {
134133
/** Allow overriding only to the allowed value */
135134
export function oneWayOverride<T>(allowedValue: T): CustomOverrideLogic {
136135
return (oldValue, newValue) => {
137-
// Only allow override if setting to allowed value
136+
// Only allow override if setting to allowed value or current value
137+
if (newValue === oldValue) {
138+
return newValue;
139+
}
138140
if (newValue === allowedValue) {
139141
return newValue;
140142
}

src/common/config/userConfig.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -183,11 +183,12 @@ export const UserConfigSchema = z4.object({
183183
.describe(
184184
"API key for Voyage AI embeddings service (required for vector search operations with text-to-embedding conversion)."
185185
)
186-
.register(configRegistry, { isSecret: true }),
186+
.register(configRegistry, { isSecret: true, overrideBehavior: "override" }),
187187
embeddingsValidation: z4
188188
.preprocess(parseBoolean, z4.boolean())
189189
.default(true)
190-
.describe("When set to false, disables validation of embeddings dimensions."),
190+
.describe("When set to false, disables validation of embeddings dimensions.")
191+
.register(configRegistry, { overrideBehavior: oneWayOverride(true) }),
191192
vectorSearchDimensions: z4.coerce
192193
.number()
193194
.default(1024)

tests/unit/common/config/configOverrides.test.ts

Lines changed: 44 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ describe("configOverrides", () => {
1414
connectionString: "mongodb://localhost:27017",
1515
vectorSearchDimensions: 1024,
1616
vectorSearchSimilarityFunction: "euclidean",
17-
disableEmbeddingsValidation: false,
17+
embeddingsValidation: false,
1818
previewFeatures: [],
1919
loggers: ["disk", "mcp"],
2020
exportTimeoutMs: 300_000,
@@ -63,6 +63,41 @@ describe("configOverrides", () => {
6363
expect(result).toEqual(baseConfig);
6464
});
6565

66+
describe("boolean edge cases", () => {
67+
it("should parse correctly for true value", () => {
68+
const request: RequestContext = {
69+
headers: {
70+
"x-mongodb-mcp-read-only": "true",
71+
},
72+
};
73+
const result = applyConfigOverrides({ baseConfig: baseConfig as UserConfig, request });
74+
expect(result.readOnly).toBe(true);
75+
});
76+
77+
it("should parse correctly for false value", () => {
78+
const request: RequestContext = {
79+
headers: {
80+
"x-mongodb-mcp-read-only": "false",
81+
},
82+
};
83+
const result = applyConfigOverrides({ baseConfig: baseConfig as UserConfig, request });
84+
expect(result.readOnly).toBe(false);
85+
});
86+
87+
for (const value of ["True", "False", "TRUE", "FALSE", "0", "1", ""]) {
88+
it(`should throw an error for ${value}`, () => {
89+
const request: RequestContext = {
90+
headers: {
91+
"x-mongodb-mcp-read-only": value,
92+
},
93+
};
94+
expect(() => applyConfigOverrides({ baseConfig: baseConfig as UserConfig, request })).toThrow(
95+
`Invalid boolean value: ${value}`
96+
);
97+
});
98+
}
99+
});
100+
66101
it("should return base config when request has no headers or query", () => {
67102
const result = applyConfigOverrides({ baseConfig: baseConfig as UserConfig, request: {} });
68103
expect(result).toEqual(baseConfig);
@@ -256,7 +291,7 @@ describe("configOverrides", () => {
256291
"notificationTimeoutMs",
257292
"exportTimeoutMs",
258293
"atlasTemporaryDatabaseUserLifetimeMs",
259-
"disableEmbeddingsValidation",
294+
"embeddingsValidation",
260295
"previewFeatures",
261296
]);
262297
});
@@ -294,22 +329,22 @@ describe("configOverrides", () => {
294329
});
295330

296331
it("should allow disableEmbeddingsValidation override from true to false", () => {
297-
const request: RequestContext = { headers: { "x-mongodb-mcp-disable-embeddings-validation": "false" } };
332+
const request: RequestContext = { headers: { "x-mongodb-mcp-embeddings-validation": "true" } };
298333
const result = applyConfigOverrides({
299-
baseConfig: { ...baseConfig, disableEmbeddingsValidation: true } as UserConfig,
334+
baseConfig: { ...baseConfig, embeddingsValidation: true } as UserConfig,
300335
request,
301336
});
302-
expect(result.disableEmbeddingsValidation).toBe(false);
337+
expect(result.embeddingsValidation).toBe(true);
303338
});
304339

305-
it("should throw when trying to override disableEmbeddingsValidation from false to true", () => {
306-
const request: RequestContext = { headers: { "x-mongodb-mcp-disable-embeddings-validation": "true" } };
340+
it("should throw when trying to override embeddingsValidation from false to true", () => {
341+
const request: RequestContext = { headers: { "x-mongodb-mcp-embeddings-validation": "false" } };
307342
expect(() =>
308343
applyConfigOverrides({
309-
baseConfig: { ...baseConfig, disableEmbeddingsValidation: false } as UserConfig,
344+
baseConfig: { ...baseConfig, embeddingsValidation: true } as UserConfig,
310345
request,
311346
})
312-
).toThrow("Cannot apply override for disableEmbeddingsValidation: Can only set to false");
347+
).toThrow("Cannot apply override for embeddingsValidation: Can only set to true");
313348
});
314349
});
315350

0 commit comments

Comments
 (0)