mcp-meilisearch 1.2.7 → 1.3.0

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/README.md CHANGED
@@ -6,6 +6,7 @@ A Model Context Protocol (MCP) server implementation that provides a bridge betw
6
6
 
7
7
  - **MCP Server**: Exposes Meilisearch APIs as tools using the Model Context Protocol.
8
8
  - **Web Client Demo**: A demo interface showcasing search functionalities.
9
+ - **AI Inference**: Intelligent tool selection based on user queries.
9
10
 
10
11
  ## Key Features
11
12
 
@@ -13,6 +14,7 @@ A Model Context Protocol (MCP) server implementation that provides a bridge betw
13
14
  - **Real-time Communication**: Enables seamless interaction between clients and the server.
14
15
  - **Meilisearch API Support**: Full access to Meilisearch functionalities.
15
16
  - **Web Client Demo**: Updated interface for demonstrating search capabilities.
17
+ - **AI Inference**: Uses OpenAI to intelligently select the most appropriate tool based on user queries.
16
18
 
17
19
  ## Getting Started
18
20
 
@@ -21,6 +23,7 @@ A Model Context Protocol (MCP) server implementation that provides a bridge betw
21
23
  - Node.js v20 or higher.
22
24
  - A running Meilisearch instance (local or remote).
23
25
  - API key for Meilisearch (if required).
26
+ - OpenAI API key (if using AI inference).
24
27
 
25
28
  ### Installation
26
29
 
@@ -55,20 +58,54 @@ pnpm add mcp-meilisearch
55
58
  - `sessionTimeout`: Session timeout in milliseconds (Default: 3600000)
56
59
  - `sessionCleanupInterval`: Session cleanup interval in milliseconds (Default: 60000)
57
60
 
61
+ #### AI Inference Options
62
+
63
+ - `openaiApiKey`: OpenAI API key for AI inference
64
+ - `llmModel`: AI model to use (Default: "gpt-3.5-turbo")
65
+
58
66
  ### Using the MCPClient
59
67
 
60
- The package also exports the MCPClient class for client-side integration:
68
+ The package exports the MCPClient class for client-side integration:
61
69
 
62
70
  ```typescript
63
71
  import { MCPClient } from "mcp-meilisearch/client";
64
72
 
65
73
  const client = new MCPClient("mcp-meilisearch-client");
74
+
66
75
  await client.connectToServer("http://localhost:4995/mcp");
67
76
 
68
- // Call a tool
69
77
  const result = await client.callTool("search-across-all-indexes", {
70
78
  q: "search kiosco antonio",
71
79
  });
80
+
81
+ // Use AI inference to choose the most appropriate tool
82
+ // First enable AI inference
83
+ client.setUseAI(true);
84
+
85
+ const result = await client.callToolWithAI("Find articles about cucumber");
86
+ console.log(`Tool used: ${result.toolUsed}`);
87
+ console.log(`Reasoning: ${result.reasoning}`);
88
+ console.log(`Results: ${JSON.stringify(result.data)}`);
89
+ ```
90
+
91
+ #### AI Inference Client Methods
92
+
93
+ - `setUseAI(use: boolean)`: Enable or disable AI inference.
94
+ - `callToolWithAI(query: string, specificTools?: string[])`: Process a user query with AI inference, optionally limiting to specific tools.
95
+
96
+ ### Starting the Server
97
+
98
+ You can start the server programmatically:
99
+
100
+ ```typescript
101
+ import mcpMeilisearchServer from "mcp-meilisearch";
102
+
103
+ await mcpMeilisearchServer({
104
+ meilisearchHost: "http://localhost:7700",
105
+ meilisearchApiKey: "your_api_key",
106
+ openaiApiKey: "your_openai_api_key", // Required for AI inference
107
+ llmModel: "gpt-4", // Optional, defaults to gpt-3.5-turbo
108
+ });
72
109
  ```
73
110
 
74
111
  ## Tools
