mcp-meilisearch 1.0.29 → 1.1.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/package.json +2 -2
- package/dist/azure/index.d.ts +0 -4
- package/dist/azure/index.d.ts.map +0 -1
- package/dist/azure/index.js +0 -196
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mcp-meilisearch",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "Model Context Protocol (MCP) implementation for Meilisearch",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
"build": "tsc && tsc --project tsconfig.types.json",
|
|
27
27
|
"server": "npm run build && node --env-file=.env dist",
|
|
28
28
|
"demo": "npm run build & npm run dev --workspace=demo",
|
|
29
|
-
"prepublishOnly": "npm version
|
|
29
|
+
"prepublishOnly": "rm -rf dist && npm version minor && npm run build"
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
32
|
"@modelcontextprotocol/sdk": "^1.10.1",
|
package/dist/azure/index.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/azure/index.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,aAAa,EAAwB,MAAM,kBAAkB,CAAC;AAsFvE,QAAA,MAAM,WAAW,EAAE,aAgHlB,CAAC;AA8BF,eAAe,WAAW,CAAC"}
|
package/dist/azure/index.js
DELETED
|
@@ -1,196 +0,0 @@
|
|
|
1
|
-
import { IncomingMessage } from "http";
|
|
2
|
-
import { randomUUID } from "node:crypto";
|
|
3
|
-
import { initServer } from "../server.js";
|
|
4
|
-
import { configHandler } from "../utils/config-handler.js";
|
|
5
|
-
import { createErrorResponse } from "../utils/error-handler.js";
|
|
6
|
-
const SESSION_ID_HEADER_NAME = "mcp-session-id";
|
|
7
|
-
const SESSION_TIMEOUT = Number(process.env.SESSION_TIMEOUT) || 3600000;
|
|
8
|
-
let mcpServer = null;
|
|
9
|
-
const sessions = new Map();
|
|
10
|
-
const baseHeaders = {
|
|
11
|
-
"Access-Control-Allow-Origin": process.env.ALLOWED_ORIGINS || "*",
|
|
12
|
-
"Access-Control-Allow-Methods": "GET, POST, OPTIONS",
|
|
13
|
-
"Access-Control-Allow-Headers": `Origin, X-Requested-With, Content-Type, Accept, ${SESSION_ID_HEADER_NAME}`,
|
|
14
|
-
};
|
|
15
|
-
function adaptRequest(req) {
|
|
16
|
-
const adaptedReq = Object.create(IncomingMessage.prototype);
|
|
17
|
-
adaptedReq.headers = req.headers;
|
|
18
|
-
adaptedReq.method = req.method;
|
|
19
|
-
adaptedReq.url = req.url;
|
|
20
|
-
adaptedReq.body = req.body;
|
|
21
|
-
return adaptedReq;
|
|
22
|
-
}
|
|
23
|
-
function createResponseAdapter(context, extraHeaders = {}) {
|
|
24
|
-
const res = {
|
|
25
|
-
headers: new Map(),
|
|
26
|
-
statusCode: 200,
|
|
27
|
-
bodyChunks: [],
|
|
28
|
-
setHeader(name, value) {
|
|
29
|
-
this.headers.set(name, value);
|
|
30
|
-
return this;
|
|
31
|
-
},
|
|
32
|
-
writeHead(statusCode, headers) {
|
|
33
|
-
this.statusCode = statusCode;
|
|
34
|
-
if (headers && !Array.isArray(headers)) {
|
|
35
|
-
Object.entries(headers).forEach(([k, v]) => this.headers.set(k, v));
|
|
36
|
-
}
|
|
37
|
-
return this;
|
|
38
|
-
},
|
|
39
|
-
write(chunk) {
|
|
40
|
-
if (chunk)
|
|
41
|
-
this.bodyChunks.push(chunk);
|
|
42
|
-
return this;
|
|
43
|
-
},
|
|
44
|
-
end(data) {
|
|
45
|
-
if (data)
|
|
46
|
-
this.bodyChunks.push(data);
|
|
47
|
-
const responseHeaders = {};
|
|
48
|
-
this.headers.forEach((value, key) => {
|
|
49
|
-
responseHeaders[key] = value;
|
|
50
|
-
});
|
|
51
|
-
context.res = {
|
|
52
|
-
status: this.statusCode,
|
|
53
|
-
headers: { ...responseHeaders, ...baseHeaders, ...extraHeaders },
|
|
54
|
-
body: this.bodyChunks.join(""),
|
|
55
|
-
};
|
|
56
|
-
return this;
|
|
57
|
-
},
|
|
58
|
-
};
|
|
59
|
-
return res;
|
|
60
|
-
}
|
|
61
|
-
function sendError(context, status, message) {
|
|
62
|
-
context.res = {
|
|
63
|
-
status,
|
|
64
|
-
headers: { "Content-Type": "application/json", ...baseHeaders },
|
|
65
|
-
body: JSON.stringify(createErrorResponse(message)),
|
|
66
|
-
};
|
|
67
|
-
}
|
|
68
|
-
const httpTrigger = async function (context, req) {
|
|
69
|
-
if (!mcpServer) {
|
|
70
|
-
try {
|
|
71
|
-
const options = {
|
|
72
|
-
httpPort: 0,
|
|
73
|
-
transport: "http",
|
|
74
|
-
mcpEndpoint: "/api/mcp",
|
|
75
|
-
meilisearchApiKey: process.env.MEILISEARCH_API_KEY || "",
|
|
76
|
-
meilisearchHost: process.env.MEILISEARCH_HOST || "http://localhost:7700",
|
|
77
|
-
};
|
|
78
|
-
configHandler.setMeilisearchHost(options.meilisearchHost);
|
|
79
|
-
configHandler.setMeilisearchApiKey(options.meilisearchApiKey);
|
|
80
|
-
const server = await initServer("http", options);
|
|
81
|
-
if (server.mcpServer) {
|
|
82
|
-
mcpServer = server.mcpServer;
|
|
83
|
-
context.log("MCP server initialized successfully");
|
|
84
|
-
}
|
|
85
|
-
else {
|
|
86
|
-
throw new Error("Failed to initialize MCP server");
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
catch (error) {
|
|
90
|
-
sendError(context, 503, "Failed to initialize MCP server");
|
|
91
|
-
return;
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
if (req.method === "OPTIONS") {
|
|
95
|
-
context.res = { status: 200, headers: baseHeaders, body: "" };
|
|
96
|
-
return;
|
|
97
|
-
}
|
|
98
|
-
const sessionId = req.headers[SESSION_ID_HEADER_NAME.toLowerCase()];
|
|
99
|
-
try {
|
|
100
|
-
if (req.method === "GET") {
|
|
101
|
-
if (!sessionId || !sessions.has(sessionId)) {
|
|
102
|
-
sendError(context, 400, "Bad Request: invalid session ID");
|
|
103
|
-
return;
|
|
104
|
-
}
|
|
105
|
-
const session = sessions.get(sessionId);
|
|
106
|
-
session.lastActivity = Date.now();
|
|
107
|
-
try {
|
|
108
|
-
const res = createResponseAdapter(context);
|
|
109
|
-
await mcpServer.handleGetRequest(adaptRequest(req), res);
|
|
110
|
-
if (!context.res)
|
|
111
|
-
res.end();
|
|
112
|
-
}
|
|
113
|
-
catch (error) {
|
|
114
|
-
context.log.error(`Error handling GET request: ${error}`);
|
|
115
|
-
sendError(context, 500, `Error in GET request: ${error}`);
|
|
116
|
-
}
|
|
117
|
-
return;
|
|
118
|
-
}
|
|
119
|
-
if (req.method === "POST") {
|
|
120
|
-
if (sessionId && sessions.has(sessionId)) {
|
|
121
|
-
const session = sessions.get(sessionId);
|
|
122
|
-
session.lastActivity = Date.now();
|
|
123
|
-
try {
|
|
124
|
-
const res = createResponseAdapter(context);
|
|
125
|
-
await mcpServer.handlePostRequest(adaptRequest(req), res, req.body);
|
|
126
|
-
if (!context.res)
|
|
127
|
-
res.end();
|
|
128
|
-
}
|
|
129
|
-
catch (error) {
|
|
130
|
-
context.log.error(`Error handling POST request: ${error}`);
|
|
131
|
-
sendError(context, 500, `Error in POST request: ${error}`);
|
|
132
|
-
}
|
|
133
|
-
return;
|
|
134
|
-
}
|
|
135
|
-
if (mcpServer.isInitializeRequest?.(req.body)) {
|
|
136
|
-
const newSessionId = randomUUID();
|
|
137
|
-
sessions.set(newSessionId, {
|
|
138
|
-
transport: null,
|
|
139
|
-
lastActivity: Date.now(),
|
|
140
|
-
});
|
|
141
|
-
try {
|
|
142
|
-
const res = createResponseAdapter(context, {
|
|
143
|
-
[SESSION_ID_HEADER_NAME]: newSessionId,
|
|
144
|
-
"Access-Control-Expose-Headers": SESSION_ID_HEADER_NAME,
|
|
145
|
-
});
|
|
146
|
-
await mcpServer.handlePostRequest(adaptRequest(req), res, req.body);
|
|
147
|
-
if (!context.res)
|
|
148
|
-
res.end();
|
|
149
|
-
context.log(`New session created: ${newSessionId}`);
|
|
150
|
-
}
|
|
151
|
-
catch (error) {
|
|
152
|
-
context.log.error(`Error initializing session: ${error}`);
|
|
153
|
-
sessions.delete(newSessionId);
|
|
154
|
-
sendError(context, 500, `Error initializing session: ${error}`);
|
|
155
|
-
}
|
|
156
|
-
return;
|
|
157
|
-
}
|
|
158
|
-
sendError(context, 400, "Invalid request: missing session ID or not an initialize request");
|
|
159
|
-
return;
|
|
160
|
-
}
|
|
161
|
-
sendError(context, 405, "Method not allowed");
|
|
162
|
-
}
|
|
163
|
-
catch (error) {
|
|
164
|
-
context.log.error(`Error handling MCP request: ${error}`);
|
|
165
|
-
sendError(context, 500, `Internal server error: ${error}`);
|
|
166
|
-
}
|
|
167
|
-
};
|
|
168
|
-
const cleanupInterval = setInterval(() => {
|
|
169
|
-
const now = Date.now();
|
|
170
|
-
for (const [id, info] of sessions.entries()) {
|
|
171
|
-
if (now - info.lastActivity > SESSION_TIMEOUT) {
|
|
172
|
-
try {
|
|
173
|
-
if (info.transport)
|
|
174
|
-
info.transport.close();
|
|
175
|
-
sessions.delete(id);
|
|
176
|
-
}
|
|
177
|
-
catch (error) {
|
|
178
|
-
console.error(`Error cleaning up session ${id}:`, error);
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
}, 60000);
|
|
183
|
-
if (typeof process !== "undefined" && process.env.FUNCTIONS_WORKER_RUNTIME) {
|
|
184
|
-
process.on("SIGTERM", () => {
|
|
185
|
-
clearInterval(cleanupInterval);
|
|
186
|
-
if (mcpServer && typeof mcpServer.shutdown === "function") {
|
|
187
|
-
try {
|
|
188
|
-
mcpServer.shutdown();
|
|
189
|
-
}
|
|
190
|
-
catch (error) {
|
|
191
|
-
console.error(`Error shutting down MCP server: ${error}`);
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
});
|
|
195
|
-
}
|
|
196
|
-
export default httpTrigger;
|