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

mongodb-js / mongodb-mcp-server / 17155288437

22 Aug 2025 12:29PM UTC coverage: 82.014% (-0.03%) from 82.04%
17155288437

Pull #468

github

web-flow
Merge 3bb127c20 into ca68195c4
Pull Request #468: chore: update readme with the new tool and resources

855 of 1075 branches covered (79.53%)

Branch coverage included in aggregate %.

2 of 2 new or added lines in 2 files covered. (100.0%)

97 existing lines in 8 files now uncovered.

4357 of 5280 relevant lines covered (82.52%)

70.4 hits per line

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

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

16
export interface SessionOptions {
17
    apiBaseUrl: string;
18
    apiClientId?: string;
19
    apiClientSecret?: string;
20
    logger: CompositeLogger;
21
    exportsManager: ExportsManager;
22
    connectionManager: ConnectionManager;
23
}
24

25
export type SessionEvents = {
26
    connect: [];
27
    close: [];
28
    disconnect: [];
29
    "connection-error": [string];
30
};
31

32
export class Session extends EventEmitter<SessionEvents> {
2✔
33
    readonly sessionId: string = new ObjectId().toString();
2✔
34
    readonly exportsManager: ExportsManager;
35
    readonly connectionManager: ConnectionManager;
36
    readonly apiClient: ApiClient;
37
    mcpClient?: {
38
        name?: string;
39
        version?: string;
40
        title?: string;
41
    };
42

43
    public logger: CompositeLogger;
44

45
    constructor({
2✔
46
        apiBaseUrl,
96✔
47
        apiClientId,
96✔
48
        apiClientSecret,
96✔
49
        logger,
96✔
50
        connectionManager,
96✔
51
        exportsManager,
96✔
52
    }: SessionOptions) {
96✔
53
        super();
96✔
54

55
        this.logger = logger;
96✔
56
        const credentials: ApiClientCredentials | undefined =
96✔
57
            apiClientId && apiClientSecret
96✔
58
                ? {
44✔
59
                      clientId: apiClientId,
44✔
60
                      clientSecret: apiClientSecret,
44✔
61
                  }
44✔
62
                : undefined;
52✔
63

64
        this.apiClient = new ApiClient({ baseUrl: apiBaseUrl, credentials }, logger);
96✔
65
        this.exportsManager = exportsManager;
96✔
66
        this.connectionManager = connectionManager;
96✔
67
        this.connectionManager.on("connection-succeeded", () => this.emit("connect"));
96✔
68
        this.connectionManager.on("connection-timed-out", (error) => this.emit("connection-error", error.errorReason));
96✔
69
        this.connectionManager.on("connection-closed", () => this.emit("disconnect"));
96✔
70
        this.connectionManager.on("connection-errored", (error) => this.emit("connection-error", error.errorReason));
96✔
71
    }
96✔
72

73
    setMcpClient(mcpClient: Implementation | undefined): void {
2✔
74
        if (!mcpClient) {
82!
UNCOV
75
            this.connectionManager.setClientName("unknown");
×
UNCOV
76
            this.logger.debug({
×
UNCOV
77
                id: LogId.serverMcpClientSet,
×
UNCOV
78
                context: "session",
×
UNCOV
79
                message: "MCP client info not found",
×
UNCOV
80
            });
×
UNCOV
81
        }
×
82

83
        this.mcpClient = {
82✔
84
            name: mcpClient?.name || "unknown",
82!
85
            version: mcpClient?.version || "unknown",
82!
86
            title: mcpClient?.title || "unknown",
82✔
87
        };
82✔
88

89
        // Set the client name on the connection manager for appName generation
90
        this.connectionManager.setClientName(this.mcpClient.name || "unknown");
82!
91
    }
82✔
92

93
    async disconnect(): Promise<void> {
2✔
94
        const atlasCluster = this.connectedAtlasCluster;
788✔
95

96
        try {
788✔
97
            await this.connectionManager.disconnect();
788✔
98
        } catch (err: unknown) {
788!
UNCOV
99
            const error = err instanceof Error ? err : new Error(String(err));
×
UNCOV
100
            this.logger.error({
×
UNCOV
101
                id: LogId.mongodbDisconnectFailure,
×
UNCOV
102
                context: "session",
×
UNCOV
103
                message: `Error closing service provider: ${error.message}`,
×
UNCOV
104
            });
×
UNCOV
105
        }
×
106

107
        if (atlasCluster?.username && atlasCluster?.projectId) {
788✔
108
            void this.apiClient
1✔
109
                .deleteDatabaseUser({
1✔
110
                    params: {
1✔
111
                        path: {
1✔
112
                            groupId: atlasCluster.projectId,
1✔
113
                            username: atlasCluster.username,
1✔
114
                            databaseName: "admin",
1✔
115
                        },
1✔
116
                    },
1✔
117
                })
1✔
118
                .catch((err: unknown) => {
1✔
UNCOV
119
                    const error = err instanceof Error ? err : new Error(String(err));
×
UNCOV
120
                    this.logger.error({
×
UNCOV
121
                        id: LogId.atlasDeleteDatabaseUserFailure,
×
UNCOV
122
                        context: "session",
×
UNCOV
123
                        message: `Error deleting previous database user: ${error.message}`,
×
UNCOV
124
                    });
×
125
                });
1✔
126
        }
1✔
127
    }
788✔
128

129
    async close(): Promise<void> {
2✔
130
        await this.disconnect();
80✔
131
        await this.apiClient.close();
80✔
132
        await this.exportsManager.close();
79✔
133
        this.emit("close");
79✔
134
    }
80✔
135

136
    async connectToMongoDB(settings: ConnectionSettings): Promise<void> {
2✔
137
        try {
399✔
138
            await this.connectionManager.connect({ ...settings });
399✔
139
        } catch (error: unknown) {
399✔
140
            const message = error instanceof Error ? error.message : (error as string);
27!
141
            this.emit("connection-error", message);
27✔
142
            throw error;
27✔
143
        }
27✔
144
    }
399✔
145

146
    get isConnectedToMongoDB(): boolean {
2✔
147
        return this.connectionManager.currentConnectionState.tag === "connected";
2,179✔
148
    }
2,179✔
149

150
    get serviceProvider(): NodeDriverServiceProvider {
2✔
151
        if (this.isConnectedToMongoDB) {
306✔
152
            const state = this.connectionManager.currentConnectionState as ConnectionStateConnected;
306✔
153
            return state.serviceProvider;
306✔
154
        }
306!
155

UNCOV
156
        throw new MongoDBError(ErrorCodes.NotConnectedToMongoDB, "Not connected to MongoDB");
×
157
    }
306✔
158

159
    get connectedAtlasCluster(): AtlasClusterConnectionInfo | undefined {
2✔
160
        return this.connectionManager.currentConnectionState.connectedAtlasCluster;
1,022✔
161
    }
1,022✔
162
}
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