Add simple web UI for browsing the registry (#757)

## Summary

Adds a clean, minimal web interface at `/` for browsing MCP servers in
the registry. Built as a single self-contained HTML file embedded in the
Go binary.

## Features

- Responsive grid layout (1/2/3 columns based on screen size)
- Search servers by name
- Filter to show only latest versions (default on)
- "Recently Updated" section for servers updated in the last hour
- Expandable cards with full server metadata and JSON viewer
- Debug modal to switch between production/staging/local/custom API
endpoints
- Full URL parameter support and browser history navigation

## Implementation

- Single HTML file (~400 lines) with Tailwind CSS via CDN
- Zero build dependencies
- Embedded using `//go:embed` 
- Served directly from router at root path
- Uses stable v0.1 API endpoints

Fixes #99

---

AI disclosure: this is 99% vibed with Claude. It's intended as a v0 to
get something up and working, and then maybe at a later date we can
replace it with something more real.
This commit is contained in:
adam jones 2025-11-10 12:37:36 +00:00 • committed by GitHub
commit 8cf317af68
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -184,14 +184,19 @@ func NewHumaAPI(cfg *config.Config, registry service.RegistryService, mux *http.
// Add /metrics for Prometheus metrics using promhttp
mux.Handle("/metrics", metrics.PrometheusHandler())
// Add redirect from / to docs and 404 handler for all other routes
// Add UI and 404 handler for all other routes
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
if r.URL.Path == "/" {
http.Redirect(w, r, "https://github.com/modelcontextprotocol/registry/tree/main/docs", http.StatusTemporaryRedirect)
// Serve UI at root
w.Header().Set("Content-Type", "text/html; charset=utf-8")
_, err := w.Write([]byte(v0.GetUIHTML()))
if err != nil {
http.Error(w, "Failed to write response", http.StatusInternalServerError)
}
return
}
// Handle 404 for all other routes
// Handle 404 for all non-matched routes
handle404(w, r)
})