mongodb-mcp-server 0.0.4
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/workflows/code_health.yaml +65 -0
- package/.github/workflows/prepare_release.yaml +45 -0
- package/.github/workflows/publish.yaml +70 -0
- package/.prettierignore +5 -0
- package/.prettierrc.json +37 -0
- package/.vscode/launch.json +17 -0
- package/CONTRIBUTING.md +185 -0
- package/LICENSE +202 -0
- package/README.md +234 -0
- package/dist/common/atlas/apiClient.js +147 -0
- package/dist/common/atlas/apiClient.js.map +1 -0
- package/dist/common/atlas/apiClientError.js +17 -0
- package/dist/common/atlas/apiClientError.js.map +1 -0
- package/dist/config.js +85 -0
- package/dist/config.js.map +1 -0
- package/dist/errors.js +12 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.js +26 -0
- package/dist/index.js.map +1 -0
- package/dist/logger.js +97 -0
- package/dist/logger.js.map +1 -0
- package/dist/server.js +45 -0
- package/dist/server.js.map +1 -0
- package/dist/session.js +30 -0
- package/dist/session.js.map +1 -0
- package/dist/tools/atlas/atlasTool.js +9 -0
- package/dist/tools/atlas/atlasTool.js.map +1 -0
- package/dist/tools/atlas/createAccessList.js +64 -0
- package/dist/tools/atlas/createAccessList.js.map +1 -0
- package/dist/tools/atlas/createDBUser.js +58 -0
- package/dist/tools/atlas/createDBUser.js.map +1 -0
- package/dist/tools/atlas/createFreeCluster.js +51 -0
- package/dist/tools/atlas/createFreeCluster.js.map +1 -0
- package/dist/tools/atlas/createProject.js +53 -0
- package/dist/tools/atlas/createProject.js.map +1 -0
- package/dist/tools/atlas/inspectAccessList.js +41 -0
- package/dist/tools/atlas/inspectAccessList.js.map +1 -0
- package/dist/tools/atlas/inspectCluster.js +42 -0
- package/dist/tools/atlas/inspectCluster.js.map +1 -0
- package/dist/tools/atlas/listClusters.js +97 -0
- package/dist/tools/atlas/listClusters.js.map +1 -0
- package/dist/tools/atlas/listDBUsers.js +52 -0
- package/dist/tools/atlas/listDBUsers.js.map +1 -0
- package/dist/tools/atlas/listOrgs.js +30 -0
- package/dist/tools/atlas/listOrgs.js.map +1 -0
- package/dist/tools/atlas/listProjects.js +42 -0
- package/dist/tools/atlas/listProjects.js.map +1 -0
- package/dist/tools/atlas/tools.js +23 -0
- package/dist/tools/atlas/tools.js.map +1 -0
- package/dist/tools/mongodb/create/createCollection.js +23 -0
- package/dist/tools/mongodb/create/createCollection.js.map +1 -0
- package/dist/tools/mongodb/create/createIndex.js +33 -0
- package/dist/tools/mongodb/create/createIndex.js.map +1 -0
- package/dist/tools/mongodb/create/insertMany.js +33 -0
- package/dist/tools/mongodb/create/insertMany.js.map +1 -0
- package/dist/tools/mongodb/delete/deleteMany.js +31 -0
- package/dist/tools/mongodb/delete/deleteMany.js.map +1 -0
- package/dist/tools/mongodb/delete/dropCollection.js +25 -0
- package/dist/tools/mongodb/delete/dropCollection.js.map +1 -0
- package/dist/tools/mongodb/delete/dropDatabase.js +25 -0
- package/dist/tools/mongodb/delete/dropDatabase.js.map +1 -0
- package/dist/tools/mongodb/metadata/collectionSchema.js +38 -0
- package/dist/tools/mongodb/metadata/collectionSchema.js.map +1 -0
- package/dist/tools/mongodb/metadata/collectionStorageSize.js +28 -0
- package/dist/tools/mongodb/metadata/collectionStorageSize.js.map +1 -0
- package/dist/tools/mongodb/metadata/connect.js +86 -0
- package/dist/tools/mongodb/metadata/connect.js.map +1 -0
- package/dist/tools/mongodb/metadata/dbStats.js +28 -0
- package/dist/tools/mongodb/metadata/dbStats.js.map +1 -0
- package/dist/tools/mongodb/metadata/explain.js +77 -0
- package/dist/tools/mongodb/metadata/explain.js.map +1 -0
- package/dist/tools/mongodb/metadata/listCollections.js +35 -0
- package/dist/tools/mongodb/metadata/listCollections.js.map +1 -0
- package/dist/tools/mongodb/metadata/listDatabases.js +23 -0
- package/dist/tools/mongodb/metadata/listDatabases.js.map +1 -0
- package/dist/tools/mongodb/mongodbTool.js +58 -0
- package/dist/tools/mongodb/mongodbTool.js.map +1 -0
- package/dist/tools/mongodb/read/aggregate.js +38 -0
- package/dist/tools/mongodb/read/aggregate.js.map +1 -0
- package/dist/tools/mongodb/read/collectionIndexes.js +23 -0
- package/dist/tools/mongodb/read/collectionIndexes.js.map +1 -0
- package/dist/tools/mongodb/read/count.js +34 -0
- package/dist/tools/mongodb/read/count.js.map +1 -0
- package/dist/tools/mongodb/read/find.js +51 -0
- package/dist/tools/mongodb/read/find.js.map +1 -0
- package/dist/tools/mongodb/tools.js +41 -0
- package/dist/tools/mongodb/tools.js.map +1 -0
- package/dist/tools/mongodb/update/renameCollection.js +31 -0
- package/dist/tools/mongodb/update/renameCollection.js.map +1 -0
- package/dist/tools/mongodb/update/updateMany.js +56 -0
- package/dist/tools/mongodb/update/updateMany.js.map +1 -0
- package/dist/tools/tool.js +56 -0
- package/dist/tools/tool.js.map +1 -0
- package/eslint.config.js +35 -0
- package/jest.config.js +22 -0
- package/package.json +76 -0
- package/scripts/apply.ts +129 -0
- package/scripts/filter.ts +67 -0
- package/scripts/generate.sh +11 -0
- package/src/common/atlas/apiClient.ts +202 -0
- package/src/common/atlas/apiClientError.ts +21 -0
- package/src/common/atlas/openapi.d.ts +5849 -0
- package/src/config.ts +124 -0
- package/src/errors.ts +13 -0
- package/src/index.ts +30 -0
- package/src/logger.ts +117 -0
- package/src/server.ts +64 -0
- package/src/session.ts +37 -0
- package/src/tools/atlas/atlasTool.ts +10 -0
- package/src/tools/atlas/createAccessList.ts +78 -0
- package/src/tools/atlas/createDBUser.ts +70 -0
- package/src/tools/atlas/createFreeCluster.ts +55 -0
- package/src/tools/atlas/createProject.ts +63 -0
- package/src/tools/atlas/inspectAccessList.ts +44 -0
- package/src/tools/atlas/inspectCluster.ts +47 -0
- package/src/tools/atlas/listClusters.ts +104 -0
- package/src/tools/atlas/listDBUsers.ts +62 -0
- package/src/tools/atlas/listOrgs.ts +34 -0
- package/src/tools/atlas/listProjects.ts +46 -0
- package/src/tools/atlas/tools.ts +23 -0
- package/src/tools/mongodb/create/createCollection.ts +26 -0
- package/src/tools/mongodb/create/createIndex.ts +41 -0
- package/src/tools/mongodb/create/insertMany.ts +40 -0
- package/src/tools/mongodb/delete/deleteMany.ts +38 -0
- package/src/tools/mongodb/delete/dropCollection.ts +27 -0
- package/src/tools/mongodb/delete/dropDatabase.ts +26 -0
- package/src/tools/mongodb/metadata/collectionSchema.ts +41 -0
- package/src/tools/mongodb/metadata/collectionStorageSize.ts +30 -0
- package/src/tools/mongodb/metadata/connect.ts +94 -0
- package/src/tools/mongodb/metadata/dbStats.ts +30 -0
- package/src/tools/mongodb/metadata/explain.ts +90 -0
- package/src/tools/mongodb/metadata/listCollections.ts +38 -0
- package/src/tools/mongodb/metadata/listDatabases.ts +26 -0
- package/src/tools/mongodb/mongodbTool.ts +69 -0
- package/src/tools/mongodb/read/aggregate.ts +45 -0
- package/src/tools/mongodb/read/collectionIndexes.ts +24 -0
- package/src/tools/mongodb/read/count.ts +39 -0
- package/src/tools/mongodb/read/find.ts +62 -0
- package/src/tools/mongodb/tools.ts +41 -0
- package/src/tools/mongodb/update/renameCollection.ts +37 -0
- package/src/tools/mongodb/update/updateMany.ts +65 -0
- package/src/tools/tool.ts +90 -0
- package/src/types/mongodb-redact.d.ts +4 -0
- package/tests/integration/helpers.ts +241 -0
- package/tests/integration/inMemoryTransport.ts +58 -0
- package/tests/integration/server.test.ts +35 -0
- package/tests/integration/tools/atlas/accessLists.test.ts +100 -0
- package/tests/integration/tools/atlas/atlasHelpers.ts +110 -0
- package/tests/integration/tools/atlas/clusters.test.ts +122 -0
- package/tests/integration/tools/atlas/dbUsers.test.ts +80 -0
- package/tests/integration/tools/atlas/orgs.test.ts +24 -0
- package/tests/integration/tools/atlas/projects.test.ts +80 -0
- package/tests/integration/tools/mongodb/create/createCollection.test.ts +138 -0
- package/tests/integration/tools/mongodb/create/createIndex.test.ts +249 -0
- package/tests/integration/tools/mongodb/create/insertMany.test.ts +141 -0
- package/tests/integration/tools/mongodb/delete/deleteMany.test.ts +191 -0
- package/tests/integration/tools/mongodb/delete/dropCollection.test.ts +118 -0
- package/tests/integration/tools/mongodb/delete/dropDatabase.test.ts +114 -0
- package/tests/integration/tools/mongodb/metadata/connect.test.ts +137 -0
- package/tests/integration/tools/mongodb/metadata/listCollections.test.ts +104 -0
- package/tests/integration/tools/mongodb/metadata/listDatabases.test.ts +67 -0
- package/tests/integration/tools/mongodb/read/count.test.ts +138 -0
- package/tsconfig.jest.json +10 -0
- package/tsconfig.json +19 -0
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
|
|
3
|
+
import { AtlasToolBase } from "./atlasTool.js";
|
|
4
|
+
import { ToolArgs, OperationType } from "../tool.js";
|
|
5
|
+
|
|
6
|
+
export class InspectAccessListTool extends AtlasToolBase {
|
|
7
|
+
protected name = "atlas-inspect-access-list";
|
|
8
|
+
protected description = "Inspect Ip/CIDR ranges with access to your MongoDB Atlas clusters.";
|
|
9
|
+
protected operationType: OperationType = "read";
|
|
10
|
+
protected argsShape = {
|
|
11
|
+
projectId: z.string().describe("Atlas project ID"),
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
protected async execute({ projectId }: ToolArgs<typeof this.argsShape>): Promise<CallToolResult> {
|
|
15
|
+
this.session.ensureAuthenticated();
|
|
16
|
+
|
|
17
|
+
const accessList = await this.session.apiClient.listProjectIpAccessLists({
|
|
18
|
+
params: {
|
|
19
|
+
path: {
|
|
20
|
+
groupId: projectId,
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
if (!accessList?.results?.length) {
|
|
26
|
+
throw new Error("No access list entries found.");
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return {
|
|
30
|
+
content: [
|
|
31
|
+
{
|
|
32
|
+
type: "text",
|
|
33
|
+
text: `IP ADDRESS | CIDR | COMMENT
|
|
34
|
+
------|------|------
|
|
35
|
+
${(accessList.results || [])
|
|
36
|
+
.map((entry) => {
|
|
37
|
+
return `${entry.ipAddress} | ${entry.cidrBlock} | ${entry.comment}`;
|
|
38
|
+
})
|
|
39
|
+
.join("\n")}`,
|
|
40
|
+
},
|
|
41
|
+
],
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
|
|
3
|
+
import { AtlasToolBase } from "./atlasTool.js";
|
|
4
|
+
import { ToolArgs, OperationType } from "../tool.js";
|
|
5
|
+
import { ClusterDescription20240805 } from "../../common/atlas/openapi.js";
|
|
6
|
+
|
|
7
|
+
export class InspectClusterTool extends AtlasToolBase {
|
|
8
|
+
protected name = "atlas-inspect-cluster";
|
|
9
|
+
protected description = "Inspect MongoDB Atlas cluster";
|
|
10
|
+
protected operationType: OperationType = "read";
|
|
11
|
+
protected argsShape = {
|
|
12
|
+
projectId: z.string().describe("Atlas project ID"),
|
|
13
|
+
clusterName: z.string().describe("Atlas cluster name"),
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
protected async execute({ projectId, clusterName }: ToolArgs<typeof this.argsShape>): Promise<CallToolResult> {
|
|
17
|
+
this.session.ensureAuthenticated();
|
|
18
|
+
|
|
19
|
+
const cluster = await this.session.apiClient.getCluster({
|
|
20
|
+
params: {
|
|
21
|
+
path: {
|
|
22
|
+
groupId: projectId,
|
|
23
|
+
clusterName,
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
return this.formatOutput(cluster);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
private formatOutput(cluster?: ClusterDescription20240805): CallToolResult {
|
|
32
|
+
if (!cluster) {
|
|
33
|
+
throw new Error("Cluster not found");
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return {
|
|
37
|
+
content: [
|
|
38
|
+
{
|
|
39
|
+
type: "text",
|
|
40
|
+
text: `Cluster Name | State | MongoDB Version | Connection String
|
|
41
|
+
----------------|----------------|----------------|----------------|----------------
|
|
42
|
+
${cluster.name} | ${cluster.stateName} | ${cluster.mongoDBVersion || "N/A"} | ${cluster.connectionStrings?.standard || "N/A"}`,
|
|
43
|
+
},
|
|
44
|
+
],
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
|
|
3
|
+
import { AtlasToolBase } from "./atlasTool.js";
|
|
4
|
+
import { ToolArgs, OperationType } from "../tool.js";
|
|
5
|
+
import { PaginatedClusterDescription20240805, PaginatedOrgGroupView, Group } from "../../common/atlas/openapi.js";
|
|
6
|
+
|
|
7
|
+
export class ListClustersTool extends AtlasToolBase {
|
|
8
|
+
protected name = "atlas-list-clusters";
|
|
9
|
+
protected description = "List MongoDB Atlas clusters";
|
|
10
|
+
protected operationType: OperationType = "read";
|
|
11
|
+
protected argsShape = {
|
|
12
|
+
projectId: z.string().describe("Atlas project ID to filter clusters").optional(),
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
protected async execute({ projectId }: ToolArgs<typeof this.argsShape>): Promise<CallToolResult> {
|
|
16
|
+
this.session.ensureAuthenticated();
|
|
17
|
+
|
|
18
|
+
if (!projectId) {
|
|
19
|
+
const data = await this.session.apiClient.listClustersForAllProjects();
|
|
20
|
+
|
|
21
|
+
return this.formatAllClustersTable(data);
|
|
22
|
+
} else {
|
|
23
|
+
const project = await this.session.apiClient.getProject({
|
|
24
|
+
params: {
|
|
25
|
+
path: {
|
|
26
|
+
groupId: projectId,
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
if (!project?.id) {
|
|
32
|
+
throw new Error(`Project with ID "${projectId}" not found.`);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const data = await this.session.apiClient.listClusters({
|
|
36
|
+
params: {
|
|
37
|
+
path: {
|
|
38
|
+
groupId: project.id || "",
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
return this.formatClustersTable(project, data);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
private formatAllClustersTable(clusters?: PaginatedOrgGroupView): CallToolResult {
|
|
48
|
+
if (!clusters?.results?.length) {
|
|
49
|
+
throw new Error("No clusters found.");
|
|
50
|
+
}
|
|
51
|
+
const formattedClusters = clusters.results
|
|
52
|
+
.map((result) => {
|
|
53
|
+
return (result.clusters || []).map((cluster) => {
|
|
54
|
+
return { ...result, ...cluster, clusters: undefined };
|
|
55
|
+
});
|
|
56
|
+
})
|
|
57
|
+
.flat();
|
|
58
|
+
if (!formattedClusters.length) {
|
|
59
|
+
throw new Error("No clusters found.");
|
|
60
|
+
}
|
|
61
|
+
const rows = formattedClusters
|
|
62
|
+
.map((cluster) => {
|
|
63
|
+
return `${cluster.groupName} (${cluster.groupId}) | ${cluster.name}`;
|
|
64
|
+
})
|
|
65
|
+
.join("\n");
|
|
66
|
+
return {
|
|
67
|
+
content: [
|
|
68
|
+
{
|
|
69
|
+
type: "text",
|
|
70
|
+
text: `Project | Cluster Name
|
|
71
|
+
----------------|----------------
|
|
72
|
+
${rows}`,
|
|
73
|
+
},
|
|
74
|
+
],
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
private formatClustersTable(project: Group, clusters?: PaginatedClusterDescription20240805): CallToolResult {
|
|
79
|
+
if (!clusters?.results?.length) {
|
|
80
|
+
throw new Error("No clusters found.");
|
|
81
|
+
}
|
|
82
|
+
const rows = clusters.results
|
|
83
|
+
.map((cluster) => {
|
|
84
|
+
const connectionString = cluster.connectionStrings?.standard || "N/A";
|
|
85
|
+
const mongoDBVersion = cluster.mongoDBVersion || "N/A";
|
|
86
|
+
return `${cluster.name} | ${cluster.stateName} | ${mongoDBVersion} | ${connectionString}`;
|
|
87
|
+
})
|
|
88
|
+
.join("\n");
|
|
89
|
+
return {
|
|
90
|
+
content: [
|
|
91
|
+
{
|
|
92
|
+
type: "text",
|
|
93
|
+
text: `Here are your MongoDB Atlas clusters in project "${project.name}" (${project.id}):`,
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
type: "text",
|
|
97
|
+
text: `Cluster Name | State | MongoDB Version | Connection String
|
|
98
|
+
----------------|----------------|----------------|----------------|----------------
|
|
99
|
+
${rows}`,
|
|
100
|
+
},
|
|
101
|
+
],
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
|
|
3
|
+
import { AtlasToolBase } from "./atlasTool.js";
|
|
4
|
+
import { ToolArgs, OperationType } from "../tool.js";
|
|
5
|
+
import { DatabaseUserRole, UserScope } from "../../common/atlas/openapi.js";
|
|
6
|
+
|
|
7
|
+
export class ListDBUsersTool extends AtlasToolBase {
|
|
8
|
+
protected name = "atlas-list-db-users";
|
|
9
|
+
protected description = "List MongoDB Atlas database users";
|
|
10
|
+
protected operationType: OperationType = "read";
|
|
11
|
+
protected argsShape = {
|
|
12
|
+
projectId: z.string().describe("Atlas project ID to filter DB users"),
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
protected async execute({ projectId }: ToolArgs<typeof this.argsShape>): Promise<CallToolResult> {
|
|
16
|
+
this.session.ensureAuthenticated();
|
|
17
|
+
|
|
18
|
+
const data = await this.session.apiClient.listDatabaseUsers({
|
|
19
|
+
params: {
|
|
20
|
+
path: {
|
|
21
|
+
groupId: projectId,
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
if (!data?.results?.length) {
|
|
27
|
+
throw new Error("No database users found.");
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const output =
|
|
31
|
+
`Username | Roles | Scopes
|
|
32
|
+
----------------|----------------|----------------
|
|
33
|
+
` +
|
|
34
|
+
data.results
|
|
35
|
+
.map((user) => {
|
|
36
|
+
return `${user.username} | ${formatRoles(user.roles)} | ${formatScopes(user.scopes)}`;
|
|
37
|
+
})
|
|
38
|
+
.join("\n");
|
|
39
|
+
return {
|
|
40
|
+
content: [{ type: "text", text: output }],
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function formatRoles(roles?: DatabaseUserRole[]) {
|
|
46
|
+
if (!roles?.length) {
|
|
47
|
+
return "N/A";
|
|
48
|
+
}
|
|
49
|
+
return roles
|
|
50
|
+
.map(
|
|
51
|
+
(role) =>
|
|
52
|
+
`${role.roleName}${role.databaseName ? `@${role.databaseName}${role.collectionName ? `:${role.collectionName}` : ""}` : ""}`
|
|
53
|
+
)
|
|
54
|
+
.join(", ");
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function formatScopes(scopes?: UserScope[]) {
|
|
58
|
+
if (!scopes?.length) {
|
|
59
|
+
return "All";
|
|
60
|
+
}
|
|
61
|
+
return scopes.map((scope) => `${scope.type}:${scope.name}`).join(", ");
|
|
62
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
|
|
2
|
+
import { AtlasToolBase } from "./atlasTool.js";
|
|
3
|
+
import { OperationType } from "../tool.js";
|
|
4
|
+
|
|
5
|
+
export class ListOrganizationsTool extends AtlasToolBase {
|
|
6
|
+
protected name = "atlas-list-orgs";
|
|
7
|
+
protected description = "List MongoDB Atlas organizations";
|
|
8
|
+
protected operationType: OperationType = "read";
|
|
9
|
+
protected argsShape = {};
|
|
10
|
+
|
|
11
|
+
protected async execute(): Promise<CallToolResult> {
|
|
12
|
+
this.session.ensureAuthenticated();
|
|
13
|
+
|
|
14
|
+
const data = await this.session.apiClient.listOrganizations();
|
|
15
|
+
|
|
16
|
+
if (!data?.results?.length) {
|
|
17
|
+
throw new Error("No projects found in your MongoDB Atlas account.");
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// Format projects as a table
|
|
21
|
+
const output =
|
|
22
|
+
`Organization Name | Organization ID
|
|
23
|
+
----------------| ----------------
|
|
24
|
+
` +
|
|
25
|
+
data.results
|
|
26
|
+
.map((org) => {
|
|
27
|
+
return `${org.name} | ${org.id}`;
|
|
28
|
+
})
|
|
29
|
+
.join("\n");
|
|
30
|
+
return {
|
|
31
|
+
content: [{ type: "text", text: output }],
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
|
|
2
|
+
import { AtlasToolBase } from "./atlasTool.js";
|
|
3
|
+
import { OperationType } from "../tool.js";
|
|
4
|
+
import { z } from "zod";
|
|
5
|
+
import { ToolArgs } from "../tool.js";
|
|
6
|
+
|
|
7
|
+
export class ListProjectsTool extends AtlasToolBase {
|
|
8
|
+
protected name = "atlas-list-projects";
|
|
9
|
+
protected description = "List MongoDB Atlas projects";
|
|
10
|
+
protected operationType: OperationType = "read";
|
|
11
|
+
protected argsShape = {
|
|
12
|
+
orgId: z.string().describe("Atlas organization ID to filter projects").optional(),
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
protected async execute({ orgId }: ToolArgs<typeof this.argsShape>): Promise<CallToolResult> {
|
|
16
|
+
this.session.ensureAuthenticated();
|
|
17
|
+
|
|
18
|
+
const data = orgId
|
|
19
|
+
? await this.session.apiClient.listOrganizationProjects({
|
|
20
|
+
params: {
|
|
21
|
+
path: {
|
|
22
|
+
orgId,
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
})
|
|
26
|
+
: await this.session.apiClient.listProjects();
|
|
27
|
+
|
|
28
|
+
if (!data?.results?.length) {
|
|
29
|
+
throw new Error("No projects found in your MongoDB Atlas account.");
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Format projects as a table
|
|
33
|
+
const rows = data.results
|
|
34
|
+
.map((project) => {
|
|
35
|
+
const createdAt = project.created ? new Date(project.created).toLocaleString() : "N/A";
|
|
36
|
+
return `${project.name} | ${project.id} | ${createdAt}`;
|
|
37
|
+
})
|
|
38
|
+
.join("\n");
|
|
39
|
+
const formattedProjects = `Project Name | Project ID | Created At
|
|
40
|
+
----------------| ----------------| ----------------
|
|
41
|
+
${rows}`;
|
|
42
|
+
return {
|
|
43
|
+
content: [{ type: "text", text: formattedProjects }],
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { ListClustersTool } from "./listClusters.js";
|
|
2
|
+
import { ListProjectsTool } from "./listProjects.js";
|
|
3
|
+
import { InspectClusterTool } from "./inspectCluster.js";
|
|
4
|
+
import { CreateFreeClusterTool } from "./createFreeCluster.js";
|
|
5
|
+
import { CreateAccessListTool } from "./createAccessList.js";
|
|
6
|
+
import { InspectAccessListTool } from "./inspectAccessList.js";
|
|
7
|
+
import { ListDBUsersTool } from "./listDBUsers.js";
|
|
8
|
+
import { CreateDBUserTool } from "./createDBUser.js";
|
|
9
|
+
import { CreateProjectTool } from "./createProject.js";
|
|
10
|
+
import { ListOrganizationsTool } from "./listOrgs.js";
|
|
11
|
+
|
|
12
|
+
export const AtlasTools = [
|
|
13
|
+
ListClustersTool,
|
|
14
|
+
ListProjectsTool,
|
|
15
|
+
InspectClusterTool,
|
|
16
|
+
CreateFreeClusterTool,
|
|
17
|
+
CreateAccessListTool,
|
|
18
|
+
InspectAccessListTool,
|
|
19
|
+
ListDBUsersTool,
|
|
20
|
+
CreateDBUserTool,
|
|
21
|
+
CreateProjectTool,
|
|
22
|
+
ListOrganizationsTool,
|
|
23
|
+
];
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
|
|
2
|
+
import { DbOperationArgs, MongoDBToolBase } from "../mongodbTool.js";
|
|
3
|
+
import { OperationType, ToolArgs } from "../../tool.js";
|
|
4
|
+
|
|
5
|
+
export class CreateCollectionTool extends MongoDBToolBase {
|
|
6
|
+
protected name = "create-collection";
|
|
7
|
+
protected description =
|
|
8
|
+
"Creates a new collection in a database. If the database doesn't exist, it will be created automatically.";
|
|
9
|
+
protected argsShape = DbOperationArgs;
|
|
10
|
+
|
|
11
|
+
protected operationType: OperationType = "create";
|
|
12
|
+
|
|
13
|
+
protected async execute({ collection, database }: ToolArgs<typeof this.argsShape>): Promise<CallToolResult> {
|
|
14
|
+
const provider = await this.ensureConnected();
|
|
15
|
+
await provider.createCollection(database, collection);
|
|
16
|
+
|
|
17
|
+
return {
|
|
18
|
+
content: [
|
|
19
|
+
{
|
|
20
|
+
type: "text",
|
|
21
|
+
text: `Collection "${collection}" created in database "${database}".`,
|
|
22
|
+
},
|
|
23
|
+
],
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
|
|
3
|
+
import { DbOperationArgs, MongoDBToolBase } from "../mongodbTool.js";
|
|
4
|
+
import { ToolArgs, OperationType } from "../../tool.js";
|
|
5
|
+
import { IndexDirection } from "mongodb";
|
|
6
|
+
|
|
7
|
+
export class CreateIndexTool extends MongoDBToolBase {
|
|
8
|
+
protected name = "create-index";
|
|
9
|
+
protected description = "Create an index for a collection";
|
|
10
|
+
protected argsShape = {
|
|
11
|
+
...DbOperationArgs,
|
|
12
|
+
keys: z.record(z.string(), z.custom<IndexDirection>()).describe("The index definition"),
|
|
13
|
+
name: z.string().optional().describe("The name of the index"),
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
protected operationType: OperationType = "create";
|
|
17
|
+
|
|
18
|
+
protected async execute({
|
|
19
|
+
database,
|
|
20
|
+
collection,
|
|
21
|
+
keys,
|
|
22
|
+
name,
|
|
23
|
+
}: ToolArgs<typeof this.argsShape>): Promise<CallToolResult> {
|
|
24
|
+
const provider = await this.ensureConnected();
|
|
25
|
+
const indexes = await provider.createIndexes(database, collection, [
|
|
26
|
+
{
|
|
27
|
+
key: keys,
|
|
28
|
+
name,
|
|
29
|
+
},
|
|
30
|
+
]);
|
|
31
|
+
|
|
32
|
+
return {
|
|
33
|
+
content: [
|
|
34
|
+
{
|
|
35
|
+
text: `Created the index "${indexes[0]}" on collection "${collection}" in database "${database}"`,
|
|
36
|
+
type: "text",
|
|
37
|
+
},
|
|
38
|
+
],
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
|
|
3
|
+
import { DbOperationArgs, MongoDBToolBase } from "../mongodbTool.js";
|
|
4
|
+
import { ToolArgs, OperationType } from "../../tool.js";
|
|
5
|
+
|
|
6
|
+
export class InsertManyTool extends MongoDBToolBase {
|
|
7
|
+
protected name = "insert-many";
|
|
8
|
+
protected description = "Insert an array of documents into a MongoDB collection";
|
|
9
|
+
protected argsShape = {
|
|
10
|
+
...DbOperationArgs,
|
|
11
|
+
documents: z
|
|
12
|
+
.array(z.object({}).passthrough().describe("An individual MongoDB document"))
|
|
13
|
+
.describe(
|
|
14
|
+
"The array of documents to insert, matching the syntax of the document argument of db.collection.insertMany()"
|
|
15
|
+
),
|
|
16
|
+
};
|
|
17
|
+
protected operationType: OperationType = "create";
|
|
18
|
+
|
|
19
|
+
protected async execute({
|
|
20
|
+
database,
|
|
21
|
+
collection,
|
|
22
|
+
documents,
|
|
23
|
+
}: ToolArgs<typeof this.argsShape>): Promise<CallToolResult> {
|
|
24
|
+
const provider = await this.ensureConnected();
|
|
25
|
+
const result = await provider.insertMany(database, collection, documents);
|
|
26
|
+
|
|
27
|
+
return {
|
|
28
|
+
content: [
|
|
29
|
+
{
|
|
30
|
+
text: `Inserted \`${result.insertedCount}\` document(s) into collection "${collection}"`,
|
|
31
|
+
type: "text",
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
text: `Inserted IDs: ${Object.values(result.insertedIds).join(", ")}`,
|
|
35
|
+
type: "text",
|
|
36
|
+
},
|
|
37
|
+
],
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
|
|
3
|
+
import { DbOperationArgs, MongoDBToolBase } from "../mongodbTool.js";
|
|
4
|
+
import { ToolArgs, OperationType } from "../../tool.js";
|
|
5
|
+
|
|
6
|
+
export class DeleteManyTool extends MongoDBToolBase {
|
|
7
|
+
protected name = "delete-many";
|
|
8
|
+
protected description = "Removes all documents that match the filter from a MongoDB collection";
|
|
9
|
+
protected argsShape = {
|
|
10
|
+
...DbOperationArgs,
|
|
11
|
+
filter: z
|
|
12
|
+
.object({})
|
|
13
|
+
.passthrough()
|
|
14
|
+
.optional()
|
|
15
|
+
.describe(
|
|
16
|
+
"The query filter, specifying the deletion criteria. Matches the syntax of the filter argument of db.collection.deleteMany()"
|
|
17
|
+
),
|
|
18
|
+
};
|
|
19
|
+
protected operationType: OperationType = "delete";
|
|
20
|
+
|
|
21
|
+
protected async execute({
|
|
22
|
+
database,
|
|
23
|
+
collection,
|
|
24
|
+
filter,
|
|
25
|
+
}: ToolArgs<typeof this.argsShape>): Promise<CallToolResult> {
|
|
26
|
+
const provider = await this.ensureConnected();
|
|
27
|
+
const result = await provider.deleteMany(database, collection, filter);
|
|
28
|
+
|
|
29
|
+
return {
|
|
30
|
+
content: [
|
|
31
|
+
{
|
|
32
|
+
text: `Deleted \`${result.deletedCount}\` document(s) from collection "${collection}"`,
|
|
33
|
+
type: "text",
|
|
34
|
+
},
|
|
35
|
+
],
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
|
|
2
|
+
import { DbOperationArgs, MongoDBToolBase } from "../mongodbTool.js";
|
|
3
|
+
import { ToolArgs, OperationType } from "../../tool.js";
|
|
4
|
+
|
|
5
|
+
export class DropCollectionTool extends MongoDBToolBase {
|
|
6
|
+
protected name = "drop-collection";
|
|
7
|
+
protected description =
|
|
8
|
+
"Removes a collection or view from the database. The method also removes any indexes associated with the dropped collection.";
|
|
9
|
+
protected argsShape = {
|
|
10
|
+
...DbOperationArgs,
|
|
11
|
+
};
|
|
12
|
+
protected operationType: OperationType = "delete";
|
|
13
|
+
|
|
14
|
+
protected async execute({ database, collection }: ToolArgs<typeof this.argsShape>): Promise<CallToolResult> {
|
|
15
|
+
const provider = await this.ensureConnected();
|
|
16
|
+
const result = await provider.dropCollection(database, collection);
|
|
17
|
+
|
|
18
|
+
return {
|
|
19
|
+
content: [
|
|
20
|
+
{
|
|
21
|
+
text: `${result ? "Successfully dropped" : "Failed to drop"} collection "${collection}" from database "${database}"`,
|
|
22
|
+
type: "text",
|
|
23
|
+
},
|
|
24
|
+
],
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
|
|
2
|
+
import { DbOperationArgs, MongoDBToolBase } from "../mongodbTool.js";
|
|
3
|
+
import { ToolArgs, OperationType } from "../../tool.js";
|
|
4
|
+
|
|
5
|
+
export class DropDatabaseTool extends MongoDBToolBase {
|
|
6
|
+
protected name = "drop-database";
|
|
7
|
+
protected description = "Removes the specified database, deleting the associated data files";
|
|
8
|
+
protected argsShape = {
|
|
9
|
+
database: DbOperationArgs.database,
|
|
10
|
+
};
|
|
11
|
+
protected operationType: OperationType = "delete";
|
|
12
|
+
|
|
13
|
+
protected async execute({ database }: ToolArgs<typeof this.argsShape>): Promise<CallToolResult> {
|
|
14
|
+
const provider = await this.ensureConnected();
|
|
15
|
+
const result = await provider.dropDatabase(database);
|
|
16
|
+
|
|
17
|
+
return {
|
|
18
|
+
content: [
|
|
19
|
+
{
|
|
20
|
+
text: `${result.ok ? "Successfully dropped" : "Failed to drop"} database "${database}"`,
|
|
21
|
+
type: "text",
|
|
22
|
+
},
|
|
23
|
+
],
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
|
|
2
|
+
import { DbOperationArgs, MongoDBToolBase } from "../mongodbTool.js";
|
|
3
|
+
import { ToolArgs, OperationType } from "../../tool.js";
|
|
4
|
+
import { parseSchema, SchemaField } from "mongodb-schema";
|
|
5
|
+
|
|
6
|
+
export class CollectionSchemaTool extends MongoDBToolBase {
|
|
7
|
+
protected name = "collection-schema";
|
|
8
|
+
protected description = "Describe the schema for a collection";
|
|
9
|
+
protected argsShape = DbOperationArgs;
|
|
10
|
+
|
|
11
|
+
protected operationType: OperationType = "metadata";
|
|
12
|
+
|
|
13
|
+
protected async execute({ database, collection }: ToolArgs<typeof DbOperationArgs>): Promise<CallToolResult> {
|
|
14
|
+
const provider = await this.ensureConnected();
|
|
15
|
+
const documents = await provider.find(database, collection, {}, { limit: 5 }).toArray();
|
|
16
|
+
const schema = await parseSchema(documents);
|
|
17
|
+
|
|
18
|
+
return {
|
|
19
|
+
content: [
|
|
20
|
+
{
|
|
21
|
+
text: `Found ${schema.fields.length} fields in the schema for \`${database}.${collection}\``,
|
|
22
|
+
type: "text",
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
text: this.formatFieldOutput(schema.fields),
|
|
26
|
+
type: "text",
|
|
27
|
+
},
|
|
28
|
+
],
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
private formatFieldOutput(fields: SchemaField[]): string {
|
|
33
|
+
let result = "| Field | Type | Confidence |\n";
|
|
34
|
+
result += "|-------|------|-------------|\n";
|
|
35
|
+
for (const field of fields) {
|
|
36
|
+
const fieldType = Array.isArray(field.type) ? field.type.join(", ") : field.type;
|
|
37
|
+
result += `| ${field.name} | \`${fieldType}\` | ${(field.probability * 100).toFixed(0)}% |\n`;
|
|
38
|
+
}
|
|
39
|
+
return result;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
|
|
2
|
+
import { DbOperationArgs, MongoDBToolBase } from "../mongodbTool.js";
|
|
3
|
+
import { ToolArgs, OperationType } from "../../tool.js";
|
|
4
|
+
|
|
5
|
+
export class CollectionStorageSizeTool extends MongoDBToolBase {
|
|
6
|
+
protected name = "collection-storage-size";
|
|
7
|
+
protected description = "Gets the size of the collection in MB";
|
|
8
|
+
protected argsShape = DbOperationArgs;
|
|
9
|
+
|
|
10
|
+
protected operationType: OperationType = "metadata";
|
|
11
|
+
|
|
12
|
+
protected async execute({ database, collection }: ToolArgs<typeof DbOperationArgs>): Promise<CallToolResult> {
|
|
13
|
+
const provider = await this.ensureConnected();
|
|
14
|
+
const [{ value }] = (await provider
|
|
15
|
+
.aggregate(database, collection, [
|
|
16
|
+
{ $collStats: { storageStats: {} } },
|
|
17
|
+
{ $group: { _id: null, value: { $sum: "$storageStats.storageSize" } } },
|
|
18
|
+
])
|
|
19
|
+
.toArray()) as [{ value: number }];
|
|
20
|
+
|
|
21
|
+
return {
|
|
22
|
+
content: [
|
|
23
|
+
{
|
|
24
|
+
text: `The size of \`${database}.${collection}\` is \`${(value / 1024 / 1024).toFixed(2)} MB\``,
|
|
25
|
+
type: "text",
|
|
26
|
+
},
|
|
27
|
+
],
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
}
|