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

mongodb-js / mongodb-mcp-server / 22103999808

17 Feb 2026 03:14PM UTC coverage: 83.011% (-0.3%) from 83.329%
22103999808

push

github

web-flow
chore: release v1.6.1-prerelease.1 (#913)

Co-authored-by: mongodb-devtools-bot[bot] <189715634+mongodb-devtools-bot[bot]@users.noreply.github.com>

1663 of 2124 branches covered (78.3%)

Branch coverage included in aggregate %.

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

34 existing lines in 3 files now uncovered.

7557 of 8983 relevant lines covered (84.13%)

123.43 hits per line

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

84.38
/src/common/session.ts
1
import { ObjectId } from "bson";
3✔
2
import type { ApiClient } from "./atlas/apiClient.js";
3
import { createAtlasApiClient } from "./atlas/apiClient.js";
3✔
4
import type { Implementation } from "@modelcontextprotocol/sdk/types.js";
5
import type { CompositeLogger } from "./logger.js";
6
import { LogId } from "./logger.js";
3✔
7
import EventEmitter from "events";
3✔
8
import type {
9
    AtlasClusterConnectionInfo,
10
    ConnectionManager,
11
    ConnectionSettings,
12
    ConnectionStateConnected,
13
    ConnectionStateErrored,
14
} from "./connectionManager.js";
15
import type { ConnectionStringInfo } from "./connectionInfo.js";
16
import type { NodeDriverServiceProvider } from "@mongosh/service-provider-node-driver";
17
import { ErrorCodes, MongoDBError } from "./errors.js";
3✔
18
import type { ExportsManager } from "./exportsManager.js";
19
import type { Client } from "@mongodb-js/atlas-local";
20
import type { Keychain } from "./keychain.js";
21
import type { VectorSearchEmbeddingsManager } from "./search/vectorSearchEmbeddingsManager.js";
22
import { generateConnectionInfoFromCliArgs } from "@mongosh/arg-parser";
3✔
23
import { type UserConfig } from "../common/config/userConfig.js";
24

25
export interface SessionOptions {
26
    userConfig: UserConfig;
27
    logger: CompositeLogger;
28
    exportsManager: ExportsManager;
29
    connectionManager: ConnectionManager;
30
    keychain: Keychain;
31
    atlasLocalClient?: Client;
32
    vectorSearchEmbeddingsManager: VectorSearchEmbeddingsManager;
33
    apiClient?: ApiClient;
34
}
35

36
export type SessionEvents = {
37
    connect: [];
38
    close: [];
39
    disconnect: [];
40
    "connection-error": [ConnectionStateErrored];
41
};
42

43
export class Session extends EventEmitter<SessionEvents> {
3✔
44
    private readonly userConfig: UserConfig;
45
    readonly sessionId: string = new ObjectId().toString();
3✔
46
    readonly exportsManager: ExportsManager;
47
    readonly connectionManager: ConnectionManager;
48
    readonly apiClient?: ApiClient;
49
    readonly atlasLocalClient?: Client;
50
    readonly keychain: Keychain;
51
    readonly vectorSearchEmbeddingsManager: VectorSearchEmbeddingsManager;
52

53
    mcpClient?: {
54
        name?: string;
55
        version?: string;
56
        title?: string;
57
    };
58

59
    public logger: CompositeLogger;
60

61
    constructor({
3✔
62
        userConfig,
188✔
63
        logger,
188✔
64
        connectionManager,
188✔
65
        exportsManager,
188✔
66
        keychain,
188✔
67
        atlasLocalClient,
188✔
68
        vectorSearchEmbeddingsManager,
188✔
69
        apiClient,
188✔
70
    }: SessionOptions) {
188✔
71
        super();
188✔
72

73
        this.userConfig = userConfig;
188✔
74
        this.keychain = keychain;
188✔
75
        this.logger = logger;
188✔
76
        this.apiClient = apiClient;
188✔
77

78
        // Create default API client if not provided in the constructor and Atlas tools are enabled (credentials are provided)
79
        if (!this.apiClient && userConfig.apiClientId && userConfig.apiClientSecret) {
188✔
80
            this.apiClient = createAtlasApiClient(
14✔
81
                {
14✔
82
                    baseUrl: userConfig.apiBaseUrl,
14✔
83
                    credentials: {
14✔
84
                        clientId: userConfig.apiClientId,
14✔
85
                        clientSecret: userConfig.apiClientSecret,
14✔
86
                    },
14✔
87
                },
14✔
88
                logger
14✔
89
            );
14✔
90
        }
14✔
91

92
        this.atlasLocalClient = atlasLocalClient;
188✔
93
        this.exportsManager = exportsManager;
188✔
94
        this.connectionManager = connectionManager;
188✔
95
        this.vectorSearchEmbeddingsManager = vectorSearchEmbeddingsManager;
188✔
96
        this.connectionManager.events.on("connection-success", () => this.emit("connect"));
188✔
97
        this.connectionManager.events.on("connection-time-out", (error) => this.emit("connection-error", error));
188✔
98
        this.connectionManager.events.on("connection-close", () => this.emit("disconnect"));
188✔
99
        this.connectionManager.events.on("connection-error", (error) => this.emit("connection-error", error));
188✔
100
    }
188✔
101

102
    setMcpClient(mcpClient: Implementation | undefined): void {
3✔
103
        if (!mcpClient) {
147!
104
            this.connectionManager.setClientName("unknown");
×
105
            this.logger.debug({
×
106
                id: LogId.serverMcpClientSet,
×
107
                context: "session",
×
108
                message: "MCP client info not found",
×
109
            });
×
110
        }
×
111

112
        this.mcpClient = {
147✔
113
            name: mcpClient?.name || "unknown",
147!
114
            version: mcpClient?.version || "unknown",
147!
115
            title: mcpClient?.title || "unknown",
147✔
116
        };
147✔
117

118
        // Set the client name on the connection manager for appName generation
119
        this.connectionManager.setClientName(this.mcpClient.name || "unknown");
147!
120
    }
147✔
121

122
    async disconnect(): Promise<void> {
3✔
123
        const atlasCluster = this.connectedAtlasCluster;
864✔
124

125
        await this.connectionManager.close();
864✔
126

127
        if (atlasCluster?.username && atlasCluster?.projectId && this.apiClient) {
864!
128
            void this.apiClient
3✔
129
                .deleteDatabaseUser({
3✔
130
                    params: {
3✔
131
                        path: {
3✔
132
                            groupId: atlasCluster.projectId,
3✔
133
                            username: atlasCluster.username,
3✔
134
                            databaseName: "admin",
3✔
135
                        },
3✔
136
                    },
3✔
137
                })
3✔
138
                .catch((err: unknown) => {
3✔
UNCOV
139
                    const error = err instanceof Error ? err : new Error(String(err));
×
UNCOV
140
                    this.logger.error({
×
UNCOV
141
                        id: LogId.atlasDeleteDatabaseUserFailure,
×
UNCOV
142
                        context: "session",
×
UNCOV
143
                        message: `Error deleting previous database user: ${error.message}`,
×
UNCOV
144
                    });
×
145
                });
3✔
146
        }
3✔
147
    }
864✔
148

149
    async close(): Promise<void> {
3✔
150
        await this.disconnect();
168✔
151
        await this.apiClient?.close();
168✔
152
        await this.exportsManager.close();
168✔
153
        this.emit("close");
168✔
154
    }
168✔
155

156
    async connectToConfiguredConnection(): Promise<void> {
3✔
157
        const connectionInfo = generateConnectionInfoFromCliArgs({
36✔
158
            ...this.userConfig,
36✔
159
            connectionSpecifier: this.userConfig.connectionString,
36✔
160
        });
36✔
161
        await this.connectToMongoDB(connectionInfo);
36✔
162
    }
36✔
163

164
    async connectToMongoDB(settings: ConnectionSettings): Promise<void> {
3✔
165
        await this.connectionManager.connect({ ...settings });
406✔
166
    }
406✔
167

168
    get isConnectedToMongoDB(): boolean {
3✔
169
        return this.connectionManager.currentConnectionState.tag === "connected";
1,438✔
170
    }
1,438✔
171

172
    async isSearchSupported(): Promise<boolean> {
3✔
173
        const state = this.connectionManager.currentConnectionState;
170✔
174
        if (state.tag === "connected") {
170✔
175
            return await state.isSearchSupported();
169✔
176
        }
169✔
177

178
        return false;
1✔
179
    }
170✔
180

181
    async assertSearchSupported(): Promise<void> {
3✔
182
        const isSearchSupported = await this.isSearchSupported();
26✔
183
        if (!isSearchSupported) {
26✔
184
            throw new MongoDBError(
3✔
185
                ErrorCodes.AtlasSearchNotSupported,
3✔
186
                "Atlas Search is not supported in the current cluster."
3✔
187
            );
3✔
188
        }
3✔
189
    }
26✔
190

191
    get serviceProvider(): NodeDriverServiceProvider {
3✔
192
        if (this.isConnectedToMongoDB) {
346✔
193
            const state = this.connectionManager.currentConnectionState as ConnectionStateConnected;
346✔
194
            return state.serviceProvider;
346✔
195
        }
346!
196

197
        throw new MongoDBError(ErrorCodes.NotConnectedToMongoDB, "Not connected to MongoDB");
×
198
    }
346✔
199

200
    get connectedAtlasCluster(): AtlasClusterConnectionInfo | undefined {
3✔
201
        return this.connectionManager.currentConnectionState.connectedAtlasCluster;
1,139✔
202
    }
1,139✔
203

204
    get connectionStringInfo(): ConnectionStringInfo | undefined {
3✔
205
        return this.connectionManager.currentConnectionState.connectionStringInfo;
313✔
206
    }
313✔
207
}
3✔
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