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

mongodb-js / mongodb-mcp-server / 19928292758

04 Dec 2025 12:03PM UTC coverage: 80.172% (-0.4%) from 80.581%
19928292758

Pull #777

github

web-flow
Merge 305c35330 into 18ff7cc01
Pull Request #777: chore: adopt strict validation for all command line arguments MCP-298

1451 of 1892 branches covered (76.69%)

Branch coverage included in aggregate %.

82 of 121 new or added lines in 8 files covered. (67.77%)

18 existing lines in 2 files now uncovered.

6640 of 8200 relevant lines covered (80.98%)

79.9 hits per line

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

75.17
/src/common/config/createUserConfig.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,
8
    parseArgsWithCliOptions,
9
    CliOptionsSchema,
10
    UnknownArgumentError,
11
} from "@mongosh/arg-parser/arg-parser";
12
import type { z as z4 } from "zod/v4";
13

14
export function createUserConfig({ args }: { args: string[] }): {
1✔
15
    warnings: string[];
16
    parsed: UserConfig | undefined;
17
    error: string | undefined;
18
} {
135✔
19
    const { error: parseError, warnings, parsed } = parseUserConfigSources(args);
135✔
20

21
    if (parseError) {
135!
NEW
22
        return { error: parseError, warnings, parsed: undefined };
×
UNCOV
23
    }
×
24

25
    if (parsed.nodb) {
135!
NEW
26
        return {
×
NEW
27
            error: "Error: The --nodb argument is not supported in the MCP Server. Please remove it from your configuration.",
×
NEW
28
            warnings,
×
NEW
29
            parsed: undefined,
×
NEW
30
        };
×
UNCOV
31
    }
×
32

33
    // If we have a connectionSpecifier, which can only appear as the positional
34
    // argument, then that has to be used on priority to construct the
35
    // connection string. In this case, if there is a connection string provided
36
    // by the env variable or config file, that will be overridden.
37
    const { connectionSpecifier } = parsed;
135✔
38
    if (connectionSpecifier) {
135✔
39
        const connectionInfo = generateConnectionInfoFromCliArgs({ ...parsed, connectionSpecifier });
9✔
40
        parsed.connectionString = connectionInfo.connectionString;
9✔
41
    }
9✔
42

43
    const configParseResult = UserConfigSchema.safeParse(parsed);
135✔
44
    const mongoshArguments = CliOptionsSchema.safeParse(parsed);
135✔
45
    const error = configParseResult.error || mongoshArguments.error;
135✔
46
    if (error) {
135✔
47
        return {
11✔
48
            error: `Invalid configuration for the following fields:\n${error.issues.map((issue) => `${issue.path.join(".")} - ${issue.message}`).join("\n")}`,
11✔
49
            warnings,
11✔
50
            parsed: undefined,
11✔
51
        };
11✔
52
    }
11✔
53

54
    // TODO: Separate correctly parsed user config from all other valid
55
    // arguments relevant to mongosh's args-parser.
56
    const userConfig: UserConfig = { ...parsed, ...configParseResult.data };
124✔
57
    registerKnownSecretsInRootKeychain(userConfig);
124✔
58
    return {
124✔
59
        parsed: userConfig,
124✔
60
        warnings,
124✔
61
        error: undefined,
124✔
62
    };
124✔
63
}
124✔
64

