@@ -2,27 +2,33 @@ import fs from "fs/promises";
2
2
import { beforeEach , describe , expect , it } from "vitest" ;
3
3
import {
4
4
databaseCollectionParameters ,
5
- timeout ,
5
+ resourceChangedNotification ,
6
6
validateThrowsForInvalidArguments ,
7
7
validateToolMetadata ,
8
8
} from "../../../helpers.js" ;
9
9
import { describeWithMongoDB } from "../mongodbHelpers.js" ;
10
10
import { CallToolResult } from "@modelcontextprotocol/sdk/types.js" ;
11
11
import { Long } from "bson" ;
12
12
13
- function contentWithTextResourceURI ( content : CallToolResult [ "content" ] , namespace : string ) {
13
+ export function contentWithTextResourceURI (
14
+ content : CallToolResult [ "content" ]
15
+ ) : CallToolResult [ "content" ] [ number ] | undefined {
14
16
return content . find ( ( part ) => {
15
- return part . type === "text" && part . text . startsWith ( `Data for namespace ${ namespace } ` ) ;
17
+ return part . type === "text" && part . text . startsWith ( `Data for namespace` ) ;
16
18
} ) ;
17
19
}
18
20
19
- function contentWithResourceURILink ( content : CallToolResult [ "content" ] , namespace : string ) {
21
+ export function contentWithResourceURILink (
22
+ content : CallToolResult [ "content" ]
23
+ ) : CallToolResult [ "content" ] [ number ] | undefined {
20
24
return content . find ( ( part ) => {
21
- return part . type === "resource_link" && part . uri . startsWith ( `exported-data:// ${ namespace } ` ) ;
25
+ return part . type === "resource_link" ;
22
26
} ) ;
23
27
}
24
28
25
- function contentWithExportPath ( content : CallToolResult [ "content" ] ) {
29
+ export function contentWithExportPath (
30
+ content : CallToolResult [ "content" ]
31
+ ) : CallToolResult [ "content" ] [ number ] | undefined {
26
32
return content . find ( ( part ) => {
27
33
return (
28
34
part . type === "text" &&
@@ -89,20 +95,22 @@ describeWithMongoDB("export tool", (integration) => {
89
95
{ database : "test" , collection : "bar" , sort : [ ] , limit : 10 } ,
90
96
] ) ;
91
97
92
- it ( "when provided with incorrect namespace, export should have empty data" , async function ( ) {
98
+ beforeEach ( async ( ) => {
93
99
await integration . connectMcpClient ( ) ;
100
+ } ) ;
101
+
102
+ it ( "when provided with incorrect namespace, export should have empty data" , async function ( ) {
94
103
const response = await integration . mcpClient ( ) . callTool ( {
95
104
name : "export" ,
96
105
arguments : { database : "non-existent" , collection : "foos" } ,
97
106
} ) ;
98
- // Small timeout to let export finish
99
- await timeout ( 10 ) ;
100
-
101
107
const content = response . content as CallToolResult [ "content" ] ;
102
- const namespace = "non-existent.foos" ;
108
+ const exportURI = contentWithResourceURILink ( content ) ?. uri as string ;
109
+ await resourceChangedNotification ( integration . mcpClient ( ) , exportURI ) ;
110
+
103
111
expect ( content ) . toHaveLength ( 3 ) ;
104
- expect ( contentWithTextResourceURI ( content , namespace ) ) . toBeDefined ( ) ;
105
- expect ( contentWithResourceURILink ( content , namespace ) ) . toBeDefined ( ) ;
112
+ expect ( contentWithTextResourceURI ( content ) ) . toBeDefined ( ) ;
113
+ expect ( contentWithResourceURILink ( content ) ) . toBeDefined ( ) ;
106
114
107
115
const localPathPart = contentWithExportPath ( content ) ;
108
116
expect ( localPathPart ) . toBeDefined ( ) ;
@@ -131,10 +139,11 @@ describeWithMongoDB("export tool", (integration) => {
131
139
name : "export" ,
132
140
arguments : { database : integration . randomDbName ( ) , collection : "foo" } ,
133
141
} ) ;
134
- // Small timeout to let export finish
135
- await timeout ( 10 ) ;
142
+ const content = response . content as CallToolResult [ "content" ] ;
143
+ const exportURI = contentWithResourceURILink ( content ) ?. uri as string ;
144
+ await resourceChangedNotification ( integration . mcpClient ( ) , exportURI ) ;
136
145
137
- const localPathPart = contentWithExportPath ( response . content as CallToolResult [ "content" ] ) ;
146
+ const localPathPart = contentWithExportPath ( content ) ;
138
147
expect ( localPathPart ) . toBeDefined ( ) ;
139
148
const [ , localPath ] = / " ( .* ) " / . exec ( String ( localPathPart ?. text ) ) ?? [ ] ;
140
149
expect ( localPath ) . toBeDefined ( ) ;
@@ -154,10 +163,11 @@ describeWithMongoDB("export tool", (integration) => {
154
163
name : "export" ,
155
164
arguments : { database : integration . randomDbName ( ) , collection : "foo" , filter : { name : "foo" } } ,
156
165
} ) ;
157
- // Small timeout to let export finish
158
- await timeout ( 10 ) ;
166
+ const content = response . content as CallToolResult [ "content" ] ;
167
+ const exportURI = contentWithResourceURILink ( content ) ?. uri as string ;
168
+ await resourceChangedNotification ( integration . mcpClient ( ) , exportURI ) ;
159
169
160
- const localPathPart = contentWithExportPath ( response . content as CallToolResult [ "content" ] ) ;
170
+ const localPathPart = contentWithExportPath ( content ) ;
161
171
expect ( localPathPart ) . toBeDefined ( ) ;
162
172
const [ , localPath ] = / " ( .* ) " / . exec ( String ( localPathPart ?. text ) ) ?? [ ] ;
163
173
expect ( localPath ) . toBeDefined ( ) ;
@@ -176,10 +186,11 @@ describeWithMongoDB("export tool", (integration) => {
176
186
name : "export" ,
177
187
arguments : { database : integration . randomDbName ( ) , collection : "foo" , limit : 1 } ,
178
188
} ) ;
179
- // Small timeout to let export finish
180
- await timeout ( 10 ) ;
189
+ const content = response . content as CallToolResult [ "content" ] ;
190
+ const exportURI = contentWithResourceURILink ( content ) ?. uri as string ;
191
+ await resourceChangedNotification ( integration . mcpClient ( ) , exportURI ) ;
181
192
182
- const localPathPart = contentWithExportPath ( response . content as CallToolResult [ "content" ] ) ;
193
+ const localPathPart = contentWithExportPath ( content ) ;
183
194
expect ( localPathPart ) . toBeDefined ( ) ;
184
195
const [ , localPath ] = / " ( .* ) " / . exec ( String ( localPathPart ?. text ) ) ?? [ ] ;
185
196
expect ( localPath ) . toBeDefined ( ) ;
@@ -203,10 +214,11 @@ describeWithMongoDB("export tool", (integration) => {
203
214
sort : { longNumber : 1 } ,
204
215
} ,
205
216
} ) ;
206
- // Small timeout to let export finish
207
- await timeout ( 10 ) ;
217
+ const content = response . content as CallToolResult [ "content" ] ;
218
+ const exportURI = contentWithResourceURILink ( content ) ?. uri as string ;
219
+ await resourceChangedNotification ( integration . mcpClient ( ) , exportURI ) ;
208
220
209
- const localPathPart = contentWithExportPath ( response . content as CallToolResult [ "content" ] ) ;
221
+ const localPathPart = contentWithExportPath ( content ) ;
210
222
expect ( localPathPart ) . toBeDefined ( ) ;
211
223
const [ , localPath ] = / " ( .* ) " / . exec ( String ( localPathPart ?. text ) ) ?? [ ] ;
212
224
expect ( localPath ) . toBeDefined ( ) ;
@@ -230,10 +242,11 @@ describeWithMongoDB("export tool", (integration) => {
230
242
projection : { _id : 0 , name : 1 } ,
231
243
} ,
232
244
} ) ;
233
- // Small timeout to let export finish
234
- await timeout ( 10 ) ;
245
+ const content = response . content as CallToolResult [ "content" ] ;
246
+ const exportURI = contentWithResourceURILink ( content ) ?. uri as string ;
247
+ await resourceChangedNotification ( integration . mcpClient ( ) , exportURI ) ;
235
248
236
- const localPathPart = contentWithExportPath ( response . content as CallToolResult [ "content" ] ) ;
249
+ const localPathPart = contentWithExportPath ( content ) ;
237
250
expect ( localPathPart ) . toBeDefined ( ) ;
238
251
const [ , localPath ] = / " ( .* ) " / . exec ( String ( localPathPart ?. text ) ) ?? [ ] ;
239
252
expect ( localPath ) . toBeDefined ( ) ;
@@ -261,10 +274,11 @@ describeWithMongoDB("export tool", (integration) => {
261
274
jsonExportFormat : "relaxed" ,
262
275
} ,
263
276
} ) ;
264
- // Small timeout to let export finish
265
- await timeout ( 10 ) ;
277
+ const content = response . content as CallToolResult [ "content" ] ;
278
+ const exportURI = contentWithResourceURILink ( content ) ?. uri as string ;
279
+ await resourceChangedNotification ( integration . mcpClient ( ) , exportURI ) ;
266
280
267
- const localPathPart = contentWithExportPath ( response . content as CallToolResult [ "content" ] ) ;
281
+ const localPathPart = contentWithExportPath ( content ) ;
268
282
expect ( localPathPart ) . toBeDefined ( ) ;
269
283
const [ , localPath ] = / " ( .* ) " / . exec ( String ( localPathPart ?. text ) ) ?? [ ] ;
270
284
expect ( localPath ) . toBeDefined ( ) ;
@@ -293,10 +307,11 @@ describeWithMongoDB("export tool", (integration) => {
293
307
jsonExportFormat : "canonical" ,
294
308
} ,
295
309
} ) ;
296
- // Small timeout to let export finish
297
- await timeout ( 10 ) ;
310
+ const content = response . content as CallToolResult [ "content" ] ;
311
+ const exportURI = contentWithResourceURILink ( content ) ?. uri as string ;
312
+ await resourceChangedNotification ( integration . mcpClient ( ) , exportURI ) ;
298
313
299
- const localPathPart = contentWithExportPath ( response . content as CallToolResult [ "content" ] ) ;
314
+ const localPathPart = contentWithExportPath ( content ) ;
300
315
expect ( localPathPart ) . toBeDefined ( ) ;
301
316
const [ , localPath ] = / " ( .* ) " / . exec ( String ( localPathPart ?. text ) ) ?? [ ] ;
302
317
expect ( localPath ) . toBeDefined ( ) ;
0 commit comments