mongodb-mcp-server 0.0.4 → 0.0.6
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 +3 -0
- package/.github/dependabot.yml +10 -0
- package/.github/workflows/code_health.yaml +53 -22
- package/.github/workflows/code_health_fork.yaml +106 -0
- package/.github/workflows/codeql.yml +34 -0
- package/.github/workflows/lint.yml +37 -0
- package/.github/workflows/prepare_release.yaml +6 -4
- package/.github/workflows/publish.yaml +6 -3
- package/.prettierrc.json +1 -1
- package/README.md +18 -0
- package/dist/common/atlas/apiClient.js +28 -4
- package/dist/common/atlas/apiClient.js.map +1 -1
- package/dist/config.js +4 -7
- package/dist/config.js.map +1 -1
- package/dist/errors.js +1 -1
- package/dist/errors.js.map +1 -1
- package/dist/index.js +12 -7
- package/dist/index.js.map +1 -1
- package/dist/logger.js +72 -28
- package/dist/logger.js.map +1 -1
- package/dist/packageInfo.js +6 -0
- package/dist/packageInfo.js.map +1 -0
- package/dist/server.js +114 -10
- package/dist/server.js.map +1 -1
- package/dist/session.js +66 -16
- package/dist/session.js.map +1 -1
- package/dist/telemetry/constants.js +15 -0
- package/dist/telemetry/constants.js.map +1 -0
- package/dist/telemetry/eventCache.js +53 -0
- package/dist/telemetry/eventCache.js.map +1 -0
- package/dist/telemetry/telemetry.js +97 -0
- package/dist/telemetry/telemetry.js.map +1 -0
- package/dist/telemetry/types.js +2 -0
- package/dist/telemetry/types.js.map +1 -0
- package/dist/tools/atlas/atlasTool.js +8 -3
- package/dist/tools/atlas/atlasTool.js.map +1 -1
- package/dist/tools/atlas/{createAccessList.js → create/createAccessList.js} +1 -2
- package/dist/tools/atlas/create/createAccessList.js.map +1 -0
- package/dist/tools/atlas/{createDBUser.js → create/createDBUser.js} +1 -2
- package/dist/tools/atlas/create/createDBUser.js.map +1 -0
- package/dist/tools/atlas/{createFreeCluster.js → create/createFreeCluster.js} +5 -3
- package/dist/tools/atlas/create/createFreeCluster.js.map +1 -0
- package/dist/tools/atlas/{createProject.js → create/createProject.js} +1 -2
- package/dist/tools/atlas/create/createProject.js.map +1 -0
- package/dist/tools/atlas/metadata/connectCluster.js +97 -0
- package/dist/tools/atlas/metadata/connectCluster.js.map +1 -0
- package/dist/tools/atlas/{inspectAccessList.js → read/inspectAccessList.js} +1 -2
- package/dist/tools/atlas/read/inspectAccessList.js.map +1 -0
- package/dist/tools/atlas/{inspectCluster.js → read/inspectCluster.js} +1 -2
- package/dist/tools/atlas/read/inspectCluster.js.map +1 -0
- package/dist/tools/atlas/{listClusters.js → read/listClusters.js} +1 -2
- package/dist/tools/atlas/read/listClusters.js.map +1 -0
- package/dist/tools/atlas/{listDBUsers.js → read/listDBUsers.js} +1 -2
- package/dist/tools/atlas/read/listDBUsers.js.map +1 -0
- package/dist/tools/atlas/{listOrgs.js → read/listOrgs.js} +1 -2
- package/dist/tools/atlas/read/listOrgs.js.map +1 -0
- package/dist/tools/atlas/{listProjects.js → read/listProjects.js} +11 -5
- package/dist/tools/atlas/read/listProjects.js.map +1 -0
- package/dist/tools/atlas/tools.js +12 -10
- package/dist/tools/atlas/tools.js.map +1 -1
- package/dist/tools/mongodb/create/insertMany.js +1 -1
- package/dist/tools/mongodb/create/insertMany.js.map +1 -1
- package/dist/tools/mongodb/delete/deleteMany.js +1 -2
- package/dist/tools/mongodb/delete/deleteMany.js.map +1 -1
- package/dist/tools/mongodb/metadata/collectionSchema.js +15 -13
- package/dist/tools/mongodb/metadata/collectionSchema.js.map +1 -1
- package/dist/tools/mongodb/metadata/collectionStorageSize.js +32 -3
- package/dist/tools/mongodb/metadata/collectionStorageSize.js.map +1 -1
- package/dist/tools/mongodb/metadata/connect.js +59 -72
- package/dist/tools/mongodb/metadata/connect.js.map +1 -1
- package/dist/tools/mongodb/metadata/dbStats.js +6 -1
- package/dist/tools/mongodb/metadata/dbStats.js.map +1 -1
- package/dist/tools/mongodb/metadata/explain.js +14 -7
- package/dist/tools/mongodb/metadata/explain.js.map +1 -1
- package/dist/tools/mongodb/metadata/logs.js +45 -0
- package/dist/tools/mongodb/metadata/logs.js.map +1 -0
- package/dist/tools/mongodb/mongodbTool.js +42 -36
- package/dist/tools/mongodb/mongodbTool.js.map +1 -1
- package/dist/tools/mongodb/read/aggregate.js +4 -4
- package/dist/tools/mongodb/read/aggregate.js.map +1 -1
- package/dist/tools/mongodb/read/collectionIndexes.js +24 -5
- package/dist/tools/mongodb/read/collectionIndexes.js.map +1 -1
- package/dist/tools/mongodb/read/count.js +1 -2
- package/dist/tools/mongodb/read/count.js.map +1 -1
- package/dist/tools/mongodb/read/find.js +5 -6
- package/dist/tools/mongodb/read/find.js.map +1 -1
- package/dist/tools/mongodb/tools.js +6 -2
- package/dist/tools/mongodb/tools.js.map +1 -1
- package/dist/tools/mongodb/update/renameCollection.js +28 -4
- package/dist/tools/mongodb/update/renameCollection.js.map +1 -1
- package/dist/tools/mongodb/update/updateMany.js +7 -11
- package/dist/tools/mongodb/update/updateMany.js.map +1 -1
- package/dist/tools/tool.js +68 -15
- package/dist/tools/tool.js.map +1 -1
- package/eslint.config.js +29 -10
- package/global.d.ts +1 -0
- package/package.json +7 -3
- package/scripts/apply.ts +9 -7
- package/scripts/filter.ts +3 -2
- package/src/common/atlas/apiClient.ts +44 -11
- package/src/config.ts +16 -17
- package/src/errors.ts +1 -1
- package/src/index.ts +12 -8
- package/src/logger.ts +92 -29
- package/src/packageInfo.ts +6 -0
- package/src/server.ts +160 -11
- package/src/session.ts +102 -22
- package/src/telemetry/constants.ts +15 -0
- package/src/telemetry/eventCache.ts +62 -0
- package/src/telemetry/telemetry.ts +125 -0
- package/src/telemetry/types.ts +77 -0
- package/src/tools/atlas/atlasTool.ts +7 -5
- package/src/tools/atlas/{createAccessList.ts → create/createAccessList.ts} +2 -4
- package/src/tools/atlas/{createDBUser.ts → create/createDBUser.ts} +3 -5
- package/src/tools/atlas/{createFreeCluster.ts → create/createFreeCluster.ts} +7 -6
- package/src/tools/atlas/{createProject.ts → create/createProject.ts} +3 -4
- package/src/tools/atlas/metadata/connectCluster.ts +114 -0
- package/src/tools/atlas/{inspectAccessList.ts → read/inspectAccessList.ts} +2 -4
- package/src/tools/atlas/{inspectCluster.ts → read/inspectCluster.ts} +3 -5
- package/src/tools/atlas/{listClusters.ts → read/listClusters.ts} +3 -5
- package/src/tools/atlas/{listDBUsers.ts → read/listDBUsers.ts} +3 -5
- package/src/tools/atlas/{listOrgs.ts → read/listOrgs.ts} +2 -4
- package/src/tools/atlas/{listProjects.ts → read/listProjects.ts} +15 -7
- package/src/tools/atlas/tools.ts +12 -10
- package/src/tools/mongodb/create/insertMany.ts +1 -1
- package/src/tools/mongodb/delete/deleteMany.ts +1 -2
- package/src/tools/mongodb/metadata/collectionSchema.ts +16 -14
- package/src/tools/mongodb/metadata/collectionStorageSize.ts +41 -3
- package/src/tools/mongodb/metadata/connect.ts +78 -76
- package/src/tools/mongodb/metadata/dbStats.ts +6 -1
- package/src/tools/mongodb/metadata/explain.ts +20 -7
- package/src/tools/mongodb/metadata/logs.ts +55 -0
- package/src/tools/mongodb/mongodbTool.ts +47 -40
- package/src/tools/mongodb/read/aggregate.ts +4 -4
- package/src/tools/mongodb/read/collectionIndexes.ts +29 -5
- package/src/tools/mongodb/read/count.ts +1 -2
- package/src/tools/mongodb/read/find.ts +5 -6
- package/src/tools/mongodb/tools.ts +6 -2
- package/src/tools/mongodb/update/renameCollection.ts +33 -4
- package/src/tools/mongodb/update/updateMany.ts +7 -11
- package/src/tools/tool.ts +89 -26
- package/tests/integration/helpers.ts +94 -107
- package/tests/integration/inMemoryTransport.ts +3 -2
- package/tests/integration/server.test.ts +75 -23
- package/tests/integration/tools/atlas/accessLists.test.ts +13 -15
- package/tests/integration/tools/atlas/atlasHelpers.ts +10 -13
- package/tests/integration/tools/atlas/clusters.test.ts +79 -16
- package/tests/integration/tools/atlas/dbUsers.test.ts +9 -9
- package/tests/integration/tools/atlas/orgs.test.ts +4 -4
- package/tests/integration/tools/atlas/projects.test.ts +10 -12
- package/tests/integration/tools/mongodb/create/createCollection.test.ts +19 -62
- package/tests/integration/tools/mongodb/create/createIndex.test.ts +41 -87
- package/tests/integration/tools/mongodb/create/insertMany.test.ts +35 -78
- package/tests/integration/tools/mongodb/delete/deleteMany.test.ts +25 -62
- package/tests/integration/tools/mongodb/delete/dropCollection.test.ts +22 -71
- package/tests/integration/tools/mongodb/delete/dropDatabase.test.ts +29 -63
- package/tests/integration/tools/mongodb/metadata/collectionSchema.test.ts +154 -0
- package/tests/integration/tools/mongodb/metadata/collectionStorageSize.test.ts +86 -0
- package/tests/integration/tools/mongodb/metadata/connect.test.ts +88 -93
- package/tests/integration/tools/mongodb/metadata/dbStats.test.ts +104 -0
- package/tests/integration/tools/mongodb/metadata/explain.test.ts +171 -0
- package/tests/integration/tools/mongodb/metadata/listCollections.test.ts +28 -56
- package/tests/integration/tools/mongodb/metadata/listDatabases.test.ts +32 -26
- package/tests/integration/tools/mongodb/metadata/logs.test.ts +83 -0
- package/tests/integration/tools/mongodb/mongodbHelpers.ts +176 -0
- package/tests/integration/tools/mongodb/read/aggregate.test.ts +99 -0
- package/tests/integration/tools/mongodb/read/collectionIndexes.test.ts +99 -0
- package/tests/integration/tools/mongodb/read/count.test.ts +31 -79
- package/tests/integration/tools/mongodb/read/find.test.ts +182 -0
- package/tests/integration/tools/mongodb/update/renameCollection.test.ts +194 -0
- package/tests/integration/tools/mongodb/update/updateMany.test.ts +238 -0
- package/tests/unit/telemetry.test.ts +200 -0
- package/tsconfig.jest.json +2 -1
- package/tsconfig.json +1 -1
- package/tsconfig.lint.json +8 -0
- package/dist/tools/atlas/createAccessList.js.map +0 -1
- package/dist/tools/atlas/createDBUser.js.map +0 -1
- package/dist/tools/atlas/createFreeCluster.js.map +0 -1
- package/dist/tools/atlas/createProject.js.map +0 -1
- package/dist/tools/atlas/inspectAccessList.js.map +0 -1
- package/dist/tools/atlas/inspectCluster.js.map +0 -1
- package/dist/tools/atlas/listClusters.js.map +0 -1
- package/dist/tools/atlas/listDBUsers.js.map +0 -1
- package/dist/tools/atlas/listOrgs.js.map +0 -1
- package/dist/tools/atlas/listProjects.js.map +0 -1
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
import { MongoDBToolBase } from "../mongodbTool.js";
|
|
2
|
+
import { DbOperationArgs, MongoDBToolBase } from "../mongodbTool.js";
|
|
3
3
|
export class RenameCollectionTool extends MongoDBToolBase {
|
|
4
4
|
constructor() {
|
|
5
5
|
super(...arguments);
|
|
6
6
|
this.name = "rename-collection";
|
|
7
7
|
this.description = "Renames a collection in a MongoDB database";
|
|
8
8
|
this.argsShape = {
|
|
9
|
-
|
|
10
|
-
database: z.string().describe("Database name"),
|
|
9
|
+
...DbOperationArgs,
|
|
11
10
|
newName: z.string().describe("The new name for the collection"),
|
|
12
11
|
dropTarget: z.boolean().optional().default(false).describe("If true, drops the target collection if it exists"),
|
|
13
12
|
};
|
|
@@ -21,11 +20,36 @@ export class RenameCollectionTool extends MongoDBToolBase {
|
|
|
21
20
|
return {
|
|
22
21
|
content: [
|
|
23
22
|
{
|
|
24
|
-
text: `Collection
|
|
23
|
+
text: `Collection "${collection}" renamed to "${result.collectionName}" in database "${database}".`,
|
|
25
24
|
type: "text",
|
|
26
25
|
},
|
|
27
26
|
],
|
|
28
27
|
};
|
|
29
28
|
}
|
|
29
|
+
handleError(error, args) {
|
|
30
|
+
if (error instanceof Error && "codeName" in error) {
|
|
31
|
+
switch (error.codeName) {
|
|
32
|
+
case "NamespaceNotFound":
|
|
33
|
+
return {
|
|
34
|
+
content: [
|
|
35
|
+
{
|
|
36
|
+
text: `Cannot rename "${args.database}.${args.collection}" because it doesn't exist.`,
|
|
37
|
+
type: "text",
|
|
38
|
+
},
|
|
39
|
+
],
|
|
40
|
+
};
|
|
41
|
+
case "NamespaceExists":
|
|
42
|
+
return {
|
|
43
|
+
content: [
|
|
44
|
+
{
|
|
45
|
+
text: `Cannot rename "${args.database}.${args.collection}" to "${args.newName}" because the target collection already exists. If you want to overwrite it, set the "dropTarget" argument to true.`,
|
|
46
|
+
type: "text",
|
|
47
|
+
},
|
|
48
|
+
],
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return super.handleError(error, args);
|
|
53
|
+
}
|
|
30
54
|
}
|
|
31
55
|
//# sourceMappingURL=renameCollection.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"renameCollection.js","sourceRoot":"","sources":["../../../../src/tools/mongodb/update/renameCollection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"renameCollection.js","sourceRoot":"","sources":["../../../../src/tools/mongodb/update/renameCollection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAGrE,MAAM,OAAO,oBAAqB,SAAQ,eAAe;IAAzD;;QACc,SAAI,GAAG,mBAAmB,CAAC;QAC3B,gBAAW,GAAG,4CAA4C,CAAC;QAC3D,cAAS,GAAG;YAClB,GAAG,eAAe;YAClB,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,iCAAiC,CAAC;YAC/D,UAAU,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,mDAAmD,CAAC;SAClH,CAAC;QACQ,kBAAa,GAAkB,QAAQ,CAAC;IAoDtD,CAAC;IAlDa,KAAK,CAAC,OAAO,CAAC,EACpB,QAAQ,EACR,UAAU,EACV,OAAO,EACP,UAAU,GACoB;QAC9B,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,eAAe,EAAE,CAAC;QAC9C,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,gBAAgB,CAAC,QAAQ,EAAE,UAAU,EAAE,OAAO,EAAE;YAC1E,UAAU;SACb,CAAC,CAAC;QAEH,OAAO;YACH,OAAO,EAAE;gBACL;oBACI,IAAI,EAAE,eAAe,UAAU,iBAAiB,MAAM,CAAC,cAAc,kBAAkB,QAAQ,IAAI;oBACnG,IAAI,EAAE,MAAM;iBACf;aACJ;SACJ,CAAC;IACN,CAAC;IAES,WAAW,CACjB,KAAc,EACd,IAAqC;QAErC,IAAI,KAAK,YAAY,KAAK,IAAI,UAAU,IAAI,KAAK,EAAE,CAAC;YAChD,QAAQ,KAAK,CAAC,QAAQ,EAAE,CAAC;gBACrB,KAAK,mBAAmB;oBACpB,OAAO;wBACH,OAAO,EAAE;4BACL;gCACI,IAAI,EAAE,kBAAkB,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,UAAU,6BAA6B;gCACrF,IAAI,EAAE,MAAM;6BACf;yBACJ;qBACJ,CAAC;gBACN,KAAK,iBAAiB;oBAClB,OAAO;wBACH,OAAO,EAAE;4BACL;gCACI,IAAI,EAAE,kBAAkB,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,UAAU,SAAS,IAAI,CAAC,OAAO,qHAAqH;gCAClM,IAAI,EAAE,MAAM;6BACf;yBACJ;qBACJ,CAAC;YACV,CAAC;QACL,CAAC;QAED,OAAO,KAAK,CAAC,WAAW,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IAC1C,CAAC;CACJ"}
|
|
@@ -1,22 +1,18 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
import { MongoDBToolBase } from "../mongodbTool.js";
|
|
2
|
+
import { DbOperationArgs, MongoDBToolBase } from "../mongodbTool.js";
|
|
3
3
|
export class UpdateManyTool extends MongoDBToolBase {
|
|
4
4
|
constructor() {
|
|
5
5
|
super(...arguments);
|
|
6
6
|
this.name = "update-many";
|
|
7
7
|
this.description = "Updates all documents that match the specified filter for a collection";
|
|
8
8
|
this.argsShape = {
|
|
9
|
-
|
|
10
|
-
database: z.string().describe("Database name"),
|
|
9
|
+
...DbOperationArgs,
|
|
11
10
|
filter: z
|
|
12
|
-
.
|
|
13
|
-
.passthrough()
|
|
11
|
+
.record(z.string(), z.unknown())
|
|
14
12
|
.optional()
|
|
15
13
|
.describe("The selection criteria for the update, matching the syntax of the filter argument of db.collection.updateOne()"),
|
|
16
14
|
update: z
|
|
17
|
-
.
|
|
18
|
-
.passthrough()
|
|
19
|
-
.optional()
|
|
15
|
+
.record(z.string(), z.unknown())
|
|
20
16
|
.describe("An update document describing the modifications to apply using update operator expressions"),
|
|
21
17
|
upsert: z
|
|
22
18
|
.boolean()
|
|
@@ -31,8 +27,8 @@ export class UpdateManyTool extends MongoDBToolBase {
|
|
|
31
27
|
upsert,
|
|
32
28
|
});
|
|
33
29
|
let message = "";
|
|
34
|
-
if (result.matchedCount === 0) {
|
|
35
|
-
message =
|
|
30
|
+
if (result.matchedCount === 0 && result.modifiedCount === 0 && result.upsertedCount === 0) {
|
|
31
|
+
message = "No documents matched the filter.";
|
|
36
32
|
}
|
|
37
33
|
else {
|
|
38
34
|
message = `Matched ${result.matchedCount} document(s).`;
|
|
@@ -40,7 +36,7 @@ export class UpdateManyTool extends MongoDBToolBase {
|
|
|
40
36
|
message += ` Modified ${result.modifiedCount} document(s).`;
|
|
41
37
|
}
|
|
42
38
|
if (result.upsertedCount > 0) {
|
|
43
|
-
message += ` Upserted ${result.upsertedCount} document
|
|
39
|
+
message += ` Upserted ${result.upsertedCount} document with id: ${result.upsertedId?.toString()}.`;
|
|
44
40
|
}
|
|
45
41
|
}
|
|
46
42
|
return {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"updateMany.js","sourceRoot":"","sources":["../../../../src/tools/mongodb/update/updateMany.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"updateMany.js","sourceRoot":"","sources":["../../../../src/tools/mongodb/update/updateMany.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAGrE,MAAM,OAAO,cAAe,SAAQ,eAAe;IAAnD;;QACc,SAAI,GAAG,aAAa,CAAC;QACrB,gBAAW,GAAG,wEAAwE,CAAC;QACvF,cAAS,GAAG;YAClB,GAAG,eAAe;YAClB,MAAM,EAAE,CAAC;iBACJ,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC;iBAC/B,QAAQ,EAAE;iBACV,QAAQ,CACL,gHAAgH,CACnH;YACL,MAAM,EAAE,CAAC;iBACJ,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC;iBAC/B,QAAQ,CAAC,4FAA4F,CAAC;YAC3G,MAAM,EAAE,CAAC;iBACJ,OAAO,EAAE;iBACT,QAAQ,EAAE;iBACV,QAAQ,CAAC,4EAA4E,CAAC;SAC9F,CAAC;QACQ,kBAAa,GAAkB,QAAQ,CAAC;IAoCtD,CAAC;IAlCa,KAAK,CAAC,OAAO,CAAC,EACpB,QAAQ,EACR,UAAU,EACV,MAAM,EACN,MAAM,EACN,MAAM,GACwB;QAC9B,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,eAAe,EAAE,CAAC;QAC9C,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,UAAU,CAAC,QAAQ,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE;YAC3E,MAAM;SACT,CAAC,CAAC;QAEH,IAAI,OAAO,GAAG,EAAE,CAAC;QACjB,IAAI,MAAM,CAAC,YAAY,KAAK,CAAC,IAAI,MAAM,CAAC,aAAa,KAAK,CAAC,IAAI,MAAM,CAAC,aAAa,KAAK,CAAC,EAAE,CAAC;YACxF,OAAO,GAAG,kCAAkC,CAAC;QACjD,CAAC;aAAM,CAAC;YACJ,OAAO,GAAG,WAAW,MAAM,CAAC,YAAY,eAAe,CAAC;YACxD,IAAI,MAAM,CAAC,aAAa,GAAG,CAAC,EAAE,CAAC;gBAC3B,OAAO,IAAI,aAAa,MAAM,CAAC,aAAa,eAAe,CAAC;YAChE,CAAC;YACD,IAAI,MAAM,CAAC,aAAa,GAAG,CAAC,EAAE,CAAC;gBAC3B,OAAO,IAAI,aAAa,MAAM,CAAC,aAAa,sBAAsB,MAAM,CAAC,UAAU,EAAE,QAAQ,EAAE,GAAG,CAAC;YACvG,CAAC;QACL,CAAC;QAED,OAAO;YACH,OAAO,EAAE;gBACL;oBACI,IAAI,EAAE,OAAO;oBACb,IAAI,EAAE,MAAM;iBACf;aACJ;SACJ,CAAC;IACN,CAAC;CACJ"}
|
package/dist/tools/tool.js
CHANGED
|
@@ -1,55 +1,108 @@
|
|
|
1
|
-
import logger from "../logger.js";
|
|
2
|
-
import { mongoLogId } from "mongodb-log-writer";
|
|
3
|
-
import config from "../config.js";
|
|
1
|
+
import logger, { LogId } from "../logger.js";
|
|
4
2
|
export class ToolBase {
|
|
5
|
-
constructor(session) {
|
|
3
|
+
constructor(session, config, telemetry) {
|
|
6
4
|
this.session = session;
|
|
5
|
+
this.config = config;
|
|
6
|
+
this.telemetry = telemetry;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Creates and emits a tool telemetry event
|
|
10
|
+
* @param startTime - Start time in milliseconds
|
|
11
|
+
* @param result - Whether the command succeeded or failed
|
|
12
|
+
* @param error - Optional error if the command failed
|
|
13
|
+
*/
|
|
14
|
+
async emitToolEvent(startTime, result) {
|
|
15
|
+
const duration = Date.now() - startTime;
|
|
16
|
+
const event = {
|
|
17
|
+
timestamp: new Date().toISOString(),
|
|
18
|
+
source: "mdbmcp",
|
|
19
|
+
properties: {
|
|
20
|
+
...this.telemetry.getCommonProperties(),
|
|
21
|
+
command: this.name,
|
|
22
|
+
category: this.category,
|
|
23
|
+
component: "tool",
|
|
24
|
+
duration_ms: duration,
|
|
25
|
+
result: result.isError ? "failure" : "success",
|
|
26
|
+
},
|
|
27
|
+
};
|
|
28
|
+
await this.telemetry.emitEvents([event]);
|
|
7
29
|
}
|
|
8
30
|
register(server) {
|
|
9
31
|
if (!this.verifyAllowed()) {
|
|
10
32
|
return;
|
|
11
33
|
}
|
|
12
34
|
const callback = async (...args) => {
|
|
35
|
+
const startTime = Date.now();
|
|
13
36
|
try {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
37
|
+
logger.debug(LogId.toolExecute, "tool", `Executing ${this.name} with args: ${JSON.stringify(args)}`);
|
|
38
|
+
const result = await this.execute(...args);
|
|
39
|
+
await this.emitToolEvent(startTime, result);
|
|
40
|
+
return result;
|
|
17
41
|
}
|
|
18
42
|
catch (error) {
|
|
19
|
-
logger.error(
|
|
20
|
-
|
|
43
|
+
logger.error(LogId.toolExecuteFailure, "tool", `Error executing ${this.name}: ${error}`);
|
|
44
|
+
const toolResult = await this.handleError(error, args[0]);
|
|
45
|
+
await this.emitToolEvent(startTime, toolResult).catch(() => { });
|
|
46
|
+
return toolResult;
|
|
21
47
|
}
|
|
22
48
|
};
|
|
23
49
|
server.tool(this.name, this.description, this.argsShape, callback);
|
|
50
|
+
// This is very similar to RegisteredTool.update, but without the bugs around the name.
|
|
51
|
+
// In the upstream update method, the name is captured in the closure and not updated when
|
|
52
|
+
// the tool name changes. This means that you only get one name update before things end up
|
|
53
|
+
// in a broken state.
|
|
54
|
+
this.update = (updates) => {
|
|
55
|
+
const tools = server["_registeredTools"];
|
|
56
|
+
const existingTool = tools[this.name];
|
|
57
|
+
if (updates.name && updates.name !== this.name) {
|
|
58
|
+
delete tools[this.name];
|
|
59
|
+
this.name = updates.name;
|
|
60
|
+
tools[this.name] = existingTool;
|
|
61
|
+
}
|
|
62
|
+
if (updates.description) {
|
|
63
|
+
existingTool.description = updates.description;
|
|
64
|
+
this.description = updates.description;
|
|
65
|
+
}
|
|
66
|
+
if (updates.inputSchema) {
|
|
67
|
+
existingTool.inputSchema = updates.inputSchema;
|
|
68
|
+
}
|
|
69
|
+
server.sendToolListChanged();
|
|
70
|
+
};
|
|
24
71
|
}
|
|
25
72
|
// Checks if a tool is allowed to run based on the config
|
|
26
73
|
verifyAllowed() {
|
|
27
74
|
let errorClarification;
|
|
28
|
-
|
|
75
|
+
// Check read-only mode first
|
|
76
|
+
if (this.config.readOnly && !["read", "metadata"].includes(this.operationType)) {
|
|
77
|
+
errorClarification = `read-only mode is enabled, its operation type, \`${this.operationType}\`,`;
|
|
78
|
+
}
|
|
79
|
+
else if (this.config.disabledTools.includes(this.category)) {
|
|
29
80
|
errorClarification = `its category, \`${this.category}\`,`;
|
|
30
81
|
}
|
|
31
|
-
else if (config.disabledTools.includes(this.operationType)) {
|
|
82
|
+
else if (this.config.disabledTools.includes(this.operationType)) {
|
|
32
83
|
errorClarification = `its operation type, \`${this.operationType}\`,`;
|
|
33
84
|
}
|
|
34
|
-
else if (config.disabledTools.includes(this.name)) {
|
|
85
|
+
else if (this.config.disabledTools.includes(this.name)) {
|
|
35
86
|
errorClarification = `it`;
|
|
36
87
|
}
|
|
37
88
|
if (errorClarification) {
|
|
38
|
-
logger.debug(
|
|
89
|
+
logger.debug(LogId.toolDisabled, "tool", `Prevented registration of ${this.name} because ${errorClarification} is disabled in the config`);
|
|
39
90
|
return false;
|
|
40
91
|
}
|
|
41
92
|
return true;
|
|
42
93
|
}
|
|
43
94
|
// This method is intended to be overridden by subclasses to handle errors
|
|
44
|
-
handleError(error
|
|
95
|
+
handleError(error,
|
|
96
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
97
|
+
args) {
|
|
45
98
|
return {
|
|
46
99
|
content: [
|
|
47
100
|
{
|
|
48
101
|
type: "text",
|
|
49
102
|
text: `Error running ${this.name}: ${error instanceof Error ? error.message : String(error)}`,
|
|
103
|
+
isError: true,
|
|
50
104
|
},
|
|
51
105
|
],
|
|
52
|
-
isError: true,
|
|
53
106
|
};
|
|
54
107
|
}
|
|
55
108
|
}
|
package/dist/tools/tool.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tool.js","sourceRoot":"","sources":["../../src/tools/tool.ts"],"names":[],"mappings":"AAIA,OAAO,MAAM,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"tool.js","sourceRoot":"","sources":["../../src/tools/tool.ts"],"names":[],"mappings":"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"}
|
package/eslint.config.js
CHANGED
|
@@ -2,18 +2,34 @@ import { defineConfig, globalIgnores } from "eslint/config";
|
|
|
2
2
|
import js from "@eslint/js";
|
|
3
3
|
import globals from "globals";
|
|
4
4
|
import tseslint from "typescript-eslint";
|
|
5
|
-
import
|
|
5
|
+
import eslintPluginPrettierRecommended from "eslint-plugin-prettier/recommended";
|
|
6
|
+
import jestPlugin from "eslint-plugin-jest";
|
|
6
7
|
|
|
7
|
-
const
|
|
8
|
+
const testFiles = ["tests/**/*.test.ts", "tests/**/*.ts"];
|
|
9
|
+
|
|
10
|
+
const files = [...testFiles, "src/**/*.ts", "scripts/**/*.ts"];
|
|
8
11
|
|
|
9
12
|
export default defineConfig([
|
|
10
13
|
{ files, plugins: { js }, extends: ["js/recommended"] },
|
|
11
14
|
{ files, languageOptions: { globals: globals.node } },
|
|
15
|
+
{
|
|
16
|
+
files: testFiles,
|
|
17
|
+
plugins: {
|
|
18
|
+
jest: jestPlugin,
|
|
19
|
+
},
|
|
20
|
+
languageOptions: {
|
|
21
|
+
globals: {
|
|
22
|
+
...globals.node,
|
|
23
|
+
...jestPlugin.environments.globals.globals,
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
},
|
|
12
27
|
tseslint.configs.recommendedTypeChecked,
|
|
13
28
|
{
|
|
29
|
+
files,
|
|
14
30
|
languageOptions: {
|
|
15
31
|
parserOptions: {
|
|
16
|
-
|
|
32
|
+
project: "./tsconfig.lint.json",
|
|
17
33
|
tsconfigRootDir: import.meta.dirname,
|
|
18
34
|
},
|
|
19
35
|
},
|
|
@@ -25,11 +41,14 @@ export default defineConfig([
|
|
|
25
41
|
"@typescript-eslint/no-non-null-assertion": "error",
|
|
26
42
|
},
|
|
27
43
|
},
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
44
|
+
globalIgnores([
|
|
45
|
+
"node_modules",
|
|
46
|
+
"dist",
|
|
47
|
+
"src/common/atlas/openapi.d.ts",
|
|
48
|
+
"coverage",
|
|
49
|
+
"global.d.ts",
|
|
50
|
+
"eslint.config.js",
|
|
51
|
+
"jest.config.js",
|
|
52
|
+
]),
|
|
53
|
+
eslintPluginPrettierRecommended,
|
|
35
54
|
]);
|
package/global.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import "jest-extended";
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mongodb-mcp-server",
|
|
3
3
|
"description": "MongoDB Model Context Protocol Server",
|
|
4
|
-
"version": "0.0.
|
|
4
|
+
"version": "0.0.6",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"author": "MongoDB <info@mongodb.com>",
|
|
7
7
|
"homepage": "https://github.com/mongodb-js/mongodb-mcp-server",
|
|
@@ -34,19 +34,22 @@
|
|
|
34
34
|
"devDependencies": {
|
|
35
35
|
"@eslint/js": "^9.24.0",
|
|
36
36
|
"@jest/globals": "^29.7.0",
|
|
37
|
-
"@modelcontextprotocol/inspector": "^0.
|
|
37
|
+
"@modelcontextprotocol/inspector": "^0.10.2",
|
|
38
38
|
"@redocly/cli": "^1.34.2",
|
|
39
39
|
"@types/jest": "^29.5.14",
|
|
40
40
|
"@types/node": "^22.14.0",
|
|
41
41
|
"@types/simple-oauth2": "^5.0.7",
|
|
42
42
|
"@types/yargs-parser": "^21.0.3",
|
|
43
43
|
"eslint": "^9.24.0",
|
|
44
|
-
"eslint-config-prettier": "^10.1.
|
|
44
|
+
"eslint-config-prettier": "^10.1.2",
|
|
45
|
+
"eslint-plugin-jest": "^28.11.0",
|
|
46
|
+
"eslint-plugin-prettier": "^5.2.6",
|
|
45
47
|
"globals": "^16.0.0",
|
|
46
48
|
"jest": "^29.7.0",
|
|
47
49
|
"jest-environment-node": "^29.7.0",
|
|
48
50
|
"jest-extended": "^4.0.2",
|
|
49
51
|
"mongodb-runner": "^5.8.2",
|
|
52
|
+
"native-machine-id": "^0.1.0",
|
|
50
53
|
"openapi-types": "^12.1.3",
|
|
51
54
|
"openapi-typescript": "^7.6.1",
|
|
52
55
|
"prettier": "^3.5.3",
|
|
@@ -61,6 +64,7 @@
|
|
|
61
64
|
"@mongodb-js/devtools-connect": "^3.7.2",
|
|
62
65
|
"@mongosh/service-provider-node-driver": "^3.6.0",
|
|
63
66
|
"bson": "^6.10.3",
|
|
67
|
+
"lru-cache": "^11.1.0",
|
|
64
68
|
"mongodb": "^6.15.0",
|
|
65
69
|
"mongodb-log-writer": "^2.4.1",
|
|
66
70
|
"mongodb-redact": "^1.1.6",
|
package/scripts/apply.ts
CHANGED
|
@@ -9,13 +9,15 @@ function findObjectFromRef<T>(obj: T | OpenAPIV3_1.ReferenceObject, openapi: Ope
|
|
|
9
9
|
}
|
|
10
10
|
const paramParts = ref.split("/");
|
|
11
11
|
paramParts.shift(); // Remove the first part which is always '#'
|
|
12
|
-
|
|
12
|
+
|
|
13
|
+
let foundObj: Record<string, unknown> = openapi;
|
|
13
14
|
while (true) {
|
|
14
15
|
const part = paramParts.shift();
|
|
15
16
|
if (!part) {
|
|
16
17
|
break;
|
|
17
18
|
}
|
|
18
|
-
|
|
19
|
+
|
|
20
|
+
foundObj = foundObj[part] as Record<string, unknown>;
|
|
19
21
|
}
|
|
20
22
|
return foundObj as T;
|
|
21
23
|
}
|
|
@@ -28,7 +30,7 @@ async function main() {
|
|
|
28
30
|
process.exit(1);
|
|
29
31
|
}
|
|
30
32
|
|
|
31
|
-
const specFile =
|
|
33
|
+
const specFile = await fs.readFile(spec as string, "utf8");
|
|
32
34
|
|
|
33
35
|
const operations: {
|
|
34
36
|
path: string;
|
|
@@ -42,7 +44,7 @@ async function main() {
|
|
|
42
44
|
const openapi = JSON.parse(specFile) as OpenAPIV3_1.Document;
|
|
43
45
|
for (const path in openapi.paths) {
|
|
44
46
|
for (const method in openapi.paths[path]) {
|
|
45
|
-
const operation
|
|
47
|
+
const operation = openapi.paths[path][method] as OpenAPIV3_1.OperationObject;
|
|
46
48
|
|
|
47
49
|
if (!operation.operationId || !operation.tags?.length) {
|
|
48
50
|
continue;
|
|
@@ -101,9 +103,9 @@ async function main() {
|
|
|
101
103
|
})
|
|
102
104
|
.join("\n");
|
|
103
105
|
|
|
104
|
-
const templateFile =
|
|
106
|
+
const templateFile = await fs.readFile(file as string, "utf8");
|
|
105
107
|
const templateLines = templateFile.split("\n");
|
|
106
|
-
|
|
108
|
+
const outputLines: string[] = [];
|
|
107
109
|
let addLines = true;
|
|
108
110
|
for (const line of templateLines) {
|
|
109
111
|
if (line.includes("DO NOT EDIT. This is auto-generated code.")) {
|
|
@@ -120,7 +122,7 @@ async function main() {
|
|
|
120
122
|
}
|
|
121
123
|
const output = outputLines.join("\n");
|
|
122
124
|
|
|
123
|
-
await fs.writeFile(file, output, "utf8");
|
|
125
|
+
await fs.writeFile(file as string, output, "utf8");
|
|
124
126
|
}
|
|
125
127
|
|
|
126
128
|
main().catch((error) => {
|
package/scripts/filter.ts
CHANGED
|
@@ -8,6 +8,7 @@ async function readStdin() {
|
|
|
8
8
|
reject(err);
|
|
9
9
|
});
|
|
10
10
|
process.stdin.on("data", (chunk) => {
|
|
11
|
+
// eslint-disable-next-line @typescript-eslint/restrict-plus-operands
|
|
11
12
|
data += chunk;
|
|
12
13
|
});
|
|
13
14
|
process.stdin.on("end", () => {
|
|
@@ -42,8 +43,8 @@ function filterOpenapi(openapi: OpenAPIV3_1.Document): OpenAPIV3_1.Document {
|
|
|
42
43
|
for (const path in openapi.paths) {
|
|
43
44
|
const filteredMethods = {} as OpenAPIV3_1.PathItemObject;
|
|
44
45
|
for (const method in openapi.paths[path]) {
|
|
45
|
-
if (allowedOperations.includes(openapi.paths[path][method].operationId)) {
|
|
46
|
-
filteredMethods[method] = openapi.paths[path][method];
|
|
46
|
+
if (allowedOperations.includes((openapi.paths[path][method] as { operationId: string }).operationId)) {
|
|
47
|
+
filteredMethods[method] = openapi.paths[path][method] as OpenAPIV3_1.OperationObject;
|
|
47
48
|
}
|
|
48
49
|
}
|
|
49
50
|
if (Object.keys(filteredMethods).length > 0) {
|
|
@@ -1,17 +1,21 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
1
|
+
import createClient, { Client, Middleware } from "openapi-fetch";
|
|
2
|
+
import type { FetchOptions } from "openapi-fetch";
|
|
3
3
|
import { AccessToken, ClientCredentials } from "simple-oauth2";
|
|
4
4
|
import { ApiClientError } from "./apiClientError.js";
|
|
5
5
|
import { paths, operations } from "./openapi.js";
|
|
6
|
+
import { BaseEvent } from "../../telemetry/types.js";
|
|
7
|
+
import { packageInfo } from "../../packageInfo.js";
|
|
6
8
|
|
|
7
9
|
const ATLAS_API_VERSION = "2025-03-12";
|
|
8
10
|
|
|
11
|
+
export interface ApiClientCredentials {
|
|
12
|
+
clientId: string;
|
|
13
|
+
clientSecret: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
9
16
|
export interface ApiClientOptions {
|
|
10
|
-
credentials?:
|
|
11
|
-
|
|
12
|
-
clientSecret: string;
|
|
13
|
-
};
|
|
14
|
-
baseUrl?: string;
|
|
17
|
+
credentials?: ApiClientCredentials;
|
|
18
|
+
baseUrl: string;
|
|
15
19
|
userAgent?: string;
|
|
16
20
|
}
|
|
17
21
|
|
|
@@ -59,13 +63,12 @@ export class ApiClient {
|
|
|
59
63
|
},
|
|
60
64
|
};
|
|
61
65
|
|
|
62
|
-
constructor(options
|
|
66
|
+
constructor(options: ApiClientOptions) {
|
|
63
67
|
this.options = {
|
|
64
68
|
...options,
|
|
65
|
-
baseUrl: options?.baseUrl || "https://cloud.mongodb.com/",
|
|
66
69
|
userAgent:
|
|
67
|
-
options
|
|
68
|
-
`AtlasMCP/${
|
|
70
|
+
options.userAgent ||
|
|
71
|
+
`AtlasMCP/${packageInfo.version} (${process.platform}; ${process.arch}; ${process.env.HOSTNAME || "unknown"})`,
|
|
69
72
|
};
|
|
70
73
|
|
|
71
74
|
this.client = createClient<paths>({
|
|
@@ -91,6 +94,10 @@ export class ApiClient {
|
|
|
91
94
|
this.client.use(this.errorMiddleware);
|
|
92
95
|
}
|
|
93
96
|
|
|
97
|
+
public hasCredentials(): boolean {
|
|
98
|
+
return !!(this.oauth2Client && this.accessToken);
|
|
99
|
+
}
|
|
100
|
+
|
|
94
101
|
public async getIpInfo(): Promise<{
|
|
95
102
|
currentIpv4Address: string;
|
|
96
103
|
}> {
|
|
@@ -116,6 +123,32 @@ export class ApiClient {
|
|
|
116
123
|
}>;
|
|
117
124
|
}
|
|
118
125
|
|
|
126
|
+
async sendEvents(events: BaseEvent[]): Promise<void> {
|
|
127
|
+
let endpoint = "api/private/unauth/telemetry/events";
|
|
128
|
+
const headers: Record<string, string> = {
|
|
129
|
+
Accept: "application/json",
|
|
130
|
+
"Content-Type": "application/json",
|
|
131
|
+
"User-Agent": this.options.userAgent,
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
const accessToken = await this.getAccessToken();
|
|
135
|
+
if (accessToken) {
|
|
136
|
+
endpoint = "api/private/v1.0/telemetry/events";
|
|
137
|
+
headers["Authorization"] = `Bearer ${accessToken}`;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
const url = new URL(endpoint, this.options.baseUrl);
|
|
141
|
+
const response = await fetch(url, {
|
|
142
|
+
method: "POST",
|
|
143
|
+
headers,
|
|
144
|
+
body: JSON.stringify(events),
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
if (!response.ok) {
|
|
148
|
+
throw await ApiClientError.fromResponse(response);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
119
152
|
// DO NOT EDIT. This is auto-generated code.
|
|
120
153
|
async listClustersForAllProjects(options?: FetchOptions<operations["listClustersForAllProjects"]>) {
|
|
121
154
|
const { data } = await this.client.GET("/api/atlas/v2/clusters", options);
|
package/src/config.ts
CHANGED
|
@@ -2,27 +2,31 @@ import path from "path";
|
|
|
2
2
|
import os from "os";
|
|
3
3
|
import argv from "yargs-parser";
|
|
4
4
|
|
|
5
|
-
import packageJson from "../package.json" with { type: "json" };
|
|
6
5
|
import { ReadConcernLevel, ReadPreferenceMode, W } from "mongodb";
|
|
7
6
|
|
|
7
|
+
export interface ConnectOptions {
|
|
8
|
+
readConcern: ReadConcernLevel;
|
|
9
|
+
readPreference: ReadPreferenceMode;
|
|
10
|
+
writeConcern: W;
|
|
11
|
+
timeoutMS: number;
|
|
12
|
+
}
|
|
13
|
+
|
|
8
14
|
// If we decide to support non-string config options, we'll need to extend the mechanism for parsing
|
|
9
15
|
// env variables.
|
|
10
|
-
interface UserConfig {
|
|
11
|
-
apiBaseUrl
|
|
16
|
+
export interface UserConfig {
|
|
17
|
+
apiBaseUrl: string;
|
|
12
18
|
apiClientId?: string;
|
|
13
19
|
apiClientSecret?: string;
|
|
20
|
+
telemetry?: "enabled" | "disabled";
|
|
14
21
|
logPath: string;
|
|
15
22
|
connectionString?: string;
|
|
16
|
-
connectOptions:
|
|
17
|
-
readConcern: ReadConcernLevel;
|
|
18
|
-
readPreference: ReadPreferenceMode;
|
|
19
|
-
writeConcern: W;
|
|
20
|
-
timeoutMS: number;
|
|
21
|
-
};
|
|
23
|
+
connectOptions: ConnectOptions;
|
|
22
24
|
disabledTools: Array<string>;
|
|
25
|
+
readOnly?: boolean;
|
|
23
26
|
}
|
|
24
27
|
|
|
25
28
|
const defaults: UserConfig = {
|
|
29
|
+
apiBaseUrl: "https://cloud.mongodb.com/",
|
|
26
30
|
logPath: getLogPath(),
|
|
27
31
|
connectOptions: {
|
|
28
32
|
readConcern: "local",
|
|
@@ -31,21 +35,16 @@ const defaults: UserConfig = {
|
|
|
31
35
|
timeoutMS: 30_000,
|
|
32
36
|
},
|
|
33
37
|
disabledTools: [],
|
|
38
|
+
telemetry: "disabled",
|
|
39
|
+
readOnly: false,
|
|
34
40
|
};
|
|
35
41
|
|
|
36
|
-
const
|
|
42
|
+
export const config = {
|
|
37
43
|
...defaults,
|
|
38
44
|
...getEnvConfig(),
|
|
39
45
|
...getCliConfig(),
|
|
40
46
|
};
|
|
41
47
|
|
|
42
|
-
const config = {
|
|
43
|
-
...mergedUserConfig,
|
|
44
|
-
version: packageJson.version,
|
|
45
|
-
};
|
|
46
|
-
|
|
47
|
-
export default config;
|
|
48
|
-
|
|
49
48
|
function getLogPath(): string {
|
|
50
49
|
const localDataPath =
|
|
51
50
|
process.platform === "win32"
|
package/src/errors.ts
CHANGED
package/src/index.ts
CHANGED
|
@@ -1,30 +1,34 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
4
|
-
import logger from "./logger.js";
|
|
5
|
-
import { mongoLogId } from "mongodb-log-writer";
|
|
4
|
+
import logger, { LogId } from "./logger.js";
|
|
6
5
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
7
|
-
import config from "./config.js";
|
|
6
|
+
import { config } from "./config.js";
|
|
8
7
|
import { Session } from "./session.js";
|
|
9
8
|
import { Server } from "./server.js";
|
|
9
|
+
import { packageInfo } from "./packageInfo.js";
|
|
10
10
|
|
|
11
11
|
try {
|
|
12
|
-
const session = new Session(
|
|
12
|
+
const session = new Session({
|
|
13
|
+
apiBaseUrl: config.apiBaseUrl,
|
|
14
|
+
apiClientId: config.apiClientId,
|
|
15
|
+
apiClientSecret: config.apiClientSecret,
|
|
16
|
+
});
|
|
13
17
|
const mcpServer = new McpServer({
|
|
14
|
-
name:
|
|
15
|
-
version:
|
|
18
|
+
name: packageInfo.mcpServerName,
|
|
19
|
+
version: packageInfo.version,
|
|
16
20
|
});
|
|
17
21
|
|
|
18
22
|
const server = new Server({
|
|
19
23
|
mcpServer,
|
|
20
24
|
session,
|
|
25
|
+
userConfig: config,
|
|
21
26
|
});
|
|
22
27
|
|
|
23
28
|
const transport = new StdioServerTransport();
|
|
24
29
|
|
|
25
30
|
await server.connect(transport);
|
|
26
31
|
} catch (error: unknown) {
|
|
27
|
-
logger.emergency(
|
|
28
|
-
|
|
32
|
+
logger.emergency(LogId.serverStartFailure, "server", `Fatal error running server: ${error as string}`);
|
|
29
33
|
process.exit(1);
|
|
30
34
|
}
|