• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

mongodb-js / mongodb-mcp-server / 22304070253

23 Feb 2026 11:24AM UTC coverage: 83.19% (-0.1%) from 83.329%
22304070253

Pull #912

github

web-flow
Merge 4552887a6 into 36568a248
Pull Request #912: feat: update atlas-local-create-deployment tool to use preview image

1704 of 2177 branches covered (78.27%)

Branch coverage included in aggregate %.

11 of 11 new or added lines in 1 file covered. (100.0%)

234 existing lines in 12 files now uncovered.

7803 of 9251 relevant lines covered (84.35%)

127.49 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

80.7
/src/common/config/parseUserConfig.ts
1
import { type CliOptions, generateConnectionInfoFromCliArgs } from "@mongosh/arg-parser";
1!
2
import { Keychain } from "../keychain.js";
1✔
3
import type { Secret } from "../keychain.js";
4
import { matchingConfigKey } from "./configUtils.js";
1✔
5
import { UserConfigSchema, type UserConfig } from "./userConfig.js";
1✔
6
import {
1✔
7
    defaultParserOptions as defaultArgParserOptions,
8
    createParseArgsWithCliOptions,
9
    CliOptionsSchema,
10
    UnknownArgumentError,
11
} from "@mongosh/arg-parser/arg-parser";
12
import { z as z4 } from "zod/v4";
1✔
13

14
export type ParserOptions = typeof defaultArgParserOptions;
15

16
export const defaultParserOptions = {
1✔
17
    // This is the name of key that yargs-parser will look up in CLI
18
    // arguments (--config) and ENV variables (MDB_MCP_CONFIG) to load an
19
    // initial configuration from.
20
    config: "config",
1✔
21
    // This helps parse the relevant environment variables.
22
    envPrefix: "MDB_MCP_",
1✔
23
    configuration: {
1✔
24
        ...defaultArgParserOptions.configuration,
1✔
25
        // To avoid populating `_` with end-of-flag arguments we explicitly
26
        // populate `--` variable and altogether ignore them later.
27
        "populate--": true,
1✔
28
    },
1✔
29
} satisfies ParserOptions;
1✔
30

31
export function parseUserConfig({
1✔
32
    args,
147✔
33
    overrides,
147✔
34
    parserOptions = defaultParserOptions,
147✔
35
}: {
147✔
36
    args: string[];
37
    overrides?: z4.ZodRawShape;
38
    parserOptions?: ParserOptions;
39
}): {
40
    warnings: string[];
41
    parsed: UserConfig | undefined;
42
    error: string | undefined;
43
} {
147✔
44
    const schema = overrides
147✔
45
        ? z4.object({
1✔
46
              ...UserConfigSchema.shape,
1✔
47
              ...overrides,
1✔
48
          })
1✔
49
        : UserConfigSchema;
146✔
50

51
    const { error: parseError, warnings, parsed } = parseUserConfigSources({ args, schema, parserOptions });
147✔
52

53
    if (parseError) {
147!
54
        return { error: parseError, warnings, parsed: undefined };
×
55
    }
×
56

57
    if (parsed.nodb) {
147!
58
        return {
×
59
            error: "Error: The --nodb argument is not supported in the MCP Server. Please remove it from your configuration.",
×
60
            warnings,
×
61
            parsed: undefined,
×
62
        };
×
63
    }
×
64

65
    // If we have a connectionSpecifier, which can only appear as the positional
66
    // argument, then that has to be used on priority to construct the
67
    // connection string. In this case, if there is a connection string provided
68
    // by the env variable or config file, that will be overridden.
69
    const { connectionSpecifier } = parsed;
147✔
70
    if (connectionSpecifier) {
147✔
71
        const connectionInfo = generateConnectionInfoFromCliArgs({ ...parsed, connectionSpecifier });
9✔
72
        parsed.connectionString = connectionInfo.connectionString;
9✔
73
    }
9✔
74

75
    const configParseResult = schema.safeParse(parsed);
147✔
76
    const mongoshArguments = CliOptionsSchema.safeParse(parsed);
147✔
77
    const error = configParseResult.error || mongoshArguments.error;
147✔
78
    if (error) {
147✔
79
        return {
13✔
80
            error: `Invalid configuration for the following fields:\n${error.issues.map((issue) => `${issue.path.join(".")} - ${issue.message}`).join("\n")}`,
13✔
81
            warnings,
13✔
82
            parsed: undefined,
13✔
83
        };
13✔
84
    }
13✔
85

86
    // TODO: Separate correctly parsed user config from all other valid
87
    // arguments relevant to mongosh's args-parser.
88
    const userConfig: UserConfig = { ...parsed, ...configParseResult.data };
134✔
89
    registerKnownSecretsInRootKeychain(userConfig);
134✔
90
    return {
134✔
91
        parsed: userConfig,
134✔
92
        warnings,
134✔
93
        error: undefined,
134✔
94
    };
134✔
95
}
134✔
96

