Add MCP server
This commit is contained in:
109
servers/mcp/mcp.go
Normal file
109
servers/mcp/mcp.go
Normal file
@@ -0,0 +1,109 @@
|
||||
package mcp
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
mcpsdk "github.com/modelcontextprotocol/go-sdk/mcp"
|
||||
"github.com/rs/zerolog/log"
|
||||
"github.com/spf13/viper"
|
||||
|
||||
"git.coopgo.io/coopgo-apps/parcoursmob/core/application"
|
||||
"git.coopgo.io/coopgo-apps/parcoursmob/core/utils/geo"
|
||||
cache "git.coopgo.io/coopgo-apps/parcoursmob/core/utils/storage"
|
||||
"git.coopgo.io/coopgo-apps/parcoursmob/services"
|
||||
)
|
||||
|
||||
// MCPServer represents the MCP HTTP server
|
||||
type MCPServer struct {
|
||||
cfg *viper.Viper
|
||||
services *services.ServicesHandler
|
||||
kv cache.KVHandler
|
||||
filestorage cache.FileStorage
|
||||
applicationHandler *application.ApplicationHandler
|
||||
mcpServer *mcpsdk.Server
|
||||
geoService *geo.GeoService
|
||||
}
|
||||
|
||||
// NewMCPServer creates a new MCP server instance
|
||||
func NewMCPServer(
|
||||
cfg *viper.Viper,
|
||||
svc *services.ServicesHandler,
|
||||
applicationHandler *application.ApplicationHandler,
|
||||
kv cache.KVHandler,
|
||||
filestorage cache.FileStorage,
|
||||
) *MCPServer {
|
||||
// Initialize geocoding service
|
||||
geoType := cfg.GetString("geo.type")
|
||||
baseURL := cfg.GetString("geo." + geoType + ".url")
|
||||
autocompleteEndpoint := cfg.GetString("geo." + geoType + ".autocomplete")
|
||||
geoService := geo.NewGeoService(geoType, baseURL, autocompleteEndpoint)
|
||||
|
||||
server := &MCPServer{
|
||||
cfg: cfg,
|
||||
services: svc,
|
||||
kv: kv,
|
||||
filestorage: filestorage,
|
||||
applicationHandler: applicationHandler,
|
||||
geoService: geoService,
|
||||
}
|
||||
|
||||
// Create MCP server with implementation info
|
||||
server.mcpServer = mcpsdk.NewServer(&mcpsdk.Implementation{
|
||||
Name: "parcoursmob-mcp-server",
|
||||
Version: "1.0.0",
|
||||
}, nil)
|
||||
|
||||
// Register journey search tool
|
||||
server.registerJourneySearchTool()
|
||||
|
||||
return server
|
||||
}
|
||||
|
||||
// Run starts the MCP HTTP server with SSE transport
|
||||
func Run(
|
||||
cfg *viper.Viper,
|
||||
svc *services.ServicesHandler,
|
||||
applicationHandler *application.ApplicationHandler,
|
||||
kv cache.KVHandler,
|
||||
filestorage cache.FileStorage,
|
||||
) {
|
||||
address := cfg.GetString("server.mcp.listen")
|
||||
service_name := cfg.GetString("service_name")
|
||||
|
||||
mcpServer := NewMCPServer(cfg, svc, applicationHandler, kv, filestorage)
|
||||
|
||||
// Create HTTP server with SSE transport
|
||||
mux := http.NewServeMux()
|
||||
|
||||
// Health check endpoint
|
||||
mux.HandleFunc("/health", func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
w.Write([]byte(`{"status":"healthy"}`))
|
||||
})
|
||||
|
||||
// MCP Streamable HTTP endpoint (preferred over SSE as of 2025-03-26 spec)
|
||||
streamHandler := mcpsdk.NewStreamableHTTPHandler(func(r *http.Request) *mcpsdk.Server {
|
||||
return mcpServer.mcpServer
|
||||
}, nil)
|
||||
mux.Handle("/", streamHandler)
|
||||
|
||||
// Also support legacy SSE endpoint for backwards compatibility
|
||||
sseHandler := mcpsdk.NewSSEHandler(func(r *http.Request) *mcpsdk.Server {
|
||||
return mcpServer.mcpServer
|
||||
}, nil)
|
||||
mux.Handle("/sse", sseHandler)
|
||||
|
||||
srv := &http.Server{
|
||||
Handler: mux,
|
||||
Addr: address,
|
||||
WriteTimeout: 60 * time.Second,
|
||||
ReadTimeout: 30 * time.Second,
|
||||
}
|
||||
|
||||
log.Info().Str("service_name", service_name).Str("address", address).Msg("Running MCP HTTP server with SSE transport")
|
||||
|
||||
err := srv.ListenAndServe()
|
||||
log.Error().Err(err).Msg("MCP server error")
|
||||
}
|
||||
Reference in New Issue
Block a user