@@ -2,50 +2,28 @@ import { OperationType, TelemetryToolMetadata, ToolArgs, ToolBase, ToolCategory
22import { z } from "zod" ;
33import { CallToolResult } from "@modelcontextprotocol/sdk/types.js" ;
44import { EJSON } from "bson" ;
5-
6- const PLAYGROUND_SEARCH_URL = "https://search-playground.mongodb.com/api/tools/code-playground/search" ;
7-
8- const DEFAULT_DOCUMENTS = [
9- {
10- name : "First document" ,
11- } ,
12- {
13- name : "Second document" ,
14- } ,
15- ] ;
5+ import {
6+ PlaygroundRunError ,
7+ PlaygroundRunRequest ,
8+ PlaygroundRunResponse ,
9+ } from "../../common/playground/playgroundClient.js" ;
1610
1711const DEFAULT_SEARCH_INDEX_DEFINITION = {
1812 mappings : {
1913 dynamic : true ,
2014 } ,
2115} ;
2216
23- const DEFAULT_PIPELINE = [
24- {
25- $search : {
26- index : "default" ,
27- text : {
28- query : "first" ,
29- path : {
30- wildcard : "*" ,
31- } ,
32- } ,
33- } ,
34- } ,
35- ] ;
36-
3717const DEFAULT_SYNONYMS : Array < Record < string , unknown > > = [ ] ;
3818
3919export const RunPipelineOperationArgs = {
4020 documents : z
4121 . array ( z . record ( z . string ( ) , z . unknown ( ) ) )
4222 . max ( 500 )
43- . describe ( "Documents to run the pipeline against. 500 is maximum." )
44- . default ( DEFAULT_DOCUMENTS ) ,
23+ . describe ( "Documents to run the pipeline against. 500 is maximum." ) ,
4524 aggregationPipeline : z
4625 . array ( z . record ( z . string ( ) , z . unknown ( ) ) )
47- . describe ( "MongoDB aggregation pipeline to run on the provided documents." )
48- . default ( DEFAULT_PIPELINE ) ,
26+ . describe ( "MongoDB aggregation pipeline to run on the provided documents." ) ,
4927 searchIndexDefinition : z
5028 . record ( z . string ( ) , z . unknown ( ) )
5129 . describe ( "MongoDB search index definition to create before running the pipeline." )
@@ -58,22 +36,6 @@ export const RunPipelineOperationArgs = {
5836 . default ( DEFAULT_SYNONYMS ) ,
5937} ;
6038
61- interface RunRequest {
62- documents : string ;
63- aggregationPipeline : string ;
64- indexDefinition : string ;
65- synonyms : string ;
66- }
67-
68- interface RunResponse {
69- documents : Array < Record < string , unknown > > ;
70- }
71-
72- interface RunErrorResponse {
73- code : string ;
74- message : string ;
75- }
76-
7739export class RunPipeline extends ToolBase {
7840 protected name = "run-pipeline" ;
7941 protected description =
@@ -93,47 +55,24 @@ export class RunPipeline extends ToolBase {
9355 return { } ;
9456 }
9557
96- private async runPipeline ( runRequest : RunRequest ) : Promise < RunResponse > {
97- const options : RequestInit = {
98- method : "POST" ,
99- headers : {
100- "Content-Type" : "application/json" ,
101- } ,
102- body : JSON . stringify ( runRequest ) ,
103- } ;
104-
105- let response : Response ;
58+ private async runPipeline ( runRequest : PlaygroundRunRequest ) : Promise < PlaygroundRunResponse > {
59+ // import PlaygroundClient dynamically so we can mock it properly in the tests
60+ const { PlaygroundClient } = await import ( "../../common/playground/playgroundClient.js" ) ;
61+ const client = new PlaygroundClient ( ) ;
10662 try {
107- response = await fetch ( PLAYGROUND_SEARCH_URL , options ) ;
108- } catch {
109- throw new Error ( "Cannot run pipeline: network error." ) ;
110- }
63+ return await client . run ( runRequest ) ;
64+ } catch ( error : unknown ) {
65+ let message : string | undefined ;
11166
112- if ( ! response . ok ) {
113- const errorMessage = await this . getPlaygroundResponseError ( response ) ;
114- throw new Error ( `Pipeline run failed: ${ errorMessage } ` ) ;
115- }
67+ if ( error instanceof PlaygroundRunError ) {
68+ message = `Error code: ${ error . code } . Error message: ${ error . message } .` ;
69+ }
11670
117- try {
118- return ( await response . json ( ) ) as RunResponse ;
119- } catch {
120- throw new Error ( "Pipeline run failed: response is not valid JSON." ) ;
71+ throw new Error ( message || "Cannot run pipeline." ) ;
12172 }
12273 }
12374
124- private async getPlaygroundResponseError ( response : Response ) : Promise < string > {
125- let errorMessage = `HTTP ${ response . status } ${ response . statusText } .` ;
126- try {
127- const errorResponse = ( await response . json ( ) ) as RunErrorResponse ;
128- errorMessage += ` Error code: ${ errorResponse . code } . Error message: ${ errorResponse . message } ` ;
129- } catch {
130- // Ignore JSON parse errors
131- }
132-
133- return errorMessage ;
134- }
135-
136- private convertToRunRequest ( toolArgs : ToolArgs < typeof this . argsShape > ) : RunRequest {
75+ private convertToRunRequest ( toolArgs : ToolArgs < typeof this . argsShape > ) : PlaygroundRunRequest {
13776 try {
13877 return {
13978 documents : JSON . stringify ( toolArgs . documents ) ,
@@ -146,7 +85,7 @@ export class RunPipeline extends ToolBase {
14685 }
14786 }
14887
149- private convertToToolResult ( runResponse : RunResponse ) : CallToolResult {
88+ private convertToToolResult ( runResponse : PlaygroundRunResponse ) : CallToolResult {
15089 const content : Array < { text : string ; type : "text" } > = [
15190 {
15291 text : `Found ${ runResponse . documents . length } documents":` ,
0 commit comments