mongodb-mcp-server 0.0.4 → 0.0.5
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 +53 -4
- package/.github/workflows/prepare_release.yaml +4 -4
- package/README.md +2 -0
- package/dist/common/atlas/apiClient.js +30 -2
- package/dist/common/atlas/apiClient.js.map +1 -1
- package/dist/config.js +2 -7
- package/dist/config.js.map +1 -1
- package/dist/index.js +10 -4
- package/dist/index.js.map +1 -1
- package/dist/logger.js +52 -27
- package/dist/logger.js.map +1 -1
- package/dist/packageInfo.js +6 -0
- package/dist/packageInfo.js.map +1 -0
- package/dist/server.js +71 -8
- package/dist/server.js.map +1 -1
- package/dist/session.js +17 -12
- 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 +96 -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 +0 -1
- package/dist/tools/atlas/createAccessList.js.map +1 -1
- package/dist/tools/atlas/createDBUser.js +0 -1
- package/dist/tools/atlas/createDBUser.js.map +1 -1
- package/dist/tools/atlas/createFreeCluster.js +0 -1
- package/dist/tools/atlas/createFreeCluster.js.map +1 -1
- package/dist/tools/atlas/createProject.js +0 -1
- package/dist/tools/atlas/createProject.js.map +1 -1
- package/dist/tools/atlas/inspectAccessList.js +0 -1
- package/dist/tools/atlas/inspectAccessList.js.map +1 -1
- package/dist/tools/atlas/inspectCluster.js +0 -1
- package/dist/tools/atlas/inspectCluster.js.map +1 -1
- package/dist/tools/atlas/listClusters.js +0 -1
- package/dist/tools/atlas/listClusters.js.map +1 -1
- package/dist/tools/atlas/listDBUsers.js +0 -1
- package/dist/tools/atlas/listDBUsers.js.map +1 -1
- package/dist/tools/atlas/listOrgs.js +0 -1
- package/dist/tools/atlas/listOrgs.js.map +1 -1
- package/dist/tools/atlas/listProjects.js +10 -4
- package/dist/tools/atlas/listProjects.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 +5 -6
- 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 +10 -11
- package/dist/tools/mongodb/mongodbTool.js.map +1 -1
- package/dist/tools/mongodb/read/aggregate.js +3 -3
- 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/find.js +3 -2
- package/dist/tools/mongodb/read/find.js.map +1 -1
- package/dist/tools/mongodb/tools.js +2 -0
- 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 +5 -7
- package/dist/tools/mongodb/update/updateMany.js.map +1 -1
- package/dist/tools/tool.js +39 -10
- package/dist/tools/tool.js.map +1 -1
- package/eslint.config.js +29 -10
- package/global.d.ts +1 -0
- package/package.json +6 -2
- package/scripts/apply.ts +9 -7
- package/scripts/filter.ts +3 -2
- package/src/common/atlas/apiClient.ts +48 -7
- package/src/config.ts +4 -10
- package/src/index.ts +10 -6
- package/src/logger.ts +66 -28
- package/src/packageInfo.ts +6 -0
- package/src/server.ts +103 -9
- package/src/session.ts +34 -17
- package/src/telemetry/constants.ts +15 -0
- package/src/telemetry/eventCache.ts +62 -0
- package/src/telemetry/telemetry.ts +137 -0
- package/src/telemetry/types.ts +60 -0
- package/src/tools/atlas/atlasTool.ts +7 -5
- package/src/tools/atlas/createAccessList.ts +0 -2
- package/src/tools/atlas/createDBUser.ts +0 -2
- package/src/tools/atlas/createFreeCluster.ts +0 -2
- package/src/tools/atlas/createProject.ts +0 -1
- package/src/tools/atlas/inspectAccessList.ts +0 -2
- package/src/tools/atlas/inspectCluster.ts +0 -2
- package/src/tools/atlas/listClusters.ts +0 -2
- package/src/tools/atlas/listDBUsers.ts +0 -2
- package/src/tools/atlas/listOrgs.ts +0 -2
- package/src/tools/atlas/listProjects.ts +12 -4
- 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 +5 -6
- 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 +12 -15
- package/src/tools/mongodb/read/aggregate.ts +3 -3
- package/src/tools/mongodb/read/collectionIndexes.ts +29 -5
- package/src/tools/mongodb/read/find.ts +3 -2
- package/src/tools/mongodb/tools.ts +2 -0
- package/src/tools/mongodb/update/renameCollection.ts +33 -4
- package/src/tools/mongodb/update/updateMany.ts +5 -7
- package/src/tools/tool.ts +51 -15
- package/tests/integration/helpers.ts +84 -107
- package/tests/integration/inMemoryTransport.ts +3 -2
- package/tests/integration/server.test.ts +47 -21
- package/tests/integration/tools/atlas/accessLists.test.ts +13 -15
- package/tests/integration/tools/atlas/atlasHelpers.ts +3 -8
- package/tests/integration/tools/atlas/clusters.test.ts +12 -13
- 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 +33 -23
- 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 +165 -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/tsconfig.jest.json +2 -1
- package/tsconfig.json +1 -1
- package/tsconfig.lint.json +8 -0
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
import {
|
|
2
|
+
getResponseContent,
|
|
3
|
+
databaseCollectionParameters,
|
|
4
|
+
validateToolMetadata,
|
|
5
|
+
validateThrowsForInvalidArguments,
|
|
6
|
+
} from "../../../helpers.js";
|
|
7
|
+
import { describeWithMongoDB, validateAutoConnectBehavior } from "../mongodbHelpers.js";
|
|
8
|
+
|
|
9
|
+
describeWithMongoDB("renameCollection tool", (integration) => {
|
|
10
|
+
validateToolMetadata(integration, "rename-collection", "Renames a collection in a MongoDB database", [
|
|
11
|
+
...databaseCollectionParameters,
|
|
12
|
+
|
|
13
|
+
{
|
|
14
|
+
name: "newName",
|
|
15
|
+
description: "The new name for the collection",
|
|
16
|
+
type: "string",
|
|
17
|
+
required: true,
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
name: "dropTarget",
|
|
21
|
+
description: "If true, drops the target collection if it exists",
|
|
22
|
+
type: "boolean",
|
|
23
|
+
required: false,
|
|
24
|
+
},
|
|
25
|
+
]);
|
|
26
|
+
|
|
27
|
+
validateThrowsForInvalidArguments(integration, "rename-collection", [
|
|
28
|
+
{},
|
|
29
|
+
{ database: 123, collection: "bar" },
|
|
30
|
+
{ database: "test", collection: [], newName: "foo" },
|
|
31
|
+
{ database: "test", collection: "bar", newName: 10 },
|
|
32
|
+
{ database: "test", collection: "bar", newName: "foo", dropTarget: "true" },
|
|
33
|
+
{ database: "test", collection: "bar", newName: "foo", dropTarget: 1 },
|
|
34
|
+
]);
|
|
35
|
+
|
|
36
|
+
describe("with non-existing database", () => {
|
|
37
|
+
it("returns an error", async () => {
|
|
38
|
+
await integration.connectMcpClient();
|
|
39
|
+
const response = await integration.mcpClient().callTool({
|
|
40
|
+
name: "rename-collection",
|
|
41
|
+
arguments: { database: "non-existent", collection: "foos", newName: "bar" },
|
|
42
|
+
});
|
|
43
|
+
const content = getResponseContent(response.content);
|
|
44
|
+
expect(content).toEqual(`Cannot rename "non-existent.foos" because it doesn't exist.`);
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
describe("with non-existing collection", () => {
|
|
49
|
+
it("returns an error", async () => {
|
|
50
|
+
await integration.mongoClient().db(integration.randomDbName()).collection("bar").insertOne({});
|
|
51
|
+
|
|
52
|
+
await integration.connectMcpClient();
|
|
53
|
+
const response = await integration.mcpClient().callTool({
|
|
54
|
+
name: "rename-collection",
|
|
55
|
+
arguments: { database: integration.randomDbName(), collection: "non-existent", newName: "foo" },
|
|
56
|
+
});
|
|
57
|
+
const content = getResponseContent(response.content);
|
|
58
|
+
expect(content).toEqual(
|
|
59
|
+
`Cannot rename "${integration.randomDbName()}.non-existent" because it doesn't exist.`
|
|
60
|
+
);
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
describe("with existing collection", () => {
|
|
65
|
+
it("renames to non-existing collection", async () => {
|
|
66
|
+
await integration
|
|
67
|
+
.mongoClient()
|
|
68
|
+
.db(integration.randomDbName())
|
|
69
|
+
.collection("before")
|
|
70
|
+
.insertOne({ value: 42 });
|
|
71
|
+
|
|
72
|
+
await integration.connectMcpClient();
|
|
73
|
+
const response = await integration.mcpClient().callTool({
|
|
74
|
+
name: "rename-collection",
|
|
75
|
+
arguments: { database: integration.randomDbName(), collection: "before", newName: "after" },
|
|
76
|
+
});
|
|
77
|
+
const content = getResponseContent(response.content);
|
|
78
|
+
expect(content).toEqual(
|
|
79
|
+
`Collection "before" renamed to "after" in database "${integration.randomDbName()}".`
|
|
80
|
+
);
|
|
81
|
+
|
|
82
|
+
const docsInBefore = await integration
|
|
83
|
+
.mongoClient()
|
|
84
|
+
.db(integration.randomDbName())
|
|
85
|
+
.collection("before")
|
|
86
|
+
.find({})
|
|
87
|
+
.toArray();
|
|
88
|
+
expect(docsInBefore).toHaveLength(0);
|
|
89
|
+
|
|
90
|
+
const docsInAfter = await integration
|
|
91
|
+
.mongoClient()
|
|
92
|
+
.db(integration.randomDbName())
|
|
93
|
+
.collection("after")
|
|
94
|
+
.find({})
|
|
95
|
+
.toArray();
|
|
96
|
+
expect(docsInAfter).toHaveLength(1);
|
|
97
|
+
expect(docsInAfter[0].value).toEqual(42);
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
it("returns an error when renaming to an existing collection", async () => {
|
|
101
|
+
await integration
|
|
102
|
+
.mongoClient()
|
|
103
|
+
.db(integration.randomDbName())
|
|
104
|
+
.collection("before")
|
|
105
|
+
.insertOne({ value: 42 });
|
|
106
|
+
await integration.mongoClient().db(integration.randomDbName()).collection("after").insertOne({ value: 84 });
|
|
107
|
+
|
|
108
|
+
await integration.connectMcpClient();
|
|
109
|
+
const response = await integration.mcpClient().callTool({
|
|
110
|
+
name: "rename-collection",
|
|
111
|
+
arguments: { database: integration.randomDbName(), collection: "before", newName: "after" },
|
|
112
|
+
});
|
|
113
|
+
const content = getResponseContent(response.content);
|
|
114
|
+
expect(content).toEqual(
|
|
115
|
+
`Cannot rename "${integration.randomDbName()}.before" to "after" because the target collection already exists. If you want to overwrite it, set the "dropTarget" argument to true.`
|
|
116
|
+
);
|
|
117
|
+
|
|
118
|
+
// Ensure no data was lost
|
|
119
|
+
const docsInBefore = await integration
|
|
120
|
+
.mongoClient()
|
|
121
|
+
.db(integration.randomDbName())
|
|
122
|
+
.collection("before")
|
|
123
|
+
.find({})
|
|
124
|
+
.toArray();
|
|
125
|
+
expect(docsInBefore).toHaveLength(1);
|
|
126
|
+
expect(docsInBefore[0].value).toEqual(42);
|
|
127
|
+
|
|
128
|
+
const docsInAfter = await integration
|
|
129
|
+
.mongoClient()
|
|
130
|
+
.db(integration.randomDbName())
|
|
131
|
+
.collection("after")
|
|
132
|
+
.find({})
|
|
133
|
+
.toArray();
|
|
134
|
+
expect(docsInAfter).toHaveLength(1);
|
|
135
|
+
expect(docsInAfter[0].value).toEqual(84);
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
it("renames to existing collection with dropTarget", async () => {
|
|
139
|
+
await integration
|
|
140
|
+
.mongoClient()
|
|
141
|
+
.db(integration.randomDbName())
|
|
142
|
+
.collection("before")
|
|
143
|
+
.insertOne({ value: 42 });
|
|
144
|
+
await integration.mongoClient().db(integration.randomDbName()).collection("after").insertOne({ value: 84 });
|
|
145
|
+
|
|
146
|
+
await integration.connectMcpClient();
|
|
147
|
+
const response = await integration.mcpClient().callTool({
|
|
148
|
+
name: "rename-collection",
|
|
149
|
+
arguments: {
|
|
150
|
+
database: integration.randomDbName(),
|
|
151
|
+
collection: "before",
|
|
152
|
+
newName: "after",
|
|
153
|
+
dropTarget: true,
|
|
154
|
+
},
|
|
155
|
+
});
|
|
156
|
+
const content = getResponseContent(response.content);
|
|
157
|
+
expect(content).toEqual(
|
|
158
|
+
`Collection "before" renamed to "after" in database "${integration.randomDbName()}".`
|
|
159
|
+
);
|
|
160
|
+
|
|
161
|
+
// Ensure the data was moved
|
|
162
|
+
const docsInBefore = await integration
|
|
163
|
+
.mongoClient()
|
|
164
|
+
.db(integration.randomDbName())
|
|
165
|
+
.collection("before")
|
|
166
|
+
.find({})
|
|
167
|
+
.toArray();
|
|
168
|
+
expect(docsInBefore).toHaveLength(0);
|
|
169
|
+
|
|
170
|
+
const docsInAfter = await integration
|
|
171
|
+
.mongoClient()
|
|
172
|
+
.db(integration.randomDbName())
|
|
173
|
+
.collection("after")
|
|
174
|
+
.find({})
|
|
175
|
+
.toArray();
|
|
176
|
+
expect(docsInAfter).toHaveLength(1);
|
|
177
|
+
expect(docsInAfter[0].value).toEqual(42);
|
|
178
|
+
});
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
validateAutoConnectBehavior(
|
|
182
|
+
integration,
|
|
183
|
+
"rename-collection",
|
|
184
|
+
() => {
|
|
185
|
+
return {
|
|
186
|
+
args: { database: integration.randomDbName(), collection: "coll1", newName: "coll2" },
|
|
187
|
+
expectedResponse: `Collection "coll1" renamed to "coll2" in database "${integration.randomDbName()}".`,
|
|
188
|
+
};
|
|
189
|
+
},
|
|
190
|
+
async () => {
|
|
191
|
+
await integration.mongoClient().db(integration.randomDbName()).createCollection("coll1");
|
|
192
|
+
}
|
|
193
|
+
);
|
|
194
|
+
});
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
import {
|
|
2
|
+
databaseCollectionParameters,
|
|
3
|
+
validateToolMetadata,
|
|
4
|
+
validateThrowsForInvalidArguments,
|
|
5
|
+
getResponseContent,
|
|
6
|
+
} from "../../../helpers.js";
|
|
7
|
+
import { describeWithMongoDB, validateAutoConnectBehavior } from "../mongodbHelpers.js";
|
|
8
|
+
|
|
9
|
+
describeWithMongoDB("updateMany tool", (integration) => {
|
|
10
|
+
validateToolMetadata(
|
|
11
|
+
integration,
|
|
12
|
+
"update-many",
|
|
13
|
+
"Updates all documents that match the specified filter for a collection",
|
|
14
|
+
[
|
|
15
|
+
...databaseCollectionParameters,
|
|
16
|
+
|
|
17
|
+
{
|
|
18
|
+
name: "filter",
|
|
19
|
+
description:
|
|
20
|
+
"The selection criteria for the update, matching the syntax of the filter argument of db.collection.updateOne()",
|
|
21
|
+
type: "object",
|
|
22
|
+
required: false,
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
name: "update",
|
|
26
|
+
description:
|
|
27
|
+
"An update document describing the modifications to apply using update operator expressions",
|
|
28
|
+
type: "object",
|
|
29
|
+
required: true,
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
name: "upsert",
|
|
33
|
+
description: "Controls whether to insert a new document if no documents match the filter",
|
|
34
|
+
type: "boolean",
|
|
35
|
+
required: false,
|
|
36
|
+
},
|
|
37
|
+
]
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
validateThrowsForInvalidArguments(integration, "update-many", [
|
|
41
|
+
{},
|
|
42
|
+
{ database: 123, collection: "bar", update: {} },
|
|
43
|
+
{ database: [], collection: "bar", update: {} },
|
|
44
|
+
{ database: "test", collection: "bar", update: [] },
|
|
45
|
+
{ database: "test", collection: "bar", update: {}, filter: 123 },
|
|
46
|
+
{ database: "test", collection: "bar", update: {}, upsert: "true" },
|
|
47
|
+
{ database: "test", collection: "bar", update: {}, filter: {}, upsert: "true" },
|
|
48
|
+
{ database: "test", collection: "bar", update: {}, filter: "TRUEPREDICATE", upsert: false },
|
|
49
|
+
]);
|
|
50
|
+
|
|
51
|
+
describe("with non-existent database", () => {
|
|
52
|
+
it("doesn't update any documents", async () => {
|
|
53
|
+
await integration.connectMcpClient();
|
|
54
|
+
|
|
55
|
+
const response = await integration.mcpClient().callTool({
|
|
56
|
+
name: "update-many",
|
|
57
|
+
arguments: {
|
|
58
|
+
database: "non-existent-db",
|
|
59
|
+
collection: "coll1",
|
|
60
|
+
update: { $set: { name: "new-name" } },
|
|
61
|
+
},
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
const content = getResponseContent(response.content);
|
|
65
|
+
expect(content).toEqual("No documents matched the filter.");
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
describe("with non-existent collection", () => {
|
|
70
|
+
it("doesn't update any documents", async () => {
|
|
71
|
+
await integration
|
|
72
|
+
.mongoClient()
|
|
73
|
+
.db(integration.randomDbName())
|
|
74
|
+
.collection("coll1")
|
|
75
|
+
.insertOne({ name: "old-name" });
|
|
76
|
+
await integration.connectMcpClient();
|
|
77
|
+
|
|
78
|
+
const response = await integration.mcpClient().callTool({
|
|
79
|
+
name: "update-many",
|
|
80
|
+
arguments: {
|
|
81
|
+
database: integration.randomDbName(),
|
|
82
|
+
collection: "non-existent",
|
|
83
|
+
update: { $set: { name: "new-name" } },
|
|
84
|
+
},
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
const content = getResponseContent(response.content);
|
|
88
|
+
expect(content).toEqual("No documents matched the filter.");
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
describe("with existing collection", () => {
|
|
93
|
+
beforeEach(async () => {
|
|
94
|
+
await integration
|
|
95
|
+
.mongoClient()
|
|
96
|
+
.db(integration.randomDbName())
|
|
97
|
+
.collection("coll1")
|
|
98
|
+
.insertMany([
|
|
99
|
+
{ name: "old-name", value: 1 },
|
|
100
|
+
{ name: "old-name", value: 2 },
|
|
101
|
+
{ name: "old-name", value: 3 },
|
|
102
|
+
]);
|
|
103
|
+
});
|
|
104
|
+
it("updates all documents without filter", async () => {
|
|
105
|
+
await integration.connectMcpClient();
|
|
106
|
+
|
|
107
|
+
const response = await integration.mcpClient().callTool({
|
|
108
|
+
name: "update-many",
|
|
109
|
+
arguments: {
|
|
110
|
+
database: integration.randomDbName(),
|
|
111
|
+
collection: "coll1",
|
|
112
|
+
update: { $set: { name: "new-name" } },
|
|
113
|
+
},
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
const content = getResponseContent(response.content);
|
|
117
|
+
expect(content).toEqual("Matched 3 document(s). Modified 3 document(s).");
|
|
118
|
+
|
|
119
|
+
const docs = await integration
|
|
120
|
+
.mongoClient()
|
|
121
|
+
.db(integration.randomDbName())
|
|
122
|
+
.collection("coll1")
|
|
123
|
+
.find({})
|
|
124
|
+
.toArray();
|
|
125
|
+
|
|
126
|
+
expect(docs).toHaveLength(3);
|
|
127
|
+
for (const doc of docs) {
|
|
128
|
+
expect(doc.name).toEqual("new-name");
|
|
129
|
+
}
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
it("updates all documents that match the filter", async () => {
|
|
133
|
+
await integration.connectMcpClient();
|
|
134
|
+
|
|
135
|
+
const response = await integration.mcpClient().callTool({
|
|
136
|
+
name: "update-many",
|
|
137
|
+
arguments: {
|
|
138
|
+
database: integration.randomDbName(),
|
|
139
|
+
collection: "coll1",
|
|
140
|
+
update: { $set: { name: "new-name" } },
|
|
141
|
+
filter: { value: { $gt: 1 } },
|
|
142
|
+
},
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
const content = getResponseContent(response.content);
|
|
146
|
+
expect(content).toEqual("Matched 2 document(s). Modified 2 document(s).");
|
|
147
|
+
|
|
148
|
+
const docs = await integration
|
|
149
|
+
.mongoClient()
|
|
150
|
+
.db(integration.randomDbName())
|
|
151
|
+
.collection("coll1")
|
|
152
|
+
.find({})
|
|
153
|
+
.toArray();
|
|
154
|
+
expect(docs).toHaveLength(3);
|
|
155
|
+
for (const doc of docs) {
|
|
156
|
+
if (doc.value > 1) {
|
|
157
|
+
expect(doc.name).toEqual("new-name");
|
|
158
|
+
} else {
|
|
159
|
+
expect(doc.name).toEqual("old-name");
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
it("upserts a new document if no documents match the filter", async () => {
|
|
165
|
+
await integration.connectMcpClient();
|
|
166
|
+
|
|
167
|
+
const response = await integration.mcpClient().callTool({
|
|
168
|
+
name: "update-many",
|
|
169
|
+
arguments: {
|
|
170
|
+
database: integration.randomDbName(),
|
|
171
|
+
collection: "coll1",
|
|
172
|
+
update: { $set: { name: "new-name" } },
|
|
173
|
+
filter: { value: 4 },
|
|
174
|
+
upsert: true,
|
|
175
|
+
},
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
const content = getResponseContent(response.content);
|
|
179
|
+
expect(content).toContain("Matched 0 document(s). Upserted 1 document with id:");
|
|
180
|
+
|
|
181
|
+
const docs = await integration
|
|
182
|
+
.mongoClient()
|
|
183
|
+
.db(integration.randomDbName())
|
|
184
|
+
.collection("coll1")
|
|
185
|
+
.find({})
|
|
186
|
+
.toArray();
|
|
187
|
+
|
|
188
|
+
expect(docs).toHaveLength(4);
|
|
189
|
+
for (const doc of docs) {
|
|
190
|
+
if (doc.value === 4) {
|
|
191
|
+
expect(doc.name).toEqual("new-name");
|
|
192
|
+
} else {
|
|
193
|
+
expect(doc.name).toEqual("old-name");
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
it("doesn't upsert a new document if no documents match the filter and upsert is false", async () => {
|
|
199
|
+
await integration.connectMcpClient();
|
|
200
|
+
|
|
201
|
+
const response = await integration.mcpClient().callTool({
|
|
202
|
+
name: "update-many",
|
|
203
|
+
arguments: {
|
|
204
|
+
database: integration.randomDbName(),
|
|
205
|
+
collection: "coll1",
|
|
206
|
+
update: { $set: { name: "new-name" } },
|
|
207
|
+
filter: { value: 4 },
|
|
208
|
+
},
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
const content = getResponseContent(response.content);
|
|
212
|
+
expect(content).toContain("No documents matched the filter.");
|
|
213
|
+
|
|
214
|
+
const docs = await integration
|
|
215
|
+
.mongoClient()
|
|
216
|
+
.db(integration.randomDbName())
|
|
217
|
+
.collection("coll1")
|
|
218
|
+
.find({})
|
|
219
|
+
.toArray();
|
|
220
|
+
|
|
221
|
+
expect(docs).toHaveLength(3);
|
|
222
|
+
for (const doc of docs) {
|
|
223
|
+
expect(doc.name).toEqual("old-name");
|
|
224
|
+
}
|
|
225
|
+
});
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
validateAutoConnectBehavior(integration, "update-many", () => {
|
|
229
|
+
return {
|
|
230
|
+
args: {
|
|
231
|
+
database: integration.randomDbName(),
|
|
232
|
+
collection: "coll1",
|
|
233
|
+
update: { $set: { name: "new-name" } },
|
|
234
|
+
},
|
|
235
|
+
expectedResponse: "No documents matched the filter.",
|
|
236
|
+
};
|
|
237
|
+
});
|
|
238
|
+
});
|
package/tsconfig.jest.json
CHANGED
package/tsconfig.json
CHANGED