mongodb-mcp-server 0.1.0 → 0.1.1
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/.github/CODEOWNERS +0 -2
- package/.github/ISSUE_TEMPLATE/bug_report.yml +8 -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/.vscode/extensions.json +9 -0
- package/.vscode/settings.json +11 -0
- package/README.md +39 -22
- package/dist/common/atlas/apiClient.js +141 -34
- 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 +6 -3
- package/dist/index.js.map +1 -1
- package/dist/logger.js +2 -0
- package/dist/logger.js.map +1 -1
- package/dist/server.js +15 -11
- 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 +46 -4
- 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/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/listClusters.js +9 -18
- package/dist/tools/atlas/read/listClusters.js.map +1 -1
- package/dist/tools/mongodb/tools.js +2 -4
- package/dist/tools/mongodb/tools.js.map +1 -1
- package/eslint.config.js +2 -1
- package/{jest.config.ts → jest.config.cjs} +1 -1
- package/package.json +4 -2
- package/scripts/apply.ts +4 -1
- package/scripts/filter.ts +4 -0
- package/src/common/atlas/apiClient.ts +179 -37
- package/src/common/atlas/apiClientError.ts +58 -7
- package/src/common/atlas/cluster.ts +95 -0
- package/src/common/atlas/generatePassword.ts +10 -0
- package/src/common/atlas/openapi.d.ts +438 -15
- 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 +7 -3
- package/src/logger.ts +2 -0
- package/src/server.ts +22 -14
- 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 +72 -6
- package/src/telemetry/types.ts +0 -1
- package/src/tools/atlas/atlasTool.ts +47 -1
- package/src/tools/atlas/create/createDBUser.ts +22 -2
- package/src/tools/atlas/metadata/connectCluster.ts +5 -27
- package/src/tools/atlas/read/inspectCluster.ts +4 -40
- package/src/tools/atlas/read/listClusters.ts +19 -36
- package/src/tools/mongodb/tools.ts +2 -4
- package/src/types/mongodb-connection-string-url.d.ts +69 -0
- package/tests/integration/helpers.ts +18 -2
- package/tests/integration/telemetry.test.ts +28 -0
- package/tests/integration/tools/atlas/dbUsers.test.ts +57 -32
- package/tests/integration/tools/mongodb/metadata/connect.test.ts +2 -6
- package/tests/integration/tools/mongodb/mongodbHelpers.ts +15 -24
- package/tests/integration/tools/mongodb/read/find.test.ts +28 -0
- 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 +165 -71
- package/tsconfig.build.json +1 -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/.github/CODEOWNERS
CHANGED
|
@@ -7,6 +7,14 @@ body:
|
|
|
7
7
|
- type: markdown
|
|
8
8
|
attributes:
|
|
9
9
|
value: "Please fill out the following details to help us address the issue."
|
|
10
|
+
- type: textarea
|
|
11
|
+
id: version
|
|
12
|
+
attributes:
|
|
13
|
+
label: "Version"
|
|
14
|
+
description: "Please provide the version of the MCP Server where the bug occurred. (e.g., 0.1.0, main branch sha, etc.)"
|
|
15
|
+
placeholder: "e.g., 0.1.0"
|
|
16
|
+
validations:
|
|
17
|
+
required: true
|
|
10
18
|
- type: checkboxes
|
|
11
19
|
id: app
|
|
12
20
|
attributes:
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
---
|
|
2
|
-
name:
|
|
2
|
+
name: Checks
|
|
3
3
|
on:
|
|
4
4
|
push:
|
|
5
5
|
branches:
|
|
6
6
|
- main
|
|
7
7
|
pull_request:
|
|
8
|
+
pull_request_target:
|
|
9
|
+
branches:
|
|
10
|
+
- main
|
|
8
11
|
|
|
9
12
|
permissions: {}
|
|
10
13
|
|
|
@@ -35,3 +38,21 @@ jobs:
|
|
|
35
38
|
- name: Install dependencies
|
|
36
39
|
run: npm ci
|
|
37
40
|
- run: npm run generate
|
|
41
|
+
|
|
42
|
+
check-dep:
|
|
43
|
+
name: Check dependencies
|
|
44
|
+
runs-on: ubuntu-latest
|
|
45
|
+
steps:
|
|
46
|
+
- uses: GitHubSecurityLab/actions-permissions/monitor@v1
|
|
47
|
+
- uses: actions/checkout@v4
|
|
48
|
+
- uses: actions/setup-node@v4
|
|
49
|
+
with:
|
|
50
|
+
node-version-file: package.json
|
|
51
|
+
cache: "npm"
|
|
52
|
+
- name: Install dependencies, build and remove dev dependencies
|
|
53
|
+
run: |
|
|
54
|
+
npm ci
|
|
55
|
+
rm -rf node_modules
|
|
56
|
+
npm pkg set scripts.prepare="exit 0"
|
|
57
|
+
npm install --omit=dev
|
|
58
|
+
- run: npx -y @modelcontextprotocol/inspector --cli --method tools/list -- node dist/index.js --connectionString "mongodb://localhost"
|
|
@@ -62,26 +62,6 @@ jobs:
|
|
|
62
62
|
name: atlas-test-results
|
|
63
63
|
path: coverage/lcov.info
|
|
64
64
|
|
|
65
|
-
dep-check:
|
|
66
|
-
name: Check dependencies
|
|
67
|
-
if: github.event.pull_request.user.login != 'dependabot[bot]' && github.event.pull_request.head.repo.full_name == github.repository
|
|
68
|
-
runs-on: ubuntu-latest
|
|
69
|
-
steps:
|
|
70
|
-
- uses: GitHubSecurityLab/actions-permissions/monitor@v1
|
|
71
|
-
- uses: actions/checkout@v4
|
|
72
|
-
- uses: actions/setup-node@v4
|
|
73
|
-
with:
|
|
74
|
-
node-version-file: package.json
|
|
75
|
-
cache: "npm"
|
|
76
|
-
- name: Install dependencies & build
|
|
77
|
-
run: npm ci
|
|
78
|
-
- name: Remove dev dependencies
|
|
79
|
-
run: |
|
|
80
|
-
rm -rf node_modules
|
|
81
|
-
npm pkg set scripts.prepare="exit 0"
|
|
82
|
-
npm install --omit=dev
|
|
83
|
-
- run: npx -y @modelcontextprotocol/inspector --cli --method tools/list -- node dist/index.js --connectionString "mongodb://localhost"
|
|
84
|
-
|
|
85
65
|
coverage:
|
|
86
66
|
name: Report Coverage
|
|
87
67
|
if: always() && github.event.pull_request.user.login != 'dependabot[bot]' && github.event.pull_request.head.repo.full_name == github.repository
|
|
@@ -112,5 +92,3 @@ jobs:
|
|
|
112
92
|
uses: coverallsapp/github-action@v2.3.6
|
|
113
93
|
with:
|
|
114
94
|
file: coverage/lcov.info
|
|
115
|
-
git-branch: ${{ github.head_ref || github.ref_name }}
|
|
116
|
-
git-commit: ${{ github.event.pull_request.head.sha || github.sha }}
|
|
@@ -11,9 +11,14 @@ jobs:
|
|
|
11
11
|
run-tests:
|
|
12
12
|
name: Run MongoDB tests
|
|
13
13
|
if: github.event.pull_request.user.login == 'dependabot[bot]' || github.event.pull_request.head.repo.full_name != github.repository
|
|
14
|
-
|
|
14
|
+
strategy:
|
|
15
|
+
matrix:
|
|
16
|
+
os: [ubuntu-latest, macos-latest, windows-latest]
|
|
17
|
+
fail-fast: false
|
|
18
|
+
runs-on: ${{ matrix.os }}
|
|
15
19
|
steps:
|
|
16
20
|
- uses: GitHubSecurityLab/actions-permissions/monitor@v1
|
|
21
|
+
if: matrix.os != 'windows-latest'
|
|
17
22
|
- uses: actions/checkout@v4
|
|
18
23
|
- uses: actions/setup-node@v4
|
|
19
24
|
with:
|
|
@@ -24,71 +29,12 @@ jobs:
|
|
|
24
29
|
- name: Run tests
|
|
25
30
|
run: npm test
|
|
26
31
|
- name: Upload test results
|
|
27
|
-
if: always()
|
|
32
|
+
if: always() && matrix.os == 'ubuntu-latest'
|
|
28
33
|
uses: actions/upload-artifact@v4
|
|
29
34
|
with:
|
|
30
35
|
name: test-results
|
|
31
36
|
path: coverage/lcov.info
|
|
32
37
|
|
|
33
|
-
run-atlas-tests:
|
|
34
|
-
name: Run Atlas tests
|
|
35
|
-
if: github.event.pull_request.user.login == 'dependabot[bot]' || github.event.pull_request.head.repo.full_name != github.repository
|
|
36
|
-
runs-on: ubuntu-latest
|
|
37
|
-
steps:
|
|
38
|
-
- uses: GitHubSecurityLab/actions-permissions/monitor@v1
|
|
39
|
-
- uses: actions/checkout@v4
|
|
40
|
-
- uses: actions/setup-node@v4
|
|
41
|
-
with:
|
|
42
|
-
node-version-file: package.json
|
|
43
|
-
cache: "npm"
|
|
44
|
-
- name: Install dependencies
|
|
45
|
-
run: npm ci
|
|
46
|
-
- name: Run tests
|
|
47
|
-
env:
|
|
48
|
-
MDB_MCP_API_CLIENT_ID: ${{ secrets.TEST_ATLAS_CLIENT_ID }}
|
|
49
|
-
MDB_MCP_API_CLIENT_SECRET: ${{ secrets.TEST_ATLAS_CLIENT_SECRET }}
|
|
50
|
-
MDB_MCP_API_BASE_URL: ${{ vars.TEST_ATLAS_BASE_URL }}
|
|
51
|
-
run: npm test -- --testPathIgnorePatterns "tests/integration/tools/mongodb" --testPathIgnorePatterns "tests/integration/[^/]+\.ts"
|
|
52
|
-
- name: Upload test results
|
|
53
|
-
uses: actions/upload-artifact@v4
|
|
54
|
-
if: always()
|
|
55
|
-
with:
|
|
56
|
-
name: atlas-test-results
|
|
57
|
-
path: coverage/lcov.info
|
|
58
|
-
|
|
59
|
-
coverage:
|
|
60
|
-
name: Report Coverage
|
|
61
|
-
if: always() && github.event.pull_request.user.login == 'dependabot[bot]' || github.event.pull_request.head.repo.full_name != github.repository
|
|
62
|
-
runs-on: ubuntu-latest
|
|
63
|
-
needs: [run-tests, run-atlas-tests]
|
|
64
|
-
steps:
|
|
65
|
-
- uses: actions/checkout@v4
|
|
66
|
-
- uses: actions/setup-node@v4
|
|
67
|
-
with:
|
|
68
|
-
node-version-file: package.json
|
|
69
|
-
cache: "npm"
|
|
70
|
-
- name: Install dependencies
|
|
71
|
-
run: npm ci
|
|
72
|
-
- name: Download test results
|
|
73
|
-
uses: actions/download-artifact@v4
|
|
74
|
-
with:
|
|
75
|
-
name: test-results
|
|
76
|
-
path: coverage/mongodb
|
|
77
|
-
- name: Download atlas test results
|
|
78
|
-
uses: actions/download-artifact@v4
|
|
79
|
-
with:
|
|
80
|
-
name: atlas-test-results
|
|
81
|
-
path: coverage/atlas
|
|
82
|
-
- name: Merge coverage reports
|
|
83
|
-
run: |
|
|
84
|
-
npx -y lcov-result-merger@5.0.1 "coverage/*/lcov.info" "coverage/lcov.info"
|
|
85
|
-
- name: Coveralls GitHub Action
|
|
86
|
-
uses: coverallsapp/github-action@v2.3.6
|
|
87
|
-
with:
|
|
88
|
-
file: coverage/lcov.info
|
|
89
|
-
git-branch: ${{ github.head_ref || github.ref_name }}
|
|
90
|
-
git-commit: ${{ github.event.pull_request.head.sha || github.sha }}
|
|
91
|
-
|
|
92
38
|
merge-dependabot-pr:
|
|
93
39
|
name: Merge Dependabot PR
|
|
94
40
|
if: github.event.pull_request.user.login == 'dependabot[bot]'
|
|
@@ -96,8 +42,6 @@ jobs:
|
|
|
96
42
|
permissions:
|
|
97
43
|
pull-requests: write
|
|
98
44
|
contents: write
|
|
99
|
-
needs:
|
|
100
|
-
- coverage
|
|
101
45
|
steps:
|
|
102
46
|
- name: Enable auto-merge for Dependabot PRs
|
|
103
47
|
run: gh pr merge --auto --squash "$PR_URL"
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
{
|
|
2
|
+
// See https://go.microsoft.com/fwlink/?LinkId=827846 to learn about workspace recommendations.
|
|
3
|
+
// Extension identifier format: ${publisher}.${name}. Example: vscode.csharp
|
|
4
|
+
|
|
5
|
+
// List of extensions which should be recommended for users of this workspace.
|
|
6
|
+
"recommendations": ["firsttris.vscode-jest-runner", "orta.vscode-jest"],
|
|
7
|
+
// List of extensions recommended by VS Code that should not be recommended for users of this workspace.
|
|
8
|
+
"unwantedRecommendations": []
|
|
9
|
+
}
|
package/README.md
CHANGED
|
@@ -29,7 +29,7 @@ node -v
|
|
|
29
29
|
```
|
|
30
30
|
|
|
31
31
|
- A MongoDB connection string or Atlas API credentials, **_the Server will not start unless configured_**.
|
|
32
|
-
- **
|
|
32
|
+
- **_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
33
|
- If you have a MongoDB connection string, you can use it directly to connect to your MongoDB instance.
|
|
34
34
|
|
|
35
35
|
## Setup
|
|
@@ -38,8 +38,10 @@ node -v
|
|
|
38
38
|
|
|
39
39
|
Most MCP clients require a configuration file to be created or modified to add the MCP server.
|
|
40
40
|
|
|
41
|
+
Note: The configuration file syntax can be different across clients. Please refer to the following links for the latest expected syntax:
|
|
42
|
+
|
|
41
43
|
- **Windsurf**:https://docs.windsurf.com/windsurf/mcp
|
|
42
|
-
- **VSCode**: https://
|
|
44
|
+
- **VSCode**: https://code.visualstudio.com/docs/copilot/chat/mcp-servers
|
|
43
45
|
- **Claude Desktop**: https://modelcontextprotocol.io/quickstart/user
|
|
44
46
|
- **Cursor**: https://docs.cursor.com/context/model-context-protocol
|
|
45
47
|
|
|
@@ -49,7 +51,7 @@ You can pass your connection string via args, make sure to use a valid username
|
|
|
49
51
|
|
|
50
52
|
```json
|
|
51
53
|
{
|
|
52
|
-
"
|
|
54
|
+
"mcpServers": {
|
|
53
55
|
"MongoDB": {
|
|
54
56
|
"command": "npx",
|
|
55
57
|
"args": [
|
|
@@ -65,29 +67,44 @@ You can pass your connection string via args, make sure to use a valid username
|
|
|
65
67
|
|
|
66
68
|
#### Option 2: Atlas API credentials args
|
|
67
69
|
|
|
68
|
-
Use your Atlas API Service
|
|
70
|
+
Use your Atlas API Service Accounts credentials. Must follow all the steps in [Atlas API Access](#atlas-api-access) section.
|
|
69
71
|
|
|
70
72
|
```json
|
|
71
73
|
{
|
|
72
|
-
"
|
|
74
|
+
"mcpServers": {
|
|
73
75
|
"MongoDB": {
|
|
74
76
|
"command": "npx",
|
|
75
77
|
"args": [
|
|
76
78
|
"-y",
|
|
77
79
|
"mongodb-mcp-server",
|
|
78
80
|
"--apiClientId",
|
|
79
|
-
"your-atlas-client-id",
|
|
81
|
+
"your-atlas-service-accounts-client-id",
|
|
80
82
|
"--apiClientSecret",
|
|
81
|
-
"your-atlas-client-secret"
|
|
83
|
+
"your-atlas-service-accounts-client-secret"
|
|
82
84
|
]
|
|
83
85
|
}
|
|
84
86
|
}
|
|
85
87
|
}
|
|
86
88
|
```
|
|
87
89
|
|
|
88
|
-
|
|
90
|
+
### Option 3: Standalone Service using command arguments
|
|
91
|
+
|
|
92
|
+
Start Server using npx command:
|
|
93
|
+
|
|
94
|
+
```shell
|
|
95
|
+
npx -y mongodb-mcp-server --apiClientId="your-atlas-service-accounts-client-id" --apiClientSecret="your-atlas-service-accounts-client-secret"
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
- For a complete list of arguments see [Configuration Options](#configuration-options)
|
|
99
|
+
- To configure your Atlas Service Accounts credentials please refer to [Atlas API Access](#atlas-api-access)
|
|
100
|
+
|
|
101
|
+
#### Option 4: Standalone Service using environment variables
|
|
102
|
+
|
|
103
|
+
```shell
|
|
104
|
+
npx -y mongodb-mcp-server
|
|
105
|
+
```
|
|
89
106
|
|
|
90
|
-
|
|
107
|
+
You can use environment variables in the config file or set them and run the server via npx.
|
|
91
108
|
|
|
92
109
|
- Connection String via environment variables in the MCP file [example](#connection-string-with-environment-variables)
|
|
93
110
|
- Atlas API credentials via environment variables in the MCP file [example](#atlas-api-credentials-with-environment-variables)
|
|
@@ -227,7 +244,7 @@ To learn more about Service Accounts, check the [MongoDB Atlas documentation](ht
|
|
|
227
244
|
- After creation, you'll be shown the Client ID and Client Secret
|
|
228
245
|
- **Important:** Copy and save the Client Secret immediately as it won't be displayed again
|
|
229
246
|
|
|
230
|
-
3. **Add Access List Entry
|
|
247
|
+
3. **Add Access List Entry:**
|
|
231
248
|
|
|
232
249
|
- Add your IP address to the API access list
|
|
233
250
|
|
|
@@ -241,9 +258,9 @@ To learn more about Service Accounts, check the [MongoDB Atlas documentation](ht
|
|
|
241
258
|
Set environment variables with the prefix `MDB_MCP_` followed by the option name in uppercase with underscores:
|
|
242
259
|
|
|
243
260
|
```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"
|
|
261
|
+
# Set Atlas API credentials (via Service Accounts)
|
|
262
|
+
export MDB_MCP_API_CLIENT_ID="your-atlas-service-accounts-client-id"
|
|
263
|
+
export MDB_MCP_API_CLIENT_SECRET="your-atlas-service-accounts-client-secret"
|
|
247
264
|
|
|
248
265
|
# Set a custom MongoDB connection string
|
|
249
266
|
export MDB_MCP_CONNECTION_STRING="mongodb+srv://username:password@cluster.mongodb.net/myDatabase"
|
|
@@ -258,7 +275,7 @@ export MDB_MCP_LOG_PATH="/path/to/logs"
|
|
|
258
275
|
|
|
259
276
|
```json
|
|
260
277
|
{
|
|
261
|
-
"
|
|
278
|
+
"mcpServers": {
|
|
262
279
|
"MongoDB": {
|
|
263
280
|
"command": "npx",
|
|
264
281
|
"args": ["-y", "mongodb-mcp-server"],
|
|
@@ -274,13 +291,13 @@ export MDB_MCP_LOG_PATH="/path/to/logs"
|
|
|
274
291
|
|
|
275
292
|
```json
|
|
276
293
|
{
|
|
277
|
-
"
|
|
294
|
+
"mcpServers": {
|
|
278
295
|
"MongoDB": {
|
|
279
296
|
"command": "npx",
|
|
280
297
|
"args": ["-y", "mongodb-mcp-server"],
|
|
281
298
|
"env": {
|
|
282
|
-
"MDB_MCP_API_CLIENT_ID": "your-atlas-client-id",
|
|
283
|
-
"MDB_MCP_API_CLIENT_SECRET": "your-atlas-client-secret"
|
|
299
|
+
"MDB_MCP_API_CLIENT_ID": "your-atlas-service-accounts-client-id",
|
|
300
|
+
"MDB_MCP_API_CLIENT_SECRET": "your-atlas-service-accounts-client-secret"
|
|
284
301
|
}
|
|
285
302
|
}
|
|
286
303
|
}
|
|
@@ -292,7 +309,7 @@ export MDB_MCP_LOG_PATH="/path/to/logs"
|
|
|
292
309
|
Pass configuration options as command-line arguments when starting the server:
|
|
293
310
|
|
|
294
311
|
```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
|
|
312
|
+
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
313
|
```
|
|
297
314
|
|
|
298
315
|
#### MCP configuration file examples
|
|
@@ -301,7 +318,7 @@ npx -y mongodb-mcp-server --apiClientId="your-atlas-client-id" --apiClientSecret
|
|
|
301
318
|
|
|
302
319
|
```json
|
|
303
320
|
{
|
|
304
|
-
"
|
|
321
|
+
"mcpServers": {
|
|
305
322
|
"MongoDB": {
|
|
306
323
|
"command": "npx",
|
|
307
324
|
"args": [
|
|
@@ -319,16 +336,16 @@ npx -y mongodb-mcp-server --apiClientId="your-atlas-client-id" --apiClientSecret
|
|
|
319
336
|
|
|
320
337
|
```json
|
|
321
338
|
{
|
|
322
|
-
"
|
|
339
|
+
"mcpServers": {
|
|
323
340
|
"MongoDB": {
|
|
324
341
|
"command": "npx",
|
|
325
342
|
"args": [
|
|
326
343
|
"-y",
|
|
327
344
|
"mongodb-mcp-server",
|
|
328
345
|
"--apiClientId",
|
|
329
|
-
"your-atlas-client-id",
|
|
346
|
+
"your-atlas-service-accounts-client-id",
|
|
330
347
|
"--apiClientSecret",
|
|
331
|
-
"your-atlas-client-secret"
|
|
348
|
+
"your-atlas-service-accounts-client-secret"
|
|
332
349
|
]
|
|
333
350
|
}
|
|
334
351
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
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) {
|
|
@@ -26,13 +26,6 @@ export class ApiClient {
|
|
|
26
26
|
}
|
|
27
27
|
},
|
|
28
28
|
};
|
|
29
|
-
this.errorMiddleware = {
|
|
30
|
-
async onResponse({ response }) {
|
|
31
|
-
if (!response.ok) {
|
|
32
|
-
throw await ApiClientError.fromResponse(response);
|
|
33
|
-
}
|
|
34
|
-
},
|
|
35
|
-
};
|
|
36
29
|
this.options = {
|
|
37
30
|
...options,
|
|
38
31
|
userAgent: options.userAgent ||
|
|
@@ -58,11 +51,13 @@ export class ApiClient {
|
|
|
58
51
|
});
|
|
59
52
|
this.client.use(this.authMiddleware);
|
|
60
53
|
}
|
|
61
|
-
this.client.use(this.errorMiddleware);
|
|
62
54
|
}
|
|
63
55
|
hasCredentials() {
|
|
64
56
|
return !!(this.oauth2Client && this.accessToken);
|
|
65
57
|
}
|
|
58
|
+
async validateAccessToken() {
|
|
59
|
+
await this.getAccessToken();
|
|
60
|
+
}
|
|
66
61
|
async getIpInfo() {
|
|
67
62
|
const accessToken = await this.getAccessToken();
|
|
68
63
|
const endpoint = "api/private/ipinfo";
|
|
@@ -81,19 +76,53 @@ export class ApiClient {
|
|
|
81
76
|
return (await response.json());
|
|
82
77
|
}
|
|
83
78
|
async sendEvents(events) {
|
|
84
|
-
|
|
79
|
+
if (!this.options.credentials) {
|
|
80
|
+
await this.sendUnauthEvents(events);
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
try {
|
|
84
|
+
await this.sendAuthEvents(events);
|
|
85
|
+
}
|
|
86
|
+
catch (error) {
|
|
87
|
+
if (error instanceof ApiClientError) {
|
|
88
|
+
if (error.response.status !== 401) {
|
|
89
|
+
throw error;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
// send unauth events if any of the following are true:
|
|
93
|
+
// 1: the token is not valid (not ApiClientError)
|
|
94
|
+
// 2: if the api responded with 401 (ApiClientError with status 401)
|
|
95
|
+
await this.sendUnauthEvents(events);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
async sendAuthEvents(events) {
|
|
99
|
+
const accessToken = await this.getAccessToken();
|
|
100
|
+
if (!accessToken) {
|
|
101
|
+
throw new Error("No access token available");
|
|
102
|
+
}
|
|
103
|
+
const authUrl = new URL("api/private/v1.0/telemetry/events", this.options.baseUrl);
|
|
104
|
+
const response = await fetch(authUrl, {
|
|
105
|
+
method: "POST",
|
|
106
|
+
headers: {
|
|
107
|
+
Accept: "application/json",
|
|
108
|
+
"Content-Type": "application/json",
|
|
109
|
+
"User-Agent": this.options.userAgent,
|
|
110
|
+
Authorization: `Bearer ${accessToken}`,
|
|
111
|
+
},
|
|
112
|
+
body: JSON.stringify(events),
|
|
113
|
+
});
|
|
114
|
+
if (!response.ok) {
|
|
115
|
+
throw await ApiClientError.fromResponse(response);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
async sendUnauthEvents(events) {
|
|
85
119
|
const headers = {
|
|
86
120
|
Accept: "application/json",
|
|
87
121
|
"Content-Type": "application/json",
|
|
88
122
|
"User-Agent": this.options.userAgent,
|
|
89
123
|
};
|
|
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, {
|
|
124
|
+
const unauthUrl = new URL("api/private/unauth/telemetry/events", this.options.baseUrl);
|
|
125
|
+
const response = await fetch(unauthUrl, {
|
|
97
126
|
method: "POST",
|
|
98
127
|
headers,
|
|
99
128
|
body: JSON.stringify(events),
|
|
@@ -104,67 +133,145 @@ export class ApiClient {
|
|
|
104
133
|
}
|
|
105
134
|
// DO NOT EDIT. This is auto-generated code.
|
|
106
135
|
async listClustersForAllProjects(options) {
|
|
107
|
-
const { data } = await this.client.GET("/api/atlas/v2/clusters", options);
|
|
136
|
+
const { data, error, response } = await this.client.GET("/api/atlas/v2/clusters", options);
|
|
137
|
+
if (error) {
|
|
138
|
+
throw ApiClientError.fromError(response, error);
|
|
139
|
+
}
|
|
108
140
|
return data;
|
|
109
141
|
}
|
|
110
142
|
async listProjects(options) {
|
|
111
|
-
const { data } = await this.client.GET("/api/atlas/v2/groups", options);
|
|
143
|
+
const { data, error, response } = await this.client.GET("/api/atlas/v2/groups", options);
|
|
144
|
+
if (error) {
|
|
145
|
+
throw ApiClientError.fromError(response, error);
|
|
146
|
+
}
|
|
112
147
|
return data;
|
|
113
148
|
}
|
|
114
149
|
async createProject(options) {
|
|
115
|
-
const { data } = await this.client.POST("/api/atlas/v2/groups", options);
|
|
150
|
+
const { data, error, response } = await this.client.POST("/api/atlas/v2/groups", options);
|
|
151
|
+
if (error) {
|
|
152
|
+
throw ApiClientError.fromError(response, error);
|
|
153
|
+
}
|
|
116
154
|
return data;
|
|
117
155
|
}
|
|
118
156
|
async deleteProject(options) {
|
|
119
|
-
await this.client.DELETE("/api/atlas/v2/groups/{groupId}", options);
|
|
157
|
+
const { error, response } = await this.client.DELETE("/api/atlas/v2/groups/{groupId}", options);
|
|
158
|
+
if (error) {
|
|
159
|
+
throw ApiClientError.fromError(response, error);
|
|
160
|
+
}
|
|
120
161
|
}
|
|
121
162
|
async getProject(options) {
|
|
122
|
-
const { data } = await this.client.GET("/api/atlas/v2/groups/{groupId}", options);
|
|
163
|
+
const { data, error, response } = await this.client.GET("/api/atlas/v2/groups/{groupId}", options);
|
|
164
|
+
if (error) {
|
|
165
|
+
throw ApiClientError.fromError(response, error);
|
|
166
|
+
}
|
|
123
167
|
return data;
|
|
124
168
|
}
|
|
125
169
|
async listProjectIpAccessLists(options) {
|
|
126
|
-
const { data } = await this.client.GET("/api/atlas/v2/groups/{groupId}/accessList", options);
|
|
170
|
+
const { data, error, response } = await this.client.GET("/api/atlas/v2/groups/{groupId}/accessList", options);
|
|
171
|
+
if (error) {
|
|
172
|
+
throw ApiClientError.fromError(response, error);
|
|
173
|
+
}
|
|
127
174
|
return data;
|
|
128
175
|
}
|
|
129
176
|
async createProjectIpAccessList(options) {
|
|
130
|
-
const { data } = await this.client.POST("/api/atlas/v2/groups/{groupId}/accessList", options);
|
|
177
|
+
const { data, error, response } = await this.client.POST("/api/atlas/v2/groups/{groupId}/accessList", options);
|
|
178
|
+
if (error) {
|
|
179
|
+
throw ApiClientError.fromError(response, error);
|
|
180
|
+
}
|
|
131
181
|
return data;
|
|
132
182
|
}
|
|
133
183
|
async deleteProjectIpAccessList(options) {
|
|
134
|
-
await this.client.DELETE("/api/atlas/v2/groups/{groupId}/accessList/{entryValue}", options);
|
|
184
|
+
const { error, response } = await this.client.DELETE("/api/atlas/v2/groups/{groupId}/accessList/{entryValue}", options);
|
|
185
|
+
if (error) {
|
|
186
|
+
throw ApiClientError.fromError(response, error);
|
|
187
|
+
}
|
|
135
188
|
}
|
|
136
189
|
async listClusters(options) {
|
|
137
|
-
const { data } = await this.client.GET("/api/atlas/v2/groups/{groupId}/clusters", options);
|
|
190
|
+
const { data, error, response } = await this.client.GET("/api/atlas/v2/groups/{groupId}/clusters", options);
|
|
191
|
+
if (error) {
|
|
192
|
+
throw ApiClientError.fromError(response, error);
|
|
193
|
+
}
|
|
138
194
|
return data;
|
|
139
195
|
}
|
|
140
196
|
async createCluster(options) {
|
|
141
|
-
const { data } = await this.client.POST("/api/atlas/v2/groups/{groupId}/clusters", options);
|
|
197
|
+
const { data, error, response } = await this.client.POST("/api/atlas/v2/groups/{groupId}/clusters", options);
|
|
198
|
+
if (error) {
|
|
199
|
+
throw ApiClientError.fromError(response, error);
|
|
200
|
+
}
|
|
142
201
|
return data;
|
|
143
202
|
}
|
|
144
203
|
async deleteCluster(options) {
|
|
145
|
-
await this.client.DELETE("/api/atlas/v2/groups/{groupId}/clusters/{clusterName}", options);
|
|
204
|
+
const { error, response } = await this.client.DELETE("/api/atlas/v2/groups/{groupId}/clusters/{clusterName}", options);
|
|
205
|
+
if (error) {
|
|
206
|
+
throw ApiClientError.fromError(response, error);
|
|
207
|
+
}
|
|
146
208
|
}
|
|
147
209
|
async getCluster(options) {
|
|
148
|
-
const { data } = await this.client.GET("/api/atlas/v2/groups/{groupId}/clusters/{clusterName}", options);
|
|
210
|
+
const { data, error, response } = await this.client.GET("/api/atlas/v2/groups/{groupId}/clusters/{clusterName}", options);
|
|
211
|
+
if (error) {
|
|
212
|
+
throw ApiClientError.fromError(response, error);
|
|
213
|
+
}
|
|
149
214
|
return data;
|
|
150
215
|
}
|
|
151
216
|
async listDatabaseUsers(options) {
|
|
152
|
-
const { data } = await this.client.GET("/api/atlas/v2/groups/{groupId}/databaseUsers", options);
|
|
217
|
+
const { data, error, response } = await this.client.GET("/api/atlas/v2/groups/{groupId}/databaseUsers", options);
|
|
218
|
+
if (error) {
|
|
219
|
+
throw ApiClientError.fromError(response, error);
|
|
220
|
+
}
|
|
153
221
|
return data;
|
|
154
222
|
}
|
|
155
223
|
async createDatabaseUser(options) {
|
|
156
|
-
const { data } = await this.client.POST("/api/atlas/v2/groups/{groupId}/databaseUsers", options);
|
|
224
|
+
const { data, error, response } = await this.client.POST("/api/atlas/v2/groups/{groupId}/databaseUsers", options);
|
|
225
|
+
if (error) {
|
|
226
|
+
throw ApiClientError.fromError(response, error);
|
|
227
|
+
}
|
|
157
228
|
return data;
|
|
158
229
|
}
|
|
159
230
|
async deleteDatabaseUser(options) {
|
|
160
|
-
await this.client.DELETE("/api/atlas/v2/groups/{groupId}/databaseUsers/{databaseName}/{username}", options);
|
|
231
|
+
const { error, response } = await this.client.DELETE("/api/atlas/v2/groups/{groupId}/databaseUsers/{databaseName}/{username}", options);
|
|
232
|
+
if (error) {
|
|
233
|
+
throw ApiClientError.fromError(response, error);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
async listFlexClusters(options) {
|
|
237
|
+
const { data, error, response } = await this.client.GET("/api/atlas/v2/groups/{groupId}/flexClusters", options);
|
|
238
|
+
if (error) {
|
|
239
|
+
throw ApiClientError.fromError(response, error);
|
|
240
|
+
}
|
|
241
|
+
return data;
|
|
242
|
+
}
|
|
243
|
+
async createFlexCluster(options) {
|
|
244
|
+
const { data, error, response } = await this.client.POST("/api/atlas/v2/groups/{groupId}/flexClusters", options);
|
|
245
|
+
if (error) {
|
|
246
|
+
throw ApiClientError.fromError(response, error);
|
|
247
|
+
}
|
|
248
|
+
return data;
|
|
249
|
+
}
|
|
250
|
+
async deleteFlexCluster(options) {
|
|
251
|
+
const { error, response } = await this.client.DELETE("/api/atlas/v2/groups/{groupId}/flexClusters/{name}", options);
|
|
252
|
+
if (error) {
|
|
253
|
+
throw ApiClientError.fromError(response, error);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
async getFlexCluster(options) {
|
|
257
|
+
const { data, error, response } = await this.client.GET("/api/atlas/v2/groups/{groupId}/flexClusters/{name}", options);
|
|
258
|
+
if (error) {
|
|
259
|
+
throw ApiClientError.fromError(response, error);
|
|
260
|
+
}
|
|
261
|
+
return data;
|
|
161
262
|
}
|
|
162
263
|
async listOrganizations(options) {
|
|
163
|
-
const { data } = await this.client.GET("/api/atlas/v2/orgs", options);
|
|
264
|
+
const { data, error, response } = await this.client.GET("/api/atlas/v2/orgs", options);
|
|
265
|
+
if (error) {
|
|
266
|
+
throw ApiClientError.fromError(response, error);
|
|
267
|
+
}
|
|
164
268
|
return data;
|
|
165
269
|
}
|
|
166
270
|
async listOrganizationProjects(options) {
|
|
167
|
-
const { data } = await this.client.GET("/api/atlas/v2/orgs/{orgId}/groups", options);
|
|
271
|
+
const { data, error, response } = await this.client.GET("/api/atlas/v2/orgs/{orgId}/groups", options);
|
|
272
|
+
if (error) {
|
|
273
|
+
throw ApiClientError.fromError(response, error);
|
|
274
|
+
}
|
|
168
275
|
return data;
|
|
169
276
|
}
|
|
170
277
|
}
|