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

mongodb-js / mongodb-mcp-server / 16778685993

06 Aug 2025 01:43PM UTC coverage: 81.981% (+0.7%) from 81.319%
16778685993

Pull #423

github

web-flow
Merge 76e8ab544 into a91618672
Pull Request #423: chore: refactor connections to use the new ConnectionManager to isolate long running processes like OIDC connections MCP-81

663 of 855 branches covered (77.54%)

Branch coverage included in aggregate %.

192 of 200 new or added lines in 7 files covered. (96.0%)

7 existing lines in 2 files now uncovered.

3418 of 4123 relevant lines covered (82.9%)

61.03 hits per line

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

87.39
/src/common/session.ts
1
import { ApiClient, ApiClientCredentials } from "./atlas/apiClient.js";
2✔
2
import { Implementation } from "@modelcontextprotocol/sdk/types.js";
3
import logger, { LogId } from "./logger.js";
2✔
4
import EventEmitter from "events";
2✔
5
import {
2✔
6
    AtlasClusterConnectionInfo,
7
    ConnectionManager,
8
    ConnectionSettings,
9
    ConnectionStateConnected,
10
} from "./connectionManager.js";
11
import { NodeDriverServiceProvider } from "@mongosh/service-provider-node-driver";
12
import { ErrorCodes, MongoDBError } from "./errors.js";
2✔
13

14
export interface SessionOptions {
15
    apiBaseUrl: string;
16
    apiClientId?: string;
17
    apiClientSecret?: string;
18
    connectionManager?: ConnectionManager;
19
}
20

21
export type SessionEvents = {
22
    connect: [];
23
    close: [];
24
    disconnect: [];
25
    "connection-error": [string];
26
};
27

28
export class Session extends EventEmitter<SessionEvents> {
2✔
29
    sessionId?: string;
30
    connectionManager: ConnectionManager;
31
    apiClient: ApiClient;
32
    agentRunner?: {
33
        name: string;
34
        version: string;
35
    };
36

37
    constructor({ apiBaseUrl, apiClientId, apiClientSecret, connectionManager }: SessionOptions) {
2✔
38
        super();
80✔
39

40
        const credentials: ApiClientCredentials | undefined =
80✔
41
            apiClientId && apiClientSecret
80✔
42
                ? {
38✔
43
                      clientId: apiClientId,
38✔
44
                      clientSecret: apiClientSecret,
38✔
45
                  }
38✔
46
                : undefined;
42✔
47

48
        this.apiClient = new ApiClient({ baseUrl: apiBaseUrl, credentials });
80✔
49

50
        this.connectionManager = connectionManager ?? new ConnectionManager();
80✔
51
        this.connectionManager.on("connection-succeeded", () => this.emit("connect"));
80✔
52
        this.connectionManager.on("connection-timed-out", (error) => this.emit("connection-error", error.errorReason));
80✔
53
        this.connectionManager.on("connection-closed", () => this.emit("disconnect"));
80✔
54
        this.connectionManager.on("connection-errored", (error) => this.emit("connection-error", error.errorReason));
80✔
55
    }
80✔
56

57
    setAgentRunner(agentRunner: Implementation | undefined) {
2✔
58
        if (agentRunner?.name && agentRunner?.version) {
68✔
59
            this.agentRunner = {
68✔
60
                name: agentRunner.name,
68✔
61
                version: agentRunner.version,
68✔
62
            };
68✔
63
        }
68✔
64
    }
68✔
65

66
    async disconnect(): Promise<void> {
2✔
67
        const atlasCluster = this.connectedAtlasCluster;
684✔
68

69
        try {
684✔
70
            await this.connectionManager.disconnect();
684✔
71
        } catch (err: unknown) {
684!
NEW
72
            const error = err instanceof Error ? err : new Error(String(err));
×
NEW
73
            logger.error(LogId.mongodbDisconnectFailure, "Error closing service provider:", error.message);
×
UNCOV
74
        }
×
75

76
        if (atlasCluster?.username && atlasCluster?.projectId) {
684✔
77
            void this.apiClient
1✔
78
                .deleteDatabaseUser({
1✔
79
                    params: {
1✔
80
                        path: {
1✔
81
                            groupId: atlasCluster.projectId,
1✔
82
                            username: atlasCluster.username,
1✔
83
                            databaseName: "admin",
1✔
84
                        },
1✔
85
                    },
1✔
86
                })
1✔
87
                .catch((err: unknown) => {
1✔
88
                    const error = err instanceof Error ? err : new Error(String(err));
×
89
                    logger.error(
×
90
                        LogId.atlasDeleteDatabaseUserFailure,
×
91
                        "atlas-connect-cluster",
×
92
                        `Error deleting previous database user: ${error.message}`
×
93
                    );
×
94
                });
1✔
95
        }
1✔
96
    }
684✔
97

98
    async close(): Promise<void> {
2✔
99
        await this.disconnect();
68✔
100
        await this.apiClient.close();
68✔
101
        this.emit("close");
67✔
102
    }
68✔
103

104
    async connectToMongoDB(settings: ConnectionSettings): Promise<void> {
2✔
105
        try {
297✔
106
            await this.connectionManager.connect({ ...settings });
297✔
107
        } catch (error: unknown) {
297✔
108
            const message = error instanceof Error ? error.message : (error as string);
21!
109
            this.emit("connection-error", message);
21✔
110
            throw error;
21✔
111
        }
21✔
112
    }
297✔
113

114
    get isConnectedToMongoDB(): boolean {
2✔
115
        return this.connectionManager.currentConnectionState.tag === "connected";
1,737✔
116
    }
1,737✔
117

118
    get serviceProvider(): NodeDriverServiceProvider {
2✔
119
        if (this.isConnectedToMongoDB) {
258✔
120
            const state = this.connectionManager.currentConnectionState as ConnectionStateConnected;
258✔
121
            return state.serviceProvider;
258✔
122
        }
258!
123

NEW
124
        throw new MongoDBError(ErrorCodes.NotConnectedToMongoDB, "Not connected to MongoDB");
×
125
    }
258✔
126

127
    get connectedAtlasCluster(): AtlasClusterConnectionInfo | undefined {
2✔
128
        return this.connectionManager.currentConnectionState.connectedAtlasCluster;
925✔
129
    }
925✔
130
}
2✔
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