mongodb-mcp-server 0.1.0 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.dockerignore +11 -0
- package/.github/CODEOWNERS +0 -2
- package/.github/ISSUE_TEMPLATE/bug_report.yml +8 -0
- package/.github/workflows/check-pr-title.yml +29 -0
- package/.github/workflows/{lint.yml → check.yml} +22 -1
- package/.github/workflows/code_health.yaml +0 -22
- package/.github/workflows/code_health_fork.yaml +7 -63
- package/.github/workflows/docker.yaml +57 -0
- package/.github/workflows/stale.yml +32 -0
- package/.smithery/Dockerfile +30 -0
- package/.smithery/smithery.yaml +63 -0
- package/.vscode/extensions.json +9 -0
- package/.vscode/settings.json +11 -0
- package/CONTRIBUTING.md +1 -1
- package/Dockerfile +10 -0
- package/README.md +173 -35
- package/dist/common/atlas/apiClient.js +151 -35
- package/dist/common/atlas/apiClient.js.map +1 -1
- package/dist/common/atlas/apiClientError.js +38 -5
- package/dist/common/atlas/apiClientError.js.map +1 -1
- package/dist/common/atlas/cluster.js +66 -0
- package/dist/common/atlas/cluster.js.map +1 -0
- package/dist/common/atlas/generatePassword.js +9 -0
- package/dist/common/atlas/generatePassword.js.map +1 -0
- package/dist/helpers/EJsonTransport.js +38 -0
- package/dist/helpers/EJsonTransport.js.map +1 -0
- package/dist/helpers/connectionOptions.js +10 -0
- package/dist/helpers/connectionOptions.js.map +1 -0
- package/dist/{packageInfo.js → helpers/packageInfo.js} +1 -1
- package/dist/helpers/packageInfo.js.map +1 -0
- package/dist/index.js +23 -3
- package/dist/index.js.map +1 -1
- package/dist/logger.js +7 -0
- package/dist/logger.js.map +1 -1
- package/dist/server.js +16 -12
- package/dist/server.js.map +1 -1
- package/dist/session.js +8 -3
- package/dist/session.js.map +1 -1
- package/dist/telemetry/constants.js +1 -3
- package/dist/telemetry/constants.js.map +1 -1
- package/dist/telemetry/eventCache.js.map +1 -1
- package/dist/telemetry/telemetry.js +126 -47
- package/dist/telemetry/telemetry.js.map +1 -1
- package/dist/tools/atlas/atlasTool.js +38 -0
- package/dist/tools/atlas/atlasTool.js.map +1 -1
- package/dist/tools/atlas/create/createDBUser.js +19 -2
- package/dist/tools/atlas/create/createDBUser.js.map +1 -1
- package/dist/tools/atlas/create/createProject.js +5 -1
- package/dist/tools/atlas/create/createProject.js.map +1 -1
- package/dist/tools/atlas/metadata/connectCluster.js +5 -22
- package/dist/tools/atlas/metadata/connectCluster.js.map +1 -1
- package/dist/tools/atlas/read/inspectCluster.js +4 -24
- package/dist/tools/atlas/read/inspectCluster.js.map +1 -1
- package/dist/tools/atlas/read/listAlerts.js +41 -0
- package/dist/tools/atlas/read/listAlerts.js.map +1 -0
- package/dist/tools/atlas/read/listClusters.js +9 -18
- package/dist/tools/atlas/read/listClusters.js.map +1 -1
- package/dist/tools/atlas/read/listProjects.js +3 -1
- package/dist/tools/atlas/read/listProjects.js.map +1 -1
- package/dist/tools/atlas/tools.js +2 -0
- package/dist/tools/atlas/tools.js.map +1 -1
- package/dist/tools/mongodb/metadata/listDatabases.js.map +1 -1
- package/dist/tools/mongodb/read/count.js +2 -2
- package/dist/tools/mongodb/read/count.js.map +1 -1
- package/dist/tools/mongodb/tools.js +2 -4
- package/dist/tools/mongodb/tools.js.map +1 -1
- package/dist/tools/tool.js +38 -6
- package/dist/tools/tool.js.map +1 -1
- package/eslint.config.js +2 -1
- package/{jest.config.ts → jest.config.cjs} +1 -1
- package/package.json +11 -9
- package/scripts/apply.ts +8 -5
- package/scripts/filter.ts +5 -0
- package/src/common/atlas/apiClient.ts +190 -38
- package/src/common/atlas/apiClientError.ts +58 -7
- package/src/common/atlas/cluster.ts +94 -0
- package/src/common/atlas/generatePassword.ts +10 -0
- package/src/common/atlas/openapi.d.ts +1876 -239
- package/src/helpers/EJsonTransport.ts +47 -0
- package/src/helpers/connectionOptions.ts +20 -0
- package/src/{packageInfo.ts → helpers/packageInfo.ts} +1 -1
- package/src/index.ts +27 -3
- package/src/logger.ts +8 -0
- package/src/server.ts +23 -15
- package/src/session.ts +8 -4
- package/src/telemetry/constants.ts +2 -3
- package/src/telemetry/eventCache.ts +1 -1
- package/src/telemetry/telemetry.ts +182 -64
- package/src/telemetry/types.ts +1 -1
- package/src/tools/atlas/atlasTool.ts +47 -1
- package/src/tools/atlas/create/createDBUser.ts +22 -2
- package/src/tools/atlas/create/createProject.ts +7 -1
- package/src/tools/atlas/metadata/connectCluster.ts +5 -27
- package/src/tools/atlas/read/inspectCluster.ts +4 -40
- package/src/tools/atlas/read/listAlerts.ts +45 -0
- package/src/tools/atlas/read/listClusters.ts +19 -36
- package/src/tools/atlas/read/listProjects.ts +4 -2
- package/src/tools/atlas/tools.ts +2 -0
- package/src/tools/mongodb/metadata/listDatabases.ts +0 -1
- package/src/tools/mongodb/read/count.ts +3 -2
- package/src/tools/mongodb/tools.ts +2 -4
- package/src/tools/tool.ts +45 -8
- package/src/types/mongodb-connection-string-url.d.ts +69 -0
- package/tests/integration/helpers.ts +41 -2
- package/tests/integration/tools/atlas/accessLists.test.ts +2 -2
- package/tests/integration/tools/atlas/alerts.test.ts +42 -0
- package/tests/integration/tools/atlas/atlasHelpers.ts +5 -3
- package/tests/integration/tools/atlas/clusters.test.ts +4 -4
- package/tests/integration/tools/atlas/dbUsers.test.ts +58 -33
- package/tests/integration/tools/atlas/orgs.test.ts +2 -2
- package/tests/integration/tools/atlas/projects.test.ts +3 -3
- package/tests/integration/tools/mongodb/create/createCollection.test.ts +2 -2
- package/tests/integration/tools/mongodb/create/createIndex.test.ts +2 -2
- package/tests/integration/tools/mongodb/create/insertMany.test.ts +1 -1
- package/tests/integration/tools/mongodb/delete/dropCollection.test.ts +1 -1
- package/tests/integration/tools/mongodb/metadata/collectionSchema.test.ts +2 -2
- package/tests/integration/tools/mongodb/metadata/connect.test.ts +2 -6
- package/tests/integration/tools/mongodb/metadata/dbStats.test.ts +4 -4
- package/tests/integration/tools/mongodb/metadata/explain.test.ts +10 -10
- package/tests/integration/tools/mongodb/metadata/listCollections.test.ts +1 -1
- package/tests/integration/tools/mongodb/metadata/listDatabases.test.ts +9 -5
- package/tests/integration/tools/mongodb/metadata/logs.test.ts +4 -4
- package/tests/integration/tools/mongodb/mongodbHelpers.ts +15 -24
- package/tests/integration/tools/mongodb/read/aggregate.test.ts +22 -7
- package/tests/integration/tools/mongodb/read/collectionIndexes.test.ts +5 -5
- package/tests/integration/tools/mongodb/read/count.test.ts +15 -10
- package/tests/integration/tools/mongodb/read/find.test.ts +32 -4
- package/tests/integration/tools/mongodb/update/renameCollection.test.ts +4 -4
- package/tests/unit/EJsonTransport.test.ts +71 -0
- package/tests/unit/apiClient.test.ts +193 -0
- package/tests/unit/session.test.ts +65 -0
- package/tests/unit/telemetry.test.ts +222 -80
- package/tsconfig.build.json +2 -1
- package/dist/packageInfo.js.map +0 -1
- package/dist/telemetry/device-id.js +0 -20
- package/dist/telemetry/device-id.js.map +0 -1
- package/src/telemetry/device-id.ts +0 -21
package/README.md
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
[](https://insiders.vscode.dev/redirect/mcp/install?name=mongodb&inputs=%5B%7B%22id%22%3A%22connection_string%22%2C%22type%22%3A%22promptString%22%2C%22description%22%3A%22MongoDB%20connection%20string%22%7D%5D&config=%7B%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22mongodb-mcp-server%22%5D%2C%22env%22%3A%7B%22MDB_MCP_CONNECTION_STRING%22%3A%22%24%7Binput%3Aconnection_string%7D%22%7D%7D)
|
|
2
|
+
[](https://cursor.com/install-mcp?name=MongoDB&config=eyJjb21tYW5kIjoibnB4IC15IG1vbmdvZGItbWNwLXNlcnZlciJ9)
|
|
3
|
+
[](https://smithery.ai/server/@mongodb-js/mongodb-mcp-server)
|
|
4
|
+
|
|
1
5
|
# MongoDB MCP Server
|
|
2
6
|
|
|
3
7
|
A Model Context Protocol server for interacting with MongoDB Databases and MongoDB Atlas.
|
|
@@ -22,24 +26,28 @@ A Model Context Protocol server for interacting with MongoDB Databases and Mongo
|
|
|
22
26
|
|
|
23
27
|
## Prerequisites
|
|
24
28
|
|
|
25
|
-
- Node.js (v20 or later)
|
|
29
|
+
- Node.js (v20.10.0 or later)
|
|
26
30
|
|
|
27
31
|
```shell
|
|
28
32
|
node -v
|
|
29
33
|
```
|
|
30
34
|
|
|
31
35
|
- A MongoDB connection string or Atlas API credentials, **_the Server will not start unless configured_**.
|
|
32
|
-
- **
|
|
36
|
+
- **_Service Accounts Atlas API credentials_** are required to use the Atlas tools. You can create a service account in MongoDB Atlas and use its credentials for authentication. See [Atlas API Access](#atlas-api-access) for more details.
|
|
33
37
|
- If you have a MongoDB connection string, you can use it directly to connect to your MongoDB instance.
|
|
34
38
|
|
|
35
39
|
## Setup
|
|
36
40
|
|
|
37
41
|
### Quick Start
|
|
38
42
|
|
|
43
|
+
> **Note:** When using Atlas API credentials, be sure to assign only the minimum required permissions to your service account. See [Atlas API Permissions](#atlas-api-permissions) for details.
|
|
44
|
+
|
|
39
45
|
Most MCP clients require a configuration file to be created or modified to add the MCP server.
|
|
40
46
|
|
|
47
|
+
Note: The configuration file syntax can be different across clients. Please refer to the following links for the latest expected syntax:
|
|
48
|
+
|
|
41
49
|
- **Windsurf**:https://docs.windsurf.com/windsurf/mcp
|
|
42
|
-
- **VSCode**: https://
|
|
50
|
+
- **VSCode**: https://code.visualstudio.com/docs/copilot/chat/mcp-servers
|
|
43
51
|
- **Claude Desktop**: https://modelcontextprotocol.io/quickstart/user
|
|
44
52
|
- **Cursor**: https://docs.cursor.com/context/model-context-protocol
|
|
45
53
|
|
|
@@ -49,49 +57,155 @@ You can pass your connection string via args, make sure to use a valid username
|
|
|
49
57
|
|
|
50
58
|
```json
|
|
51
59
|
{
|
|
52
|
-
"
|
|
60
|
+
"mcpServers": {
|
|
53
61
|
"MongoDB": {
|
|
54
62
|
"command": "npx",
|
|
55
63
|
"args": [
|
|
56
64
|
"-y",
|
|
57
65
|
"mongodb-mcp-server",
|
|
58
66
|
"--connectionString",
|
|
59
|
-
"mongodb
|
|
67
|
+
"mongodb://localhost:27017/myDatabase"
|
|
60
68
|
]
|
|
61
69
|
}
|
|
62
70
|
}
|
|
63
71
|
}
|
|
64
72
|
```
|
|
65
73
|
|
|
74
|
+
NOTE: The connection string can be configured to connect to any MongoDB cluster, whether it's a local instance or an Atlas cluster.
|
|
75
|
+
|
|
66
76
|
#### Option 2: Atlas API credentials args
|
|
67
77
|
|
|
68
|
-
Use your Atlas API Service
|
|
78
|
+
Use your Atlas API Service Accounts credentials. Must follow all the steps in [Atlas API Access](#atlas-api-access) section.
|
|
69
79
|
|
|
70
80
|
```json
|
|
71
81
|
{
|
|
72
|
-
"
|
|
82
|
+
"mcpServers": {
|
|
73
83
|
"MongoDB": {
|
|
74
84
|
"command": "npx",
|
|
75
85
|
"args": [
|
|
76
86
|
"-y",
|
|
77
87
|
"mongodb-mcp-server",
|
|
78
88
|
"--apiClientId",
|
|
79
|
-
"your-atlas-client-id",
|
|
89
|
+
"your-atlas-service-accounts-client-id",
|
|
80
90
|
"--apiClientSecret",
|
|
81
|
-
"your-atlas-client-secret"
|
|
91
|
+
"your-atlas-service-accounts-client-secret"
|
|
82
92
|
]
|
|
83
93
|
}
|
|
84
94
|
}
|
|
85
95
|
}
|
|
86
96
|
```
|
|
87
97
|
|
|
88
|
-
####
|
|
98
|
+
#### Option 3: Standalone Service using command arguments
|
|
99
|
+
|
|
100
|
+
Start Server using npx command:
|
|
101
|
+
|
|
102
|
+
```shell
|
|
103
|
+
npx -y mongodb-mcp-server --apiClientId="your-atlas-service-accounts-client-id" --apiClientSecret="your-atlas-service-accounts-client-secret"
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
- For a complete list of arguments see [Configuration Options](#configuration-options)
|
|
107
|
+
- To configure your Atlas Service Accounts credentials please refer to [Atlas API Access](#atlas-api-access)
|
|
108
|
+
|
|
109
|
+
#### Option 4: Standalone Service using environment variables
|
|
110
|
+
|
|
111
|
+
```shell
|
|
112
|
+
npx -y mongodb-mcp-server
|
|
113
|
+
```
|
|
89
114
|
|
|
90
|
-
|
|
115
|
+
You can use environment variables in the config file or set them and run the server via npx.
|
|
91
116
|
|
|
92
117
|
- Connection String via environment variables in the MCP file [example](#connection-string-with-environment-variables)
|
|
93
118
|
- Atlas API credentials via environment variables in the MCP file [example](#atlas-api-credentials-with-environment-variables)
|
|
94
119
|
|
|
120
|
+
#### Option 5: Using Docker
|
|
121
|
+
|
|
122
|
+
You can run the MongoDB MCP Server in a Docker container, which provides isolation and doesn't require a local Node.js installation.
|
|
123
|
+
|
|
124
|
+
#### Run with Environment Variables
|
|
125
|
+
|
|
126
|
+
You may provide either a MongoDB connection string OR Atlas API credentials:
|
|
127
|
+
|
|
128
|
+
##### Option A: No configuration
|
|
129
|
+
|
|
130
|
+
```shell
|
|
131
|
+
docker run --rm -i \
|
|
132
|
+
mongodb/mongodb-mcp-server:latest
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
##### Option B: With MongoDB connection string
|
|
136
|
+
|
|
137
|
+
```shell
|
|
138
|
+
docker run --rm -i \
|
|
139
|
+
-e MDB_MCP_CONNECTION_STRING="mongodb+srv://username:password@cluster.mongodb.net/myDatabase" \
|
|
140
|
+
mongodb/mongodb-mcp-server:latest
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
##### Option C: With Atlas API credentials
|
|
144
|
+
|
|
145
|
+
```shell
|
|
146
|
+
docker run --rm -i \
|
|
147
|
+
-e MDB_MCP_API_CLIENT_ID="your-atlas-service-accounts-client-id" \
|
|
148
|
+
-e MDB_MCP_API_CLIENT_SECRET="your-atlas-service-accounts-client-secret" \
|
|
149
|
+
mongodb/mongodb-mcp-server:latest
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
##### Docker in MCP Configuration File
|
|
153
|
+
|
|
154
|
+
Without options:
|
|
155
|
+
|
|
156
|
+
```json
|
|
157
|
+
{
|
|
158
|
+
"mcpServers": {
|
|
159
|
+
"MongoDB": {
|
|
160
|
+
"command": "docker",
|
|
161
|
+
"args": ["run", "--rm", "-i", "mongodb/mongodb-mcp-server:latest"]
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
With connection string:
|
|
168
|
+
|
|
169
|
+
```json
|
|
170
|
+
{
|
|
171
|
+
"mcpServers": {
|
|
172
|
+
"MongoDB": {
|
|
173
|
+
"command": "docker",
|
|
174
|
+
"args": [
|
|
175
|
+
"run",
|
|
176
|
+
"--rm",
|
|
177
|
+
"-i",
|
|
178
|
+
"-e",
|
|
179
|
+
"MDB_MCP_CONNECTION_STRING=mongodb+srv://username:password@cluster.mongodb.net/myDatabase",
|
|
180
|
+
"mongodb/mongodb-mcp-server:latest"
|
|
181
|
+
]
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
With Atlas API credentials:
|
|
188
|
+
|
|
189
|
+
```json
|
|
190
|
+
{
|
|
191
|
+
"mcpServers": {
|
|
192
|
+
"MongoDB": {
|
|
193
|
+
"command": "docker",
|
|
194
|
+
"args": [
|
|
195
|
+
"run",
|
|
196
|
+
"--rm",
|
|
197
|
+
"-i",
|
|
198
|
+
"-e",
|
|
199
|
+
"MDB_MCP_API_CLIENT_ID=your-atlas-service-accounts-client-id",
|
|
200
|
+
"-e",
|
|
201
|
+
"MDB_MCP_API_CLIENT_SECRET=your-atlas-service-accounts-client-secret",
|
|
202
|
+
"mongodb/mongodb-mcp-server:latest"
|
|
203
|
+
]
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
```
|
|
208
|
+
|
|
95
209
|
## 🛠️ Supported Tools
|
|
96
210
|
|
|
97
211
|
### Tool List
|
|
@@ -108,7 +222,8 @@ Alternatively you can use environment variables in the config file or set them a
|
|
|
108
222
|
- `atlas-inspect-access-list` - Inspect IP/CIDR ranges with access to MongoDB Atlas clusters
|
|
109
223
|
- `atlas-create-access-list` - Configure IP/CIDR access list for MongoDB Atlas clusters
|
|
110
224
|
- `atlas-list-db-users` - List MongoDB Atlas database users
|
|
111
|
-
- `atlas-create-db-user` -
|
|
225
|
+
- `atlas-create-db-user` - Creates a MongoDB Atlas database user
|
|
226
|
+
- `atlas-list-alerts` - List MongoDB Atlas Alerts for a Project
|
|
112
227
|
|
|
113
228
|
NOTE: atlas tools are only available when you set credentials on [configuration](#configuration) section.
|
|
114
229
|
|
|
@@ -144,15 +259,15 @@ The MongoDB MCP Server can be configured using multiple methods, with the follow
|
|
|
144
259
|
|
|
145
260
|
### Configuration Options
|
|
146
261
|
|
|
147
|
-
| Option | Description
|
|
148
|
-
| ------------------ |
|
|
149
|
-
| `apiClientId` | Atlas API client ID for authentication
|
|
150
|
-
| `apiClientSecret` | Atlas API client secret for authentication
|
|
151
|
-
| `connectionString` | MongoDB connection string for direct database connections
|
|
152
|
-
| `logPath` | Folder to store logs
|
|
153
|
-
| `disabledTools` | An array of tool names, operation types, and/or categories of tools that will be disabled
|
|
154
|
-
| `readOnly` | When set to true, only allows read and metadata operation types, disabling create/update/delete operations
|
|
155
|
-
| `telemetry` | When set to disabled, disables telemetry collection
|
|
262
|
+
| Option | Description |
|
|
263
|
+
| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
264
|
+
| `apiClientId` | Atlas API client ID for authentication. Required for running Atlas tools. |
|
|
265
|
+
| `apiClientSecret` | Atlas API client secret for authentication. Required for running Atlas tools. |
|
|
266
|
+
| `connectionString` | MongoDB connection string for direct database connections. Optional, if not set, you'll need to call the `connect` tool before interacting with MongoDB data. |
|
|
267
|
+
| `logPath` | Folder to store logs. |
|
|
268
|
+
| `disabledTools` | An array of tool names, operation types, and/or categories of tools that will be disabled. |
|
|
269
|
+
| `readOnly` | When set to true, only allows read and metadata operation types, disabling create/update/delete operations. |
|
|
270
|
+
| `telemetry` | When set to disabled, disables telemetry collection. |
|
|
156
271
|
|
|
157
272
|
#### Log Path
|
|
158
273
|
|
|
@@ -211,13 +326,16 @@ You can disable telemetry using:
|
|
|
211
326
|
|
|
212
327
|
To use the Atlas API tools, you'll need to create a service account in MongoDB Atlas:
|
|
213
328
|
|
|
329
|
+
> **ℹ️ Note:** For a detailed breakdown of the minimum required permissions for each Atlas operation, see the [Atlas API Permissions](#atlas-api-permissions) section below.
|
|
330
|
+
|
|
214
331
|
1. **Create a Service Account:**
|
|
215
332
|
|
|
216
333
|
- Log in to MongoDB Atlas at [cloud.mongodb.com](https://cloud.mongodb.com)
|
|
217
334
|
- Navigate to Access Manager > Organization Access
|
|
218
335
|
- Click Add New > Applications > Service Accounts
|
|
219
336
|
- Enter name, description and expiration for your service account (e.g., "MCP, MCP Server Access, 7 days")
|
|
220
|
-
-
|
|
337
|
+
- **Assign only the minimum permissions needed for your use case.**
|
|
338
|
+
- See [Atlas API Permissions](#atlas-api-permissions) for details.
|
|
221
339
|
- Click "Create"
|
|
222
340
|
|
|
223
341
|
To learn more about Service Accounts, check the [MongoDB Atlas documentation](https://www.mongodb.com/docs/atlas/api/service-accounts-overview/).
|
|
@@ -227,13 +345,33 @@ To learn more about Service Accounts, check the [MongoDB Atlas documentation](ht
|
|
|
227
345
|
- After creation, you'll be shown the Client ID and Client Secret
|
|
228
346
|
- **Important:** Copy and save the Client Secret immediately as it won't be displayed again
|
|
229
347
|
|
|
230
|
-
3. **Add Access List Entry
|
|
348
|
+
3. **Add Access List Entry:**
|
|
231
349
|
|
|
232
350
|
- Add your IP address to the API access list
|
|
233
351
|
|
|
234
352
|
4. **Configure the MCP Server:**
|
|
235
353
|
- Use one of the configuration methods below to set your `apiClientId` and `apiClientSecret`
|
|
236
354
|
|
|
355
|
+
### Atlas API Permissions
|
|
356
|
+
|
|
357
|
+
> **Security Warning:** Granting the Organization Owner role is rarely necessary and can be a security risk. Assign only the minimum permissions needed for your use case.
|
|
358
|
+
|
|
359
|
+
#### Quick Reference: Required roles per operation
|
|
360
|
+
|
|
361
|
+
| What you want to do | Safest Role to Assign (where) |
|
|
362
|
+
| ------------------------------------ | --------------------------------------- |
|
|
363
|
+
| List orgs/projects | Org Member or Org Read Only (Org) |
|
|
364
|
+
| Create new projects | Org Project Creator (Org) |
|
|
365
|
+
| View clusters/databases in a project | Project Read Only (Project) |
|
|
366
|
+
| Create/manage clusters in a project | Project Cluster Manager (Project) |
|
|
367
|
+
| Manage project access lists | Project IP Access List Admin (Project) |
|
|
368
|
+
| Manage database users | Project Database Access Admin (Project) |
|
|
369
|
+
|
|
370
|
+
- **Prefer project-level roles** for most operations. Assign only to the specific projects you need to manage or view.
|
|
371
|
+
- **Avoid Organization Owner** unless you require full administrative control over all projects and settings in the organization.
|
|
372
|
+
|
|
373
|
+
For a full list of roles and their privileges, see the [Atlas User Roles documentation](https://www.mongodb.com/docs/atlas/reference/user-roles/#service-user-roles).
|
|
374
|
+
|
|
237
375
|
### Configuration Methods
|
|
238
376
|
|
|
239
377
|
#### Environment Variables
|
|
@@ -241,9 +379,9 @@ To learn more about Service Accounts, check the [MongoDB Atlas documentation](ht
|
|
|
241
379
|
Set environment variables with the prefix `MDB_MCP_` followed by the option name in uppercase with underscores:
|
|
242
380
|
|
|
243
381
|
```shell
|
|
244
|
-
# Set Atlas API credentials
|
|
245
|
-
export MDB_MCP_API_CLIENT_ID="your-atlas-client-id"
|
|
246
|
-
export MDB_MCP_API_CLIENT_SECRET="your-atlas-client-secret"
|
|
382
|
+
# Set Atlas API credentials (via Service Accounts)
|
|
383
|
+
export MDB_MCP_API_CLIENT_ID="your-atlas-service-accounts-client-id"
|
|
384
|
+
export MDB_MCP_API_CLIENT_SECRET="your-atlas-service-accounts-client-secret"
|
|
247
385
|
|
|
248
386
|
# Set a custom MongoDB connection string
|
|
249
387
|
export MDB_MCP_CONNECTION_STRING="mongodb+srv://username:password@cluster.mongodb.net/myDatabase"
|
|
@@ -258,7 +396,7 @@ export MDB_MCP_LOG_PATH="/path/to/logs"
|
|
|
258
396
|
|
|
259
397
|
```json
|
|
260
398
|
{
|
|
261
|
-
"
|
|
399
|
+
"mcpServers": {
|
|
262
400
|
"MongoDB": {
|
|
263
401
|
"command": "npx",
|
|
264
402
|
"args": ["-y", "mongodb-mcp-server"],
|
|
@@ -274,13 +412,13 @@ export MDB_MCP_LOG_PATH="/path/to/logs"
|
|
|
274
412
|
|
|
275
413
|
```json
|
|
276
414
|
{
|
|
277
|
-
"
|
|
415
|
+
"mcpServers": {
|
|
278
416
|
"MongoDB": {
|
|
279
417
|
"command": "npx",
|
|
280
418
|
"args": ["-y", "mongodb-mcp-server"],
|
|
281
419
|
"env": {
|
|
282
|
-
"MDB_MCP_API_CLIENT_ID": "your-atlas-client-id",
|
|
283
|
-
"MDB_MCP_API_CLIENT_SECRET": "your-atlas-client-secret"
|
|
420
|
+
"MDB_MCP_API_CLIENT_ID": "your-atlas-service-accounts-client-id",
|
|
421
|
+
"MDB_MCP_API_CLIENT_SECRET": "your-atlas-service-accounts-client-secret"
|
|
284
422
|
}
|
|
285
423
|
}
|
|
286
424
|
}
|
|
@@ -292,7 +430,7 @@ export MDB_MCP_LOG_PATH="/path/to/logs"
|
|
|
292
430
|
Pass configuration options as command-line arguments when starting the server:
|
|
293
431
|
|
|
294
432
|
```shell
|
|
295
|
-
npx -y mongodb-mcp-server --apiClientId="your-atlas-client-id" --apiClientSecret="your-atlas-client-secret" --connectionString="mongodb+srv://username:password@cluster.mongodb.net/myDatabase" --logPath=/path/to/logs
|
|
433
|
+
npx -y mongodb-mcp-server --apiClientId="your-atlas-service-accounts-client-id" --apiClientSecret="your-atlas-service-accounts-client-secret" --connectionString="mongodb+srv://username:password@cluster.mongodb.net/myDatabase" --logPath=/path/to/logs
|
|
296
434
|
```
|
|
297
435
|
|
|
298
436
|
#### MCP configuration file examples
|
|
@@ -301,7 +439,7 @@ npx -y mongodb-mcp-server --apiClientId="your-atlas-client-id" --apiClientSecret
|
|
|
301
439
|
|
|
302
440
|
```json
|
|
303
441
|
{
|
|
304
|
-
"
|
|
442
|
+
"mcpServers": {
|
|
305
443
|
"MongoDB": {
|
|
306
444
|
"command": "npx",
|
|
307
445
|
"args": [
|
|
@@ -319,16 +457,16 @@ npx -y mongodb-mcp-server --apiClientId="your-atlas-client-id" --apiClientSecret
|
|
|
319
457
|
|
|
320
458
|
```json
|
|
321
459
|
{
|
|
322
|
-
"
|
|
460
|
+
"mcpServers": {
|
|
323
461
|
"MongoDB": {
|
|
324
462
|
"command": "npx",
|
|
325
463
|
"args": [
|
|
326
464
|
"-y",
|
|
327
465
|
"mongodb-mcp-server",
|
|
328
466
|
"--apiClientId",
|
|
329
|
-
"your-atlas-client-id",
|
|
467
|
+
"your-atlas-service-accounts-client-id",
|
|
330
468
|
"--apiClientSecret",
|
|
331
|
-
"your-atlas-client-secret"
|
|
469
|
+
"your-atlas-service-accounts-client-secret"
|
|
332
470
|
]
|
|
333
471
|
}
|
|
334
472
|
}
|
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
import createClient from "openapi-fetch";
|
|
2
2
|
import { ClientCredentials } from "simple-oauth2";
|
|
3
3
|
import { ApiClientError } from "./apiClientError.js";
|
|
4
|
-
import { packageInfo } from "../../packageInfo.js";
|
|
4
|
+
import { packageInfo } from "../../helpers/packageInfo.js";
|
|
5
5
|
const ATLAS_API_VERSION = "2025-03-12";
|
|
6
6
|
export class ApiClient {
|
|
7
7
|
constructor(options) {
|
|
8
8
|
this.getAccessToken = async () => {
|
|
9
9
|
if (this.oauth2Client && (!this.accessToken || this.accessToken.expired())) {
|
|
10
|
-
this.accessToken = await this.oauth2Client.getToken({
|
|
10
|
+
this.accessToken = await this.oauth2Client.getToken({
|
|
11
|
+
agent: this.options.userAgent,
|
|
12
|
+
});
|
|
11
13
|
}
|
|
12
14
|
return this.accessToken?.token.access_token;
|
|
13
15
|
};
|
|
@@ -26,13 +28,6 @@ export class ApiClient {
|
|
|
26
28
|
}
|
|
27
29
|
},
|
|
28
30
|
};
|
|
29
|
-
this.errorMiddleware = {
|
|
30
|
-
async onResponse({ response }) {
|
|
31
|
-
if (!response.ok) {
|
|
32
|
-
throw await ApiClientError.fromResponse(response);
|
|
33
|
-
}
|
|
34
|
-
},
|
|
35
|
-
};
|
|
36
31
|
this.options = {
|
|
37
32
|
...options,
|
|
38
33
|
userAgent: options.userAgent ||
|
|
@@ -58,11 +53,13 @@ export class ApiClient {
|
|
|
58
53
|
});
|
|
59
54
|
this.client.use(this.authMiddleware);
|
|
60
55
|
}
|
|
61
|
-
this.client.use(this.errorMiddleware);
|
|
62
56
|
}
|
|
63
57
|
hasCredentials() {
|
|
64
58
|
return !!(this.oauth2Client && this.accessToken);
|
|
65
59
|
}
|
|
60
|
+
async validateAccessToken() {
|
|
61
|
+
await this.getAccessToken();
|
|
62
|
+
}
|
|
66
63
|
async getIpInfo() {
|
|
67
64
|
const accessToken = await this.getAccessToken();
|
|
68
65
|
const endpoint = "api/private/ipinfo";
|
|
@@ -81,19 +78,53 @@ export class ApiClient {
|
|
|
81
78
|
return (await response.json());
|
|
82
79
|
}
|
|
83
80
|
async sendEvents(events) {
|
|
84
|
-
|
|
81
|
+
if (!this.options.credentials) {
|
|
82
|
+
await this.sendUnauthEvents(events);
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
try {
|
|
86
|
+
await this.sendAuthEvents(events);
|
|
87
|
+
}
|
|
88
|
+
catch (error) {
|
|
89
|
+
if (error instanceof ApiClientError) {
|
|
90
|
+
if (error.response.status !== 401) {
|
|
91
|
+
throw error;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
// send unauth events if any of the following are true:
|
|
95
|
+
// 1: the token is not valid (not ApiClientError)
|
|
96
|
+
// 2: if the api responded with 401 (ApiClientError with status 401)
|
|
97
|
+
await this.sendUnauthEvents(events);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
async sendAuthEvents(events) {
|
|
101
|
+
const accessToken = await this.getAccessToken();
|
|
102
|
+
if (!accessToken) {
|
|
103
|
+
throw new Error("No access token available");
|
|
104
|
+
}
|
|
105
|
+
const authUrl = new URL("api/private/v1.0/telemetry/events", this.options.baseUrl);
|
|
106
|
+
const response = await fetch(authUrl, {
|
|
107
|
+
method: "POST",
|
|
108
|
+
headers: {
|
|
109
|
+
Accept: "application/json",
|
|
110
|
+
"Content-Type": "application/json",
|
|
111
|
+
"User-Agent": this.options.userAgent,
|
|
112
|
+
Authorization: `Bearer ${accessToken}`,
|
|
113
|
+
},
|
|
114
|
+
body: JSON.stringify(events),
|
|
115
|
+
});
|
|
116
|
+
if (!response.ok) {
|
|
117
|
+
throw await ApiClientError.fromResponse(response);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
async sendUnauthEvents(events) {
|
|
85
121
|
const headers = {
|
|
86
122
|
Accept: "application/json",
|
|
87
123
|
"Content-Type": "application/json",
|
|
88
124
|
"User-Agent": this.options.userAgent,
|
|
89
125
|
};
|
|
90
|
-
const
|
|
91
|
-
|
|
92
|
-
endpoint = "api/private/v1.0/telemetry/events";
|
|
93
|
-
headers["Authorization"] = `Bearer ${accessToken}`;
|
|
94
|
-
}
|
|
95
|
-
const url = new URL(endpoint, this.options.baseUrl);
|
|
96
|
-
const response = await fetch(url, {
|
|
126
|
+
const unauthUrl = new URL("api/private/unauth/telemetry/events", this.options.baseUrl);
|
|
127
|
+
const response = await fetch(unauthUrl, {
|
|
97
128
|
method: "POST",
|
|
98
129
|
headers,
|
|
99
130
|
body: JSON.stringify(events),
|
|
@@ -104,67 +135,152 @@ export class ApiClient {
|
|
|
104
135
|
}
|
|
105
136
|
// DO NOT EDIT. This is auto-generated code.
|
|
106
137
|
async listClustersForAllProjects(options) {
|
|
107
|
-
const { data } = await this.client.GET("/api/atlas/v2/clusters", options);
|
|
138
|
+
const { data, error, response } = await this.client.GET("/api/atlas/v2/clusters", options);
|
|
139
|
+
if (error) {
|
|
140
|
+
throw ApiClientError.fromError(response, error);
|
|
141
|
+
}
|
|
108
142
|
return data;
|
|
109
143
|
}
|
|
110
144
|
async listProjects(options) {
|
|
111
|
-
const { data } = await this.client.GET("/api/atlas/v2/groups", options);
|
|
145
|
+
const { data, error, response } = await this.client.GET("/api/atlas/v2/groups", options);
|
|
146
|
+
if (error) {
|
|
147
|
+
throw ApiClientError.fromError(response, error);
|
|
148
|
+
}
|
|
112
149
|
return data;
|
|
113
150
|
}
|
|
114
151
|
async createProject(options) {
|
|
115
|
-
const { data } = await this.client.POST("/api/atlas/v2/groups", options);
|
|
152
|
+
const { data, error, response } = await this.client.POST("/api/atlas/v2/groups", options);
|
|
153
|
+
if (error) {
|
|
154
|
+
throw ApiClientError.fromError(response, error);
|
|
155
|
+
}
|
|
116
156
|
return data;
|
|
117
157
|
}
|
|
118
158
|
async deleteProject(options) {
|
|
119
|
-
await this.client.DELETE("/api/atlas/v2/groups/{groupId}", options);
|
|
159
|
+
const { error, response } = await this.client.DELETE("/api/atlas/v2/groups/{groupId}", options);
|
|
160
|
+
if (error) {
|
|
161
|
+
throw ApiClientError.fromError(response, error);
|
|
162
|
+
}
|
|
120
163
|
}
|
|
121
164
|
async getProject(options) {
|
|
122
|
-
const { data } = await this.client.GET("/api/atlas/v2/groups/{groupId}", options);
|
|
165
|
+
const { data, error, response } = await this.client.GET("/api/atlas/v2/groups/{groupId}", options);
|
|
166
|
+
if (error) {
|
|
167
|
+
throw ApiClientError.fromError(response, error);
|
|
168
|
+
}
|
|
123
169
|
return data;
|
|
124
170
|
}
|
|
125
171
|
async listProjectIpAccessLists(options) {
|
|
126
|
-
const { data } = await this.client.GET("/api/atlas/v2/groups/{groupId}/accessList", options);
|
|
172
|
+
const { data, error, response } = await this.client.GET("/api/atlas/v2/groups/{groupId}/accessList", options);
|
|
173
|
+
if (error) {
|
|
174
|
+
throw ApiClientError.fromError(response, error);
|
|
175
|
+
}
|
|
127
176
|
return data;
|
|
128
177
|
}
|
|
129
178
|
async createProjectIpAccessList(options) {
|
|
130
|
-
const { data } = await this.client.POST("/api/atlas/v2/groups/{groupId}/accessList", options);
|
|
179
|
+
const { data, error, response } = await this.client.POST("/api/atlas/v2/groups/{groupId}/accessList", options);
|
|
180
|
+
if (error) {
|
|
181
|
+
throw ApiClientError.fromError(response, error);
|
|
182
|
+
}
|
|
131
183
|
return data;
|
|
132
184
|
}
|
|
133
185
|
async deleteProjectIpAccessList(options) {
|
|
134
|
-
await this.client.DELETE("/api/atlas/v2/groups/{groupId}/accessList/{entryValue}", options);
|
|
186
|
+
const { error, response } = await this.client.DELETE("/api/atlas/v2/groups/{groupId}/accessList/{entryValue}", options);
|
|
187
|
+
if (error) {
|
|
188
|
+
throw ApiClientError.fromError(response, error);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
async listAlerts(options) {
|
|
192
|
+
const { data, error, response } = await this.client.GET("/api/atlas/v2/groups/{groupId}/alerts", options);
|
|
193
|
+
if (error) {
|
|
194
|
+
throw ApiClientError.fromError(response, error);
|
|
195
|
+
}
|
|
196
|
+
return data;
|
|
135
197
|
}
|
|
136
198
|
async listClusters(options) {
|
|
137
|
-
const { data } = await this.client.GET("/api/atlas/v2/groups/{groupId}/clusters", options);
|
|
199
|
+
const { data, error, response } = await this.client.GET("/api/atlas/v2/groups/{groupId}/clusters", options);
|
|
200
|
+
if (error) {
|
|
201
|
+
throw ApiClientError.fromError(response, error);
|
|
202
|
+
}
|
|
138
203
|
return data;
|
|
139
204
|
}
|
|
140
205
|
async createCluster(options) {
|
|
141
|
-
const { data } = await this.client.POST("/api/atlas/v2/groups/{groupId}/clusters", options);
|
|
206
|
+
const { data, error, response } = await this.client.POST("/api/atlas/v2/groups/{groupId}/clusters", options);
|
|
207
|
+
if (error) {
|
|
208
|
+
throw ApiClientError.fromError(response, error);
|
|
209
|
+
}
|
|
142
210
|
return data;
|
|
143
211
|
}
|
|
144
212
|
async deleteCluster(options) {
|
|
145
|
-
await this.client.DELETE("/api/atlas/v2/groups/{groupId}/clusters/{clusterName}", options);
|
|
213
|
+
const { error, response } = await this.client.DELETE("/api/atlas/v2/groups/{groupId}/clusters/{clusterName}", options);
|
|
214
|
+
if (error) {
|
|
215
|
+
throw ApiClientError.fromError(response, error);
|
|
216
|
+
}
|
|
146
217
|
}
|
|
147
218
|
async getCluster(options) {
|
|
148
|
-
const { data } = await this.client.GET("/api/atlas/v2/groups/{groupId}/clusters/{clusterName}", options);
|
|
219
|
+
const { data, error, response } = await this.client.GET("/api/atlas/v2/groups/{groupId}/clusters/{clusterName}", options);
|
|
220
|
+
if (error) {
|
|
221
|
+
throw ApiClientError.fromError(response, error);
|
|
222
|
+
}
|
|
149
223
|
return data;
|
|
150
224
|
}
|
|
151
225
|
async listDatabaseUsers(options) {
|
|
152
|
-
const { data } = await this.client.GET("/api/atlas/v2/groups/{groupId}/databaseUsers", options);
|
|
226
|
+
const { data, error, response } = await this.client.GET("/api/atlas/v2/groups/{groupId}/databaseUsers", options);
|
|
227
|
+
if (error) {
|
|
228
|
+
throw ApiClientError.fromError(response, error);
|
|
229
|
+
}
|
|
153
230
|
return data;
|
|
154
231
|
}
|
|
155
232
|
async createDatabaseUser(options) {
|
|
156
|
-
const { data } = await this.client.POST("/api/atlas/v2/groups/{groupId}/databaseUsers", options);
|
|
233
|
+
const { data, error, response } = await this.client.POST("/api/atlas/v2/groups/{groupId}/databaseUsers", options);
|
|
234
|
+
if (error) {
|
|
235
|
+
throw ApiClientError.fromError(response, error);
|
|
236
|
+
}
|
|
157
237
|
return data;
|
|
158
238
|
}
|
|
159
239
|
async deleteDatabaseUser(options) {
|
|
160
|
-
await this.client.DELETE("/api/atlas/v2/groups/{groupId}/databaseUsers/{databaseName}/{username}", options);
|
|
240
|
+
const { error, response } = await this.client.DELETE("/api/atlas/v2/groups/{groupId}/databaseUsers/{databaseName}/{username}", options);
|
|
241
|
+
if (error) {
|
|
242
|
+
throw ApiClientError.fromError(response, error);
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
async listFlexClusters(options) {
|
|
246
|
+
const { data, error, response } = await this.client.GET("/api/atlas/v2/groups/{groupId}/flexClusters", options);
|
|
247
|
+
if (error) {
|
|
248
|
+
throw ApiClientError.fromError(response, error);
|
|
249
|
+
}
|
|
250
|
+
return data;
|
|
251
|
+
}
|
|
252
|
+
async createFlexCluster(options) {
|
|
253
|
+
const { data, error, response } = await this.client.POST("/api/atlas/v2/groups/{groupId}/flexClusters", options);
|
|
254
|
+
if (error) {
|
|
255
|
+
throw ApiClientError.fromError(response, error);
|
|
256
|
+
}
|
|
257
|
+
return data;
|
|
258
|
+
}
|
|
259
|
+
async deleteFlexCluster(options) {
|
|
260
|
+
const { error, response } = await this.client.DELETE("/api/atlas/v2/groups/{groupId}/flexClusters/{name}", options);
|
|
261
|
+
if (error) {
|
|
262
|
+
throw ApiClientError.fromError(response, error);
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
async getFlexCluster(options) {
|
|
266
|
+
const { data, error, response } = await this.client.GET("/api/atlas/v2/groups/{groupId}/flexClusters/{name}", options);
|
|
267
|
+
if (error) {
|
|
268
|
+
throw ApiClientError.fromError(response, error);
|
|
269
|
+
}
|
|
270
|
+
return data;
|
|
161
271
|
}
|
|
162
272
|
async listOrganizations(options) {
|
|
163
|
-
const { data } = await this.client.GET("/api/atlas/v2/orgs", options);
|
|
273
|
+
const { data, error, response } = await this.client.GET("/api/atlas/v2/orgs", options);
|
|
274
|
+
if (error) {
|
|
275
|
+
throw ApiClientError.fromError(response, error);
|
|
276
|
+
}
|
|
164
277
|
return data;
|
|
165
278
|
}
|
|
166
279
|
async listOrganizationProjects(options) {
|
|
167
|
-
const { data } = await this.client.GET("/api/atlas/v2/orgs/{orgId}/groups", options);
|
|
280
|
+
const { data, error, response } = await this.client.GET("/api/atlas/v2/orgs/{orgId}/groups", options);
|
|
281
|
+
if (error) {
|
|
282
|
+
throw ApiClientError.fromError(response, error);
|
|
283
|
+
}
|
|
168
284
|
return data;
|
|
169
285
|
}
|
|
170
286
|
}
|