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

mongodb-js / mongodb-mcp-server / 16449784595

22 Jul 2025 04:14PM UTC coverage: 80.241% (-1.6%) from 81.82%
16449784595

Pull #387

github

web-flow
Merge f1f43f97f into f8e500004
Pull Request #387: chore: update JIRA automation

564 of 739 branches covered (76.32%)

Branch coverage included in aggregate %.

3099 of 3826 relevant lines covered (81.0%)

47.23 hits per line

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

78.64
/src/common/config.ts
1
import path from "path";
2✔
2
import os from "os";
2✔
3
import argv from "yargs-parser";
2✔
4

5
import { ReadConcernLevel, ReadPreferenceMode, W } from "mongodb";
6

7
export interface ConnectOptions {
8
    readConcern: ReadConcernLevel;
9
    readPreference: ReadPreferenceMode;
10
    writeConcern: W;
11
    timeoutMS: number;
12
}
13

14
// If we decide to support non-string config options, we'll need to extend the mechanism for parsing
15
// env variables.
16
export interface UserConfig {
17
    apiBaseUrl: string;
18
    apiClientId?: string;
19
    apiClientSecret?: string;
20
    telemetry: "enabled" | "disabled";
21
    logPath: string;
22
    connectionString?: string;
23
    connectOptions: ConnectOptions;
24
    disabledTools: Array<string>;
25
    readOnly?: boolean;
26
    indexCheck?: boolean;
27
    transport: "stdio" | "http";
28
    httpPort: number;
29
    httpHost: string;
30
    loggers: Array<"stderr" | "disk" | "mcp">;
31
    idleTimeoutMs: number;
32
    notificationTimeoutMs: number;
33
}
34

35
const defaults: UserConfig = {
2✔
36
    apiBaseUrl: "https://cloud.mongodb.com/",
2✔
37
    logPath: getLogPath(),
2✔
38
    connectOptions: {
2✔
39
        readConcern: "local",
2✔
40
        readPreference: "secondaryPreferred",
2✔
41
        writeConcern: "majority",
2✔
42
        timeoutMS: 30_000,
2✔
43
    },
2✔
44
    disabledTools: [],
2✔
45
    telemetry: "enabled",
2✔
46
    readOnly: false,
2✔
47
    indexCheck: false,
2✔
48
    transport: "stdio",
2✔
49
    httpPort: 3000,
2✔
50
    httpHost: "127.0.0.1",
2✔
51
    loggers: ["disk", "mcp"],
2✔
52
    idleTimeoutMs: 600000, // 10 minutes
2✔
53
    notificationTimeoutMs: 540000, // 9 minutes
2✔
54
};
2✔
55

56
export const config = {
2✔
57
    ...defaults,
2✔
58
    ...getEnvConfig(),
2✔
59
    ...getCliConfig(),
2✔
60
};
2✔
61

62
function getLogPath(): string {
64✔
63
    const localDataPath =
64✔
64
        process.platform === "win32"
64!
65
            ? path.join(process.env.LOCALAPPDATA || process.env.APPDATA || os.homedir(), "mongodb")
×
66
            : path.join(os.homedir(), ".mongodb");
64✔
67

68
    const logPath = path.join(localDataPath, "mongodb-mcp", ".app-logs");
64✔
69

70
    return logPath;
64✔
71
}
64✔
72

73
// Gets the config supplied by the user as environment variables. The variable names
74
// are prefixed with `MDB_MCP_` and the keys match the UserConfig keys, but are converted
75
// to SNAKE_UPPER_CASE.
76
function getEnvConfig(): Partial<UserConfig> {
64✔
77
    function setValue(obj: Record<string, unknown>, path: string[], value: string): void {
64✔
78
        const currentField = path.shift();
96✔
79
        if (!currentField) {
96!
80
            return;
×
81
        }
×
82
        if (path.length === 0) {
96✔
83
            const numberValue = Number(value);
96✔
84
            if (!isNaN(numberValue)) {
96!
85
                obj[currentField] = numberValue;
×
86
                return;
×
87
            }
×
88

89
            const booleanValue = value.toLocaleLowerCase();
96✔
90
            if (booleanValue === "true" || booleanValue === "false") {
96!
91
                obj[currentField] = booleanValue === "true";
×
92
                return;
×
93
            }
×
94

95
            // Try to parse an array of values
96
            if (value.indexOf(",") !== -1) {
96!
97
                obj[currentField] = value.split(",").map((v) => v.trim());
×
98
                return;
×
99
            }
×
100

101
            obj[currentField] = value;
96✔
102
            return;
96✔
103
        }
96!
104

105
        if (!obj[currentField]) {
×
106
            obj[currentField] = {};
×
107
        }
×
108

109
        setValue(obj[currentField] as Record<string, unknown>, path, value);
×
110
    }
96✔
111

112
    const result: Record<string, unknown> = {};
64✔
113
    const mcpVariables = Object.entries(process.env).filter(
64✔
114
        ([key, value]) => value !== undefined && key.startsWith("MDB_MCP_")
64✔
115
    ) as [string, string][];
64✔
116
    for (const [key, value] of mcpVariables) {
64✔
117
        const fieldPath = key
96✔
118
            .replace("MDB_MCP_", "")
96✔
119
            .split(".")
96✔
120
            .map((part) => SNAKE_CASE_toCamelCase(part));
96✔
121

122
        setValue(result, fieldPath, value);
96✔
123
    }
96✔
124

125
    return result;
64✔
126
}
64✔
127

128
function SNAKE_CASE_toCamelCase(str: string): string {
96✔
129
    return str.toLowerCase().replace(/([-_][a-z])/g, (group) => group.toUpperCase().replace("_", ""));
96✔
130
}
96✔
131

132
// Reads the cli args and parses them into a UserConfig object.
133
function getCliConfig() {
64✔
134
    return argv(process.argv.slice(2), {
64✔
135
        array: ["disabledTools", "loggers"],
64✔
136
    }) as unknown as Partial<UserConfig>;
64✔
137
}
64✔
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