44 validateThrowsForInvalidArguments ,
55 getResponseContent ,
66 defaultTestConfig ,
7+ expectDefined ,
78} from "../../../helpers.js" ;
89import { beforeEach , describe , expect , it , vi , afterEach } from "vitest" ;
910import {
@@ -17,6 +18,7 @@ import * as constants from "../../../../../src/helpers/constants.js";
1718import { freshInsertDocuments } from "./find.test.js" ;
1819import { BSON } from "bson" ;
1920import { DOCUMENT_EMBEDDINGS } from "./vyai/embeddings.js" ;
21+ import type { ToolEvent } from "../../../../../src/telemetry/types.js" ;
2022
2123describeWithMongoDB ( "aggregate tool" , ( integration ) => {
2224 afterEach ( ( ) => {
@@ -151,6 +153,36 @@ describeWithMongoDB("aggregate tool", (integration) => {
151153 ) ;
152154 } ) ;
153155
156+ it ( "should emit tool event without auto-embedding usage metadata" , async ( ) => {
157+ const mockEmitEvents = vi . spyOn ( integration . mcpServer ( ) [ "telemetry" ] , "emitEvents" ) ;
158+ vi . spyOn ( integration . mcpServer ( ) [ "telemetry" ] , "isTelemetryEnabled" ) . mockReturnValue ( true ) ;
159+
160+ const mongoClient = integration . mongoClient ( ) ;
161+ await mongoClient
162+ . db ( integration . randomDbName ( ) )
163+ . collection ( "people" )
164+ . insertMany ( [
165+ { name : "Peter" , age : 5 } ,
166+ { name : "Laura" , age : 10 } ,
167+ { name : "Søren" , age : 15 } ,
168+ ] ) ;
169+
170+ await integration . connectMcpClient ( ) ;
171+ await integration . mcpClient ( ) . callTool ( {
172+ name : "aggregate" ,
173+ arguments : {
174+ database : integration . randomDbName ( ) ,
175+ collection : "people" ,
176+ pipeline : [ { $match : { age : { $gt : 8 } } } , { $sort : { name : - 1 } } ] ,
177+ } ,
178+ } ) ;
179+
180+ expect ( mockEmitEvents ) . toHaveBeenCalled ( ) ;
181+ const emittedEvent = mockEmitEvents . mock . lastCall ?. [ 0 ] [ 0 ] as ToolEvent ;
182+ expectDefined ( emittedEvent ) ;
183+ expect ( emittedEvent . properties . embeddingsGeneratedBy ) . toBeUndefined ( ) ;
184+ } ) ;
185+
154186 for ( const disabledOpType of [ "create" , "update" , "delete" ] as const ) {
155187 it ( `can not run $out stages when ${ disabledOpType } operation is disabled` , async ( ) => {
156188 await integration . connectMcpClient ( ) ;
@@ -393,6 +425,10 @@ describeWithMongoDB(
393425 await integration . mongoClient ( ) . db ( integration . randomDbName ( ) ) . collection ( "databases" ) . drop ( ) ;
394426 } ) ;
395427
428+ afterEach ( ( ) => {
429+ vi . clearAllMocks ( ) ;
430+ } ) ;
431+
396432 validateToolMetadata ( integration , "aggregate" , "Run an aggregation against a MongoDB collection" , "read" , [
397433 ...databaseCollectionParameters ,
398434 {
@@ -462,6 +498,50 @@ If the user requests additional filtering, include filters in \`$vectorSearch.fi
462498 ) ;
463499 } ) ;
464500
501+ it ( "should emit tool event with auto-embedding usage metadata" , async ( ) => {
502+ const mockEmitEvents = vi . spyOn ( integration . mcpServer ( ) [ "telemetry" ] , "emitEvents" ) ;
503+ vi . spyOn ( integration . mcpServer ( ) [ "telemetry" ] , "isTelemetryEnabled" ) . mockReturnValue ( true ) ;
504+
505+ await waitUntilSearchIsReady ( integration . mongoClient ( ) ) ;
506+ await createVectorSearchIndexAndWait ( integration . mongoClient ( ) , integration . randomDbName ( ) , "databases" , [
507+ {
508+ type : "vector" ,
509+ path : "description_embedding" ,
510+ numDimensions : 256 ,
511+ similarity : "cosine" ,
512+ quantization : "none" ,
513+ } ,
514+ ] ) ;
515+
516+ await integration . mcpClient ( ) . callTool ( {
517+ name : "aggregate" ,
518+ arguments : {
519+ database : integration . randomDbName ( ) ,
520+ collection : "databases" ,
521+ pipeline : [
522+ {
523+ $vectorSearch : {
524+ index : "default" ,
525+ path : "description_embedding" ,
526+ queryVector : "some data" ,
527+ numCandidates : 10 ,
528+ limit : 10 ,
529+ embeddingParameters : {
530+ model : "voyage-3-large" ,
531+ outputDimension : "256" ,
532+ } ,
533+ } ,
534+ } ,
535+ ] ,
536+ } ,
537+ } ) ;
538+
539+ expect ( mockEmitEvents ) . toHaveBeenCalled ( ) ;
540+ const emittedEvent = mockEmitEvents . mock . lastCall ?. [ 0 ] [ 0 ] as ToolEvent ;
541+ expectDefined ( emittedEvent ) ;
542+ expect ( emittedEvent . properties . embeddingsGeneratedBy ) . toBe ( "mcp" ) ;
543+ } ) ;
544+
465545 for ( const [ dataType , embedding ] of Object . entries ( DOCUMENT_EMBEDDINGS ) ) {
466546 for ( const similarity of [ "euclidean" , "cosine" , "dotProduct" ] ) {
467547 describe ( `querying with dataType ${ dataType } and similarity ${ similarity } ` , ( ) => {
0 commit comments