@@ -10,45 +10,57 @@ import io.ktor.util.collections.*
1010
1111private val logger = KotlinLogging .logger {}
1212
13+ public val Mcp : ApplicationPlugin <Unit > = createApplicationPlugin(" Mcp" ) {
14+ application.install(SSE )
15+ }
16+
17+ public fun Routing.mcp (path : String , block : () -> Server ) {
18+ route(path) {
19+ mcp(block)
20+ }
21+ }
22+
1323/* *
1424 * Configures the Ktor Application to handle Model Context Protocol (MCP) over Server-Sent Events (SSE).
1525 */
16- public fun Application. MCP (block : () -> Server ) {
26+ public fun Routing. mcp (block : () -> Server ) {
1727 val servers = ConcurrentMap <String , Server >()
1828
19- install(SSE )
20- routing {
21- sse(" /sse" ) {
22- val transport = SSEServerTransport (" /message" , this )
23- logger.info { " New SSE connection established with sessionId: ${transport.sessionId} " }
29+ sse {
30+ val transport = SSEServerTransport (" " , this ) // same endpoint
31+ logger.info { " New SSE connection established with sessionId: ${transport.sessionId} " }
2432
25- val server = block()
33+ val server = block()
2634
27- servers[transport.sessionId] = server
28- logger.debug { " Server instance created and stored for sessionId: ${transport.sessionId} " }
35+ servers[transport.sessionId] = server
36+ logger.debug { " Server instance created and stored for sessionId: ${transport.sessionId} " }
2937
30- server.onCloseCallback = {
31- logger.info { " Server connection closed for sessionId: ${transport.sessionId} " }
32- servers.remove(transport.sessionId)
33- }
34-
35- server.connect(transport)
36- logger.debug { " Server connected to transport for sessionId: ${transport.sessionId} " }
38+ server.onCloseCallback = {
39+ logger.info { " Server connection closed for sessionId: ${transport.sessionId} " }
40+ servers.remove(transport.sessionId)
3741 }
3842
39- post( " /message " ) {
40- val sessionId: String = call.request.queryParameters[ " sessionId" ] !!
41- logger.debug { " Received message for sessionId: $sessionId " }
43+ server.connect(transport)
44+ logger.debug { " Server connected to transport for sessionId: ${transport. sessionId} " }
45+ }
4246
43- val transport = servers[sessionId]?.transport as ? SSEServerTransport
44- if (transport == null ) {
45- logger.warn { " Session not found for sessionId: $sessionId " }
46- call.respond(HttpStatusCode .NotFound , " Session not found " )
47+ post {
48+ val sessionId : String = call.request.queryParameters[ " sessionId " ]
49+ ? : run {
50+ call.respond(HttpStatusCode .BadRequest , " sessionId query parameter is not provided " )
4751 return @post
4852 }
4953
50- transport.handlePostMessage(call)
51- logger.trace { " Message handled for sessionId: $sessionId " }
54+ logger.debug { " Received message for sessionId: $sessionId " }
55+
56+ val transport = servers[sessionId]?.transport as ? SSEServerTransport
57+ if (transport == null ) {
58+ logger.warn { " Session not found for sessionId: $sessionId " }
59+ call.respond(HttpStatusCode .NotFound , " Session not found" )
60+ return @post
5261 }
62+
63+ transport.handlePostMessage(call)
64+ logger.trace { " Message handled for sessionId: $sessionId " }
5365 }
5466}
0 commit comments