65
function parseUserConfigSources(cliArguments: string[]): {
135✔
66
    error: string | undefined;
67
    warnings: string[];
68
    parsed: Partial<CliOptions & z4.infer<typeof UserConfigSchema>>;
69
} {
135✔
70
    let parsed: Partial<CliOptions & z4.infer<typeof UserConfigSchema>>;
135✔
71
    let deprecated: Record<string, keyof UserConfig>;
135✔
72
    try {
135✔
73
        const { parsed: parsedResult, deprecated: deprecatedResult } = parseArgsWithCliOptions({
135✔
74
            args: cliArguments,
135✔
75
            schema: UserConfigSchema,
135✔
76
            parserOptions: {
135✔
77
                // This helps parse the relevant environment variables.
78
                envPrefix: "MDB_MCP_",
135✔
79
                configuration: {
135✔
80
                    ...defaultParserOptions.configuration,
135✔
81
                    // To avoid populating `_` with end-of-flag arguments we explicitly
82
                    // populate `--` variable and altogether ignore them later.
83
                    "populate--": true,
135✔
84
                },
135✔
85
            },
135✔
86
        });
135✔
87
        parsed = parsedResult;
135✔
88
        deprecated = deprecatedResult;
135✔
89

90
        // Delete fileNames - this is a field populated by mongosh but not used by us.
91
        delete parsed.fileNames;
135✔
92
    } catch (error) {
135!
NEW
93
        let errorMessage: string | undefined;
×
NEW
94
        if (error instanceof UnknownArgumentError) {
×
NEW
95
            const matchingKey = matchingConfigKey(error.argument.replace(/^(--)/, ""));
×
NEW
96
            if (matchingKey) {
×
NEW
97
                errorMessage = `Error: Invalid command line argument '${error.argument}'. Did you mean '--${matchingKey}'?`;
×
NEW
98
            } else {
×
NEW
99
                errorMessage = `Error: Invalid command line argument '${error.argument}'.`;
×
NEW
100
            }
×
NEW
101
        }
×
102

NEW
103
        return {
×
NEW
104
            error: errorMessage,
×
NEW
105
            warnings: [],
×
NEW
106
            parsed: {},
×
NEW
107
        };
×
UNCOV
108
    }
×
109

110
    const deprecationWarnings = [
135✔
111
        ...getWarnings(parsed, cliArguments),
135✔
112
        ...Object.entries(deprecated).map(([deprecated, replacement]) => {
135✔
113
            return `Warning: The --${deprecated} argument is deprecated. Use --${replacement} instead.`;
9✔
114
        }),
135✔
115
    ];
135✔
116

117
    return {
135✔
118
        error: undefined,
135✔
119
        warnings: deprecationWarnings,
135✔
120
        parsed,
135✔
121
    };
135✔
122
}
135✔
123

124
function registerKnownSecretsInRootKeychain(userConfig: Partial<UserConfig>): void {
124✔
125
    const keychain = Keychain.root;
124✔
126

127
    const maybeRegister = (value: string | undefined, kind: Secret["kind"]): void => {
124✔
128
        if (value) {
1,488✔
129
            keychain.register(value, kind);
24✔
130
        }
24✔
131
    };
1,488✔
132

133
    maybeRegister(userConfig.apiClientId, "user");
124✔
134
    maybeRegister(userConfig.apiClientSecret, "password");
124✔
135
    maybeRegister(userConfig.awsAccessKeyId, "password");
124✔
136
    maybeRegister(userConfig.awsIamSessionToken, "password");
124✔
137
    maybeRegister(userConfig.awsSecretAccessKey, "password");
124✔
138
    maybeRegister(userConfig.awsSessionToken, "password");
124✔
139
    maybeRegister(userConfig.password, "password");
124✔
140
    maybeRegister(userConfig.tlsCAFile, "url");
124✔
141
    maybeRegister(userConfig.tlsCRLFile, "url");
124✔
142
    maybeRegister(userConfig.tlsCertificateKeyFile, "url");
124✔
143
    maybeRegister(userConfig.tlsCertificateKeyFilePassword, "password");
124✔
144
    maybeRegister(userConfig.username, "user");
124✔
145
}
124✔
146

147
function getWarnings(config: Partial<UserConfig>, cliArguments: string[]): string[] {
135✔
148
    const warnings = [];
135✔
149

150
    if (cliArguments.find((argument: string) => argument.startsWith("--connectionString"))) {
135✔
151
        warnings.push(
6✔
152
            "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✔
153
        );
6✔
154
    }
6✔
155

156
    const searchEnabled = config.previewFeatures?.includes("search");
135!
157
    const embeddingsProviderConfigured = !!config.voyageApiKey;
135✔
158
    if (searchEnabled && !embeddingsProviderConfigured) {
135!
NEW
159
        warnings.push(`\
×
160
Warning: Vector search is enabled but no embeddings provider is configured.
161
- Set an embeddings provider configuration option to enable auto-embeddings during document insertion and text-based queries with $vectorSearch.\
UNCOV
162
`);
×
UNCOV
163
    }
×
164

165
    if (!searchEnabled && embeddingsProviderConfigured) {
135!
NEW
166
        warnings.push(`\
×
167
Warning: An embeddings provider is configured but the 'search' preview feature is not enabled.
168
- Enable vector search by adding 'search' to the 'previewFeatures' configuration option, or remove the embeddings provider configuration if not needed.\
UNCOV
169
`);
×
UNCOV
170
    }
×
171
    return warnings;
135✔
172
}
135✔
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

© 2025 Coveralls, Inc