mcp-meilisearch 1.0.6 → 1.0.7
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 +64 -1
- package/dist/config.d.ts +4 -4
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +1 -1
- package/dist/http.js +0 -0
- package/dist/index.d.ts +10 -15
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -38
- package/dist/server.d.ts +9 -11
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +14 -27
- package/dist/utils/api-handler.d.ts +2 -1
- package/dist/utils/api-handler.d.ts.map +1 -1
- package/dist/utils/api-handler.js +9 -10
- package/dist/utils/config-handler.d.ts +30 -0
- package/dist/utils/config-handler.d.ts.map +1 -0
- package/dist/utils/config-handler.js +37 -0
- package/dist/utils/config-service.d.ts +30 -0
- package/dist/utils/config-service.d.ts.map +1 -0
- package/dist/utils/config-service.js +37 -0
- package/package.json +3 -5
- package/dist/client.d.ts +0 -27
- package/dist/client.d.ts.map +0 -1
- package/dist/client.js +0 -146
package/README.md
CHANGED
|
@@ -88,7 +88,7 @@ npm run start:client # Start the web client
|
|
|
88
88
|
Visit the following URL in your browser:
|
|
89
89
|
|
|
90
90
|
```
|
|
91
|
-
http://localhost:
|
|
91
|
+
http://localhost:8080
|
|
92
92
|
```
|
|
93
93
|
|
|
94
94
|
## Development
|
|
@@ -106,3 +106,66 @@ This project uses:
|
|
|
106
106
|
- `utils/`: Utility functions for API communication and error handling.
|
|
107
107
|
- `server.ts`: Main MCP server implementation.
|
|
108
108
|
- `client/`: Web client for testing and demonstration.
|
|
109
|
+
|
|
110
|
+
## Vite Plugin Integration
|
|
111
|
+
|
|
112
|
+
This package provides a Vite plugin for easy integration with your Vite-based applications.
|
|
113
|
+
|
|
114
|
+
### Using the MCP Vite Plugin
|
|
115
|
+
|
|
116
|
+
Add the plugin to your Vite configuration:
|
|
117
|
+
|
|
118
|
+
```typescript
|
|
119
|
+
// vite.config.ts
|
|
120
|
+
import { defineConfig } from "vite";
|
|
121
|
+
import { mcpPlugin } from "mcp-meilisearch";
|
|
122
|
+
|
|
123
|
+
export default defineConfig({
|
|
124
|
+
plugins: [
|
|
125
|
+
// Your other plugins...
|
|
126
|
+
mcpPlugin({
|
|
127
|
+
transport: "http",
|
|
128
|
+
mcpEndpoint: "/mcp",
|
|
129
|
+
sessionTimeout: 3600000, // 1 hour
|
|
130
|
+
sessionCleanupInterval: 60000, // 1 minute
|
|
131
|
+
meilisearchApiKey: "your-api-key-here",
|
|
132
|
+
meilisearchHost: "http://localhost:7700",
|
|
133
|
+
}),
|
|
134
|
+
],
|
|
135
|
+
});
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
### Plugin Options
|
|
139
|
+
|
|
140
|
+
#### MCP Server Options
|
|
141
|
+
|
|
142
|
+
- `transport`: Transport type for MCP server ("http" | "stdio") (Default: "http")
|
|
143
|
+
- `httpPort`: HTTP port for MCP server (Default: 8080)
|
|
144
|
+
- `mcpEndpoint`: MCP endpoint path (Default: "/mcp")
|
|
145
|
+
|
|
146
|
+
#### Session Options
|
|
147
|
+
|
|
148
|
+
- `sessionTimeout`: Session timeout in milliseconds (Default: 3600000)
|
|
149
|
+
- `sessionCleanupInterval`: Session cleanup interval in milliseconds (Default: 60000)
|
|
150
|
+
|
|
151
|
+
#### Meilisearch Connection Options
|
|
152
|
+
|
|
153
|
+
- `meilisearchHost`: URL of the Meilisearch instance (Default: "http://localhost:7700")
|
|
154
|
+
- `meilisearchApiKey`: API key for authenticating with Meilisearch (Default: "")
|
|
155
|
+
|
|
156
|
+
### Using the MCPClient
|
|
157
|
+
|
|
158
|
+
The package also exports the MCPClient class for client-side integration:
|
|
159
|
+
|
|
160
|
+
```typescript
|
|
161
|
+
import { MCPClient } from "mcp-meilisearch";
|
|
162
|
+
|
|
163
|
+
const client = new MCPClient("meilisearch");
|
|
164
|
+
await client.connectToServer("http://localhost:3000/mcp");
|
|
165
|
+
|
|
166
|
+
// Call a tool
|
|
167
|
+
const result = await client.callTool("search", {
|
|
168
|
+
indexUid: "movies",
|
|
169
|
+
q: "star wars",
|
|
170
|
+
});
|
|
171
|
+
```
|
package/dist/config.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Meilisearch
|
|
2
|
+
* Meilisearch Configuration
|
|
3
3
|
*
|
|
4
4
|
* This file contains the configuration settings for connecting to the Meilisearch server.
|
|
5
5
|
* Configuration is loaded from environment variables with sensible defaults.
|
|
6
6
|
*/
|
|
7
|
-
export interface
|
|
7
|
+
export interface MeilisearchConfig {
|
|
8
8
|
/** The URL of the Meilisearch instance */
|
|
9
9
|
host: string;
|
|
10
10
|
/** The API key for authenticating with Meilisearch */
|
|
@@ -15,7 +15,7 @@ export interface ServerConfig {
|
|
|
15
15
|
/**
|
|
16
16
|
* Load and initialize configuration from environment variables
|
|
17
17
|
*/
|
|
18
|
-
export declare const loadConfig: () =>
|
|
19
|
-
export declare const config:
|
|
18
|
+
export declare const loadConfig: () => MeilisearchConfig;
|
|
19
|
+
export declare const config: MeilisearchConfig;
|
|
20
20
|
export default config;
|
|
21
21
|
//# sourceMappingURL=config.d.ts.map
|
package/dist/config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,MAAM,WAAW,
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,MAAM,WAAW,iBAAiB;IAChC,0CAA0C;IAC1C,IAAI,EAAE,MAAM,CAAC;IACb,sDAAsD;IACtD,MAAM,EAAE,MAAM,CAAC;IACf,mDAAmD;IACnD,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,eAAO,MAAM,UAAU,QAAO,iBAM7B,CAAC;AAGF,eAAO,MAAM,MAAM,mBAAe,CAAC;AAGnC,eAAe,MAAM,CAAC"}
|
package/dist/config.js
CHANGED
package/dist/http.js
CHANGED
|
File without changes
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { Plugin } from "vite";
|
|
2
|
-
import { MCPClient } from "./client.js";
|
|
3
2
|
/**
|
|
4
3
|
* Options for the MCP Vite plugin
|
|
5
4
|
*/
|
|
@@ -19,16 +18,6 @@ export interface MCPPluginOptions {
|
|
|
19
18
|
* @default "/mcp"
|
|
20
19
|
*/
|
|
21
20
|
mcpEndpoint?: string;
|
|
22
|
-
/**
|
|
23
|
-
* Server name
|
|
24
|
-
* @default "meilisearch"
|
|
25
|
-
*/
|
|
26
|
-
serverName?: string;
|
|
27
|
-
/**
|
|
28
|
-
* Server version
|
|
29
|
-
* @default "1.0.0"
|
|
30
|
-
*/
|
|
31
|
-
serverVersion?: string;
|
|
32
21
|
/**
|
|
33
22
|
* Session timeout in milliseconds
|
|
34
23
|
* @default 3600000 (1 hour)
|
|
@@ -39,6 +28,16 @@ export interface MCPPluginOptions {
|
|
|
39
28
|
* @default 60000 (1 minute)
|
|
40
29
|
*/
|
|
41
30
|
sessionCleanupInterval?: number;
|
|
31
|
+
/**
|
|
32
|
+
* The URL of the Meilisearch instance
|
|
33
|
+
* @default "http://localhost:7700"
|
|
34
|
+
*/
|
|
35
|
+
meilisearchHost: string;
|
|
36
|
+
/**
|
|
37
|
+
* The API key for authenticating with Meilisearch
|
|
38
|
+
* @default ""
|
|
39
|
+
*/
|
|
40
|
+
meilisearchApiKey: string;
|
|
42
41
|
}
|
|
43
42
|
/**
|
|
44
43
|
* Creates a Vite plugin that integrates with the MCP server
|
|
@@ -46,9 +45,5 @@ export interface MCPPluginOptions {
|
|
|
46
45
|
* @returns A Vite plugin
|
|
47
46
|
*/
|
|
48
47
|
export declare function mcpPlugin(options?: MCPPluginOptions): Plugin;
|
|
49
|
-
export { MCPClient };
|
|
50
|
-
/**
|
|
51
|
-
* Default export for convenience
|
|
52
|
-
*/
|
|
53
48
|
export default mcpPlugin;
|
|
54
49
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAM9B;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B;;;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;;;OAGG;IACH,eAAe,EAAE,MAAM,CAAC;IAExB;;;OAGG;IACH,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CACvB,OAAO,GAAE,gBAGR,GACA,MAAM,CAsGR;AAED,eAAe,SAAS,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,37 +1,25 @@
|
|
|
1
|
-
import { MCPClient } from "./client.js";
|
|
2
1
|
import { initServer } from "./server.js";
|
|
3
2
|
import { randomUUID } from "node:crypto";
|
|
3
|
+
import { configHandler } from "./utils/config-handler.js";
|
|
4
4
|
import { createErrorResponse } from "./utils/error-handler.js";
|
|
5
5
|
/**
|
|
6
6
|
* Creates a Vite plugin that integrates with the MCP server
|
|
7
7
|
* @param options Configuration options for the MCP server
|
|
8
8
|
* @returns A Vite plugin
|
|
9
9
|
*/
|
|
10
|
-
export function mcpPlugin(options = {
|
|
10
|
+
export function mcpPlugin(options = {
|
|
11
|
+
meilisearchApiKey: "",
|
|
12
|
+
meilisearchHost: "http://localhost:7700",
|
|
13
|
+
}) {
|
|
14
|
+
configHandler.setMeilisearchHost(options.meilisearchHost);
|
|
15
|
+
configHandler.setMeilisearchApiKey(options.meilisearchApiKey);
|
|
11
16
|
const pluginId = `mcp-plugin-${randomUUID().slice(0, 8)}`;
|
|
12
17
|
let mcpServerInstance = null;
|
|
13
|
-
// Set default options
|
|
14
18
|
const transport = options.transport || "http";
|
|
15
19
|
return {
|
|
16
20
|
name: "vite:mcp-plugin",
|
|
17
|
-
apply: "serve", // Only apply this plugin during development
|
|
18
21
|
configureServer(server) {
|
|
19
|
-
// Store the custom config in Vite's server context for sharing
|
|
20
22
|
server.config.env.VITE_MCP_PLUGIN_ID = pluginId;
|
|
21
|
-
// Configure process.env variables with MCP server options
|
|
22
|
-
if (options.httpPort)
|
|
23
|
-
process.env.MCP_HTTP_PORT = String(options.httpPort);
|
|
24
|
-
if (options.mcpEndpoint)
|
|
25
|
-
process.env.MCP_ENDPOINT = options.mcpEndpoint;
|
|
26
|
-
if (options.serverName)
|
|
27
|
-
process.env.MCP_SERVER_NAME = options.serverName;
|
|
28
|
-
if (options.serverVersion)
|
|
29
|
-
process.env.MCP_SERVER_VERSION = options.serverVersion;
|
|
30
|
-
if (options.sessionTimeout)
|
|
31
|
-
process.env.MCP_SESSION_TIMEOUT = String(options.sessionTimeout);
|
|
32
|
-
if (options.sessionCleanupInterval)
|
|
33
|
-
process.env.MCP_SESSION_CLEANUP_INTERVAL = String(options.sessionCleanupInterval);
|
|
34
|
-
// Add CORS middleware
|
|
35
23
|
server.middlewares.use((req, res, next) => {
|
|
36
24
|
res.setHeader("Access-Control-Allow-Origin", "*");
|
|
37
25
|
res.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
|
|
@@ -43,12 +31,10 @@ export function mcpPlugin(options = {}) {
|
|
|
43
31
|
}
|
|
44
32
|
next();
|
|
45
33
|
});
|
|
46
|
-
// Handle MCP endpoint requests
|
|
47
34
|
server.middlewares.use(async (req, res, next) => {
|
|
48
35
|
const mcpEndpoint = options.mcpEndpoint || "/mcp";
|
|
49
36
|
const url = req.url || "/";
|
|
50
37
|
if (url.startsWith(mcpEndpoint)) {
|
|
51
|
-
// Only proceed if MCP server is initialized
|
|
52
38
|
if (!mcpServerInstance) {
|
|
53
39
|
console.error("MCP server not initialized yet");
|
|
54
40
|
res.statusCode = 503;
|
|
@@ -88,18 +74,8 @@ export function mcpPlugin(options = {}) {
|
|
|
88
74
|
server.httpServer?.on("listening", async () => {
|
|
89
75
|
console.log(`Vite server is ready, initializing MCP server with ${transport} transport`);
|
|
90
76
|
try {
|
|
91
|
-
|
|
92
|
-
const serverInstances = await initServer(transport);
|
|
77
|
+
const serverInstances = await initServer(transport, options);
|
|
93
78
|
mcpServerInstance = serverInstances.mcpServer;
|
|
94
|
-
const hostConfig = server.config.server;
|
|
95
|
-
const protocol = hostConfig.https ? "https" : "http";
|
|
96
|
-
const host = hostConfig.host === true
|
|
97
|
-
? "localhost"
|
|
98
|
-
: hostConfig.host || "localhost";
|
|
99
|
-
const port = hostConfig.port || 3000;
|
|
100
|
-
const mcpEndpoint = options.mcpEndpoint || "/mcp";
|
|
101
|
-
console.log(`MCP server initialized with ${transport} transport`);
|
|
102
|
-
console.log(`MCP endpoint available at: ${protocol}://${host}:${port}${mcpEndpoint}`);
|
|
103
79
|
}
|
|
104
80
|
catch (error) {
|
|
105
81
|
console.error("Failed to initialize MCP server:", error);
|
|
@@ -107,7 +83,6 @@ export function mcpPlugin(options = {}) {
|
|
|
107
83
|
});
|
|
108
84
|
},
|
|
109
85
|
closeBundle() {
|
|
110
|
-
// Clean up resources when Vite is shutting down
|
|
111
86
|
if (mcpServerInstance) {
|
|
112
87
|
try {
|
|
113
88
|
console.log("Shutting down MCP server...");
|
|
@@ -122,9 +97,4 @@ export function mcpPlugin(options = {}) {
|
|
|
122
97
|
},
|
|
123
98
|
};
|
|
124
99
|
}
|
|
125
|
-
// Export the MCPClient class for external use
|
|
126
|
-
export { MCPClient };
|
|
127
|
-
/**
|
|
128
|
-
* Default export for convenience
|
|
129
|
-
*/
|
|
130
100
|
export default mcpPlugin;
|
package/dist/server.d.ts
CHANGED
|
@@ -6,11 +6,16 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
|
6
6
|
interface ServerConfig {
|
|
7
7
|
httpPort: number;
|
|
8
8
|
mcpEndpoint: string;
|
|
9
|
-
serverName: string;
|
|
10
|
-
serverVersion: string;
|
|
11
9
|
sessionTimeout: number;
|
|
12
10
|
sessionCleanupInterval: number;
|
|
13
11
|
}
|
|
12
|
+
/**
|
|
13
|
+
* Return type for the initServer function
|
|
14
|
+
*/
|
|
15
|
+
export interface ServerInstances {
|
|
16
|
+
mcpServer?: MCPServer;
|
|
17
|
+
viteServer?: any;
|
|
18
|
+
}
|
|
14
19
|
/**
|
|
15
20
|
* Implementation of an MCP server for Meilisearch
|
|
16
21
|
*/
|
|
@@ -18,9 +23,9 @@ declare class MCPServer {
|
|
|
18
23
|
private readonly JSON_RPC;
|
|
19
24
|
private readonly SESSION_ID_HEADER_NAME;
|
|
20
25
|
private server;
|
|
26
|
+
private config;
|
|
21
27
|
private cleanupInterval;
|
|
22
28
|
private sessions;
|
|
23
|
-
private config;
|
|
24
29
|
/**
|
|
25
30
|
* Creates a new MCP server instance
|
|
26
31
|
* @param server The underlying MCP server implementation
|
|
@@ -84,19 +89,12 @@ declare class MCPServer {
|
|
|
84
89
|
*/
|
|
85
90
|
private cleanupExpiredSessions;
|
|
86
91
|
}
|
|
87
|
-
/**
|
|
88
|
-
* Return type for the initServer function
|
|
89
|
-
*/
|
|
90
|
-
export interface ServerInstances {
|
|
91
|
-
mcpServer?: MCPServer;
|
|
92
|
-
viteServer?: any;
|
|
93
|
-
}
|
|
94
92
|
/**
|
|
95
93
|
* Initialize the MCP server with the specified transport
|
|
96
94
|
* @param transport The transport type to use ("stdio" or "http")
|
|
97
95
|
* @returns A promise that resolves to the server instances
|
|
98
96
|
* @throws Error if the transport type is unsupported
|
|
99
97
|
*/
|
|
100
|
-
export declare const initServer: (transport: "stdio" | "http") => Promise<ServerInstances>;
|
|
98
|
+
export declare const initServer: (transport: "stdio" | "http", config?: Partial<ServerConfig>) => Promise<ServerInstances>;
|
|
101
99
|
export {};
|
|
102
100
|
//# sourceMappingURL=server.d.ts.map
|
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;AAgBvD,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAIpE;;GAEG;AACH,UAAU,YAAY;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,
|
|
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,MAAM,WAAW,eAAe;IAC9B,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;IAQjE;;;;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;IAkChB;;OAEG;IACH,QAAQ,IAAI,IAAI;IAsBhB;;;;;OAKG;YACW,uBAAuB;IA6CrC;;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;CA4B/B;AA8JD;;;;;GAKG;AACH,eAAO,MAAM,UAAU,GACrB,WAAW,OAAO,GAAG,MAAM,EAC3B,SAAS,OAAO,CAAC,YAAY,CAAC,KAC7B,OAAO,CAAC,eAAe,CAezB,CAAC"}
|
package/dist/server.js
CHANGED
|
@@ -15,10 +15,8 @@ import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/
|
|
|
15
15
|
const DEFAULT_CONFIG = {
|
|
16
16
|
httpPort: 8080,
|
|
17
17
|
mcpEndpoint: "/mcp",
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
sessionCleanupInterval: 60000, // 1 minute
|
|
21
|
-
sessionTimeout: 3600000, // 1 hour
|
|
18
|
+
sessionTimeout: 3600000,
|
|
19
|
+
sessionCleanupInterval: 60000,
|
|
22
20
|
};
|
|
23
21
|
/**
|
|
24
22
|
* Implementation of an MCP server for Meilisearch
|
|
@@ -27,9 +25,9 @@ class MCPServer {
|
|
|
27
25
|
JSON_RPC = "2.0";
|
|
28
26
|
SESSION_ID_HEADER_NAME = "mcp-session-id";
|
|
29
27
|
server;
|
|
28
|
+
config;
|
|
30
29
|
cleanupInterval = null;
|
|
31
30
|
sessions = new Map();
|
|
32
|
-
config;
|
|
33
31
|
/**
|
|
34
32
|
* Creates a new MCP server instance
|
|
35
33
|
* @param server The underlying MCP server implementation
|
|
@@ -263,25 +261,14 @@ class MCPServer {
|
|
|
263
261
|
/**
|
|
264
262
|
* Initialize the MCP server with HTTP transport using Vite
|
|
265
263
|
*/
|
|
266
|
-
const initServerHTTPTransport = async () => {
|
|
264
|
+
const initServerHTTPTransport = async (customConfig) => {
|
|
267
265
|
const config = {
|
|
268
266
|
...DEFAULT_CONFIG,
|
|
269
|
-
|
|
270
|
-
? parseInt(process.env.MCP_HTTP_PORT, 10)
|
|
271
|
-
: DEFAULT_CONFIG.httpPort,
|
|
272
|
-
mcpEndpoint: process.env.MCP_ENDPOINT || DEFAULT_CONFIG.mcpEndpoint,
|
|
273
|
-
serverName: process.env.MCP_SERVER_NAME || DEFAULT_CONFIG.serverName,
|
|
274
|
-
serverVersion: process.env.MCP_SERVER_VERSION || DEFAULT_CONFIG.serverVersion,
|
|
275
|
-
sessionTimeout: process.env.MCP_SESSION_TIMEOUT
|
|
276
|
-
? parseInt(process.env.MCP_SESSION_TIMEOUT, 10)
|
|
277
|
-
: DEFAULT_CONFIG.sessionTimeout,
|
|
278
|
-
sessionCleanupInterval: process.env.MCP_SESSION_CLEANUP_INTERVAL
|
|
279
|
-
? parseInt(process.env.MCP_SESSION_CLEANUP_INTERVAL, 10)
|
|
280
|
-
: DEFAULT_CONFIG.sessionCleanupInterval,
|
|
267
|
+
...customConfig,
|
|
281
268
|
};
|
|
282
269
|
const serverInstance = new McpServer({
|
|
283
|
-
|
|
284
|
-
|
|
270
|
+
version: "1.0.0",
|
|
271
|
+
name: "mcp-meilisearch",
|
|
285
272
|
});
|
|
286
273
|
// Register all tools
|
|
287
274
|
registerIndexTools(serverInstance);
|
|
@@ -367,15 +354,15 @@ const initServerHTTPTransport = async () => {
|
|
|
367
354
|
* @returns MCP server instance
|
|
368
355
|
*/
|
|
369
356
|
const initServerStdioTransport = async () => {
|
|
370
|
-
// Use environment variables if available, otherwise use defaults
|
|
371
357
|
const config = {
|
|
372
358
|
...DEFAULT_CONFIG,
|
|
373
|
-
|
|
374
|
-
|
|
359
|
+
host: process.env.MEILISEARCH_HOST,
|
|
360
|
+
apiKey: process.env.MEILISEARCH_API_KEY,
|
|
375
361
|
};
|
|
362
|
+
// Use environment variables if available, otherwise use defaults
|
|
376
363
|
const serverInstance = new McpServer({
|
|
377
|
-
|
|
378
|
-
|
|
364
|
+
version: "1.0.0",
|
|
365
|
+
name: "mcp-meilisearch",
|
|
379
366
|
});
|
|
380
367
|
// Register all tools
|
|
381
368
|
registerIndexTools(serverInstance);
|
|
@@ -404,14 +391,14 @@ const initServerStdioTransport = async () => {
|
|
|
404
391
|
* @returns A promise that resolves to the server instances
|
|
405
392
|
* @throws Error if the transport type is unsupported
|
|
406
393
|
*/
|
|
407
|
-
export const initServer = async (transport) => {
|
|
394
|
+
export const initServer = async (transport, config) => {
|
|
408
395
|
try {
|
|
409
396
|
switch (transport) {
|
|
410
397
|
case "stdio":
|
|
411
398
|
const stdioServer = await initServerStdioTransport();
|
|
412
399
|
return { mcpServer: stdioServer };
|
|
413
400
|
case "http":
|
|
414
|
-
return await initServerHTTPTransport();
|
|
401
|
+
return await initServerHTTPTransport(config);
|
|
415
402
|
default:
|
|
416
403
|
throw new Error(`Unsupported transport type: ${transport}`);
|
|
417
404
|
}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { AxiosRequestConfig, AxiosResponse } from
|
|
1
|
+
import { AxiosRequestConfig, AxiosResponse } from "axios";
|
|
2
2
|
/**
|
|
3
3
|
* Meilisearch API client
|
|
4
4
|
*
|
|
5
5
|
* This module provides a configured Axios instance for making requests to the Meilisearch API.
|
|
6
|
+
* Uses request interceptors to dynamically update host and API key from the configHandler.
|
|
6
7
|
*/
|
|
7
8
|
/**
|
|
8
9
|
* Creates a configured Axios instance for Meilisearch API requests
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api-handler.d.ts","sourceRoot":"","sources":["../../src/utils/api-handler.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"api-handler.d.ts","sourceRoot":"","sources":["../../src/utils/api-handler.ts"],"names":[],"mappings":"AACA,OAAc,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAEjE;;;;;GAKG;AAEH;;;;GAIG;AACH,eAAO,MAAM,eAAe;UAalB,CAAC,aACA,MAAM,WACF,kBAAkB,KAC1B,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;WACrB,CAAC,aACD,MAAM,SACJ,GAAG,WACD,kBAAkB,KAC1B,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;UACtB,CAAC,aACA,MAAM,SACJ,GAAG,WACD,kBAAkB,KAC1B,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;YACpB,CAAC,aACF,MAAM,SACJ,GAAG,WACD,kBAAkB,KAC1B,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;aACnB,CAAC,aACH,MAAM,WACF,kBAAkB,KAC1B,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;CAE/B,CAAC;AAEF,eAAO,MAAM,SAAS;UA1BZ,CAAC,aACA,MAAM,WACF,kBAAkB,KAC1B,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;WACrB,CAAC,aACD,MAAM,SACJ,GAAG,WACD,kBAAkB,KAC1B,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;UACtB,CAAC,aACA,MAAM,SACJ,GAAG,WACD,kBAAkB,KAC1B,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;YACpB,CAAC,aACF,MAAM,SACJ,GAAG,WACD,kBAAkB,KAC1B,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;aACnB,CAAC,aACH,MAAM,WACF,kBAAkB,KAC1B,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;CAIU,CAAC;AAE3C,eAAe,SAAS,CAAC"}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
1
|
+
import { configHandler } from "./config-handler.js";
|
|
2
|
+
import axios from "axios";
|
|
3
3
|
/**
|
|
4
4
|
* Meilisearch API client
|
|
5
5
|
*
|
|
6
6
|
* This module provides a configured Axios instance for making requests to the Meilisearch API.
|
|
7
|
+
* Uses request interceptors to dynamically update host and API key from the configHandler.
|
|
7
8
|
*/
|
|
8
9
|
/**
|
|
9
10
|
* Creates a configured Axios instance for Meilisearch API requests
|
|
@@ -12,12 +13,12 @@ import config from '../config.js';
|
|
|
12
13
|
*/
|
|
13
14
|
export const createApiClient = () => {
|
|
14
15
|
const instance = axios.create({
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
}
|
|
20
|
-
|
|
16
|
+
headers: { "Content-Type": "application/json" },
|
|
17
|
+
});
|
|
18
|
+
instance.interceptors.request.use((config) => {
|
|
19
|
+
config.baseURL = configHandler.getMeilisearchHost();
|
|
20
|
+
config.headers.Authorization = `Bearer ${configHandler.getMeilisearchApiKey()}`;
|
|
21
|
+
return config;
|
|
21
22
|
});
|
|
22
23
|
return {
|
|
23
24
|
get: (url, config) => instance.get(url, config),
|
|
@@ -27,7 +28,5 @@ export const createApiClient = () => {
|
|
|
27
28
|
delete: (url, config) => instance.delete(url, config),
|
|
28
29
|
};
|
|
29
30
|
};
|
|
30
|
-
// Create and export a singleton instance of the API client
|
|
31
31
|
export const apiClient = createApiClient();
|
|
32
|
-
// Re-export for direct use
|
|
33
32
|
export default apiClient;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration service to store and retrieve Meilisearch configuration
|
|
3
|
+
*/
|
|
4
|
+
declare class ConfigHandler {
|
|
5
|
+
private _meilisearchHost;
|
|
6
|
+
private _meilisearchApiKey;
|
|
7
|
+
/**
|
|
8
|
+
* Set the Meilisearch host URL
|
|
9
|
+
* @param host The URL of the Meilisearch instance
|
|
10
|
+
*/
|
|
11
|
+
setMeilisearchHost(host: string): void;
|
|
12
|
+
/**
|
|
13
|
+
* Set the Meilisearch API key
|
|
14
|
+
* @param apiKey The API key for Meilisearch
|
|
15
|
+
*/
|
|
16
|
+
setMeilisearchApiKey(apiKey: string): void;
|
|
17
|
+
/**
|
|
18
|
+
* Get the current Meilisearch host URL
|
|
19
|
+
* @returns The URL of the Meilisearch instance
|
|
20
|
+
*/
|
|
21
|
+
getMeilisearchHost(): string;
|
|
22
|
+
/**
|
|
23
|
+
* Get the current Meilisearch API key
|
|
24
|
+
* @returns The API key for Meilisearch
|
|
25
|
+
*/
|
|
26
|
+
getMeilisearchApiKey(): string;
|
|
27
|
+
}
|
|
28
|
+
export declare const configHandler: ConfigHandler;
|
|
29
|
+
export default configHandler;
|
|
30
|
+
//# sourceMappingURL=config-handler.d.ts.map
|
|
@@ -0,0 +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"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration service to store and retrieve Meilisearch configuration
|
|
3
|
+
*/
|
|
4
|
+
class ConfigHandler {
|
|
5
|
+
_meilisearchHost = "";
|
|
6
|
+
_meilisearchApiKey = "";
|
|
7
|
+
/**
|
|
8
|
+
* Set the Meilisearch host URL
|
|
9
|
+
* @param host The URL of the Meilisearch instance
|
|
10
|
+
*/
|
|
11
|
+
setMeilisearchHost(host) {
|
|
12
|
+
this._meilisearchHost = host;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Set the Meilisearch API key
|
|
16
|
+
* @param apiKey The API key for Meilisearch
|
|
17
|
+
*/
|
|
18
|
+
setMeilisearchApiKey(apiKey) {
|
|
19
|
+
this._meilisearchApiKey = apiKey || "";
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Get the current Meilisearch host URL
|
|
23
|
+
* @returns The URL of the Meilisearch instance
|
|
24
|
+
*/
|
|
25
|
+
getMeilisearchHost() {
|
|
26
|
+
return this._meilisearchHost;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Get the current Meilisearch API key
|
|
30
|
+
* @returns The API key for Meilisearch
|
|
31
|
+
*/
|
|
32
|
+
getMeilisearchApiKey() {
|
|
33
|
+
return this._meilisearchApiKey;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
export const configHandler = new ConfigHandler();
|
|
37
|
+
export default configHandler;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A simple configuration service to store and retrieve Meilisearch configuration
|
|
3
|
+
*/
|
|
4
|
+
declare class ConfigService {
|
|
5
|
+
private _meilisearchHost;
|
|
6
|
+
private _meilisearchApiKey;
|
|
7
|
+
/**
|
|
8
|
+
* Set the Meilisearch host URL
|
|
9
|
+
* @param host The URL of the Meilisearch instance
|
|
10
|
+
*/
|
|
11
|
+
setMeilisearchHost(host: string): void;
|
|
12
|
+
/**
|
|
13
|
+
* Set the Meilisearch API key
|
|
14
|
+
* @param apiKey The API key for Meilisearch
|
|
15
|
+
*/
|
|
16
|
+
setMeilisearchApiKey(apiKey: string): void;
|
|
17
|
+
/**
|
|
18
|
+
* Get the current Meilisearch host URL
|
|
19
|
+
* @returns The URL of the Meilisearch instance
|
|
20
|
+
*/
|
|
21
|
+
getMeilisearchHost(): string;
|
|
22
|
+
/**
|
|
23
|
+
* Get the current Meilisearch API key
|
|
24
|
+
* @returns The API key for Meilisearch
|
|
25
|
+
*/
|
|
26
|
+
getMeilisearchApiKey(): string;
|
|
27
|
+
}
|
|
28
|
+
export declare const configService: ConfigService;
|
|
29
|
+
export default configService;
|
|
30
|
+
//# sourceMappingURL=config-service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config-service.d.ts","sourceRoot":"","sources":["../../src/utils/config-service.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"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A simple configuration service to store and retrieve Meilisearch configuration
|
|
3
|
+
*/
|
|
4
|
+
class ConfigService {
|
|
5
|
+
_meilisearchHost = "";
|
|
6
|
+
_meilisearchApiKey = "";
|
|
7
|
+
/**
|
|
8
|
+
* Set the Meilisearch host URL
|
|
9
|
+
* @param host The URL of the Meilisearch instance
|
|
10
|
+
*/
|
|
11
|
+
setMeilisearchHost(host) {
|
|
12
|
+
this._meilisearchHost = host;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Set the Meilisearch API key
|
|
16
|
+
* @param apiKey The API key for Meilisearch
|
|
17
|
+
*/
|
|
18
|
+
setMeilisearchApiKey(apiKey) {
|
|
19
|
+
this._meilisearchApiKey = apiKey || "";
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Get the current Meilisearch host URL
|
|
23
|
+
* @returns The URL of the Meilisearch instance
|
|
24
|
+
*/
|
|
25
|
+
getMeilisearchHost() {
|
|
26
|
+
return this._meilisearchHost;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Get the current Meilisearch API key
|
|
30
|
+
* @returns The API key for Meilisearch
|
|
31
|
+
*/
|
|
32
|
+
getMeilisearchApiKey() {
|
|
33
|
+
return this._meilisearchApiKey;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
export const configService = new ConfigService();
|
|
37
|
+
export default configService;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mcp-meilisearch",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.7",
|
|
4
4
|
"description": "Model Context Protocol (MCP) implementation for Meilisearch",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -14,10 +14,8 @@
|
|
|
14
14
|
],
|
|
15
15
|
"scripts": {
|
|
16
16
|
"build": "tsc && tsc --project tsconfig.types.json",
|
|
17
|
-
"
|
|
18
|
-
"
|
|
19
|
-
"server": "npm run serve:stdio && node --env-file=.env dist/stdio.js",
|
|
20
|
-
"client": "npm run serve:http && node --env-file=.env dist/http.js & npm run preview --workspace=client",
|
|
17
|
+
"server": "npm run build && node --env-file=.env dist/index.js",
|
|
18
|
+
"client": "npm run server & npm run dev --workspace=client",
|
|
21
19
|
"prepare": "npm version patch",
|
|
22
20
|
"prepublishOnly": "npm run build"
|
|
23
21
|
},
|
package/dist/client.d.ts
DELETED
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
export declare class MCPClient {
|
|
2
|
-
tools: {
|
|
3
|
-
name: string;
|
|
4
|
-
description: string;
|
|
5
|
-
}[];
|
|
6
|
-
private client;
|
|
7
|
-
private tries;
|
|
8
|
-
private transport;
|
|
9
|
-
private onToolsUpdatedCallback;
|
|
10
|
-
constructor(serverName: string);
|
|
11
|
-
setOnToolsUpdatedCallback(callback: (tools: Array<{
|
|
12
|
-
name: string;
|
|
13
|
-
description: string;
|
|
14
|
-
}>) => void): void;
|
|
15
|
-
connectToServer(serverUrl: string): Promise<void>;
|
|
16
|
-
listTools(): Promise<void>;
|
|
17
|
-
private setUpNotifications;
|
|
18
|
-
callTool(name: string, args?: Record<string, any>): Promise<{
|
|
19
|
-
success: boolean;
|
|
20
|
-
data?: any;
|
|
21
|
-
error?: string;
|
|
22
|
-
}>;
|
|
23
|
-
private setUpTransport;
|
|
24
|
-
cleanup(): Promise<void>;
|
|
25
|
-
close(): Promise<void>;
|
|
26
|
-
}
|
|
27
|
-
//# sourceMappingURL=client.d.ts.map
|
package/dist/client.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAQA,qBAAa,SAAS;IACpB,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,sBAAsB,CAEd;gBAEJ,UAAU,EAAE,MAAM;IAOvB,yBAAyB,CAC9B,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,CAAC,KAAK,IAAI;IAKnE,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAwBjD,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC;IAsChC,OAAO,CAAC,kBAAkB;IAkBpB,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;IAuCF,OAAO,CAAC,cAAc;IAWhB,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAUxB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAG7B"}
|
package/dist/client.js
DELETED
|
@@ -1,146 +0,0 @@
|
|
|
1
|
-
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
2
|
-
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
|
|
3
|
-
import { TextContentSchema, LoggingMessageNotificationSchema, ToolListChangedNotificationSchema, } from "@modelcontextprotocol/sdk/types.js";
|
|
4
|
-
export class MCPClient {
|
|
5
|
-
tools = [];
|
|
6
|
-
client;
|
|
7
|
-
tries = 0;
|
|
8
|
-
transport = null;
|
|
9
|
-
onToolsUpdatedCallback = null;
|
|
10
|
-
constructor(serverName) {
|
|
11
|
-
this.client = new Client({
|
|
12
|
-
name: serverName,
|
|
13
|
-
version: "1.0.0",
|
|
14
|
-
});
|
|
15
|
-
}
|
|
16
|
-
setOnToolsUpdatedCallback(callback) {
|
|
17
|
-
this.onToolsUpdatedCallback = callback;
|
|
18
|
-
}
|
|
19
|
-
async connectToServer(serverUrl) {
|
|
20
|
-
const url = new URL(serverUrl);
|
|
21
|
-
try {
|
|
22
|
-
console.log(`Connecting to MCP server at ${serverUrl}...`);
|
|
23
|
-
this.transport = new StreamableHTTPClientTransport(url);
|
|
24
|
-
await this.client.connect(this.transport);
|
|
25
|
-
console.log("✅ Successfully connected to server");
|
|
26
|
-
this.setUpTransport();
|
|
27
|
-
this.setUpNotifications();
|
|
28
|
-
await this.listTools();
|
|
29
|
-
}
|
|
30
|
-
catch (e) {
|
|
31
|
-
this.tries++;
|
|
32
|
-
if (this.tries > 5) {
|
|
33
|
-
console.error("❌ Failed to connect to MCP server: ", e);
|
|
34
|
-
throw e;
|
|
35
|
-
}
|
|
36
|
-
console.info(`⚠️ Retry attempt ${this.tries} to connect to server`);
|
|
37
|
-
await new Promise((resolve) => setTimeout(resolve, this.tries * 1000));
|
|
38
|
-
await this.connectToServer(serverUrl);
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
async listTools() {
|
|
42
|
-
try {
|
|
43
|
-
console.log("📋 Fetching available tools...");
|
|
44
|
-
const toolsResult = await this.client.listTools();
|
|
45
|
-
if (!toolsResult) {
|
|
46
|
-
console.error("❌ Received null or undefined tools result");
|
|
47
|
-
this.tools = [];
|
|
48
|
-
}
|
|
49
|
-
else if (toolsResult.tools && Array.isArray(toolsResult.tools)) {
|
|
50
|
-
this.tools = toolsResult.tools.map((tool) => ({
|
|
51
|
-
name: tool.name,
|
|
52
|
-
description: tool.description ?? "",
|
|
53
|
-
}));
|
|
54
|
-
}
|
|
55
|
-
else {
|
|
56
|
-
console.error("❌ Invalid tools response format:", toolsResult);
|
|
57
|
-
this.tools = [];
|
|
58
|
-
}
|
|
59
|
-
if (this.onToolsUpdatedCallback) {
|
|
60
|
-
this.onToolsUpdatedCallback([...this.tools]);
|
|
61
|
-
}
|
|
62
|
-
if (this.tools.length) {
|
|
63
|
-
console.log(`✅ Successfully loaded ${this.tools.length} tools`);
|
|
64
|
-
}
|
|
65
|
-
else {
|
|
66
|
-
console.warn("⚠️ No tools were returned from the server or an error occurred.");
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
catch (error) {
|
|
70
|
-
console.error(`❌ Error fetching tools: ${error}`);
|
|
71
|
-
this.tools = [];
|
|
72
|
-
if (this.onToolsUpdatedCallback) {
|
|
73
|
-
this.onToolsUpdatedCallback([...this.tools]);
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
setUpNotifications() {
|
|
78
|
-
console.log("Setting up notification handlers...");
|
|
79
|
-
this.client.setNotificationHandler(LoggingMessageNotificationSchema, (notification) => {
|
|
80
|
-
console.log("📢 LoggingMessage received:", notification);
|
|
81
|
-
});
|
|
82
|
-
this.client.setNotificationHandler(ToolListChangedNotificationSchema, async (notification) => {
|
|
83
|
-
console.log("🔄 ToolListChanged notification received:", notification);
|
|
84
|
-
await this.listTools();
|
|
85
|
-
});
|
|
86
|
-
console.log("✅ Notification handlers set up");
|
|
87
|
-
}
|
|
88
|
-
async callTool(name, args) {
|
|
89
|
-
try {
|
|
90
|
-
console.log(`\n🔧 Calling tool: ${name}`);
|
|
91
|
-
console.log("With arguments:", JSON.stringify(args, null, 2));
|
|
92
|
-
const result = await this.client.callTool({ name, arguments: args });
|
|
93
|
-
if (!result) {
|
|
94
|
-
return {
|
|
95
|
-
success: false,
|
|
96
|
-
error: "Received null or undefined result from tool",
|
|
97
|
-
};
|
|
98
|
-
}
|
|
99
|
-
const content = result.content;
|
|
100
|
-
if (!content?.length) {
|
|
101
|
-
return { success: true, data: [] };
|
|
102
|
-
}
|
|
103
|
-
const processedContent = content.reduce((acc, item) => {
|
|
104
|
-
const parse = TextContentSchema.safeParse(item);
|
|
105
|
-
if (parse.success) {
|
|
106
|
-
try {
|
|
107
|
-
return JSON.parse(parse.data.text);
|
|
108
|
-
}
|
|
109
|
-
catch (e) {
|
|
110
|
-
return parse.data.text;
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
return item;
|
|
114
|
-
}, {});
|
|
115
|
-
return { success: true, data: processedContent };
|
|
116
|
-
}
|
|
117
|
-
catch (error) {
|
|
118
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
119
|
-
return { success: false, error: errorMessage };
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
setUpTransport() {
|
|
123
|
-
if (this.transport === null)
|
|
124
|
-
return;
|
|
125
|
-
this.transport.onclose = () => {
|
|
126
|
-
console.log("🔌 Transport closed");
|
|
127
|
-
};
|
|
128
|
-
this.transport.onerror = async (error) => {
|
|
129
|
-
console.log("❌ Transport error:", error);
|
|
130
|
-
await this.cleanup();
|
|
131
|
-
};
|
|
132
|
-
}
|
|
133
|
-
async cleanup() {
|
|
134
|
-
console.log("Cleaning up resources...");
|
|
135
|
-
try {
|
|
136
|
-
await this.client.close();
|
|
137
|
-
console.log("✅ Client closed successfully");
|
|
138
|
-
}
|
|
139
|
-
catch (error) {
|
|
140
|
-
console.error("❌ Error during cleanup:", error);
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
async close() {
|
|
144
|
-
await this.cleanup();
|
|
145
|
-
}
|
|
146
|
-
}
|