Skip to main content
Glama

Last9 Observability MCP

Official
Apache 2.0
122
45
  • Apple
http_server.go3.07 kB
package main import ( "context" "encoding/json" "log" "net/http" "os" "os/signal" "sync" "syscall" "time" "last9-mcp/internal/models" last9mcp "github.com/last9/mcp-go-sdk/mcp" "github.com/modelcontextprotocol/go-sdk/mcp" ) // HTTPServer wraps the MCP server for HTTP transport type HTTPServer struct { server *last9mcp.Last9MCPServer config models.Config toolsMap map[string]interface{} sessions map[string]*MCPSession mu sync.RWMutex } // MCPSession represents an MCP session state type MCPSession struct { ID string Initialized bool Capabilities map[string]interface{} CreatedAt time.Time } // NewHTTPServer creates a new HTTP-based MCP server func NewHTTPServer(server *last9mcp.Last9MCPServer, config models.Config) *HTTPServer { return &HTTPServer{ server: server, config: config, sessions: make(map[string]*MCPSession), } } // Start starts the HTTP server with streamable HTTP support func (h *HTTPServer) Start() error { // url is host:port url := h.config.Host + ":" + h.config.Port // Create a mux to handle multiple endpoints mux := http.NewServeMux() // Create the streamable HTTP handler for the main MCP endpoint mcpHandler := mcp.NewStreamableHTTPHandler(func(req *http.Request) *mcp.Server { return h.server.Server }, nil) // Register handlers mux.Handle("/", mcpHandler) // Main MCP endpoint mux.HandleFunc("/health", h.handleHealth) // Create HTTP server with timeouts httpServer := &http.Server{ Addr: url, Handler: mux, ReadTimeout: 30 * time.Second, WriteTimeout: 30 * time.Second, IdleTimeout: 60 * time.Second, } log.Printf("🚀 MCP server listening on %s", url) // add shutdown hook signalChan := make(chan os.Signal, 1) signal.Notify(signalChan, syscall.SIGINT, syscall.SIGTERM) // Start server in a goroutine serverErr := make(chan error, 1) go func() { if err := httpServer.ListenAndServe(); err != nil && err != http.ErrServerClosed { serverErr <- err } }() // Wait for context cancellation or server error select { // add signal chan case sig := <-signalChan: log.Printf("🛑 Received signal: %v, initiating graceful shutdown...", sig) case err := <-serverErr: log.Printf("❌ Server error: %v", err) return err } shutdownCtx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() // Attempt graceful shutdown if err := httpServer.Shutdown(shutdownCtx); err != nil { log.Printf("❌ Graceful shutdown failed: %v", err) return err } log.Printf("✅ HTTP server shutdown complete") if err := h.server.Shutdown(shutdownCtx); err != nil { log.Printf("❌ MCP server shutdown error: %v", err) return err } log.Printf("✅ MCP server shutdown complete") return nil } func (h *HTTPServer) handleHealth(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusOK) json.NewEncoder(w).Encode(map[string]string{ "status": "healthy", "server": "last9-mcp", "version": "1.0.0", }) }

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/last9/last9-mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server