97
function parseUserConfigSources<T extends typeof UserConfigSchema>({
147✔
98
    args,
147✔
99
    schema = UserConfigSchema as T,
147✔
100
    parserOptions,
147✔
101
}: {
147✔
102
    args: string[];
103
    schema: T;
104
    parserOptions: ParserOptions;
105
}): {
106
    error: string | undefined;
107
    warnings: string[];
108
    parsed: Partial<CliOptions & z4.infer<T>>;
109
} {
147✔
110
    let parsed: Partial<CliOptions & z4.infer<T>>;
147✔
111
    let deprecated: Record<string, string>;
147✔
112
    try {
147✔
113
        const { parsed: parsedResult, deprecated: deprecatedResult } = createParseArgsWithCliOptions({
147✔
114
            schema,
147✔
115
            parserOptions,
147✔
116
        })({
147✔
117
            args,
147✔
118
        });
147✔
119
        parsed = parsedResult;
147✔
120
        deprecated = deprecatedResult as Record<string, string>;
147✔
121

122
        // Delete fileNames - this is a field populated by mongosh but not used by us.
123
        delete parsed.fileNames;
147✔
124
    } catch (error) {
147!
125
        let errorMessage: string | undefined;
×
126
        if (error instanceof UnknownArgumentError) {
×
127
            const matchingKey = matchingConfigKey(error.argument.replace(/^(--)/, ""));
×
128
            if (matchingKey) {
×
129
                errorMessage = `Error: Invalid command line argument '${error.argument}'. Did you mean '--${matchingKey}'?`;
×
130
            } else {
×
131
                errorMessage = `Error: Invalid command line argument '${error.argument}'.`;
×
132
            }
×
UNCOV
133
        }
×
134

135
        return {
×
136
            error: errorMessage,
×
137
            warnings: [],
×
138
            parsed: {},
×
139
        };
×
UNCOV
140
    }
×
141

142
    const deprecationWarnings = [
147✔
143
        ...getWarnings(parsed, args),
147✔
144
        ...Object.entries(deprecated).map(([deprecated, replacement]) => {
147✔
145
            return `Warning: The --${deprecated} argument is deprecated. Use --${replacement} instead.`;
9✔
146
        }),
147✔
147
    ];
147✔
148

149
    return {
147✔
150
        error: undefined,
147✔
151
        warnings: deprecationWarnings,
147✔
152
        parsed,
147✔
153
    };
147✔
154
}
147✔
155

156
function registerKnownSecretsInRootKeychain(userConfig: Partial<UserConfig>): void {
134✔
157
    const keychain = Keychain.root;
134✔
158

159
    const maybeRegister = (value: string | undefined, kind: Secret["kind"]): void => {
134✔
160
        if (value) {
1,876✔
161
            keychain.register(value, kind);
46✔
162
        }
46✔
163
    };
1,876✔
164

165
    maybeRegister(userConfig.apiClientId, "user");
134✔
166
    maybeRegister(userConfig.apiClientSecret, "password");
134✔
167
    maybeRegister(userConfig.awsAccessKeyId, "password");
134✔
168
    maybeRegister(userConfig.awsIamSessionToken, "password");
134✔
169
    maybeRegister(userConfig.awsSecretAccessKey, "password");
134✔
170
    maybeRegister(userConfig.awsSessionToken, "password");
134✔
171
    maybeRegister(userConfig.password, "password");
134✔
172
    maybeRegister(userConfig.tlsCAFile, "url");
134✔
173
    maybeRegister(userConfig.tlsCRLFile, "url");
134✔
174
    maybeRegister(userConfig.tlsCertificateKeyFile, "url");
134✔
175
    maybeRegister(userConfig.tlsCertificateKeyFilePassword, "password");
134✔
176
    maybeRegister(userConfig.username, "user");
134✔
177
    maybeRegister(userConfig.voyageApiKey, "password");
134✔
178
    maybeRegister(userConfig.connectionString, "mongodb uri");
134✔
179
}
134✔
180

181
function getWarnings(config: Partial<UserConfig>, cliArguments: string[]): string[] {
147✔
182
    const warnings = [];
147✔
183

184
    if (cliArguments.find((argument: string) => argument.startsWith("--connectionString"))) {
147✔
185
        warnings.push(
6✔
186
            "Warning: The --connectionString argument is deprecated. Prefer using the MDB_MCP_CONNECTION_STRING environment variable or the first positional argument for the connection string."
6✔
187
        );
6✔
188
    }
6✔
189

190
    const searchEnabled = config.previewFeatures?.includes("search");
147!
191
    const embeddingsProviderConfigured = !!config.voyageApiKey;
147✔
192
    if (searchEnabled && !embeddingsProviderConfigured) {
147!
UNCOV
193
        warnings.push(`\
×
194
Warning: Vector search is enabled but no embeddings provider is configured.
195
- Set an embeddings provider configuration option to enable auto-embeddings during document insertion and text-based queries with $vectorSearch.\
196
`);
×
UNCOV
197
    }
×
198

199
    if (!searchEnabled && embeddingsProviderConfigured) {
147✔
200
        warnings.push(`\
1✔
201
Warning: An embeddings provider is configured but the 'search' preview feature is not enabled.
202
- Enable vector search by adding 'search' to the 'previewFeatures' configuration option, or remove the embeddings provider configuration if not needed.\
203
`);
1✔
204
    }
1✔
205
    return warnings;
147✔
206
}
147✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc