-
Notifications
You must be signed in to change notification settings - Fork 702
Description
Problem Statement
I'm trying to use this the streamable http server from this package from within an existing server that uses fiber as it's webserver.
Under the hood fiber uses fasthttp and not go their own http server.
I've tried 2 things to implement this (somewhat cleanly) so far but both result in panics from within the go-mcp package:
Attempt 1:
var s *server.MCPServer
func createServer() {
s = server.NewMCPServer("server", "1.0.0")
}
func handlePost(c *fiber.Ctx) error {
return c.Send(s.HandleMessage(context.Background(), c.Body()))
}Attempt 2:
var httpServer *server.StreamableHTTPServer
func createServer() {
httpServer = server.NewStreamableHTTPServer(
server.NewMCPServer("server", "1.0.0"),
)
}
func handlePost(c *fiber.Ctx) error {
httpRequestBody := bytes.NewBuffer(c.Body())
httpRequest, err := http.NewRequest("POST", "http://localhost:8000/mcp", httpRequestBody)
if err != nil {
return err
}
const forServer = false
err = fasthttpadaptor.ConvertRequest(c.Context(), httpRequest, forServer)
if err != nil {
return err
}
// Note that i have not included the code for HttpCompliantResponseWriter but it's basically a simple collector for the http.ResponseWriter interface
responseWriter := &HttpCompliantResponseWriter{}
httpServer.ServeHTTP(responseWriter, httpRequest)
// Note that this is most likely not spec compliant but only for debugging perposes to see if this works
return c.Status(responseWriter.StatusCode).Send(responseWriter.Bytes)
}Proposed Solution
A fasthttp specific implementation would be amazing.
But that's an extra dependency and it might only be for a very little amound of users.
Personally i would like to have some sort of generic method i can call for a streamable http server so i can use this everywhere with every http server.
For example:
var httpServer *server.GenericStreamableHTTPServer
func createServer() {
httpServer = server.NewGenericStreamableHTTPServer(
server.NewMCPServer("server", "1.0.0"),
)
}
func handlePost(c *fiber.Ctx) error {
session, err := getMcpSession(c) // some user logic to get the current session
if err != nil {
return err
}
response, status, err := httpServer.Handle(
session, // the session type might be a interface or struct defined by mcp-go
c.Body(),
)
if err != nil {
return err
}
return c.Status(status).Send(response)
}Alternatives/Workarounds Considered
Spawning a internal server just for go-mcp and proxying all mcp route traffic to it.
But that's a lot of resources wasted on nothing.