runHTTP serves the MCP protocol over streamable HTTP transport.
()
| 78 | |
| 79 | // runHTTP serves the MCP protocol over streamable HTTP transport. |
| 80 | func runHTTP() error { |
| 81 | cfg, err := gosqlxmcp.LoadConfig() |
| 82 | if err != nil { |
| 83 | return fmt.Errorf("configuration error: %w", err) |
| 84 | } |
| 85 | |
| 86 | ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM) |
| 87 | defer stop() |
| 88 | |
| 89 | srv := gosqlxmcp.New(cfg) |
| 90 | |
| 91 | // Build handler chain: MCP → auth → rate limiter |
| 92 | handler := gosqlxmcp.RateLimitMiddleware(srv.Handler()) |
| 93 | |
| 94 | mux := http.NewServeMux() |
| 95 | mux.Handle("/mcp", handler) |
| 96 | mux.Handle("/mcp/", handler) |
| 97 | mux.HandleFunc("/health", func(w http.ResponseWriter, r *http.Request) { |
| 98 | w.Header().Set("Content-Type", "application/json") |
| 99 | fmt.Fprintf(w, `{"status":"ok","version":"%s","tools":7}`, gosqlx.Version) |
| 100 | }) |
| 101 | |
| 102 | httpSrv := &http.Server{ |
| 103 | Addr: cfg.Addr(), |
| 104 | Handler: mux, |
| 105 | } |
| 106 | |
| 107 | go func() { |
| 108 | <-ctx.Done() |
| 109 | shutdownCtx, cancel := context.WithTimeout(context.Background(), 5*time.Second) |
| 110 | defer cancel() |
| 111 | _ = httpSrv.Shutdown(shutdownCtx) |
| 112 | }() |
| 113 | |
| 114 | log.Printf("gosqlx-mcp: listening on %s (auth=%v)\n", cfg.Addr(), cfg.AuthEnabled()) |
| 115 | if err := httpSrv.ListenAndServe(); err != nil && err != http.ErrServerClosed { |
| 116 | return fmt.Errorf("server error: %w", err) |
| 117 | } |
| 118 | return nil |
| 119 | } |
no test coverage detected