Skip to content

Commit 9cf0447

Browse files
committed
wip
1 parent 99039bb commit 9cf0447

File tree

6 files changed

+213
-3
lines changed

6 files changed

+213
-3
lines changed

package-lock.json

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@
5858
"dependencies": {
5959
"@modelcontextprotocol/sdk": "^1.8.0",
6060
"@mongodb-js/devtools-connect": "^3.7.2",
61+
"@mongodb-js/get-os-info": "^0.4.1",
6162
"@mongosh/service-provider-node-driver": "^3.6.0",
6263
"bson": "^6.10.3",
6364
"mongodb": "^6.15.0",

src/index.ts

Lines changed: 52 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,38 @@ import config from "./config.js";
88
import { Session } from "./session.js";
99
import { Server } from "./server.js";
1010

11-
try {
11+
const POLL_INTERVAL_MS = 2000; // 2 seconds
12+
const MAX_RETRIES = 15; // 30 seconds total
13+
const CLIENT_VERSION_TIMEOUT = new Error('Timeout waiting for client version');
14+
15+
async function pollClientVersion(mcpServer: McpServer): Promise<void> {
16+
let attempts = 0;
17+
18+
return new Promise((resolve, reject) => {
19+
const interval = setInterval(async () => {
20+
try {
21+
const client = await mcpServer.server.getClientVersion();
22+
if (client?.name && client?.version) {
23+
clearInterval(interval);
24+
logger.info(
25+
mongoLogId(1_000_003),
26+
"server",
27+
`Connected to client: ${client.name} v${client.version}`
28+
);
29+
resolve();
30+
} else if (++attempts >= MAX_RETRIES) {
31+
clearInterval(interval);
32+
reject(CLIENT_VERSION_TIMEOUT);
33+
}
34+
} catch (error: unknown) {
35+
clearInterval(interval);
36+
reject(error);
37+
}
38+
}, POLL_INTERVAL_MS);
39+
});
40+
}
41+
42+
async function main() {
1243
const session = new Session();
1344
const mcpServer = new McpServer({
1445
name: "MongoDB Atlas",
@@ -23,8 +54,26 @@ try {
2354
const transport = new StdioServerTransport();
2455

2556
await server.connect(transport);
26-
} catch (error: unknown) {
27-
logger.emergency(mongoLogId(1_000_004), "server", `Fatal error running server: ${error as string}`);
57+
try {
58+
await pollClientVersion(mcpServer);
59+
} catch (error) {
60+
logger.warning(
61+
mongoLogId(1_000_006),
62+
"server",
63+
"Client version information unavailable after 30 seconds"
64+
);
65+
66+
}
67+
}
2868

69+
// Start the server
70+
try {
71+
await main();
72+
} catch (error: unknown) {
73+
logger.emergency(
74+
mongoLogId(1_000_004),
75+
"server",
76+
`Fatal error running server: ${error as string}`
77+
);
2978
process.exit(1);
3079
}

src/server.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { AtlasTools } from "./tools/atlas/tools.js";
55
import { MongoDbTools } from "./tools/mongodb/tools.js";
66
import logger, { initializeLogger } from "./logger.js";
77
import { mongoLogId } from "mongodb-log-writer";
8+
import { getOsInfo } from '@mongodb-js/get-os-info';
89

910
export class Server {
1011
public readonly session: Session;
@@ -18,6 +19,11 @@ export class Server {
1819
async connect(transport: Transport) {
1920
this.mcpServer.server.registerCapabilities({ logging: {} });
2021

22+
23+
// log telemetry
24+
const osInfo = await getOsInfo();
25+
logger.info(mongoLogId(1_000_005), "server", `Server started with osInfo ${JSON.stringify(osInfo)}`);
26+
2127
this.registerTools();
2228

2329
await initializeLogger(this.mcpServer);
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
declare module '@mongodb-js/get-os-info' {
2+
export function getOsInfo(): Promise<{
3+
platform: string;
4+
arch: string;
5+
version: string;
6+
release: string;
7+
}>;
8+
}

tracking-plan-mcp.md

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
# Atlas MCP Server Tracking Plan
2+
3+
Generated on April 16, 2025
4+
5+
## MDB MCP Event
6+
7+
All events in the MCP server follow this base structure with common properties. Specific event types will have additional properties as detailed below.
8+
9+
**Base Properties**:
10+
11+
- **timestamp** (required): `string`
12+
- ISO 8601 timestamp when the event occurred
13+
- **machine_id** (required): `string`
14+
- Unique anonymous identifier of the machine
15+
- **mcp\_server\_version** (required): `string`
16+
- The version of the MCP server.
17+
- **mcp\_server\_name** (required): `string`
18+
- The name of the MCP server.
19+
- **mcp\_client\_version** (required): `string`
20+
- The version of the MCP agent.
21+
- **mcp\_client\_name** (required): `string`
22+
- The name of the agent calling the MCP server. (e.g. claude)
23+
- **platform** (required): `string`
24+
- The platform on which the MCP server is running.
25+
- **arch** (required): `string`
26+
- The architecture of the system's processor.
27+
- **os\_type** (optional): `string | undefined`
28+
- The type of operating system.
29+
- **os\_version** (optional): `string | undefined`
30+
- Detailed kernel or system version information.
31+
- **os\_linux\_dist** (optional): `string | undefined`
32+
- The Linux distribution name, if applicable.
33+
- **component** (required): `string`
34+
- The component generating the event (e.g., "server", "tool", "atlas", "mongodb")
35+
- **action** (required): `string`
36+
- The specific action being performed
37+
38+
## Events per component
39+
40+
### Server Component
41+
42+
#### Server Lifecycle
43+
**component**: `"server"`
44+
**action**: `"lifecycle"`
45+
46+
**Additional Properties**:
47+
- **state** (required): `"start" | "stop"`
48+
- The lifecycle state change
49+
- **startup_time_ms** (optional): `number`
50+
- Time taken for the server to start. Present when state is "start".
51+
- **connected_services** (optional): `string[] | undefined`
52+
- List of services connected at launch. Present when state is "start".
53+
- **runtime_duration_ms** (optional): `number`
54+
- The total runtime duration. Present when state is "stop".
55+
- **exit_code** (optional): `number`
56+
- The exit code. Present when state is "stop".
57+
- **reason** (optional): `string | undefined`
58+
- The stop reason (e.g., "normal", "error", "timeout"). Present when state is "stop".
59+
60+
#### Tool Registration
61+
**component**: `"tool"`
62+
**action**: `"register" | "deregister"`
63+
64+
**Additional Properties**:
65+
- **count** (required): `number`
66+
- The number of tools registered
67+
- **tool_list** (required): `string[]`
68+
- List of tools registered
69+
70+
71+
#### Tool Call
72+
**component**: `"tool"`
73+
**action**: `"call"`
74+
75+
**Additional Properties**:
76+
- **name** (required): `string`
77+
- The name of the tool
78+
- **target** (required): `"mongodb" | "atlas"`
79+
- The service being targeted by the tool
80+
- **operation** (required): `string`
81+
- The type of operation being performed
82+
- For MongoDB: `"query" | "aggregation" | "insert" | "update" | "delete" | "index" | "metadata" | "connect"`
83+
- For Atlas: `"list_clusters" | "list_projects" | "create_cluster" | "manage_access_list" | "manage_database_user" | "connect"`
84+
- **duration_ms** (required): `number`
85+
- Execution time in milliseconds
86+
- **success** (required): `boolean`
87+
- Whether the call succeeded
88+
- **error_code** (optional): `string | undefined`
89+
- Error code if operation failed
90+
- **error_type** (optional): `string | undefined`
91+
- Type of error if operation failed
92+
- **state** (optional): `"attempt" | "success" | "failure"`
93+
- Connection state (when operation is "connect")
94+
- **doc_count** (optional): `number | undefined`
95+
- Number of affected documents (MongoDB only)
96+
- **database** (optional): `string | undefined`
97+
- Target database name (MongoDB only)
98+
- **collection** (optional): `string | undefined`
99+
- Target collection name (MongoDB only)
100+
- **connection_id** (optional): `string | undefined`
101+
- Connection identifier (required when operation is "connect")
102+
- **project_id** (optional): `string | undefined`
103+
- Atlas project ID (Atlas only)
104+
- **org_id** (optional): `string | undefined`
105+
- Atlas organization ID (Atlas only)
106+
- **cluster_name** (optional): `string | undefined`
107+
- Target cluster name (Atlas only)
108+
- **is_atlas** (optional): `boolean | undefined`
109+
- Whether using Atlas connection string (when operation is "connect")
110+
111+
#### Error
112+
**component**: `"error"`
113+
**action**: `"occur"`
114+
115+
**Additional Properties**:
116+
- **code** (required): `number`
117+
- The error code
118+
- **context** (required): `string`
119+
- Where the error occurred (e.g., "auth", "tool", "connection")
120+
- **type** (required): `string`
121+
- Error category or type
122+
123+
### Authentication Component
124+
125+
#### Authentication
126+
**component**: `"auth"`
127+
**action**: `"authenticate"`
128+
129+
**Additional Properties**:
130+
- **target** (required): `"mongodb" | "atlas"`
131+
- The service being authenticated with
132+
- **success** (required): `boolean`
133+
- Whether authentication succeeded
134+
- **method** (required): `string`
135+
- Authentication method used
136+
- **duration_ms** (required): `number`
137+
- Time taken to authenticate
138+
- **error_code** (optional): `string | undefined`
139+
- Error code if failed

0 commit comments

Comments
 (0)