@@ -19,10 +19,15 @@ import {
19
19
TransportRequestParams ,
20
20
} from "@elastic/elasticsearch" ;
21
21
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js" ;
22
+ import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js" ;
22
23
import fs from "fs" ;
24
+ import yargs from "yargs" ;
25
+ import { hideBin } from "yargs/helpers" ;
26
+ import { Request , Response } from "express" ;
23
27
// @ts -expect-error ignore `with` keyword
24
28
import pkg from './package.json' with { type : 'json' }
25
29
30
+
26
31
// Product metadata, used to generate the request User-Agent header and
27
32
// passed to the McpServer constructor.
28
33
const product = {
@@ -498,18 +503,71 @@ const config: ElasticsearchConfig = {
498
503
pathPrefix : process . env . ES_PATH_PREFIX || "" ,
499
504
} ;
500
505
506
+ //transport mode selection using yargs
507
+ const argv = yargs ( hideBin ( process . argv ) )
508
+ . option ( "mcp-transport" , {
509
+ type : "string" ,
510
+ choices : [ "stdio" , "http" ] ,
511
+ default : "stdio" ,
512
+ description : "Choose transport mode: stdio or http"
513
+ } ) . strict ( ) . parseSync ( ) ;
514
+
515
+ const transportMode = argv [ "mcp-transport" ]
516
+
517
+
501
518
async function main ( ) {
502
- const transport = new StdioServerTransport ( ) ;
503
519
const server = await createElasticsearchMcpServer ( config ) ;
504
520
505
- await server . connect ( transport ) ;
521
+ if ( transportMode === "http" ) {
522
+ const express = ( await import ( "express" ) ) . default ;
506
523
507
- process . on ( "SIGINT" , async ( ) => {
508
- await server . close ( ) ;
509
- process . exit ( 0 ) ;
510
- } ) ;
524
+ const app = express ( ) ;
525
+ app . use ( express . json ( ) ) ;
526
+
527
+ app . post ( "/mcp" , async ( req : Request , res : Response ) => {
528
+ try {
529
+ const transport : StreamableHTTPServerTransport =
530
+ new StreamableHTTPServerTransport ( {
531
+ sessionIdGenerator : undefined ,
532
+ } ) ;
533
+ res . on ( "close" , ( ) => {
534
+ console . log ( "Request closed" ) ;
535
+ transport . close ( ) ;
536
+ server . close ( ) ;
537
+ } ) ;
538
+ await server . connect ( transport ) ;
539
+ await transport . handleRequest ( req , res , req . body ) ;
540
+ } catch ( error ) {
541
+ console . error ( "Error handling MCP request:" , error ) ;
542
+ if ( ! res . headersSent ) {
543
+ res . status ( 500 ) . json ( {
544
+ jsonrpc : "2.0" ,
545
+ error : {
546
+ code : - 32603 ,
547
+ message : "Internal server error" ,
548
+ } ,
549
+ id : null ,
550
+ } ) ;
551
+ }
552
+ }
553
+ } ) ;
554
+ const PORT = 3002 ;
555
+ app . listen ( PORT , ( ) => {
556
+ console . log ( `MCP Stateless Streamable HTTP Server listening on port ${ PORT } ` ) ;
557
+ } ) ;
558
+ } else {
559
+ const transport = new StdioServerTransport ( ) ;
560
+
561
+ await server . connect ( transport ) ;
562
+
563
+ process . on ( "SIGINT" , async ( ) => {
564
+ await server . close ( ) ;
565
+ process . exit ( 0 ) ;
566
+ } ) ;
567
+ }
511
568
}
512
569
570
+
513
571
main ( ) . catch ( ( error ) => {
514
572
console . error (
515
573
"Server error:" ,
0 commit comments