mcp-meilisearch 1.0.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 +108 -0
- package/dist/client.js +146 -0
- package/dist/config.js +20 -0
- package/dist/http.js +2 -0
- package/dist/index.js +2 -0
- package/dist/server.js +383 -0
- package/dist/stdio.js +2 -0
- package/dist/tools/document-tools.js +208 -0
- package/dist/tools/index-tools.js +146 -0
- package/dist/tools/search-tools.js +221 -0
- package/dist/tools/settings-tools.js +309 -0
- package/dist/tools/system-tools.js +210 -0
- package/dist/tools/task-tools.js +190 -0
- package/dist/tools/vector-tools.js +214 -0
- package/dist/utils/api-handler.js +33 -0
- package/dist/utils/error-handler.js +35 -0
- package/package.json +42 -0
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import apiClient from "../utils/api-handler.js";
|
|
3
|
+
import { createErrorResponse } from "../utils/error-handler.js";
|
|
4
|
+
/**
|
|
5
|
+
* Register task management tools with the MCP server
|
|
6
|
+
*
|
|
7
|
+
* @param server - The MCP server instance
|
|
8
|
+
*/
|
|
9
|
+
export const registerTaskTools = (server) => {
|
|
10
|
+
// Get all tasks
|
|
11
|
+
server.tool("list-tasks", "List tasks with optional filtering", {
|
|
12
|
+
limit: z
|
|
13
|
+
.number()
|
|
14
|
+
.min(0)
|
|
15
|
+
.optional()
|
|
16
|
+
.describe("Maximum number of tasks to return"),
|
|
17
|
+
from: z
|
|
18
|
+
.number()
|
|
19
|
+
.min(0)
|
|
20
|
+
.optional()
|
|
21
|
+
.describe("Task uid from which to start fetching"),
|
|
22
|
+
statuses: z
|
|
23
|
+
.array(z.enum(["enqueued", "processing", "succeeded", "failed", "canceled"]))
|
|
24
|
+
.optional()
|
|
25
|
+
.describe("Statuses of tasks to return"),
|
|
26
|
+
types: z
|
|
27
|
+
.array(z.enum([
|
|
28
|
+
"indexCreation",
|
|
29
|
+
"indexUpdate",
|
|
30
|
+
"indexDeletion",
|
|
31
|
+
"documentAddition",
|
|
32
|
+
"documentUpdate",
|
|
33
|
+
"documentDeletion",
|
|
34
|
+
"settingsUpdate",
|
|
35
|
+
"dumpCreation",
|
|
36
|
+
"taskCancelation",
|
|
37
|
+
]))
|
|
38
|
+
.optional()
|
|
39
|
+
.describe("Types of tasks to return"),
|
|
40
|
+
indexUids: z
|
|
41
|
+
.array(z.string())
|
|
42
|
+
.optional()
|
|
43
|
+
.describe("UIDs of the indexes on which tasks were performed"),
|
|
44
|
+
uids: z
|
|
45
|
+
.array(z.number())
|
|
46
|
+
.optional()
|
|
47
|
+
.describe("UIDs of specific tasks to return"),
|
|
48
|
+
}, async ({ limit, from, statuses, types, indexUids, uids, }) => {
|
|
49
|
+
try {
|
|
50
|
+
const params = {};
|
|
51
|
+
if (limit !== undefined)
|
|
52
|
+
params.limit = limit;
|
|
53
|
+
if (from !== undefined)
|
|
54
|
+
params.from = from;
|
|
55
|
+
if (statuses && statuses.length > 0)
|
|
56
|
+
params.statuses = statuses.join(",");
|
|
57
|
+
if (types && types.length > 0)
|
|
58
|
+
params.types = types.join(",");
|
|
59
|
+
if (indexUids && indexUids.length > 0)
|
|
60
|
+
params.indexUids = indexUids.join(",");
|
|
61
|
+
if (uids && uids.length > 0)
|
|
62
|
+
params.uids = uids.join(",");
|
|
63
|
+
const response = await apiClient.get("/tasks", { params });
|
|
64
|
+
return {
|
|
65
|
+
content: [
|
|
66
|
+
{ type: "text", text: JSON.stringify(response.data, null, 2) },
|
|
67
|
+
],
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
catch (error) {
|
|
71
|
+
return createErrorResponse(error);
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
// Get a specific task
|
|
75
|
+
server.tool("get-task", "Get information about a specific task", {
|
|
76
|
+
taskUid: z.number().describe("Unique identifier of the task"),
|
|
77
|
+
}, async ({ taskUid }) => {
|
|
78
|
+
try {
|
|
79
|
+
const response = await apiClient.get(`/tasks/${taskUid}`);
|
|
80
|
+
return {
|
|
81
|
+
content: [
|
|
82
|
+
{ type: "text", text: JSON.stringify(response.data, null, 2) },
|
|
83
|
+
],
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
catch (error) {
|
|
87
|
+
return createErrorResponse(error);
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
// Cancel tasks
|
|
91
|
+
server.tool("cancel-tasks", "Cancel tasks based on provided filters", {
|
|
92
|
+
statuses: z
|
|
93
|
+
.array(z.enum(["enqueued", "processing"]))
|
|
94
|
+
.optional()
|
|
95
|
+
.describe("Statuses of tasks to cancel"),
|
|
96
|
+
types: z
|
|
97
|
+
.array(z.enum([
|
|
98
|
+
"indexCreation",
|
|
99
|
+
"indexUpdate",
|
|
100
|
+
"indexDeletion",
|
|
101
|
+
"documentAddition",
|
|
102
|
+
"documentUpdate",
|
|
103
|
+
"documentDeletion",
|
|
104
|
+
"settingsUpdate",
|
|
105
|
+
"dumpCreation",
|
|
106
|
+
"taskCancelation",
|
|
107
|
+
]))
|
|
108
|
+
.optional()
|
|
109
|
+
.describe("Types of tasks to cancel"),
|
|
110
|
+
indexUids: z
|
|
111
|
+
.array(z.string())
|
|
112
|
+
.optional()
|
|
113
|
+
.describe("UIDs of the indexes on which tasks to cancel were performed"),
|
|
114
|
+
uids: z
|
|
115
|
+
.array(z.number())
|
|
116
|
+
.optional()
|
|
117
|
+
.describe("UIDs of the tasks to cancel"),
|
|
118
|
+
}, async ({ statuses, types, indexUids, uids }) => {
|
|
119
|
+
try {
|
|
120
|
+
const body = {};
|
|
121
|
+
if (statuses && statuses.length > 0)
|
|
122
|
+
body.statuses = statuses;
|
|
123
|
+
if (types && types.length > 0)
|
|
124
|
+
body.types = types;
|
|
125
|
+
if (indexUids && indexUids.length > 0)
|
|
126
|
+
body.indexUids = indexUids;
|
|
127
|
+
if (uids && uids.length > 0)
|
|
128
|
+
body.uids = uids;
|
|
129
|
+
const response = await apiClient.post("/tasks/cancel", body);
|
|
130
|
+
return {
|
|
131
|
+
content: [
|
|
132
|
+
{ type: "text", text: JSON.stringify(response.data, null, 2) },
|
|
133
|
+
],
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
catch (error) {
|
|
137
|
+
return createErrorResponse(error);
|
|
138
|
+
}
|
|
139
|
+
});
|
|
140
|
+
// Wait for a task to complete
|
|
141
|
+
server.tool("wait-for-task", "Wait for a specific task to complete", {
|
|
142
|
+
taskUid: z.number().describe("Unique identifier of the task to wait for"),
|
|
143
|
+
timeoutMs: z
|
|
144
|
+
.number()
|
|
145
|
+
.min(0)
|
|
146
|
+
.optional()
|
|
147
|
+
.describe("Maximum time to wait in milliseconds (default: 5000)"),
|
|
148
|
+
intervalMs: z
|
|
149
|
+
.number()
|
|
150
|
+
.min(100)
|
|
151
|
+
.optional()
|
|
152
|
+
.describe("Polling interval in milliseconds (default: 500)"),
|
|
153
|
+
}, async ({ taskUid, timeoutMs = 5000, intervalMs = 500, }) => {
|
|
154
|
+
try {
|
|
155
|
+
const startTime = Date.now();
|
|
156
|
+
let taskCompleted = false;
|
|
157
|
+
let taskData = null;
|
|
158
|
+
while (!taskCompleted && Date.now() - startTime < timeoutMs) {
|
|
159
|
+
// Fetch the current task status
|
|
160
|
+
const response = await apiClient.get(`/tasks/${taskUid}`);
|
|
161
|
+
taskData = response.data;
|
|
162
|
+
// Check if the task has completed
|
|
163
|
+
if (["succeeded", "failed", "canceled"].includes(taskData.status)) {
|
|
164
|
+
taskCompleted = true;
|
|
165
|
+
}
|
|
166
|
+
else {
|
|
167
|
+
// Wait for the polling interval
|
|
168
|
+
await new Promise((resolve) => setTimeout(resolve, intervalMs));
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
if (!taskCompleted) {
|
|
172
|
+
return {
|
|
173
|
+
content: [
|
|
174
|
+
{
|
|
175
|
+
type: "text",
|
|
176
|
+
text: `Task ${taskUid} did not complete within the timeout period of ${timeoutMs}ms`,
|
|
177
|
+
},
|
|
178
|
+
],
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
return {
|
|
182
|
+
content: [{ type: "text", text: JSON.stringify(taskData, null, 2) }],
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
catch (error) {
|
|
186
|
+
return createErrorResponse(error);
|
|
187
|
+
}
|
|
188
|
+
});
|
|
189
|
+
};
|
|
190
|
+
export default registerTaskTools;
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import apiClient from "../utils/api-handler.js";
|
|
3
|
+
import { createErrorResponse } from "../utils/error-handler.js";
|
|
4
|
+
/**
|
|
5
|
+
* Meilisearch Vector Search Tools
|
|
6
|
+
*
|
|
7
|
+
* This module implements MCP tools for vector search capabilities in Meilisearch.
|
|
8
|
+
* Note: Vector search is an experimental feature in Meilisearch.
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Register vector search tools with the MCP server
|
|
12
|
+
*
|
|
13
|
+
* @param server - The MCP server instance
|
|
14
|
+
*/
|
|
15
|
+
export const registerVectorTools = (server) => {
|
|
16
|
+
// Enable vector search experimental feature
|
|
17
|
+
server.tool("enable-vector-search", "Enable the vector search experimental feature in Meilisearch", {}, async () => {
|
|
18
|
+
try {
|
|
19
|
+
const response = await apiClient.post("/experimental-features", {
|
|
20
|
+
vectorStore: true,
|
|
21
|
+
});
|
|
22
|
+
return {
|
|
23
|
+
content: [
|
|
24
|
+
{ type: "text", text: JSON.stringify(response.data, null, 2) },
|
|
25
|
+
],
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
catch (error) {
|
|
29
|
+
return createErrorResponse(error);
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
// Get experimental features status
|
|
33
|
+
server.tool("get-experimental-features", "Get the status of experimental features in Meilisearch", {}, async () => {
|
|
34
|
+
try {
|
|
35
|
+
const response = await apiClient.get("/experimental-features");
|
|
36
|
+
return {
|
|
37
|
+
content: [
|
|
38
|
+
{ type: "text", text: JSON.stringify(response.data, null, 2) },
|
|
39
|
+
],
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
catch (error) {
|
|
43
|
+
return createErrorResponse(error);
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
// Update embedders configuration
|
|
47
|
+
server.tool("update-embedders", "Configure embedders for vector search", {
|
|
48
|
+
indexUid: z.string().describe("Unique identifier of the index"),
|
|
49
|
+
embedders: z
|
|
50
|
+
.string()
|
|
51
|
+
.describe("JSON object containing embedder configurations"),
|
|
52
|
+
}, async ({ indexUid, embedders }) => {
|
|
53
|
+
try {
|
|
54
|
+
// Parse the embedders string to ensure it's valid JSON
|
|
55
|
+
const parsedEmbedders = JSON.parse(embedders);
|
|
56
|
+
// Ensure embedders is an object
|
|
57
|
+
if (typeof parsedEmbedders !== "object" ||
|
|
58
|
+
parsedEmbedders === null ||
|
|
59
|
+
Array.isArray(parsedEmbedders)) {
|
|
60
|
+
return {
|
|
61
|
+
isError: true,
|
|
62
|
+
content: [
|
|
63
|
+
{ type: "text", text: "Embedders must be a JSON object" },
|
|
64
|
+
],
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
const response = await apiClient.patch(`/indexes/${indexUid}/settings/embedders`, parsedEmbedders);
|
|
68
|
+
return {
|
|
69
|
+
content: [
|
|
70
|
+
{ type: "text", text: JSON.stringify(response.data, null, 2) },
|
|
71
|
+
],
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
catch (error) {
|
|
75
|
+
return createErrorResponse(error);
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
// Get embedders configuration
|
|
79
|
+
server.tool("get-embedders", "Get the embedders configuration for an index", {
|
|
80
|
+
indexUid: z.string().describe("Unique identifier of the index"),
|
|
81
|
+
}, async ({ indexUid }) => {
|
|
82
|
+
try {
|
|
83
|
+
const response = await apiClient.get(`/indexes/${indexUid}/settings/embedders`);
|
|
84
|
+
return {
|
|
85
|
+
content: [
|
|
86
|
+
{ type: "text", text: JSON.stringify(response.data, null, 2) },
|
|
87
|
+
],
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
catch (error) {
|
|
91
|
+
return createErrorResponse(error);
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
// Reset embedders configuration
|
|
95
|
+
server.tool("reset-embedders", "Reset the embedders configuration for an index", {
|
|
96
|
+
indexUid: z.string().describe("Unique identifier of the index"),
|
|
97
|
+
}, async ({ indexUid }) => {
|
|
98
|
+
try {
|
|
99
|
+
const response = await apiClient.delete(`/indexes/${indexUid}/settings/embedders`);
|
|
100
|
+
return {
|
|
101
|
+
content: [
|
|
102
|
+
{ type: "text", text: JSON.stringify(response.data, null, 2) },
|
|
103
|
+
],
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
catch (error) {
|
|
107
|
+
return createErrorResponse(error);
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
// Perform vector search
|
|
111
|
+
server.tool("vector-search", "Perform a vector search in a Meilisearch index", {
|
|
112
|
+
indexUid: z.string().describe("Unique identifier of the index"),
|
|
113
|
+
vector: z
|
|
114
|
+
.string()
|
|
115
|
+
.describe("JSON array representing the vector to search for"),
|
|
116
|
+
limit: z
|
|
117
|
+
.number()
|
|
118
|
+
.min(1)
|
|
119
|
+
.max(1000)
|
|
120
|
+
.optional()
|
|
121
|
+
.describe("Maximum number of results to return (default: 20)"),
|
|
122
|
+
offset: z
|
|
123
|
+
.number()
|
|
124
|
+
.min(0)
|
|
125
|
+
.optional()
|
|
126
|
+
.describe("Number of results to skip (default: 0)"),
|
|
127
|
+
filter: z
|
|
128
|
+
.string()
|
|
129
|
+
.optional()
|
|
130
|
+
.describe("Filter to apply (e.g., 'genre = horror AND year > 2020')"),
|
|
131
|
+
embedder: z
|
|
132
|
+
.string()
|
|
133
|
+
.optional()
|
|
134
|
+
.describe("Name of the embedder to use (if omitted, a 'vector' must be provided)"),
|
|
135
|
+
attributes: z
|
|
136
|
+
.array(z.string())
|
|
137
|
+
.optional()
|
|
138
|
+
.describe("Attributes to include in the vector search"),
|
|
139
|
+
query: z
|
|
140
|
+
.string()
|
|
141
|
+
.optional()
|
|
142
|
+
.describe("Text query to search for (if using 'embedder' instead of 'vector')"),
|
|
143
|
+
hybrid: z
|
|
144
|
+
.boolean()
|
|
145
|
+
.optional()
|
|
146
|
+
.describe("Whether to perform a hybrid search (combining vector and text search)"),
|
|
147
|
+
hybridRatio: z
|
|
148
|
+
.number()
|
|
149
|
+
.min(0)
|
|
150
|
+
.max(1)
|
|
151
|
+
.optional()
|
|
152
|
+
.describe("Ratio of vector vs text search in hybrid search (0-1, default: 0.5)"),
|
|
153
|
+
}, async ({ indexUid, vector, limit, offset, filter, embedder, attributes, query, hybrid, hybridRatio, }) => {
|
|
154
|
+
try {
|
|
155
|
+
const searchParams = {};
|
|
156
|
+
// Add required vector parameter
|
|
157
|
+
if (vector) {
|
|
158
|
+
try {
|
|
159
|
+
searchParams.vector = JSON.parse(vector);
|
|
160
|
+
}
|
|
161
|
+
catch (parseError) {
|
|
162
|
+
return {
|
|
163
|
+
isError: true,
|
|
164
|
+
content: [
|
|
165
|
+
{ type: "text", text: "Vector must be a valid JSON array" },
|
|
166
|
+
],
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
// Add embedder parameters
|
|
171
|
+
if (embedder) {
|
|
172
|
+
searchParams.embedder = embedder;
|
|
173
|
+
if (query !== undefined) {
|
|
174
|
+
searchParams.q = query;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
// Ensure we have either vector or (embedder + query)
|
|
178
|
+
if (!vector && (!embedder || query === undefined)) {
|
|
179
|
+
return {
|
|
180
|
+
isError: true,
|
|
181
|
+
content: [
|
|
182
|
+
{
|
|
183
|
+
type: "text",
|
|
184
|
+
text: "Either 'vector' or both 'embedder' and 'query' must be provided",
|
|
185
|
+
},
|
|
186
|
+
],
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
// Add optional parameters
|
|
190
|
+
if (limit !== undefined)
|
|
191
|
+
searchParams.limit = limit;
|
|
192
|
+
if (offset !== undefined)
|
|
193
|
+
searchParams.offset = offset;
|
|
194
|
+
if (filter)
|
|
195
|
+
searchParams.filter = filter;
|
|
196
|
+
if (attributes?.length)
|
|
197
|
+
searchParams.attributes = attributes;
|
|
198
|
+
if (hybrid !== undefined)
|
|
199
|
+
searchParams.hybrid = hybrid;
|
|
200
|
+
if (hybridRatio !== undefined)
|
|
201
|
+
searchParams.hybridRatio = hybridRatio;
|
|
202
|
+
const response = await apiClient.post(`/indexes/${indexUid}/search`, searchParams);
|
|
203
|
+
return {
|
|
204
|
+
content: [
|
|
205
|
+
{ type: "text", text: JSON.stringify(response.data, null, 2) },
|
|
206
|
+
],
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
catch (error) {
|
|
210
|
+
return createErrorResponse(error);
|
|
211
|
+
}
|
|
212
|
+
});
|
|
213
|
+
};
|
|
214
|
+
export default registerVectorTools;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import axios from 'axios';
|
|
2
|
+
import config from '../config.js';
|
|
3
|
+
/**
|
|
4
|
+
* Meilisearch API client
|
|
5
|
+
*
|
|
6
|
+
* This module provides a configured Axios instance for making requests to the Meilisearch API.
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Creates a configured Axios instance for Meilisearch API requests
|
|
10
|
+
*
|
|
11
|
+
* @returns An Axios instance with base configuration
|
|
12
|
+
*/
|
|
13
|
+
export const createApiClient = () => {
|
|
14
|
+
const instance = axios.create({
|
|
15
|
+
baseURL: config.host,
|
|
16
|
+
headers: {
|
|
17
|
+
Authorization: `Bearer ${config.apiKey}`,
|
|
18
|
+
'Content-Type': 'application/json',
|
|
19
|
+
},
|
|
20
|
+
timeout: config.timeout,
|
|
21
|
+
});
|
|
22
|
+
return {
|
|
23
|
+
get: (url, config) => instance.get(url, config),
|
|
24
|
+
post: (url, data, config) => instance.post(url, data, config),
|
|
25
|
+
put: (url, data, config) => instance.put(url, data, config),
|
|
26
|
+
patch: (url, data, config) => instance.patch(url, data, config),
|
|
27
|
+
delete: (url, config) => instance.delete(url, config),
|
|
28
|
+
};
|
|
29
|
+
};
|
|
30
|
+
// Create and export a singleton instance of the API client
|
|
31
|
+
export const apiClient = createApiClient();
|
|
32
|
+
// Re-export for direct use
|
|
33
|
+
export default apiClient;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error handling utilities for Meilisearch API responses
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Formats Meilisearch API errors for consistent error messaging
|
|
6
|
+
*
|
|
7
|
+
* @param error - The error from the API request
|
|
8
|
+
* @returns A formatted error message
|
|
9
|
+
*/
|
|
10
|
+
export const handleApiError = (error) => {
|
|
11
|
+
// If it's an Axios error with a response
|
|
12
|
+
if (error.isAxiosError && error.response) {
|
|
13
|
+
const { status, data } = error.response;
|
|
14
|
+
// Return formatted error with status code and response data
|
|
15
|
+
return `Meilisearch API error (${status}): ${JSON.stringify(data)}`;
|
|
16
|
+
}
|
|
17
|
+
// If it's a network error or other error
|
|
18
|
+
return `Error connecting to Meilisearch: ${error.message}`;
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* Creates a standardized error response object for MCP tools
|
|
22
|
+
*
|
|
23
|
+
* @param error - The error from the API request
|
|
24
|
+
* @returns An MCP tool response object with error flag
|
|
25
|
+
*/
|
|
26
|
+
export const createErrorResponse = (error) => {
|
|
27
|
+
return {
|
|
28
|
+
isError: true,
|
|
29
|
+
content: [{ type: "text", text: handleApiError(error) }],
|
|
30
|
+
};
|
|
31
|
+
};
|
|
32
|
+
export default {
|
|
33
|
+
handleApiError,
|
|
34
|
+
createErrorResponse,
|
|
35
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "mcp-meilisearch",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Model Context Protocol (MCP) implementation for Meilisearch",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"files": [
|
|
9
|
+
"dist",
|
|
10
|
+
"README.md"
|
|
11
|
+
],
|
|
12
|
+
"workspaces": [
|
|
13
|
+
"client"
|
|
14
|
+
],
|
|
15
|
+
"scripts": {
|
|
16
|
+
"build:http": "tsc && chmod 755 dist/http.js",
|
|
17
|
+
"build:stdio": "tsc && chmod 755 dist/stdio.js",
|
|
18
|
+
"server": "npm run build:stdio && node --env-file=.env dist/stdio.js",
|
|
19
|
+
"client": "npm run build:http && node --env-file=.env dist/http.js & npm run preview --workspace=client",
|
|
20
|
+
"prepare": "tsc",
|
|
21
|
+
"prepublishOnly": "npm run build:http && npm run build:stdio"
|
|
22
|
+
},
|
|
23
|
+
"dependencies": {
|
|
24
|
+
"@modelcontextprotocol/sdk": "^1.10.1",
|
|
25
|
+
"axios": "^1.9.0",
|
|
26
|
+
"express": "^5.1.0",
|
|
27
|
+
"vue": "^3.5.13",
|
|
28
|
+
"zod": "^3.24.4"
|
|
29
|
+
},
|
|
30
|
+
"devDependencies": {
|
|
31
|
+
"@types/express": "^5.0.1",
|
|
32
|
+
"@types/node": "^22.14.0",
|
|
33
|
+
"@vitejs/plugin-vue": "^5.2.3",
|
|
34
|
+
"@vue/tsconfig": "^0.7.0",
|
|
35
|
+
"typescript": "^5.8.3",
|
|
36
|
+
"vite": "^6.3.5"
|
|
37
|
+
},
|
|
38
|
+
"engines": {
|
|
39
|
+
"node": ">=20.12.2",
|
|
40
|
+
"npm": ">=10.5.0"
|
|
41
|
+
}
|
|
42
|
+
}
|