mcp-meilisearch 1.4.7 → 1.4.9
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 +120 -7
- package/dist/index.js +1 -1
- package/dist/server.d.ts +3 -3
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +14 -18
- package/dist/tools/core/ai-tools.d.ts.map +1 -1
- package/dist/tools/core/ai-tools.js +10 -8
- package/dist/tools/meilisearch/settings-tools.d.ts.map +1 -1
- package/dist/tools/meilisearch/settings-tools.js +45 -0
- package/dist/utils/ai-handler.d.ts +1 -1
- package/dist/utils/ai-handler.d.ts.map +1 -1
- package/dist/utils/ai-handler.js +2 -6
- package/dist/utils/error-handler.d.ts +2 -2
- package/dist/utils/error-handler.js +1 -1
- package/dist/utils/response-handler.d.ts +1 -1
- package/dist/utils/response-handler.d.ts.map +1 -1
- package/dist/utils/response-handler.js +100 -69
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -354,18 +354,131 @@ The MCP server exposes various tools that allow you to interact with Meilisearch
|
|
|
354
354
|
- **Parameters**:
|
|
355
355
|
- `indexUid` (string, required): Unique identifier of the index.
|
|
356
356
|
|
|
357
|
-
####
|
|
357
|
+
#### Get Settings Tools
|
|
358
|
+
|
|
359
|
+
The following tools retrieve specific settings for a Meilisearch index:
|
|
360
|
+
|
|
361
|
+
- **get-displayed-attributes**
|
|
362
|
+
- **get-searchable-attributes**
|
|
363
|
+
- **get-filterable-attributes**
|
|
364
|
+
- **get-sortable-attributes**
|
|
365
|
+
- **get-ranking-rules**
|
|
366
|
+
- **get-stop-words**
|
|
367
|
+
- **get-synonyms**
|
|
368
|
+
- **get-typo-tolerance**
|
|
369
|
+
- **get-pagination**
|
|
370
|
+
- **get-faceting**
|
|
371
|
+
- **get-dictionary**
|
|
372
|
+
- **get-proximity-precision**
|
|
373
|
+
- **get-separator-tokens**
|
|
374
|
+
- **get-non-separator-tokens**
|
|
375
|
+
- **get-word-dictionary**
|
|
376
|
+
|
|
377
|
+
All these tools have the same parameter:
|
|
378
|
+
|
|
379
|
+
- `indexUid` (string, required): Unique identifier of the index.
|
|
380
|
+
|
|
381
|
+
#### Update Settings Tools
|
|
382
|
+
|
|
383
|
+
The following tools update specific settings for a Meilisearch index:
|
|
384
|
+
|
|
385
|
+
- **update-displayed-attributes**
|
|
358
386
|
|
|
359
|
-
- **Description**: Get the specific setting for an index.
|
|
360
|
-
- **Parameters**:
|
|
361
387
|
- `indexUid` (string, required): Unique identifier of the index.
|
|
388
|
+
- `displayedAttributes` (string, required): JSON array of attributes to display, e.g. ["title", "description"].
|
|
362
389
|
|
|
363
|
-
|
|
390
|
+
- **update-searchable-attributes**
|
|
364
391
|
|
|
365
|
-
- **Description**: Update a specific setting for an index.
|
|
366
|
-
- **Parameters**:
|
|
367
392
|
- `indexUid` (string, required): Unique identifier of the index.
|
|
368
|
-
- `
|
|
393
|
+
- `searchableAttributes` (string, required): JSON array of attributes that can be searched, e.g. ["title", "description"].
|
|
394
|
+
|
|
395
|
+
- **update-filterable-attributes**
|
|
396
|
+
|
|
397
|
+
- `indexUid` (string, required): Unique identifier of the index.
|
|
398
|
+
- `filterableAttributes` (string, required): JSON array of attributes that can be used as filters, e.g. ["genre", "director"].
|
|
399
|
+
|
|
400
|
+
- **update-sortable-attributes**
|
|
401
|
+
|
|
402
|
+
- `indexUid` (string, required): Unique identifier of the index.
|
|
403
|
+
- `sortableAttributes` (string, required): JSON array of attributes that can be used for sorting, e.g. ["price", "date"].
|
|
404
|
+
|
|
405
|
+
- **update-ranking-rules**
|
|
406
|
+
|
|
407
|
+
- `indexUid` (string, required): Unique identifier of the index.
|
|
408
|
+
- `rankingRules` (string, required): JSON array of ranking rules, e.g. ["typo", "words", "proximity", "attribute", "sort", "exactness"].
|
|
409
|
+
|
|
410
|
+
- **update-stop-words**
|
|
411
|
+
|
|
412
|
+
- `indexUid` (string, required): Unique identifier of the index.
|
|
413
|
+
- `stopWords` (string, required): JSON array of words to ignore in search queries, e.g. ["the", "a", "an"].
|
|
414
|
+
|
|
415
|
+
- **update-synonyms**
|
|
416
|
+
|
|
417
|
+
- `indexUid` (string, required): Unique identifier of the index.
|
|
418
|
+
- `synonyms` (string, required): JSON object mapping words to their synonyms, e.g. {"movie": ["film"]}.
|
|
419
|
+
|
|
420
|
+
- **update-typo-tolerance**
|
|
421
|
+
|
|
422
|
+
- `indexUid` (string, required): Unique identifier of the index.
|
|
423
|
+
- `typoTolerance` (string, required): JSON object with typo tolerance configuration, e.g. {"enabled": true, "minWordSizeForTypos": {"oneTypo": 5, "twoTypos": 9}}.
|
|
424
|
+
|
|
425
|
+
- **update-pagination**
|
|
426
|
+
|
|
427
|
+
- `indexUid` (string, required): Unique identifier of the index.
|
|
428
|
+
- `pagination` (string, required): JSON object with pagination configuration, e.g. {"maxTotalHits": 1000}.
|
|
429
|
+
|
|
430
|
+
- **update-faceting**
|
|
431
|
+
|
|
432
|
+
- `indexUid` (string, required): Unique identifier of the index.
|
|
433
|
+
- `faceting` (string, required): JSON object with faceting configuration, e.g. {"maxValuesPerFacet": 100}.
|
|
434
|
+
|
|
435
|
+
- **update-dictionary**
|
|
436
|
+
|
|
437
|
+
- `indexUid` (string, required): Unique identifier of the index.
|
|
438
|
+
- `dictionary` (string, required): JSON array of words to consider as a single word, e.g. ["San Francisco", "New York"].
|
|
439
|
+
|
|
440
|
+
- **update-proximity-precision**
|
|
441
|
+
|
|
442
|
+
- `indexUid` (string, required): Unique identifier of the index.
|
|
443
|
+
- `proximityPrecision` (string, required): String with proximity precision value, can be 'byWord' or 'byAttribute'.
|
|
444
|
+
|
|
445
|
+
- **update-separator-tokens**
|
|
446
|
+
|
|
447
|
+
- `indexUid` (string, required): Unique identifier of the index.
|
|
448
|
+
- `separatorTokens` (string, required): JSON array of tokens that should be considered as word separators, e.g. ["-", "_"].
|
|
449
|
+
|
|
450
|
+
- **update-non-separator-tokens**
|
|
451
|
+
|
|
452
|
+
- `indexUid` (string, required): Unique identifier of the index.
|
|
453
|
+
- `nonSeparatorTokens` (string, required): JSON array of tokens that should not be considered as word separators, e.g. ["@", "."].
|
|
454
|
+
|
|
455
|
+
- **update-word-dictionary**
|
|
456
|
+
- `indexUid` (string, required): Unique identifier of the index.
|
|
457
|
+
- `wordDictionary` (string, required): JSON array of custom words to add to the dictionary, e.g. ["cbuilder", "meilisearch"].
|
|
458
|
+
|
|
459
|
+
#### Reset Settings Tools
|
|
460
|
+
|
|
461
|
+
The following tools reset specific settings for a Meilisearch index to their default values:
|
|
462
|
+
|
|
463
|
+
- **reset-displayed-attributes**
|
|
464
|
+
- **reset-searchable-attributes**
|
|
465
|
+
- **reset-filterable-attributes**
|
|
466
|
+
- **reset-sortable-attributes**
|
|
467
|
+
- **reset-ranking-rules**
|
|
468
|
+
- **reset-stop-words**
|
|
469
|
+
- **reset-synonyms**
|
|
470
|
+
- **reset-typo-tolerance**
|
|
471
|
+
- **reset-pagination**
|
|
472
|
+
- **reset-faceting**
|
|
473
|
+
- **reset-dictionary**
|
|
474
|
+
- **reset-proximity-precision**
|
|
475
|
+
- **reset-separator-tokens**
|
|
476
|
+
- **reset-non-separator-tokens**
|
|
477
|
+
- **reset-word-dictionary**
|
|
478
|
+
|
|
479
|
+
All these reset tools have the same parameter:
|
|
480
|
+
|
|
481
|
+
- `indexUid` (string, required): Unique identifier of the index.
|
|
369
482
|
|
|
370
483
|
### Task Tools
|
|
371
484
|
|
package/dist/index.js
CHANGED
|
@@ -21,7 +21,7 @@ export async function mcpMeilisearchServer(options = defaultOptions) {
|
|
|
21
21
|
aiService.initialize(apiKey, aiProviderName, llmModel);
|
|
22
22
|
}
|
|
23
23
|
else {
|
|
24
|
-
console.warn("AI provider API key not found.
|
|
24
|
+
console.warn("AI provider API key not found. Continuing without it.");
|
|
25
25
|
}
|
|
26
26
|
let mcpServerInstance = null;
|
|
27
27
|
const transport = options.transport;
|
package/dist/server.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { IncomingMessage, ServerResponse } from "http";
|
|
2
2
|
import { ServerOptions } from "./types/options.js";
|
|
3
|
-
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
3
|
+
import { McpServer as McpServerInstance } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
4
4
|
/**
|
|
5
5
|
* Return type for the initServer function
|
|
6
6
|
*/
|
|
@@ -21,8 +21,8 @@ export declare const defaultOptions: {
|
|
|
21
21
|
export declare class MCPServer {
|
|
22
22
|
private readonly JSON_RPC;
|
|
23
23
|
private readonly SESSION_ID_HEADER_NAME;
|
|
24
|
-
private server;
|
|
25
24
|
private config;
|
|
25
|
+
private server;
|
|
26
26
|
private cleanupInterval;
|
|
27
27
|
private sessions;
|
|
28
28
|
/**
|
|
@@ -30,7 +30,7 @@ export declare class MCPServer {
|
|
|
30
30
|
* @param server The underlying MCP server implementation
|
|
31
31
|
* @param config Configuration options
|
|
32
32
|
*/
|
|
33
|
-
constructor(server:
|
|
33
|
+
constructor(server: McpServerInstance, config?: Partial<ServerOptions>);
|
|
34
34
|
/**
|
|
35
35
|
* Handles an HTTP request and routes it to the appropriate handler
|
|
36
36
|
* @param req The HTTP request
|
package/dist/server.d.ts.map
CHANGED
|
@@ -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;AAOvD,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,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;AAOvD,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAWnD,OAAO,EAAE,SAAS,IAAI,iBAAiB,EAAE,MAAM,yCAAyC,CAAC;AAGzF;;GAEG;AACH,UAAU,cAAc;IACtB,SAAS,EAAE,SAAS,CAAC;CACtB;AASD,eAAO,MAAM,cAAc;;;;;;;CAO1B,CAAC;AAEF;;GAEG;AACH,qBAAa,SAAS;IACpB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAAoB;IAE3D,OAAO,CAAC,MAAM,CAAgB;IAC9B,OAAO,CAAC,MAAM,CAAoB;IAClC,OAAO,CAAC,eAAe,CAA+B;IACtD,OAAO,CAAC,QAAQ,CAAuC;IAEvD;;;;OAIG;gBACS,MAAM,EAAE,iBAAiB,EAAE,MAAM,GAAE,OAAO,CAAC,aAAa,CAAM;IAO1E;;;;;OAKG;IACG,iBAAiB,CACrB,GAAG,EAAE,eAAe,EACpB,GAAG,EAAE,cAAc,EACnB,WAAW,GAAE,MAAmC,GAC/C,OAAO,CAAC,IAAI,CAAC;IA+ChB;;;;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;IAQ3B;;OAEG;IACH,OAAO,CAAC,sBAAsB;CA2B/B;AAyDD;;;;;;GAMG;AACH,eAAO,MAAM,UAAU,GACrB,YAAW,MAAM,GAAG,OAAgB,EACpC,SAAS,OAAO,CAAC,aAAa,CAAC,KAC9B,OAAO,CAAC,cAAc,CAcxB,CAAC"}
|
package/dist/server.js
CHANGED
|
@@ -3,7 +3,6 @@ import { InitializeRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
|
|
|
3
3
|
import registerAITools from "./tools/core/ai-tools.js";
|
|
4
4
|
import { createErrorResponse } from "./utils/error-handler.js";
|
|
5
5
|
import registerTaskTools from "./tools/meilisearch/task-tools.js";
|
|
6
|
-
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
7
6
|
import registerIndexTools from "./tools/meilisearch/index-tools.js";
|
|
8
7
|
import registerSearchTools from "./tools/meilisearch/search-tools.js";
|
|
9
8
|
import registerSystemTools from "./tools/meilisearch/system-tools.js";
|
|
@@ -11,6 +10,7 @@ import registerVectorTools from "./tools/meilisearch/vector-tools.js";
|
|
|
11
10
|
import registerDocumentTools from "./tools/meilisearch/document-tools.js";
|
|
12
11
|
import registerSettingsTools from "./tools/meilisearch/settings-tools.js";
|
|
13
12
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
13
|
+
import { McpServer as McpServerInstance } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
14
14
|
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
|
|
15
15
|
export const defaultOptions = {
|
|
16
16
|
httpPort: 4995,
|
|
@@ -26,8 +26,8 @@ export const defaultOptions = {
|
|
|
26
26
|
export class MCPServer {
|
|
27
27
|
JSON_RPC = "2.0";
|
|
28
28
|
SESSION_ID_HEADER_NAME = "mcp-session-id";
|
|
29
|
-
server;
|
|
30
29
|
config;
|
|
30
|
+
server;
|
|
31
31
|
cleanupInterval = null;
|
|
32
32
|
sessions = new Map();
|
|
33
33
|
/**
|
|
@@ -293,10 +293,11 @@ export class MCPServer {
|
|
|
293
293
|
}
|
|
294
294
|
}
|
|
295
295
|
/**
|
|
296
|
-
*
|
|
296
|
+
* Create a new MCP server instance
|
|
297
|
+
* @returns MCP server instance
|
|
297
298
|
*/
|
|
298
|
-
const
|
|
299
|
-
const serverInstance = new
|
|
299
|
+
const createServerInstance = () => {
|
|
300
|
+
const serverInstance = new McpServerInstance({
|
|
300
301
|
version: "1.0.0",
|
|
301
302
|
name: "mcp-meilisearch",
|
|
302
303
|
});
|
|
@@ -308,6 +309,13 @@ const initServerHTTPTransport = async (customConfig) => {
|
|
|
308
309
|
registerSystemTools(serverInstance);
|
|
309
310
|
registerTaskTools(serverInstance);
|
|
310
311
|
registerAITools(serverInstance);
|
|
312
|
+
return serverInstance;
|
|
313
|
+
};
|
|
314
|
+
/**
|
|
315
|
+
* Initialize the MCP server with HTTP transport
|
|
316
|
+
*/
|
|
317
|
+
const initServerHTTPTransport = async (customConfig) => {
|
|
318
|
+
const serverInstance = createServerInstance();
|
|
311
319
|
const server = new MCPServer(serverInstance, customConfig);
|
|
312
320
|
return { mcpServer: server };
|
|
313
321
|
};
|
|
@@ -316,22 +324,10 @@ const initServerHTTPTransport = async (customConfig) => {
|
|
|
316
324
|
* @returns MCP server instance
|
|
317
325
|
*/
|
|
318
326
|
const initServerStdioTransport = async (customConfig) => {
|
|
319
|
-
const serverInstance =
|
|
320
|
-
version: "1.0.0",
|
|
321
|
-
name: "mcp-meilisearch",
|
|
322
|
-
});
|
|
323
|
-
registerIndexTools(serverInstance);
|
|
324
|
-
registerDocumentTools(serverInstance);
|
|
325
|
-
registerSearchTools(serverInstance);
|
|
326
|
-
registerSettingsTools(serverInstance);
|
|
327
|
-
registerVectorTools(serverInstance);
|
|
328
|
-
registerSystemTools(serverInstance);
|
|
329
|
-
registerTaskTools(serverInstance);
|
|
330
|
-
registerAITools(serverInstance);
|
|
327
|
+
const serverInstance = createServerInstance();
|
|
331
328
|
const server = new MCPServer(serverInstance, customConfig);
|
|
332
329
|
const transport = new StdioServerTransport();
|
|
333
330
|
await serverInstance.connect(transport);
|
|
334
|
-
console.info("Meilisearch MCP Server is running on stdio transport");
|
|
335
331
|
process.on("SIGINT", () => {
|
|
336
332
|
console.info("Shutting down stdio server...");
|
|
337
333
|
process.exit(0);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ai-tools.d.ts","sourceRoot":"","sources":["../../../src/tools/core/ai-tools.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ai-tools.d.ts","sourceRoot":"","sources":["../../../src/tools/core/ai-tools.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAqBpE;;;GAGG;AACH,eAAO,MAAM,eAAe,GAAI,QAAQ,SAAS,SA2DhD,CAAC;AAEF,eAAe,eAAe,CAAC"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { zodToJsonSchema } from "zod-to-json-schema";
|
|
3
3
|
import { AIService } from "../../utils/ai-handler.js";
|
|
4
|
-
import { cleanNullValues } from "../../utils/response-handler.js";
|
|
5
4
|
import { createErrorResponse } from "../../utils/error-handler.js";
|
|
5
|
+
import { convertNullToUndefined } from "../../utils/response-handler.js";
|
|
6
6
|
/**
|
|
7
7
|
* Register AI tools with the MCP server
|
|
8
8
|
* @param server - The MCP server instance
|
|
@@ -17,7 +17,8 @@ export const registerAITools = (server) => {
|
|
|
17
17
|
}, { category: "core" }, async ({ query, specificTools }) => {
|
|
18
18
|
try {
|
|
19
19
|
const aiService = AIService.getInstance();
|
|
20
|
-
const
|
|
20
|
+
const registeredTools = Object.entries(server._registeredTools);
|
|
21
|
+
const availableTools = registeredTools
|
|
21
22
|
.filter(([_, { annotations }]) => annotations?.category !== "core")
|
|
22
23
|
.map(([name, { description, inputSchema }]) => {
|
|
23
24
|
const { definitions } = zodToJsonSchema(inputSchema, "parameters");
|
|
@@ -28,17 +29,18 @@ export const registerAITools = (server) => {
|
|
|
28
29
|
};
|
|
29
30
|
});
|
|
30
31
|
aiService.setAvailableTools(availableTools);
|
|
31
|
-
const
|
|
32
|
-
if (
|
|
33
|
-
return createErrorResponse(
|
|
32
|
+
const response = await aiService.processQuery(query, specificTools);
|
|
33
|
+
if (response.error)
|
|
34
|
+
return createErrorResponse(response.error);
|
|
34
35
|
return {
|
|
36
|
+
isError: false,
|
|
35
37
|
content: [
|
|
36
38
|
{
|
|
37
39
|
type: "text",
|
|
38
40
|
text: JSON.stringify({
|
|
39
|
-
toolName:
|
|
40
|
-
reasoning:
|
|
41
|
-
parameters:
|
|
41
|
+
toolName: response.toolName,
|
|
42
|
+
reasoning: response.reasoning,
|
|
43
|
+
parameters: convertNullToUndefined(response.parameters),
|
|
42
44
|
}, null, 2),
|
|
43
45
|
},
|
|
44
46
|
],
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"settings-tools.d.ts","sourceRoot":"","sources":["../../../src/tools/meilisearch/settings-tools.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE;;;;GAIG;AAEH;;;;GAIG;AACH,eAAO,MAAM,qBAAqB,GAAI,QAAQ,SAAS,
|
|
1
|
+
{"version":3,"file":"settings-tools.d.ts","sourceRoot":"","sources":["../../../src/tools/meilisearch/settings-tools.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE;;;;GAIG;AAEH;;;;GAIG;AACH,eAAO,MAAM,qBAAqB,GAAI,QAAQ,SAAS,SA2uCtD,CAAC;AAEF,eAAe,qBAAqB,CAAC"}
|
|
@@ -93,6 +93,9 @@ export const registerSettingsTools = (server) => {
|
|
|
93
93
|
// Update displayed attributes setting
|
|
94
94
|
server.tool("update-displayed-attributes", "Update the displayed attributes setting for a Meilisearch index", {
|
|
95
95
|
indexUid: z.string().describe("Unique identifier of the index"),
|
|
96
|
+
displayedAttributes: z
|
|
97
|
+
.string()
|
|
98
|
+
.describe('JSON array of attributes to display, e.g. ["title", "description"]'),
|
|
96
99
|
}, { category: "meilisearch" }, async ({ indexUid, displayedAttributes }) => {
|
|
97
100
|
try {
|
|
98
101
|
const response = await apiClient.put(`/indexes/${indexUid}/settings/displayed-attributes`, displayedAttributes);
|
|
@@ -141,6 +144,9 @@ export const registerSettingsTools = (server) => {
|
|
|
141
144
|
// Update filterable attributes setting
|
|
142
145
|
server.tool("update-filterable-attributes", "Update the filterable attributes setting for a Meilisearch index", {
|
|
143
146
|
indexUid: z.string().describe("Unique identifier of the index"),
|
|
147
|
+
filterableAttributes: z
|
|
148
|
+
.string()
|
|
149
|
+
.describe('JSON array of attributes that can be used as filters, e.g. ["genre", "director"]'),
|
|
144
150
|
}, { category: "meilisearch" }, async ({ indexUid, filterableAttributes }) => {
|
|
145
151
|
try {
|
|
146
152
|
const response = await apiClient.put(`/indexes/${indexUid}/settings/filterable-attributes`, filterableAttributes);
|
|
@@ -189,6 +195,9 @@ export const registerSettingsTools = (server) => {
|
|
|
189
195
|
// Update sortable attributes setting
|
|
190
196
|
server.tool("update-sortable-attributes", "Update the sortable attributes setting for a Meilisearch index", {
|
|
191
197
|
indexUid: z.string().describe("Unique identifier of the index"),
|
|
198
|
+
sortableAttributes: z
|
|
199
|
+
.string()
|
|
200
|
+
.describe('JSON array of attributes that can be used for sorting, e.g. ["price", "date"]'),
|
|
192
201
|
}, { category: "meilisearch" }, async ({ indexUid, sortableAttributes }) => {
|
|
193
202
|
try {
|
|
194
203
|
const response = await apiClient.put(`/indexes/${indexUid}/settings/sortable-attributes`, sortableAttributes);
|
|
@@ -237,6 +246,9 @@ export const registerSettingsTools = (server) => {
|
|
|
237
246
|
// Update searchable attributes setting
|
|
238
247
|
server.tool("update-searchable-attributes", "Update the searchable attributes setting for a Meilisearch index", {
|
|
239
248
|
indexUid: z.string().describe("Unique identifier of the index"),
|
|
249
|
+
searchableAttributes: z
|
|
250
|
+
.string()
|
|
251
|
+
.describe('JSON array of attributes that can be searched, e.g. ["title", "description"]'),
|
|
240
252
|
}, { category: "meilisearch" }, async ({ indexUid, searchableAttributes }) => {
|
|
241
253
|
try {
|
|
242
254
|
const response = await apiClient.put(`/indexes/${indexUid}/settings/searchable-attributes`, searchableAttributes);
|
|
@@ -285,6 +297,9 @@ export const registerSettingsTools = (server) => {
|
|
|
285
297
|
// Update ranking rules setting
|
|
286
298
|
server.tool("update-ranking-rules", "Update the ranking rules setting for a Meilisearch index", {
|
|
287
299
|
indexUid: z.string().describe("Unique identifier of the index"),
|
|
300
|
+
rankingRules: z
|
|
301
|
+
.string()
|
|
302
|
+
.describe('JSON array of ranking rules, e.g. ["typo", "words", "proximity", "attribute", "sort", "exactness"]'),
|
|
288
303
|
}, { category: "meilisearch" }, async ({ indexUid, rankingRules }) => {
|
|
289
304
|
try {
|
|
290
305
|
const response = await apiClient.put(`/indexes/${indexUid}/settings/ranking-rules`, rankingRules);
|
|
@@ -333,6 +348,9 @@ export const registerSettingsTools = (server) => {
|
|
|
333
348
|
// Update stop words setting
|
|
334
349
|
server.tool("update-stop-words", "Update the stop words setting for a Meilisearch index", {
|
|
335
350
|
indexUid: z.string().describe("Unique identifier of the index"),
|
|
351
|
+
stopWords: z
|
|
352
|
+
.string()
|
|
353
|
+
.describe('JSON array of words to ignore in search queries, e.g. ["the", "a", "an"]'),
|
|
336
354
|
}, { category: "meilisearch" }, async ({ indexUid, stopWords }) => {
|
|
337
355
|
try {
|
|
338
356
|
const response = await apiClient.put(`/indexes/${indexUid}/settings/stop-words`, stopWords);
|
|
@@ -381,6 +399,9 @@ export const registerSettingsTools = (server) => {
|
|
|
381
399
|
// Update synonyms setting
|
|
382
400
|
server.tool("update-synonyms", "Update the synonyms setting for a Meilisearch index", {
|
|
383
401
|
indexUid: z.string().describe("Unique identifier of the index"),
|
|
402
|
+
synonyms: z
|
|
403
|
+
.string()
|
|
404
|
+
.describe('JSON object mapping words to their synonyms, e.g. {"movie": ["film"]}'),
|
|
384
405
|
}, { category: "meilisearch" }, async ({ indexUid, synonyms }) => {
|
|
385
406
|
try {
|
|
386
407
|
const response = await apiClient.put(`/indexes/${indexUid}/settings/synonyms`, synonyms);
|
|
@@ -429,6 +450,9 @@ export const registerSettingsTools = (server) => {
|
|
|
429
450
|
// Update typo tolerance setting
|
|
430
451
|
server.tool("update-typo-tolerance", "Update the typo tolerance setting for a Meilisearch index", {
|
|
431
452
|
indexUid: z.string().describe("Unique identifier of the index"),
|
|
453
|
+
typoTolerance: z
|
|
454
|
+
.string()
|
|
455
|
+
.describe('JSON object with typo tolerance configuration, e.g. {"enabled": true, "minWordSizeForTypos": {"oneTypo": 5, "twoTypos": 9}}'),
|
|
432
456
|
}, { category: "meilisearch" }, async ({ indexUid, typoTolerance }) => {
|
|
433
457
|
try {
|
|
434
458
|
const response = await apiClient.put(`/indexes/${indexUid}/settings/typo-tolerance`, typoTolerance);
|
|
@@ -477,6 +501,9 @@ export const registerSettingsTools = (server) => {
|
|
|
477
501
|
// Update pagination setting
|
|
478
502
|
server.tool("update-pagination", "Update the pagination setting for a Meilisearch index", {
|
|
479
503
|
indexUid: z.string().describe("Unique identifier of the index"),
|
|
504
|
+
pagination: z
|
|
505
|
+
.string()
|
|
506
|
+
.describe('JSON object with pagination configuration, e.g. {"maxTotalHits": 1000}'),
|
|
480
507
|
}, { category: "meilisearch" }, async ({ indexUid, pagination }) => {
|
|
481
508
|
try {
|
|
482
509
|
const response = await apiClient.put(`/indexes/${indexUid}/settings/pagination`, pagination);
|
|
@@ -525,6 +552,9 @@ export const registerSettingsTools = (server) => {
|
|
|
525
552
|
// Update faceting setting
|
|
526
553
|
server.tool("update-faceting", "Update the faceting setting for a Meilisearch index", {
|
|
527
554
|
indexUid: z.string().describe("Unique identifier of the index"),
|
|
555
|
+
faceting: z
|
|
556
|
+
.string()
|
|
557
|
+
.describe('JSON object with faceting configuration, e.g. {"maxValuesPerFacet": 100}'),
|
|
528
558
|
}, { category: "meilisearch" }, async ({ indexUid, faceting }) => {
|
|
529
559
|
try {
|
|
530
560
|
const response = await apiClient.put(`/indexes/${indexUid}/settings/faceting`, faceting);
|
|
@@ -573,6 +603,9 @@ export const registerSettingsTools = (server) => {
|
|
|
573
603
|
// Update dictionary setting
|
|
574
604
|
server.tool("update-dictionary", "Update the dictionary setting for a Meilisearch index", {
|
|
575
605
|
indexUid: z.string().describe("Unique identifier of the index"),
|
|
606
|
+
dictionary: z
|
|
607
|
+
.string()
|
|
608
|
+
.describe('JSON array of words to consider as a single word, e.g. ["San Francisco", "New York"]'),
|
|
576
609
|
}, { category: "meilisearch" }, async ({ indexUid, dictionary }) => {
|
|
577
610
|
try {
|
|
578
611
|
const response = await apiClient.put(`/indexes/${indexUid}/settings/dictionary`, dictionary);
|
|
@@ -621,6 +654,9 @@ export const registerSettingsTools = (server) => {
|
|
|
621
654
|
// Update proximity precision setting
|
|
622
655
|
server.tool("update-proximity-precision", "Update the proximity precision setting for a Meilisearch index", {
|
|
623
656
|
indexUid: z.string().describe("Unique identifier of the index"),
|
|
657
|
+
proximityPrecision: z
|
|
658
|
+
.string()
|
|
659
|
+
.describe("String with proximity precision value, can be 'byWord' or 'byAttribute'"),
|
|
624
660
|
}, { category: "meilisearch" }, async ({ indexUid, proximityPrecision }) => {
|
|
625
661
|
try {
|
|
626
662
|
const response = await apiClient.put(`/indexes/${indexUid}/settings/proximity-precision`, proximityPrecision);
|
|
@@ -669,6 +705,9 @@ export const registerSettingsTools = (server) => {
|
|
|
669
705
|
// Update separator tokens setting
|
|
670
706
|
server.tool("update-separator-tokens", "Update the separator tokens setting for a Meilisearch index", {
|
|
671
707
|
indexUid: z.string().describe("Unique identifier of the index"),
|
|
708
|
+
separatorTokens: z
|
|
709
|
+
.string()
|
|
710
|
+
.describe('JSON array of tokens that should be considered as word separators, e.g. ["-", "_"]'),
|
|
672
711
|
}, { category: "meilisearch" }, async ({ indexUid, separatorTokens }) => {
|
|
673
712
|
try {
|
|
674
713
|
const response = await apiClient.put(`/indexes/${indexUid}/settings/separator-tokens`, separatorTokens);
|
|
@@ -717,6 +756,9 @@ export const registerSettingsTools = (server) => {
|
|
|
717
756
|
// Update non-separator tokens setting
|
|
718
757
|
server.tool("update-non-separator-tokens", "Update the non-separator tokens setting for a Meilisearch index", {
|
|
719
758
|
indexUid: z.string().describe("Unique identifier of the index"),
|
|
759
|
+
nonSeparatorTokens: z
|
|
760
|
+
.string()
|
|
761
|
+
.describe('JSON array of tokens that should not be considered as word separators, e.g. ["@", "."]'),
|
|
720
762
|
}, { category: "meilisearch" }, async ({ indexUid, nonSeparatorTokens }) => {
|
|
721
763
|
try {
|
|
722
764
|
const response = await apiClient.put(`/indexes/${indexUid}/settings/non-separator-tokens`, nonSeparatorTokens);
|
|
@@ -765,6 +807,9 @@ export const registerSettingsTools = (server) => {
|
|
|
765
807
|
// Update word dictionary setting
|
|
766
808
|
server.tool("update-word-dictionary", "Update the word dictionary setting for a Meilisearch index", {
|
|
767
809
|
indexUid: z.string().describe("Unique identifier of the index"),
|
|
810
|
+
wordDictionary: z
|
|
811
|
+
.string()
|
|
812
|
+
.describe('JSON array of custom words to add to the dictionary, e.g. ["cbuilder", "meilisearch"]'),
|
|
768
813
|
}, { category: "meilisearch" }, async ({ indexUid, wordDictionary }) => {
|
|
769
814
|
try {
|
|
770
815
|
const response = await apiClient.put(`/indexes/${indexUid}/settings/word-dictionary`, wordDictionary);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ai-handler.d.ts","sourceRoot":"","sources":["../../src/utils/ai-handler.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAG5D,UAAU,MAAM;IACd,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACrC;AAmBD,UAAU,cAAc;IACtB,
|
|
1
|
+
{"version":3,"file":"ai-handler.d.ts","sourceRoot":"","sources":["../../src/utils/ai-handler.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAG5D,UAAU,MAAM;IACd,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACrC;AAmBD,UAAU,cAAc;IACtB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACtC;AAED;;;;;GAKG;AACH,qBAAa,SAAS;IACpB,OAAO,CAAC,cAAc,CAAgB;IACtC,OAAO,CAAC,KAAK,CAA2B;IACxC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAA0B;IACjD,OAAO,CAAC,MAAM,CAAC,iBAAiB,CAAkB;IAClD,OAAO,CAAC,QAAQ,CAAmC;IACnD,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAwB;IACrD,OAAO,CAAC,MAAM,CAAgD;IAE9D;;;OAGG;IACH,OAAO;IAEP;;;OAGG;WACW,WAAW,IAAI,SAAS;IAOtC;;;;;;OAMG;IACH,UAAU,CACR,MAAM,EAAE,MAAM,EACd,QAAQ,GAAE,qBAAgC,EAC1C,KAAK,CAAC,EAAE,MAAM,GACb,IAAI;IAyBP;;;OAGG;IACH,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI;IAIxC,iBAAiB,IAAI,OAAO;IAI5B;;;;OAIG;IACH,OAAO,CAAC,kBAAkB;IAgB1B;;;;OAIG;IACH,OAAO,CAAC,gBAAgB;IAaxB;;;;;OAKG;IACG,YAAY,CAChB,KAAK,EAAE,MAAM,EACb,aAAa,CAAC,EAAE,MAAM,EAAE,GACvB,OAAO,CAAC,cAAc,CAAC;YA4BZ,kBAAkB;YA6DlB,uBAAuB;CAuDtC"}
|
package/dist/utils/ai-handler.js
CHANGED
|
@@ -154,7 +154,6 @@ export class AIService {
|
|
|
154
154
|
parameters: JSON.parse(toolCall.arguments),
|
|
155
155
|
};
|
|
156
156
|
return {
|
|
157
|
-
error: null,
|
|
158
157
|
toolName: inferenceToolResponse.name,
|
|
159
158
|
parameters: inferenceToolResponse.parameters,
|
|
160
159
|
reasoning: JSON.stringify(inferenceToolResponse, null, 2),
|
|
@@ -168,7 +167,6 @@ export class AIService {
|
|
|
168
167
|
};
|
|
169
168
|
}
|
|
170
169
|
return {
|
|
171
|
-
error: null,
|
|
172
170
|
toolName: toolCall.name,
|
|
173
171
|
parameters: toolCall.parameters,
|
|
174
172
|
reasoning: JSON.stringify(toolCall, null, 2),
|
|
@@ -177,7 +175,7 @@ export class AIService {
|
|
|
177
175
|
return { error: "No tool call or content in OpenAI response" };
|
|
178
176
|
}
|
|
179
177
|
catch (error) {
|
|
180
|
-
return { error
|
|
178
|
+
return { error };
|
|
181
179
|
}
|
|
182
180
|
}
|
|
183
181
|
async processHuggingFaceQuery(tools, messages) {
|
|
@@ -203,7 +201,6 @@ export class AIService {
|
|
|
203
201
|
parameters: JSON.parse(toolCall.arguments),
|
|
204
202
|
};
|
|
205
203
|
return {
|
|
206
|
-
error: null,
|
|
207
204
|
toolName: inferenceToolResponse.name,
|
|
208
205
|
parameters: inferenceToolResponse.parameters,
|
|
209
206
|
reasoning: JSON.stringify(inferenceToolResponse, null, 2),
|
|
@@ -214,7 +211,6 @@ export class AIService {
|
|
|
214
211
|
if (!toolCall)
|
|
215
212
|
return { error: "Invalid tool call format in content" };
|
|
216
213
|
return {
|
|
217
|
-
error: null,
|
|
218
214
|
toolName: toolCall.name,
|
|
219
215
|
parameters: toolCall.parameters,
|
|
220
216
|
reasoning: JSON.stringify(toolCall, null, 2),
|
|
@@ -223,7 +219,7 @@ export class AIService {
|
|
|
223
219
|
return { error: "No tool call or content in Hugging Face response" };
|
|
224
220
|
}
|
|
225
221
|
catch (error) {
|
|
226
|
-
return { error
|
|
222
|
+
return { error };
|
|
227
223
|
}
|
|
228
224
|
}
|
|
229
225
|
}
|
|
@@ -14,7 +14,7 @@ export declare const handleApiError: (error: any) => string;
|
|
|
14
14
|
export declare const createErrorResponse: (error: any) => {
|
|
15
15
|
isError: boolean;
|
|
16
16
|
content: {
|
|
17
|
-
type:
|
|
17
|
+
type: "text";
|
|
18
18
|
text: string;
|
|
19
19
|
}[];
|
|
20
20
|
};
|
|
@@ -23,7 +23,7 @@ declare const _default: {
|
|
|
23
23
|
createErrorResponse: (error: any) => {
|
|
24
24
|
isError: boolean;
|
|
25
25
|
content: {
|
|
26
|
-
type:
|
|
26
|
+
type: "text";
|
|
27
27
|
text: string;
|
|
28
28
|
}[];
|
|
29
29
|
};
|
|
@@ -12,7 +12,7 @@ export const handleApiError = (error) => {
|
|
|
12
12
|
return `Meilisearch API error (${status}): ${JSON.stringify(data)}`;
|
|
13
13
|
}
|
|
14
14
|
// If it's a network error or other error
|
|
15
|
-
return
|
|
15
|
+
return JSON.stringify(error);
|
|
16
16
|
};
|
|
17
17
|
/**
|
|
18
18
|
* Creates a standardized error response object for MCP tools
|
|
@@ -11,5 +11,5 @@ export declare function markdownToJson<T>(markdownJsonString: string): T | null;
|
|
|
11
11
|
* Recursively removes null values from an object, replacing them with undefined
|
|
12
12
|
* This ensures optional parameters are properly handled by JSON schema validation
|
|
13
13
|
*/
|
|
14
|
-
export declare function
|
|
14
|
+
export declare function convertNullToUndefined(obj: unknown, seen?: WeakMap<object, unknown>): unknown;
|
|
15
15
|
//# sourceMappingURL=response-handler.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"response-handler.d.ts","sourceRoot":"","sources":["../../src/utils/response-handler.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"response-handler.d.ts","sourceRoot":"","sources":["../../src/utils/response-handler.ts"],"names":[],"mappings":"AA0CA;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,kBAAkB,EAAE,MAAM,GAAG,CAAC,GAAG,IAAI,CAuDtE;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CACpC,GAAG,EAAE,OAAO,EACZ,IAAI,GAAE,OAAO,CAAC,MAAM,EAAE,OAAO,CAAiB,GAC7C,OAAO,CA6BT"}
|
|
@@ -1,3 +1,41 @@
|
|
|
1
|
+
function tryParseJsonString(str) {
|
|
2
|
+
if (typeof str === "string" &&
|
|
3
|
+
str.length >= 2 &&
|
|
4
|
+
((str.startsWith("{") && str.endsWith("}")) ||
|
|
5
|
+
(str.startsWith("[") && str.endsWith("]")))) {
|
|
6
|
+
try {
|
|
7
|
+
return JSON.parse(str);
|
|
8
|
+
}
|
|
9
|
+
catch {
|
|
10
|
+
return str;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
return str;
|
|
14
|
+
}
|
|
15
|
+
function parseNestedJsonStrings(obj) {
|
|
16
|
+
if (Array.isArray(obj)) {
|
|
17
|
+
return obj.map(parseNestedJsonStrings);
|
|
18
|
+
}
|
|
19
|
+
if (obj !== null && typeof obj === "object") {
|
|
20
|
+
const result = {};
|
|
21
|
+
for (const key in obj) {
|
|
22
|
+
if (Object.prototype.hasOwnProperty.call(obj, key)) {
|
|
23
|
+
result[key] = parseNestedJsonStrings(obj[key]);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return result;
|
|
27
|
+
}
|
|
28
|
+
if (typeof obj === "string") {
|
|
29
|
+
return tryParseJsonString(obj);
|
|
30
|
+
}
|
|
31
|
+
return obj;
|
|
32
|
+
}
|
|
33
|
+
const TRAILING_COMMA_REGEX = /,\s*([}\]])/g;
|
|
34
|
+
const SINGLE_LINE_COMMENT_REGEX = /\/\/[^\r\n]*/g;
|
|
35
|
+
const MULTI_LINE_COMMENT_REGEX = /\/\*[\s\S]*?\*\//g;
|
|
36
|
+
const FENCE_REGEX = /^```(?:json)?\s*([\s\S]*?)\s*```$/;
|
|
37
|
+
const JSON_TAG_REGEX = /<json>\s*([\s\S]*?)\s*<\/json>/;
|
|
38
|
+
const UNQUOTED_KEYS_REGEX = /([{,]\s*)([a-zA-Z_][a-zA-Z0-9_]*)\s*:/g;
|
|
1
39
|
/**
|
|
2
40
|
* Transforms a string, potentially containing JSON embedded in Markdown
|
|
3
41
|
* or with non-standard features like comments and trailing commas,
|
|
@@ -7,94 +45,87 @@
|
|
|
7
45
|
* @returns A parsed JavaScript object/array, or null if parsing fails.
|
|
8
46
|
*/
|
|
9
47
|
export function markdownToJson(markdownJsonString) {
|
|
10
|
-
if (typeof markdownJsonString !== "string"
|
|
48
|
+
if (typeof markdownJsonString !== "string")
|
|
11
49
|
return null;
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
const fenceMatch =
|
|
16
|
-
if (fenceMatch && fenceMatch[1]) {
|
|
17
|
-
|
|
50
|
+
let jsonString = markdownJsonString.trim();
|
|
51
|
+
if (!jsonString)
|
|
52
|
+
return null;
|
|
53
|
+
const fenceMatch = jsonString.match(FENCE_REGEX);
|
|
54
|
+
if (fenceMatch && fenceMatch[1] !== undefined) {
|
|
55
|
+
jsonString = fenceMatch[1].trim();
|
|
18
56
|
}
|
|
19
57
|
else {
|
|
20
|
-
const
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
S = jsonTagMatch[1].trim();
|
|
58
|
+
const jsonTagMatch = jsonString.match(JSON_TAG_REGEX);
|
|
59
|
+
if (jsonTagMatch && jsonTagMatch[1] !== undefined) {
|
|
60
|
+
jsonString = jsonTagMatch[1].trim();
|
|
24
61
|
}
|
|
25
62
|
}
|
|
26
|
-
if (
|
|
63
|
+
if (jsonString === "")
|
|
27
64
|
return null;
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
65
|
+
let parsedJson;
|
|
66
|
+
try {
|
|
67
|
+
parsedJson = JSON.parse(jsonString);
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
let cleanedJson = jsonString;
|
|
71
|
+
cleanedJson = cleanedJson.replace(SINGLE_LINE_COMMENT_REGEX, "");
|
|
72
|
+
cleanedJson = cleanedJson.replace(MULTI_LINE_COMMENT_REGEX, "");
|
|
73
|
+
cleanedJson = cleanedJson.trim();
|
|
74
|
+
if (cleanedJson === "")
|
|
75
|
+
return null;
|
|
76
|
+
cleanedJson = cleanedJson.replace(TRAILING_COMMA_REGEX, "$1");
|
|
77
|
+
cleanedJson = cleanedJson.replace(UNQUOTED_KEYS_REGEX, '$1"$2":');
|
|
78
|
+
try {
|
|
79
|
+
parsedJson = JSON.parse(cleanedJson);
|
|
80
|
+
}
|
|
81
|
+
catch (error) {
|
|
82
|
+
console.error("Failed to parse JSON after transformations.");
|
|
83
|
+
console.error("Original string:", markdownJsonString);
|
|
84
|
+
console.error("String after extraction (before cleaning):", jsonString);
|
|
85
|
+
console.error("Processed string that failed parsing:", cleanedJson);
|
|
86
|
+
console.error("Error:", error);
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
32
90
|
try {
|
|
33
|
-
const parsedJson = JSON.parse(S);
|
|
34
91
|
return parseNestedJsonStrings(parsedJson);
|
|
35
92
|
}
|
|
36
93
|
catch (error) {
|
|
37
|
-
console.error("
|
|
38
|
-
console.error("
|
|
39
|
-
console.error("Processed string that failed:", S);
|
|
94
|
+
console.error("Error during nested JSON string parsing:");
|
|
95
|
+
console.error("Parsed object before nested parsing:", parsedJson);
|
|
40
96
|
console.error("Error:", error);
|
|
41
97
|
return null;
|
|
42
98
|
}
|
|
43
99
|
}
|
|
44
|
-
function tryParseJsonString(str) {
|
|
45
|
-
try {
|
|
46
|
-
if (typeof str === "string" &&
|
|
47
|
-
((str.startsWith("[") && str.endsWith("]")) ||
|
|
48
|
-
(str.startsWith("{") && str.endsWith("}")))) {
|
|
49
|
-
return JSON.parse(str);
|
|
50
|
-
}
|
|
51
|
-
return str;
|
|
52
|
-
}
|
|
53
|
-
catch {
|
|
54
|
-
return str;
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
function parseNestedJsonStrings(obj) {
|
|
58
|
-
if (Array.isArray(obj)) {
|
|
59
|
-
return obj.map((item) => parseNestedJsonStrings(item));
|
|
60
|
-
}
|
|
61
|
-
else if (obj !== null && typeof obj === "object") {
|
|
62
|
-
const result = {};
|
|
63
|
-
for (const key of Object.keys(obj)) {
|
|
64
|
-
result[key] = parseNestedJsonStrings(obj[key]);
|
|
65
|
-
}
|
|
66
|
-
return result;
|
|
67
|
-
}
|
|
68
|
-
else if (typeof obj === "string") {
|
|
69
|
-
return tryParseJsonString(obj);
|
|
70
|
-
}
|
|
71
|
-
return obj;
|
|
72
|
-
}
|
|
73
100
|
/**
|
|
74
101
|
* Recursively removes null values from an object, replacing them with undefined
|
|
75
102
|
* This ensures optional parameters are properly handled by JSON schema validation
|
|
76
103
|
*/
|
|
77
|
-
export function
|
|
78
|
-
if (
|
|
79
|
-
return
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
else {
|
|
96
|
-
result[key] = value;
|
|
104
|
+
export function convertNullToUndefined(obj, seen = new WeakMap()) {
|
|
105
|
+
if (obj === null)
|
|
106
|
+
return undefined;
|
|
107
|
+
if (obj === undefined || typeof obj !== "object")
|
|
108
|
+
return obj;
|
|
109
|
+
if (seen.has(obj))
|
|
110
|
+
return seen.get(obj);
|
|
111
|
+
if (obj instanceof Date)
|
|
112
|
+
return new Date(obj.getTime());
|
|
113
|
+
if (obj instanceof RegExp)
|
|
114
|
+
return new RegExp(obj.source, obj.flags);
|
|
115
|
+
if (Array.isArray(obj)) {
|
|
116
|
+
const result = [];
|
|
117
|
+
seen.set(obj, result);
|
|
118
|
+
for (const item of obj) {
|
|
119
|
+
result.push(convertNullToUndefined(item, seen));
|
|
97
120
|
}
|
|
121
|
+
return result;
|
|
122
|
+
}
|
|
123
|
+
const result = {};
|
|
124
|
+
seen.set(obj, result);
|
|
125
|
+
const keys = Object.keys(obj);
|
|
126
|
+
for (const key of keys) {
|
|
127
|
+
const value = obj[key];
|
|
128
|
+
result[key] = convertNullToUndefined(value, seen);
|
|
98
129
|
}
|
|
99
130
|
return result;
|
|
100
131
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mcp-meilisearch",
|
|
3
|
-
"version": "1.4.
|
|
3
|
+
"version": "1.4.9",
|
|
4
4
|
"description": "Model Context Protocol (MCP) implementation for Meilisearch",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
"@modelcontextprotocol/sdk": "^1.11.4",
|
|
34
34
|
"axios": "^1.9.0",
|
|
35
35
|
"openai": "^4.100.0",
|
|
36
|
-
"zod": "^3.25.
|
|
36
|
+
"zod": "^3.25.7"
|
|
37
37
|
},
|
|
38
38
|
"devDependencies": {
|
|
39
39
|
"@types/node": "^22.15.19",
|