package/dist/client.d.ts CHANGED
@@ -1,4 +1,9 @@
1
1
  export declare class MCPClient {
2
+ /**
3
+ * Flag to enable/disable AI inference
4
+ * When enabled, user queries are processed by an AI to determine which tool to use
5
+ */
6
+ useAI: boolean;
2
7
  /**
3
8
  * Indicates whether the client is connected to the MCP server
4
9
  * Used to track the connection state and control async operations
@@ -11,12 +16,18 @@ export declare class MCPClient {
11
16
  tools: {
12
17
  name: string;
13
18
  description: string;
19
+ parameters: Record<string, any>;
14
20
  }[];
15
21
  private client;
16
22
  private tries;
17
23
  private transport;
18
24
  private toolsUpdatedCallback;
19
25
  constructor(serverName: string);
26
+ /**
27
+ * Set whether to use AI inference for tool selection
28
+ * @param use Whether to use AI inference
29
+ */
30
+ setUseAI(use: boolean): void;
20
31
  /**
21
32
  * Registers a callback to be called when the list of available tools changes
22
33
  * @param callback The function to call when tools are updated
@@ -52,6 +63,19 @@ export declare class MCPClient {
52
63
  data?: any;
53
64
  error?: string;
54
65
  }>;
66
+ /**
67
+ * Process a user query through the AI to determine which tool to use
68
+ * @param query The user's query
69
+ * @param specificTools Optional array of specific tools to consider
70
+ * @returns The result of calling the selected tool, or an error
71
+ */
72
+ callToolWithAI(query: string, specificTools?: string[]): Promise<{
73
+ success: boolean;
74
+ data?: any;
75
+ error?: string;
76
+ toolUsed?: string;
77
+ reasoning?: string;
78
+ }>;
55
79
  private setUpTransport;
56
80
  /**
57
81
  * Closes the connection to the server and resets the connection state
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAQA,qBAAa,SAAS;IACpB;;;OAGG;IACH,WAAW,EAAE,OAAO,CAAS;IAE7B;;;OAGG;IACH,KAAK,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,EAAE,CAAM;IAEpD,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,KAAK,CAAa;IAC1B,OAAO,CAAC,SAAS,CAA8C;IAC/D,OAAO,CAAC,oBAAoB,CAEZ;gBAEJ,UAAU,EAAE,MAAM;IAI9B;;;OAGG;IACH,sBAAsB,CACpB,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,CAAC,KAAK,IAAI;IAKzE;;;;;OAKG;IACG,WAAW,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAOhE;;;;OAIG;IACG,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;YAsBzC,SAAS;IAuBvB,OAAO,CAAC,kBAAkB;IAW1B;;;;;;OAMG;IACG,QAAQ,CACZ,IAAI,EAAE,MAAM,EACZ,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GACzB,OAAO,CAAC;QACT,OAAO,EAAE,OAAO,CAAC;QACjB,IAAI,CAAC,EAAE,GAAG,CAAC;QACX,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,CAAC;IAwCF,OAAO,CAAC,cAAc;IAKtB;;;OAGG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;CAK/B"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAQA,qBAAa,SAAS;IACpB;;;OAGG;IACH,KAAK,EAAE,OAAO,CAAS;IAEvB;;;OAGG;IACH,WAAW,EAAE,OAAO,CAAS;IAE7B;;;OAGG;IACH,KAAK,EAAE;QACL,IAAI,EAAE,MAAM,CAAC;QACb,WAAW,EAAE,MAAM,CAAC;QACpB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;KACjC,EAAE,CAAM;IAET,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,KAAK,CAAa;IAC1B,OAAO,CAAC,SAAS,CAA8C;IAC/D,OAAO,CAAC,oBAAoB,CAEZ;gBAEJ,UAAU,EAAE,MAAM;IAI9B;;;OAGG;IACH,QAAQ,CAAC,GAAG,EAAE,OAAO,GAAG,IAAI;IAI5B;;;OAGG;IACH,sBAAsB,CACpB,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,CAAC,KAAK,IAAI;IAKzE;;;;;OAKG;IACG,WAAW,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAOhE;;;;OAIG;IACG,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;YAuBzC,SAAS;IAwBvB,OAAO,CAAC,kBAAkB;IAW1B;;;;;;OAMG;IACG,QAAQ,CACZ,IAAI,EAAE,MAAM,EACZ,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GACzB,OAAO,CAAC;QACT,OAAO,EAAE,OAAO,CAAC;QACjB,IAAI,CAAC,EAAE,GAAG,CAAC;QACX,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,CAAC;IA2CF;;;;;OAKG;IACG,cAAc,CAClB,KAAK,EAAE,MAAM,EACb,aAAa,CAAC,EAAE,MAAM,EAAE,GACvB,OAAO,CAAC;QACT,OAAO,EAAE,OAAO,CAAC;QACjB,IAAI,CAAC,EAAE,GAAG,CAAC;QACX,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,SAAS,CAAC,EAAE,MAAM,CAAC;KACpB,CAAC;IAmCF,OAAO,CAAC,cAAc;IAKtB;;;OAGG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;CAK/B"}
package/dist/client.js CHANGED
@@ -1,7 +1,12 @@
1
+ import { TextContentSchema, LoggingMessageNotificationSchema, ToolListChangedNotificationSchema, } from "@modelcontextprotocol/sdk/types.js";
1
2
  import { Client } from "@modelcontextprotocol/sdk/client/index.js";
2
3
  import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
3
- import { TextContentSchema, LoggingMessageNotificationSchema, ToolListChangedNotificationSchema, } from "@modelcontextprotocol/sdk/types.js";
4
4
  export class MCPClient {
5
+ /**
6
+ * Flag to enable/disable AI inference
7
+ * When enabled, user queries are processed by an AI to determine which tool to use
8
+ */
9
+ useAI = false;
5
10
  /**
6
11
  * Indicates whether the client is connected to the MCP server
7
12
  * Used to track the connection state and control async operations
@@ -19,6 +24,13 @@ export class MCPClient {
19
24
  constructor(serverName) {
20
25
  this.client = new Client({ name: serverName, version: "1.0.0" });
21
26
  }
27
+ /**
28
+ * Set whether to use AI inference for tool selection
29
+ * @param use Whether to use AI inference
30
+ */
31
+ setUseAI(use) {
32
+ this.useAI = use;
33
+ }
22
34
  /**
23
35
  * Registers a callback to be called when the list of available tools changes
24
36
  * @param callback The function to call when tools are updated
@@ -73,6 +85,7 @@ export class MCPClient {
73
85
  this.tools = toolsResult.tools.map((tool) => ({
74
86
  name: tool.name,
75
87
  description: tool.description ?? "",
88
+ parameters: tool.parameters || {},
76
89
  }));
77
90
  }
78
91
  else {
@@ -109,7 +122,10 @@ export class MCPClient {
109
122
  };
110
123
  }
111
124
  if (result.isError) {
112
- throw new Error("MCP Server error");
125
+ return {
126
+ success: false,
127
+ error: JSON.stringify(result.content),
128
+ };
113
129
  }
114
130
  const content = result.content;
115
131
  if (!content?.length) {
@@ -134,6 +150,42 @@ export class MCPClient {
134
150
  return { success: false, error: errorMessage };
135
151
  }
136
152
  }
153
+ /**
154
+ * Process a user query through the AI to determine which tool to use
155
+ * @param query The user's query
156
+ * @param specificTools Optional array of specific tools to consider
157
+ * @returns The result of calling the selected tool, or an error
158
+ */
159
+ async callToolWithAI(query, specificTools) {
160
+ try {
161
+ const result = await this.callTool("process-ai-query", {
162
+ query,
163
+ specificTools,
164
+ });
165
+ if (!result.success)
166
+ return result;
167
+ const { toolName, parameters, reasoning } = result.data;
168
+ if (!toolName) {
169
+ return {
170
+ success: false,
171
+ error: "AI could not determine which tool to use for this query",
172
+ };
173
+ }
174
+ const toolResult = await this.callTool(toolName, parameters);
175
+ return {
176
+ ...toolResult,
177
+ reasoning,
178
+ toolUsed: toolName,
179
+ };
180
+ }
181
+ catch (error) {
182
+ const errorMessage = error instanceof Error ? error.message : String(error);
183
+ return {
184
+ success: false,
185
+ error: `AI inference error: ${errorMessage}`,
186
+ };
187
+ }
188
+ }
137
189
  setUpTransport() {
138
190
  if (this.transport == null)
139
191
  return;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAG7B,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAKnD;;;;GAIG;AACH,wBAAsB,oBAAoB,CACxC,OAAO,GAAE,aAGR,GACA,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CA8GtB;AAkCD,eAAe,oBAAoB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAI7B,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAKnD;;;;GAIG;AACH,wBAAsB,oBAAoB,CACxC,OAAO,GAAE,aAGR,GACA,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAwHtB;AAwCD,eAAe,oBAAoB,CAAC"}
package/dist/index.js CHANGED
@@ -1,5 +1,6 @@
1
1
  import { createServer } from "node:http";
2
2
  import { parse as parseUrl } from "node:url";
3
+ import { AIService } from "./utils/ai-handler.js";
3
4
  import { initServer } from "./server.js";
4
5
  import { configHandler } from "./utils/config-handler.js";
5
6
  import { createErrorResponse } from "./utils/error-handler.js";
@@ -9,11 +10,21 @@ import { createErrorResponse } from "./utils/error-handler.js";
9
10
  * @returns A promise that resolves to the HTTP server instance
10
11
  */
11
12
  export async function mcpMeilisearchServer(options = {
12
- meilisearchApiKey: "",
13
13
  meilisearchHost: "http://localhost:7700",
14
+ meilisearchApiKey: "",
14
15
  }) {
16
+ configHandler.setLlmModel(options.llmModel);
17
+ configHandler.setOpenaiApiKey(options.openaiApiKey);
15
18
  configHandler.setMeilisearchHost(options.meilisearchHost);
16
19
  configHandler.setMeilisearchApiKey(options.meilisearchApiKey);
20
+ const aiService = AIService.getInstance();
21
+ const apiKey = configHandler.getOpenaiApiKey();
22
+ if (apiKey) {
23
+ aiService.initialize(apiKey);
24
+ }
25
+ else {
26
+ console.warn("OpenAI API key not found. AI will not be available");
27
+ }
17
28
  const httpPort = options.httpPort || 4995;
18
29
  const transport = options.transport || "http";
19
30
  let mcpServerInstance = null;
@@ -80,7 +91,6 @@ export async function mcpMeilisearchServer(options = {
80
91
  try {
81
92
  const serverInstances = await initServer(transport, options);
82
93
  mcpServerInstance = serverInstances.mcpServer;
83
- console.log("MCP server initialized successfully");
84
94
  }
85
95
  catch (error) {
86
96
  console.error("Failed to initialize MCP server:", error);
@@ -125,6 +135,12 @@ if (import.meta.url === `file://${process.argv?.[1]}`) {
125
135
  case "apiKey":
126
136
  options.meilisearchApiKey = value;
127
137
  break;
138
+ case "openaiApiKey":
139
+ options.openaiApiKey = value;
140
+ break;
141
+ case "llmModel":
142
+ options.llmModel = value;
143
+ break;
128
144
  }
129
145
  }
130
146
  mcpMeilisearchServer(options)
@@ -0,0 +1,3 @@
1
+ declare const _default: "\n\t\tAnswer the user's request using the relevant tool(s), if they are available. Check that all the required parameters for each tool call are provided or can reasonably be inferred from context. IF there are no relevant tools or there are missing values for required parameters, ask the user to supply these values; otherwise proceed with the tool calls. If the user provides a specific value for a parameter (for example provided in quotes), make sure to use that value EXACTLY. DO NOT make up values for or ask about optional parameters. Carefully analyze descriptive terms in the request as they may indicate required parameter values that should be included even if not explicitly quoted.\n\n\t\t<identity>\n\t\tYou are an AI programming assistant.\n\t\tWhen asked for your name, you must respond with \"Pati\".\n\t\tFollow the user's requirements carefully & to the letter.\n\t\tIf you are asked to generate content that is harmful, hateful, racist, sexist, lewd, violent, or completely irrelevant to software engineering, only respond with \"Sorry, I can't assist with that.\"\n\t\tKeep your answers short and impersonal.\n\t\t</identity>\n\n\t\t<instructions>\n\t\tYou are a highly sophisticated automated coding agent with expert-level knowledge across many different programming languages and frameworks.\n\t\tThe user will ask a question, or ask you to perform a task, and it may require lots of research to answer correctly. There is a selection of tools that let you perform actions or retrieve helpful context to answer the user's question.\n\t\tIf you can infer the project type (languages, frameworks, and libraries) from the user's query or the context that you have, make sure to keep them in mind when making changes.\n\t\tIf the user wants you to implement a feature and they have not specified the files to edit, first break down the user's request into smaller concepts and think about the kinds of files you need to grasp each concept.\n\t\tIf you aren't sure which tool is relevant, you can call multiple tools. You can call tools repeatedly to take actions or gather as much context as needed until you have completed the task fully. Don't give up unless you are sure the request cannot be fulfilled with the tools you have. It's YOUR RESPONSIBILITY to make sure that you have done all you can to collect necessary context.\n\t\tPrefer using the semantic_search tool to search for context unless you know the exact string or filename pattern you're searching for.\n\t\tDon't make assumptions about the situation- gather context first, then perform the task or answer the question.\n\t\tThink creatively and explore the workspace in order to make a complete fix.\n\t\tDon't repeat yourself after a tool call, pick up where you left off.\n\t\tNEVER print out a codeblock with file changes unless the user asked for it. Use the insert_edit_into_file tool instead.\n\t\tNEVER print out a codeblock with a terminal command to run unless the user asked for it. Use the run_in_terminal tool instead.\n\t\tYou don't need to read a file if it's already provided in context.\n\t\t</instructions>\n\n\t\t<toolUseInstructions>\n\t\tWhen using a tool, follow the json schema very carefully and make sure to include ALL required properties.\n\t\tAlways output valid JSON when using a tool.\n\t\tIf a tool exists to do a task, use the tool instead of asking the user to manually take an action.\n\t\tIf you say that you will take an action, then go ahead and use the tool to do it. No need to ask permission.\n\t\tNever use multi_tool_use.parallel or any tool that does not exist. Use tools using the proper procedure, DO NOT write out a json codeblock with the tool inputs.\n\t\tNever say the name of a tool to a user. For example, instead of saying that you'll use the run_in_terminal tool, say \"I'll run the command in a terminal\".\n\t\tIf you think running multiple tools can answer the user's question, prefer calling them in parallel whenever possible, but do not call semantic_search in parallel.\n\t\tIf semantic_search returns the full contents of the text files in the workspace, you have all the workspace context.\n\t\tDon't call the run_in_terminal tool multiple times in parallel. Instead, run one command and wait for the output before running the next command.\n\t\tAfter you have performed the user's task, if the user corrected something you did, expressed a coding preference, or communicated a fact that you need to remember, use the update_user_preferences tool to save their preferences.\n\t\t</toolUseInstructions>\n\n\t\t<editFileInstructions>\n\t\tDon't try to edit an existing file without reading it first, so you can make changes properly.\n\t\tUse the insert_edit_into_file tool to edit files. When editing files, group your changes by file.\n\t\tNEVER show the changes to the user, just call the tool, and the edits will be applied and shown to the user.\n\t\tNEVER print a codeblock that represents a change to a file, use insert_edit_into_file instead.\n\t\tFor each file, give a short description of what needs to be changed, then use the insert_edit_into_file tool. You can use any tool multiple times in a response, and you can keep writing text after using a tool.\n\t\tFollow best practices when editing files. If a popular external library exists to solve a problem, use it and properly install the package e.g. with \"npm install\" or creating a \"requirements.txt\".\n\t\tAfter editing a file, you MUST call get_errors to validate the change. Fix the errors if they are relevant to your change or the prompt, and remember to validate that they were actually fixed.\n\t\tThe insert_edit_into_file tool is very smart and can understand how to apply your edits to the user's files, you just need to provide minimal hints.\n\t\tWhen you use the insert_edit_into_file tool, avoid repeating existing code, instead use comments to represent regions of unchanged code. The tool prefers that you are as concise as possible. For example:\n\t\t// ...existing code...\n\t\tchanged code\n\t\t// ...existing code...\n\t\tchanged code\n\t\t// ...existing code...\n\n\t\tHere is an example of how you should format an edit to an existing Person class:\n\t\tclass Person {\n\t\t\t// ...existing code...\n\t\t\tage: number;\n\t\t\t// ...existing code...\n\t\t\tgetAge() {\n\t\t\t\treturn this.age;\n\t\t\t}\n\t\t}\n\t\t</editFileInstructions>\n\n\t\t<functions>\n\t\tMCP_TOOLS\n\t\t</functions>\n\n\t\t<context>\n\t\tMy current OS is: Linux\n\t\tI am working in a workspace that has the following structure:\n\t\t```\n\t\texample.txt\n\t\traw_complete_instructions.txt\n\t\traw_instructions.txt\n\t\t```\n\t\tThis view of the workspace structure may be truncated. You can use tools to collect more context if needed.\n\t\t</context>\n\n\t\t<reminder>\n\t\tWhen using the insert_edit_into_file tool, avoid repeating existing code, instead use a line comment with `...existing code...` to represent regions of unchanged code.\n\t\t</reminder>\n\n\t\t<tool_format>\n\t\t<function_calls>\n\t\t<invoke name=\"[tool_name]\">\n\t\t<parameter name=\"[param_name]\">[param_value]\n\t\t";
2
+ export default _default;
3
+ //# sourceMappingURL=general.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"general.d.ts","sourceRoot":"","sources":["../../src/prompts/general.ts"],"names":[],"mappings":";AAAA,wBAyFI"}
@@ -0,0 +1,90 @@
1
+ export default `
2
+ Answer the user's request using the relevant tool(s), if they are available. Check that all the required parameters for each tool call are provided or can reasonably be inferred from context. IF there are no relevant tools or there are missing values for required parameters, ask the user to supply these values; otherwise proceed with the tool calls. If the user provides a specific value for a parameter (for example provided in quotes), make sure to use that value EXACTLY. DO NOT make up values for or ask about optional parameters. Carefully analyze descriptive terms in the request as they may indicate required parameter values that should be included even if not explicitly quoted.
3
+
4
+ <identity>
5
+ You are an AI programming assistant.
6
+ When asked for your name, you must respond with "Pati".
7
+ Follow the user's requirements carefully & to the letter.
8
+ If you are asked to generate content that is harmful, hateful, racist, sexist, lewd, violent, or completely irrelevant to software engineering, only respond with "Sorry, I can't assist with that."
9
+ Keep your answers short and impersonal.
10
+ </identity>
11
+
12
+ <instructions>
13
+ You are a highly sophisticated automated coding agent with expert-level knowledge across many different programming languages and frameworks.
14
+ The user will ask a question, or ask you to perform a task, and it may require lots of research to answer correctly. There is a selection of tools that let you perform actions or retrieve helpful context to answer the user's question.
15
+ If you can infer the project type (languages, frameworks, and libraries) from the user's query or the context that you have, make sure to keep them in mind when making changes.
16
+ If the user wants you to implement a feature and they have not specified the files to edit, first break down the user's request into smaller concepts and think about the kinds of files you need to grasp each concept.
17
+ If you aren't sure which tool is relevant, you can call multiple tools. You can call tools repeatedly to take actions or gather as much context as needed until you have completed the task fully. Don't give up unless you are sure the request cannot be fulfilled with the tools you have. It's YOUR RESPONSIBILITY to make sure that you have done all you can to collect necessary context.
18
+ Prefer using the semantic_search tool to search for context unless you know the exact string or filename pattern you're searching for.
19
+ Don't make assumptions about the situation- gather context first, then perform the task or answer the question.
20
+ Think creatively and explore the workspace in order to make a complete fix.
21
+ Don't repeat yourself after a tool call, pick up where you left off.
22
+ NEVER print out a codeblock with file changes unless the user asked for it. Use the insert_edit_into_file tool instead.
23
+ NEVER print out a codeblock with a terminal command to run unless the user asked for it. Use the run_in_terminal tool instead.
24
+ You don't need to read a file if it's already provided in context.
25
+ </instructions>
26
+
27
+ <toolUseInstructions>
28
+ When using a tool, follow the json schema very carefully and make sure to include ALL required properties.
29
+ Always output valid JSON when using a tool.
30
+ If a tool exists to do a task, use the tool instead of asking the user to manually take an action.
31
+ If you say that you will take an action, then go ahead and use the tool to do it. No need to ask permission.
32
+ Never use multi_tool_use.parallel or any tool that does not exist. Use tools using the proper procedure, DO NOT write out a json codeblock with the tool inputs.
33
+ Never say the name of a tool to a user. For example, instead of saying that you'll use the run_in_terminal tool, say "I'll run the command in a terminal".
34
+ If you think running multiple tools can answer the user's question, prefer calling them in parallel whenever possible, but do not call semantic_search in parallel.
35
+ If semantic_search returns the full contents of the text files in the workspace, you have all the workspace context.
36
+ Don't call the run_in_terminal tool multiple times in parallel. Instead, run one command and wait for the output before running the next command.
37
+ After you have performed the user's task, if the user corrected something you did, expressed a coding preference, or communicated a fact that you need to remember, use the update_user_preferences tool to save their preferences.
38
+ </toolUseInstructions>
39
+
40
+ <editFileInstructions>
41
+ Don't try to edit an existing file without reading it first, so you can make changes properly.
42
+ Use the insert_edit_into_file tool to edit files. When editing files, group your changes by file.
43
+ NEVER show the changes to the user, just call the tool, and the edits will be applied and shown to the user.
44
+ NEVER print a codeblock that represents a change to a file, use insert_edit_into_file instead.
45
+ For each file, give a short description of what needs to be changed, then use the insert_edit_into_file tool. You can use any tool multiple times in a response, and you can keep writing text after using a tool.
46
+ Follow best practices when editing files. If a popular external library exists to solve a problem, use it and properly install the package e.g. with "npm install" or creating a "requirements.txt".
47
+ After editing a file, you MUST call get_errors to validate the change. Fix the errors if they are relevant to your change or the prompt, and remember to validate that they were actually fixed.
48
+ The insert_edit_into_file tool is very smart and can understand how to apply your edits to the user's files, you just need to provide minimal hints.
49
+ When you use the insert_edit_into_file tool, avoid repeating existing code, instead use comments to represent regions of unchanged code. The tool prefers that you are as concise as possible. For example:
50
+ // ...existing code...
51
+ changed code
52
+ // ...existing code...
53
+ changed code
54
+ // ...existing code...
55
+
56
+ Here is an example of how you should format an edit to an existing Person class:
57
+ class Person {
58
+ // ...existing code...
59
+ age: number;
60
+ // ...existing code...
61
+ getAge() {
62
+ return this.age;
63
+ }
64
+ }
65
+ </editFileInstructions>
66
+
67
+ <functions>
68
+ MCP_TOOLS
69
+ </functions>
70
+
71
+ <context>
72
+ My current OS is: Linux
73
+ I am working in a workspace that has the following structure:
74
+ \`\`\`
75
+ example.txt
76
+ raw_complete_instructions.txt
77
+ raw_instructions.txt
78
+ \`\`\`
79
+ This view of the workspace structure may be truncated. You can use tools to collect more context if needed.
80
+ </context>
81
+
82
+ <reminder>
83
+ When using the insert_edit_into_file tool, avoid repeating existing code, instead use a line comment with \`...existing code...\` to represent regions of unchanged code.
84
+ </reminder>
85
+
86
+ <tool_format>
87
+ <function_calls>
88
+ <invoke name="[tool_name]">
89
+ <parameter name="[param_name]">[param_value]
90
+ `;
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,MAAM,CAAC;AAevD,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAIpE;;GAEG;AACH,UAAU,YAAY;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;IACvB,sBAAsB,EAAE,MAAM,CAAC;CAChC;AAED;;GAEG;AACH,UAAU,cAAc;IACtB,SAAS,EAAE,SAAS,CAAC;CACtB;AAiBD;;GAEG;AACH,qBAAa,SAAS;IACpB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAAoB;IAE3D,OAAO,CAAC,MAAM,CAAY;IAC1B,OAAO,CAAC,MAAM,CAAe;IAC7B,OAAO,CAAC,eAAe,CAA+B;IACtD,OAAO,CAAC,QAAQ,CAAuC;IAEvD;;;;OAIG;gBACS,MAAM,EAAE,SAAS,EAAE,MAAM,GAAE,OAAO,CAAC,YAAY,CAAM;IAOjE;;;;OAIG;IACG,gBAAgB,CACpB,GAAG,EAAE,eAAe,EACpB,GAAG,EAAE,cAAc,GAClB,OAAO,CAAC,IAAI,CAAC;IA+BhB;;;;;OAKG;IACG,iBAAiB,CACrB,GAAG,EAAE,eAAe,EACpB,GAAG,EAAE,cAAc,EACnB,IAAI,EAAE,GAAG,GACR,OAAO,CAAC,IAAI,CAAC;IA+BhB;;OAEG;IACH,QAAQ,IAAI,IAAI;IAqBhB;;;;;OAKG;YACW,uBAAuB;IAwCrC;;OAEG;IACH,OAAO,CAAC,+BAA+B;IAWvC;;OAEG;YACW,gBAAgB;IAmB9B;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAa3B;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAKxB;;OAEG;IACH,OAAO,CAAC,qBAAqB;IAO7B;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAUzB;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAM3B;;OAEG;IACH,OAAO,CAAC,sBAAsB;CA0B/B;AAsED;;;;;GAKG;AACH,eAAO,MAAM,UAAU,GACrB,WAAW,OAAO,GAAG,MAAM,EAC3B,SAAS,OAAO,CAAC,YAAY,CAAC,KAC7B,OAAO,CAAC,cAAc,CAcxB,CAAC"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,MAAM,CAAC;AAgBvD,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAIpE;;GAEG;AACH,UAAU,YAAY;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;IACvB,sBAAsB,EAAE,MAAM,CAAC;CAChC;AAED;;GAEG;AACH,UAAU,cAAc;IACtB,SAAS,EAAE,SAAS,CAAC;CACtB;AAiBD;;GAEG;AACH,qBAAa,SAAS;IACpB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAAoB;IAE3D,OAAO,CAAC,MAAM,CAAY;IAC1B,OAAO,CAAC,MAAM,CAAe;IAC7B,OAAO,CAAC,eAAe,CAA+B;IACtD,OAAO,CAAC,QAAQ,CAAuC;IAEvD;;;;OAIG;gBACS,MAAM,EAAE,SAAS,EAAE,MAAM,GAAE,OAAO,CAAC,YAAY,CAAM;IAOjE;;;;OAIG;IACG,gBAAgB,CACpB,GAAG,EAAE,eAAe,EACpB,GAAG,EAAE,cAAc,GAClB,OAAO,CAAC,IAAI,CAAC;IA+BhB;;;;;OAKG;IACG,iBAAiB,CACrB,GAAG,EAAE,eAAe,EACpB,GAAG,EAAE,cAAc,EACnB,IAAI,EAAE,GAAG,GACR,OAAO,CAAC,IAAI,CAAC;IA+BhB;;OAEG;IACH,QAAQ,IAAI,IAAI;IAqBhB;;;;;OAKG;YACW,uBAAuB;IAuCrC;;OAEG;IACH,OAAO,CAAC,+BAA+B;IAWvC;;OAEG;YACW,gBAAgB;IAmB9B;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAa3B;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAKxB;;OAEG;IACH,OAAO,CAAC,qBAAqB;IAO7B;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAUzB;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAM3B;;OAEG;IACH,OAAO,CAAC,sBAAsB;CA0B/B;AAwED;;;;;GAKG;AACH,eAAO,MAAM,UAAU,GACrB,WAAW,OAAO,GAAG,MAAM,EAC3B,SAAS,OAAO,CAAC,YAAY,CAAC,KAC7B,OAAO,CAAC,cAAc,CAcxB,CAAC"}
package/dist/server.js CHANGED
@@ -1,5 +1,6 @@
1
1
  import { randomUUID } from "node:crypto";
2
2
  import { InitializeRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
3
+ import registerAITools from "./tools/ai-tools.js";
3
4
  import registerTaskTools from "./tools/task-tools.js";
4
5
  import registerIndexTools from "./tools/index-tools.js";
5
6
  import registerSearchTools from "./tools/search-tools.js";
@@ -122,7 +123,6 @@ export class MCPServer {
122
123
  * @param body The request body
123
124
  */
124
125
  async handleInitializeRequest(req, res, body) {
125
- console.log("Handling initialize request");
126
126
  const newSessionId = randomUUID();
127
127
  const transport = new StreamableHTTPServerTransport({
128
128
  sessionIdGenerator: () => newSessionId,
@@ -264,6 +264,7 @@ const initServerHTTPTransport = async (customConfig) => {
264
264
  registerVectorTools(serverInstance);
265
265
  registerSystemTools(serverInstance);
266
266
  registerTaskTools(serverInstance);
267
+ registerAITools(serverInstance);
267
268
  const server = new MCPServer(serverInstance, config);
268
269
  return { mcpServer: server };
269
270
  };
@@ -288,6 +289,7 @@ const initServerStdioTransport = async () => {
288
289
  registerVectorTools(serverInstance);
289
290
  registerSystemTools(serverInstance);
290
291
  registerTaskTools(serverInstance);
292
+ registerAITools(serverInstance);
291
293
  const server = new MCPServer(serverInstance, config);
292
294
  const transport = new StdioServerTransport();
293
295
  await serverInstance.connect(transport);
package/dist/stdio.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { mcpMeilisearchServer } from "./index.js";
2
2
  mcpMeilisearchServer({
3
3
  transport: "stdio",
4
- meilisearchHost: process.env.VITE_MEILISEARCH_HOST,
5
- meilisearchApiKey: process.env.VITE_MEILISEARCH_API_KEY,
4
+ meilisearchHost: process.env.MEILISEARCH_HOST,
5
+ meilisearchApiKey: process.env.MEILISEARCH_API_KEY,
6
6
  });
@@ -0,0 +1,8 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ /**
3
+ * Register AI tools with the MCP server
4
+ * @param server - The MCP server instance
5
+ */
6
+ export declare const registerAITools: (server: McpServer) => void;
7
+ export default registerAITools;
8
+ //# sourceMappingURL=ai-tools.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ai-tools.d.ts","sourceRoot":"","sources":["../../src/tools/ai-tools.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAcpE;;;GAGG;AACH,eAAO,MAAM,eAAe,GAAI,QAAQ,SAAS,SAqEhD,CAAC;AAEF,eAAe,eAAe,CAAC"}
@@ -0,0 +1,66 @@
1
+ import { z } from "zod";
2
+ import { AIService } from "../utils/ai-handler.js";
3
+ import { createErrorResponse } from "../utils/error-handler.js";
4
+ /**
5
+ * Register AI tools with the MCP server
6
+ * @param server - The MCP server instance
7
+ */
8
+ export const registerAITools = (server) => {
9
+ server.tool("process-ai-query", "Process a natural language query using AI to determine which tool to use", {
10
+ query: z.string().describe("The natural language query to process"),
11
+ specificTools: z
12
+ .array(z.string())
13
+ .optional()
14
+ .describe("Optional array of specific tool names to consider"),
15
+ }, async ({ query, specificTools }) => {
16
+ try {
17
+ const aiService = AIService.getInstance();
18
+ const availableTools = Object.entries(server._registeredTools)
19
+ .filter(([name]) => name !== "process-ai-query")
20
+ .map(([name, { description }]) => ({
21
+ name,
22
+ description,
23
+ parameters: {},
24
+ }));
25
+ aiService.setAvailableTools(availableTools);
26
+ const result = await aiService.processQuery(query, specificTools);
27
+ if (!aiService.client) {
28
+ return {
29
+ isError: true,
30
+ content: [
31
+ {
32
+ type: "text",
33
+ text: "AI service not initialized. Please provide an API key.",
34
+ },
35
+ ],
36
+ };
37
+ }
38
+ if (!result) {
39
+ return {
40
+ content: [
41
+ {
42
+ type: "text",
43
+ text: "AI couldn't determine an appropriate tool to use for this query.",
44
+ },
45
+ ],
46
+ };
47
+ }
48
+ return {
49
+ content: [
50
+ {
51
+ type: "text",
52
+ text: JSON.stringify({
53
+ toolName: result.toolName,
54
+ parameters: result.parameters,
55
+ reasoning: result.reasoning || "No explanation provided",
56
+ }, null, 2),
57
+ },
58
+ ],
59
+ };
60
+ }
61
+ catch (error) {
62
+ return createErrorResponse(error);
63
+ }
64
+ });
65
+ };
66
+ export default registerAITools;
@@ -147,7 +147,7 @@ export const registerSearchTools = (server) => {
147
147
  params: { limit: 1000 },
148
148
  });
149
149
  const indexUids = indexesResponse.data.results.map((index) => index.uid);
150
- if (!indexUids || indexUids.length === 0) {
150
+ if (!indexUids?.length) {
151
151
  return {
152
152
  content: [
153
153
  {
@@ -35,5 +35,14 @@ export interface ServerOptions {
35
35
  * @default 60000 (1 minute)
36
36
  */
37
37
  sessionCleanupInterval?: number;
38
+ /**
39
+ * OpenAI API key for AI inference
40
+ */
41
+ openaiApiKey?: string;
42
+ /**
43
+ * AI model to use for inference
44
+ * @default "gpt-3.5-turbo"
45
+ */
46
+ llmModel?: string;
38
47
  }
39
48
  //# sourceMappingURL=options.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"options.d.ts","sourceRoot":"","sources":["../../src/types/options.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,aAAa;IAC5B;;;;OAIG;IACH,eAAe,EAAE,MAAM,CAAC;IAExB;;;OAGG;IACH,iBAAiB,EAAE,MAAM,CAAC;IAC1B;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAE7B;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB;;;OAGG;IACH,sBAAsB,CAAC,EAAE,MAAM,CAAC;CACjC"}
1
+ {"version":3,"file":"options.d.ts","sourceRoot":"","sources":["../../src/types/options.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,aAAa;IAC5B;;;;OAIG;IACH,eAAe,EAAE,MAAM,CAAC;IAExB;;;OAGG;IACH,iBAAiB,EAAE,MAAM,CAAC;IAC1B;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAE7B;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB;;;OAGG;IACH,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAEhC;;OAEG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB"}
@@ -0,0 +1,66 @@
1
+ import { OpenAI } from "openai";
2
+ /**
3
+ * AI Inference Service
4
+ *
5
+ * This service handles the interaction with the AI to determine the appropriate tools
6
+ * to use based on the user's query
7
+ */
8
+ export declare class AIService {
9
+ client: OpenAI | null;
10
+ private static instance;
11
+ private availableTools;
12
+ private model;
13
+ private systemPrompt;
14
+ private static serverInitialized;
15
+ /**
16
+ * Private constructor to prevent direct instantiation
17
+ * Use getInstance() method instead
18
+ */
19
+ private constructor();
20
+ /**
21
+ * Get the singleton instance of AIService
22
+ * @returns The singleton AIService instance
23
+ */
24
+ static getInstance(): AIService;
25
+ /**
26
+ * Initialize the AI service with an API key and optionally set the model
27
+ * This should ONLY be called from the server side
28
+ * @param apiKey OpenAI API key (required)
29
+ * @param model Optional model to use (defaults to gpt-3.5-turbo)
30
+ */
31
+ initialize(apiKey: string, model?: string): void;
32
+ /**
33
+ * Set the available tools that can be used by the AI
34
+ * @param tools Array of tools with name, description, and parameters
35
+ */
36
+ setAvailableTools(tools: {
37
+ name: string;
38
+ description: string;
39
+ parameters: Record<string, any>;
40
+ }[]): void;
41
+ /**
42
+ * Get tool definitions for the AI in the format expected by OpenAI
43
+ * @param toolNames Optional array of tool names to filter by (if not provided, all tools will be included)
44
+ * @returns Array of tool definitions
45
+ */
46
+ private getToolDefinitions;
47
+ /**
48
+ * Attempt to extract specific tool names from the user query
49
+ * @param query The user's query
50
+ * @returns Array of tool names mentioned in the query, or empty array if none found
51
+ */
52
+ private extractToolNames;
53
+ /**
54
+ * Process a user query and determine which tool to use
55
+ * @param query User query
56
+ * @param specificTools Optional array of specific tool names to consider
57
+ * @returns Object containing the selected tool name and parameters
58
+ */
59
+ processQuery(query: string, specificTools?: string[]): Promise<{
60
+ toolName: string;
61
+ parameters: Record<string, any>;
62
+ reasoning?: string;
63
+ } | null>;
64
+ private setSystemPrompt;
65
+ }
66
+ //# sourceMappingURL=ai-handler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ai-handler.d.ts","sourceRoot":"","sources":["../../src/utils/ai-handler.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAYhC;;;;;GAKG;AACH,qBAAa,SAAS;IACpB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAQ;IAC7B,OAAO,CAAC,MAAM,CAAC,QAAQ,CAA0B;IACjD,OAAO,CAAC,cAAc,CAIb;IACT,OAAO,CAAC,KAAK,CAA2B;IACxC,OAAO,CAAC,YAAY,CAAyB;IAC7C,OAAO,CAAC,MAAM,CAAC,iBAAiB,CAAkB;IAElD;;;OAGG;IACH,OAAO;IAEP;;;OAGG;WACW,WAAW,IAAI,SAAS;IAOtC;;;;;OAKG;IACH,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI;IAYhD;;;OAGG;IACH,iBAAiB,CACf,KAAK,EAAE;QACL,IAAI,EAAE,MAAM,CAAC;QACb,WAAW,EAAE,MAAM,CAAC;QACpB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;KACjC,EAAE,GACF,IAAI;IAUP;;;;OAIG;IACH,OAAO,CAAC,kBAAkB;IAwB1B;;;;OAIG;IACH,OAAO,CAAC,gBAAgB;IAaxB;;;;;OAKG;IACG,YAAY,CAChB,KAAK,EAAE,MAAM,EACb,aAAa,CAAC,EAAE,MAAM,EAAE,GACvB,OAAO,CAAC;QACT,QAAQ,EAAE,MAAM,CAAC;QACjB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;QAChC,SAAS,CAAC,EAAE,MAAM,CAAC;KACpB,GAAG,IAAI,CAAC;IAwCT,OAAO,CAAC,eAAe;CAGxB"}
@@ -0,0 +1,139 @@
1
+ import { OpenAI } from "openai";
2
+ import generalPrompt from "../prompts/general.js";
3
+ /**
4
+ * AI Inference Service
5
+ *
6
+ * This service handles the interaction with the AI to determine the appropriate tools
7
+ * to use based on the user's query
8
+ */
9
+ export class AIService {
10
+ client = null;
11
+ static instance = null;
12
+ availableTools = [];
13
+ model = "gpt-3.5-turbo";
14
+ systemPrompt = generalPrompt;
15
+ static serverInitialized = false;
16
+ /**
17
+ * Private constructor to prevent direct instantiation
18
+ * Use getInstance() method instead
19
+ */
20
+ constructor() { }
21
+ /**
22
+ * Get the singleton instance of AIService
23
+ * @returns The singleton AIService instance
24
+ */
25
+ static getInstance() {
26
+ if (!AIService.instance) {
27
+ AIService.instance = new AIService();
28
+ }
29
+ return AIService.instance;
30
+ }
31
+ /**
32
+ * Initialize the AI service with an API key and optionally set the model
33
+ * This should ONLY be called from the server side
34
+ * @param apiKey OpenAI API key (required)
35
+ * @param model Optional model to use (defaults to gpt-3.5-turbo)
36
+ */
37
+ initialize(apiKey, model) {
38
+ if (AIService.serverInitialized) {
39
+ console.warn("AIService has already been initialized by the server.");
40
+ return;
41
+ }
42
+ this.client = new OpenAI({ apiKey });
43
+ if (model)
44
+ this.model = model;
45
+ AIService.serverInitialized = true;
46
+ }
47
+ /**
48
+ * Set the available tools that can be used by the AI
49
+ * @param tools Array of tools with name, description, and parameters
50
+ */
51
+ setAvailableTools(tools) {
52
+ this.availableTools = tools;
53
+ this.setSystemPrompt(this.systemPrompt.replace("MCP_TOOLS", JSON.stringify(this.availableTools, null, 2)));
54
+ }
55
+ /**
56
+ * Get tool definitions for the AI in the format expected by OpenAI
57
+ * @param toolNames Optional array of tool names to filter by (if not provided, all tools will be included)
58
+ * @returns Array of tool definitions
59
+ */
60
+ getToolDefinitions(toolNames) {
61
+ if (!toolNames?.length) {
62
+ return this.availableTools.map((tool) => ({
63
+ type: "function",
64
+ function: {
65
+ name: tool.name,
66
+ description: tool.description,
67
+ parameters: tool.parameters,
68
+ },
69
+ }));
70
+ }
71
+ return this.availableTools
72
+ .filter((tool) => toolNames.includes(tool.name))
73
+ .map((tool) => ({
74
+ type: "function",
75
+ function: {
76
+ name: tool.name,
77
+ description: tool.description,
78
+ parameters: tool.parameters,
79
+ },
80
+ }));
81
+ }
82
+ /**
83
+ * Attempt to extract specific tool names from the user query
84
+ * @param query The user's query
85
+ * @returns Array of tool names mentioned in the query, or empty array if none found
86
+ */
87
+ extractToolNames(query) {
88
+ const mentionedTools = [];
89
+ for (const tool of this.availableTools) {
90
+ const toolNameRegex = new RegExp(`\\b${tool.name}\\b`, "i");
91
+ if (toolNameRegex.test(query)) {
92
+ mentionedTools.push(tool.name);
93
+ }
94
+ }
95
+ return mentionedTools;
96
+ }
97
+ /**
98
+ * Process a user query and determine which tool to use
99
+ * @param query User query
100
+ * @param specificTools Optional array of specific tool names to consider
101
+ * @returns Object containing the selected tool name and parameters
102
+ */
103
+ async processQuery(query, specificTools) {
104
+ try {
105
+ if (!this.client)
106
+ return null;
107
+ const mentionedTools = this.extractToolNames(query);
108
+ const toolsToUse = specificTools || (mentionedTools.length ? mentionedTools : undefined);
109
+ const tools = this.getToolDefinitions(toolsToUse);
110
+ const messages = [
111
+ { role: "user", content: query },
112
+ { role: "system", content: this.systemPrompt },
113
+ ];
114
+ const response = await this.client.chat.completions.create({
115
+ tools,
116
+ messages,
117
+ model: this.model,
118
+ tool_choice: "auto",
119
+ });
120
+ const message = response.choices[0].message;
121
+ if (message.tool_calls?.length) {
122
+ const toolCall = message.tool_calls[0];
123
+ return {
124
+ toolName: toolCall.function.name,
125
+ reasoning: message.content || undefined,
126
+ parameters: JSON.parse(toolCall.function.arguments),
127
+ };
128
+ }
129
+ return null;
130
+ }
131
+ catch (error) {
132
+ console.error("Error in AI inference:", error);
133
+ throw error;
134
+ }
135
+ }
136
+ setSystemPrompt(prompt) {
137
+ this.systemPrompt = prompt;
138
+ }
139
+ }
@@ -4,6 +4,8 @@
4
4
  declare class ConfigHandler {
5
5
  private _meilisearchHost;
6
6
  private _meilisearchApiKey;
7
+ private _openaiApiKey;
8
+ private _llmModel;
7
9
  /**
8
10
  * Set the Meilisearch host URL
9
11
  * @param host The URL of the Meilisearch instance
@@ -13,7 +15,7 @@ declare class ConfigHandler {
13
15
  * Set the Meilisearch API key
14
16
  * @param apiKey The API key for Meilisearch
15
17
  */
16
- setMeilisearchApiKey(apiKey: string): void;
18
+ setMeilisearchApiKey(apiKey?: string): void;
17
19
  /**
18
20
  * Get the current Meilisearch host URL
19
21
  * @returns The URL of the Meilisearch instance
@@ -24,6 +26,26 @@ declare class ConfigHandler {
24
26
  * @returns The API key for Meilisearch
25
27
  */
26
28
  getMeilisearchApiKey(): string;
29
+ /**
30
+ * Set the OpenAI API key
31
+ * @param apiKey The API key for OpenAI
32
+ */
33
+ setOpenaiApiKey(apiKey?: string): void;
34
+ /**
35
+ * Get the current OpenAI API key
36
+ * @returns The API key for OpenAI
37
+ */
38
+ getOpenaiApiKey(): string;
39
+ /**
40
+ * Set the AI model to use
41
+ * @param model The model name (e.g., gpt-3.5-turbo, gpt-4)
42
+ */
43
+ setLlmModel(model?: string): void;
44
+ /**
45
+ * Get the current AI model
46
+ * @returns The model name
47
+ */
48
+ getLlmModel(): string;
27
49
  }
28
50
  export declare const configHandler: ConfigHandler;
29
51
  export default configHandler;
@@ -1 +1 @@
1
- {"version":3,"file":"config-handler.d.ts","sourceRoot":"","sources":["../../src/utils/config-handler.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,cAAM,aAAa;IACjB,OAAO,CAAC,gBAAgB,CAAM;IAC9B,OAAO,CAAC,kBAAkB,CAAM;IAEhC;;;OAGG;IACH,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAItC;;;OAGG;IACH,oBAAoB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAI1C;;;OAGG;IACH,kBAAkB,IAAI,MAAM;IAI5B;;;OAGG;IACH,oBAAoB,IAAI,MAAM;CAG/B;AAED,eAAO,MAAM,aAAa,eAAsB,CAAC;AAEjD,eAAe,aAAa,CAAC"}
1
+ {"version":3,"file":"config-handler.d.ts","sourceRoot":"","sources":["../../src/utils/config-handler.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,cAAM,aAAa;IACjB,OAAO,CAAC,gBAAgB,CAAM;IAC9B,OAAO,CAAC,kBAAkB,CAAM;IAChC,OAAO,CAAC,aAAa,CAAM;IAC3B,OAAO,CAAC,SAAS,CAAmB;IAEpC;;;OAGG;IACH,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAItC;;;OAGG;IACH,oBAAoB,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI;IAI3C;;;OAGG;IACH,kBAAkB,IAAI,MAAM;IAI5B;;;OAGG;IACH,oBAAoB,IAAI,MAAM;IAI9B;;;OAGG;IACH,eAAe,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI;IAItC;;;OAGG;IACH,eAAe,IAAI,MAAM;IAIzB;;;OAGG;IACH,WAAW,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI;IAIjC;;;OAGG;IACH,WAAW,IAAI,MAAM;CAGtB;AAED,eAAO,MAAM,aAAa,eAAsB,CAAC;AAEjD,eAAe,aAAa,CAAC"}
@@ -4,6 +4,8 @@
4
4
  class ConfigHandler {
5
5
  _meilisearchHost = "";
6
6
  _meilisearchApiKey = "";
7
+ _openaiApiKey = "";
8
+ _llmModel = "gpt-3.5-turbo";
7
9
  /**
8
10
  * Set the Meilisearch host URL
9
11
  * @param host The URL of the Meilisearch instance
@@ -32,6 +34,34 @@ class ConfigHandler {
32
34
  getMeilisearchApiKey() {
33
35
  return this._meilisearchApiKey;
34
36
  }
37
+ /**
38
+ * Set the OpenAI API key
39
+ * @param apiKey The API key for OpenAI
40
+ */
41
+ setOpenaiApiKey(apiKey) {
42
+ this._openaiApiKey = apiKey || "";
43
+ }
44
+ /**
45
+ * Get the current OpenAI API key
46
+ * @returns The API key for OpenAI
47
+ */
48
+ getOpenaiApiKey() {
49
+ return this._openaiApiKey;
50
+ }
51
+ /**
52
+ * Set the AI model to use
53
+ * @param model The model name (e.g., gpt-3.5-turbo, gpt-4)
54
+ */
55
+ setLlmModel(model) {
56
+ this._llmModel = model || "gpt-3.5-turbo";
57
+ }
58
+ /**
59
+ * Get the current AI model
60
+ * @returns The model name
61
+ */
62
+ getLlmModel() {
63
+ return this._llmModel;
64
+ }
35
65
  }
36
66
  export const configHandler = new ConfigHandler();
37
67
  export default configHandler;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mcp-meilisearch",
3
- "version": "1.2.7",
3
+ "version": "1.3.0",
4
4
  "description": "Model Context Protocol (MCP) implementation for Meilisearch",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -23,14 +23,15 @@
23
23
  "demo"
24
24
  ],
25
25
  "scripts": {
26
- "build": "tsc && tsc --project tsconfig.types.json",
26
+ "build": "tsc && tsc -p tsconfig.types.json",
27
27
  "demo": "npm run build & npm run dev --workspace=demo",
28
28
  "server": "npm run build && node --env-file=.env dist/index.js",
29
- "prepublishOnly": "rm -rf dist && npm version patch && npm run build"
29
+ "prepublishOnly": "rm -rf dist && npm version minor && npm run build"
30
30
  },
31
31
  "dependencies": {
32
32
  "@modelcontextprotocol/sdk": "^1.11.2",
33
33
  "axios": "^1.9.0",
34
+ "openai": "^4.98.0",
34
35
  "zod": "^3.24.4"
35
36
  },
36
37
  "devDependencies": {