mcp-meilisearch 1.0.29 → 1.2.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.
@@ -1 +1 @@
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;AAInD;;;;GAIG;AACH,wBAAsB,oBAAoB,CACxC,OAAO,GAAE,aAGR,GACA,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAqGtB;AAkCD,eAAe,oBAAoB,CAAC"}
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"}
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { createServer } from "node:http";
2
- import { initServer } from "./server.js";
3
2
  import { parse as parseUrl } from "node:url";
3
+ import { initServer } from "./server.js";
4
4
  import { configHandler } from "./utils/config-handler.js";
5
5
  import { createErrorResponse } from "./utils/error-handler.js";
6
6
  /**
@@ -14,9 +14,9 @@ export async function mcpMeilisearchServer(options = {
14
14
  }) {
15
15
  configHandler.setMeilisearchHost(options.meilisearchHost);
16
16
  configHandler.setMeilisearchApiKey(options.meilisearchApiKey);
17
- let mcpServerInstance = null;
18
17
  const httpPort = options.httpPort || 4995;
19
18
  const transport = options.transport || "http";
19
+ let mcpServerInstance = null;
20
20
  const mcpEndpoint = options.mcpEndpoint || "/mcp";
21
21
  const server = createServer(async (req, res) => {
22
22
  res.setHeader("Access-Control-Allow-Origin", "*");
@@ -53,7 +53,13 @@ export async function mcpMeilisearchServer(options = {
53
53
  req.on("end", async () => {
54
54
  try {
55
55
  const jsonBody = JSON.parse(body);
56
- await mcpServerInstance.handlePostRequest(req, res, jsonBody);
56
+ if (mcpServerInstance) {
57
+ await mcpServerInstance.handlePostRequest(req, res, jsonBody);
58
+ }
59
+ else {
60
+ res.statusCode = 503;
61
+ res.end(JSON.stringify(createErrorResponse("MCP server not initialized yet")));
62
+ }
57
63
  }
58
64
  catch {
59
65
  res.statusCode = 400;
package/dist/server.d.ts CHANGED
@@ -12,14 +12,13 @@ interface ServerConfig {
12
12
  /**
13
13
  * Return type for the initServer function
14
14
  */
15
- interface ServerInstances {
16
- mcpServer?: MCPServer;
17
- viteServer?: any;
15
+ interface ServerInstance {
16
+ mcpServer: MCPServer;
18
17
  }
19
18
  /**
20
19
  * Implementation of an MCP server for Meilisearch
21
20
  */
22
- declare class MCPServer {
21
+ export declare class MCPServer {
23
22
  private readonly JSON_RPC;
24
23
  private readonly SESSION_ID_HEADER_NAME;
25
24
  private server;
@@ -95,6 +94,6 @@ declare class MCPServer {
95
94
  * @returns A promise that resolves to the server instances
96
95
  * @throws Error if the transport type is unsupported
97
96
  */
98
- export declare const initServer: (transport: "stdio" | "http", config?: Partial<ServerConfig>) => Promise<ServerInstances>;
97
+ export declare const initServer: (transport: "stdio" | "http", config?: Partial<ServerConfig>) => Promise<ServerInstance>;
99
98
  export {};
100
99
  //# sourceMappingURL=server.d.ts.map
@@ -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,eAAe;IACvB,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,UAAU,CAAC,EAAE,GAAG,CAAC;CAClB;AAiBD;;GAEG;AACH,cAAM,SAAS;IACb,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,eAAe,CAczB,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;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"}
package/dist/server.js CHANGED
@@ -20,7 +20,7 @@ const DEFAULT_CONFIG = {
20
20
  /**
21
21
  * Implementation of an MCP server for Meilisearch
22
22
  */
23
- class MCPServer {
23
+ export class MCPServer {
24
24
  JSON_RPC = "2.0";
25
25
  SESSION_ID_HEADER_NAME = "mcp-session-id";
26
26
  server;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mcp-meilisearch",
3
- "version": "1.0.29",
3
+ "version": "1.2.0",
4
4
  "description": "Model Context Protocol (MCP) implementation for Meilisearch",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -24,9 +24,9 @@
24
24
  ],
25
25
  "scripts": {
26
26
  "build": "tsc && tsc --project tsconfig.types.json",
27
- "server": "npm run build && node --env-file=.env dist",
28
27
  "demo": "npm run build & npm run dev --workspace=demo",
29
- "prepublishOnly": "npm version patch && npm run build"
28
+ "server": "npm run build && node --env-file=.env dist/index.js",
29
+ "prepublishOnly": "rm -rf dist && npm version minor && npm run build"
30
30
  },
31
31
  "dependencies": {
32
32
  "@modelcontextprotocol/sdk": "^1.10.1",
@@ -1,4 +0,0 @@
1
- import { AzureFunction } from "@azure/functions";
2
- declare const httpTrigger: AzureFunction;
3
- export default httpTrigger;
4
- //# sourceMappingURL=index.d.ts.map
@@ -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"}
@@ -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;