|
5 | 5 | * SPDX-License-Identifier: Apache-2.0
|
6 | 6 | */
|
7 | 7 |
|
| 8 | +import express, { Request, Response } from "express"; |
8 | 9 | import { z } from "zod";
|
9 | 10 | import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
| 11 | +import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js"; |
10 | 12 | import { Client, estypes, ClientOptions } from "@elastic/elasticsearch";
|
11 | 13 | import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
12 | 14 | import fs from "fs";
|
13 | 15 |
|
14 | 16 | // Configuration schema with auth options
|
15 | 17 | const ConfigSchema = z
|
16 | 18 | .object({
|
| 19 | + sse_addr: z |
| 20 | + .string() |
| 21 | + .trim() |
| 22 | + .optional() |
| 23 | + .describe("Address for SSE server (optional)"), |
| 24 | + |
17 | 25 | url: z
|
18 | 26 | .string()
|
19 | 27 | .trim()
|
@@ -403,23 +411,57 @@ export async function createElasticsearchMcpServer(
|
403 | 411 | }
|
404 | 412 |
|
405 | 413 | const config: ElasticsearchConfig = {
|
| 414 | + sse_addr: process.env.SSE_ADDR || "", |
406 | 415 | url: process.env.ES_URL || "",
|
407 | 416 | apiKey: process.env.ES_API_KEY || "",
|
408 | 417 | username: process.env.ES_USERNAME || "",
|
409 | 418 | password: process.env.ES_PASSWORD || "",
|
410 | 419 | caCert: process.env.ES_CA_CERT || "",
|
411 | 420 | };
|
412 | 421 |
|
| 422 | +async function create_sse_server(server: any) { |
| 423 | + const app = express(); |
| 424 | + |
| 425 | + const transports: {[sessionId: string]: SSEServerTransport} = {}; |
| 426 | + |
| 427 | + app.get("/sse", async (_: Request, res: Response) => { |
| 428 | + const transport = new SSEServerTransport('/messages', res); |
| 429 | + transports[transport.sessionId] = transport; |
| 430 | + res.on("close", () => { |
| 431 | + delete transports[transport.sessionId]; |
| 432 | + }); |
| 433 | + await server.connect(transport); |
| 434 | + }); |
| 435 | + |
| 436 | + app.post("/messages", async (req: Request, res: Response) => { |
| 437 | + const sessionId = req.query.sessionId as string; |
| 438 | + const transport = transports[sessionId]; |
| 439 | + if (transport) { |
| 440 | + await transport.handlePostMessage(req, res); |
| 441 | + } else { |
| 442 | + res.status(400).send('No transport found for sessionId'); |
| 443 | + } |
| 444 | + }); |
| 445 | + |
| 446 | + console.info("SSE server started on: ", process.env.SSE_ADDR); |
| 447 | + app.listen(process.env.SSE_ADDR); |
| 448 | +} |
| 449 | + |
413 | 450 | async function main() {
|
414 |
| - const transport = new StdioServerTransport(); |
| 451 | + console.info("Starting Elasticsearch MCP server..."); |
415 | 452 | const server = await createElasticsearchMcpServer(config);
|
416 | 453 |
|
417 |
| - await server.connect(transport); |
| 454 | + if (process.env.SSE_ADDR) { |
| 455 | + await create_sse_server(server); |
| 456 | + } else { |
| 457 | + const transport = new StdioServerTransport(); |
| 458 | + await server.connect(transport); |
418 | 459 |
|
419 |
| - process.on("SIGINT", async () => { |
420 |
| - await server.close(); |
421 |
| - process.exit(0); |
422 |
| - }); |
| 460 | + process.on("SIGINT", async () => { |
| 461 | + await server.close(); |
| 462 | + process.exit(0); |
| 463 | + }); |
| 464 | + } |
423 | 465 | }
|
424 | 466 |
|
425 | 467 | main().catch((error) => {
|
|
0 commit comments