@@ -12,6 +12,7 @@ import (
1212 "github.com/co-browser/agent-browser/internal/backend/models"
1313 "github.com/co-browser/agent-browser/internal/log"
1414 "github.com/co-browser/agent-browser/internal/web/templates"
15+ "github.com/co-browser/agent-browser/internal/web/templates/components"
1516 // "github.com/gorilla/mux" // Example: Assuming a router like gorilla/mux for path params
1617)
1718
@@ -54,7 +55,7 @@ func (h *APIHandlers) RegisterRoutes(mux *http.ServeMux /* or other router type
5455 mux .HandleFunc ("POST /api/mcp/servers/update/" , h .routeServerUpdateRequests )
5556
5657 // For delete requests (remove server)
57- mux .HandleFunc ("POST /api/mcp/servers/remove /" , h .routeServerDeleteRequests )
58+ mux .HandleFunc ("DELETE /api/mcp/servers/" , h .routeServerDeleteRequests )
5859
5960 // For POST requests (rediscover tools)
6061 mux .HandleFunc ("POST /api/mcp/servers/" , h .routeServerPostRequests )
@@ -142,15 +143,16 @@ func (h *APIHandlers) routeServerUpdateRequests(w http.ResponseWriter, r *http.R
142143
143144// routeServerDeleteRequests handles DELETE requests for server-specific paths (Recommended structure)
144145func (h * APIHandlers ) routeServerDeleteRequests (w http.ResponseWriter , r * http.Request ) {
145- serverID , subpath , err := parseServerPath (r .URL .Path , "/api/mcp/servers/remove/" )
146+ // Update prefix to match the new route pattern
147+ serverID , subpath , err := parseServerPath (r .URL .Path , "/api/mcp/servers/" )
146148 if err != nil {
147149 http .Error (w , err .Error (), http .StatusBadRequest )
148150 return
149151 }
150152
151153 switch subpath {
152154 case "" :
153- // POST /api/mcp/servers/remove /:id - Remove server
155+ // DELETE /api/mcp/servers/:id - Remove server
154156 h .RemoveMCPServer (w , r , serverID )
155157 default :
156158 http .NotFound (w , r )
@@ -191,32 +193,44 @@ func (h *APIHandlers) AddMCPServer(w http.ResponseWriter, r *http.Request) {
191193 // Parse form data
192194 if err := r .ParseForm (); err != nil {
193195 h .logger .Error ().Err (err ).Msg ("Failed to parse form data" )
194- http .Redirect (w , r , "/error?error=Form parse error" , http .StatusSeeOther )
196+ w .WriteHeader (http .StatusBadRequest )
197+ // Use components package directly
198+ components .AddServerErrorFeedback ("Form parse error" ).Render (r .Context (), w )
195199 return
196200 }
197201
198202 name := r .FormValue ("name" )
199203 url := r .FormValue ("url" )
200204
201205 if name == "" || url == "" {
202- http .Redirect (w , r , "/error?error=Missing name or url" , http .StatusSeeOther )
206+ w .WriteHeader (http .StatusBadRequest )
207+ // Use components package directly
208+ components .AddServerErrorFeedback ("Missing name or url" ).Render (r .Context (), w )
203209 return
204210 }
205211
206- _ , err := h .backendService .AddMCPServer (name , url )
212+ server , err := h .backendService .AddMCPServer (name , url )
207213 if err != nil {
208214 h .logger .Error ().Err (err ).Msg ("Error adding MCP server via API" )
209-
210- if err .Error () == fmt .Sprintf ("MCP server with URL '%s' already exists" , url ) {
211- http .Redirect (w , r , "/error?error=Server already exists" , http .StatusSeeOther )
212- return
215+ errorMsg := "Internal server error adding server"
216+ statusCode := http .StatusInternalServerError
217+ if strings .Contains (err .Error (), "already exists" ) {
218+ statusCode = http .StatusBadRequest
219+ errorMsg = fmt .Sprintf ("Server with URL '%s' already exists" , url )
213220 }
214-
215- http .Redirect (w , r , "/error?error=Internal server error" , http .StatusSeeOther )
221+ w .WriteHeader (statusCode )
222+ // Use components package directly
223+ components .AddServerErrorFeedback (errorMsg ).Render (r .Context (), w )
216224 return
217225 }
218226
219- http .Redirect (w , r , "/success" , http .StatusSeeOther )
227+ // Success: Return success alert fragment for the feedback div
228+ w .WriteHeader (http .StatusOK )
229+ // Send HX-Trigger to reset form after successful request (Optional - requires JS listener)
230+ // w.Header().Set("HX-Trigger", "resetAddForm")
231+ // Use components package directly
232+ components .AddServerSuccessFeedback (server .Name ).Render (r .Context (), w )
233+ // SSE refresh will handle list update separately
220234}
221235
222236// ListMCPServers handles GET /api/mcp/servers - Returns full JSON
@@ -239,24 +253,16 @@ func (h *APIHandlers) ListMCPServersFragment(w http.ResponseWriter, r *http.Requ
239253 servers , err := h .backendService .ListMCPServers ()
240254 if err != nil {
241255 h .logger .Error ().Err (err ).Msg ("Error listing MCP servers for fragment" )
242- // Optionally render an error message within the fragment
243- // w.WriteHeader(http.StatusInternalServerError)
244- // templates.ServerErrorFragment("Failed to load servers").Render(r.Context(), w)
245- // For now, return empty list on error
246- servers = []models.MCPServer {}
256+ w .WriteHeader (http .StatusInternalServerError )
257+ // Use components package directly for error feedback
258+ components .AddServerErrorFeedback ("Failed to load server list" ).Render (r .Context (), w )
259+ return
247260 }
248261
249262 // Set content type to HTML
250263 w .Header ().Set ("Content-Type" , "text/html; charset=utf-8" )
251-
252- // Render only the body component
253- component := templates .ServerListBodyComponent (servers )
254- err = component .Render (r .Context (), w )
255- if err != nil {
256- h .logger .Error ().Err (err ).Msg ("Error rendering server list fragment" )
257- // Don't write header again if Render already wrote partial content
258- // http.Error(w, "Failed to render server list fragment", http.StatusInternalServerError)
259- }
264+ // Render the list body component directly using parent templates package
265+ templates .ServerListBodyComponent (servers ).Render (r .Context (), w )
260266}
261267
262268// GetMCPServer handles GET /api/mcp/servers/:id
@@ -337,22 +343,25 @@ func (h *APIHandlers) UpdateMCPServer(w http.ResponseWriter, r *http.Request, se
337343 }
338344}
339345
340- // RemoveMCPServer handles POST /api/mcp/servers/:id
346+ // RemoveMCPServer handles DELETE /api/mcp/servers/:id
341347func (h * APIHandlers ) RemoveMCPServer (w http.ResponseWriter , r * http.Request , serverID int64 ) {
342348 err := h .backendService .RemoveMCPServer (serverID )
343-
344349 if err != nil {
345- h .logger .Error ().Err (err ).Int64 ("serverId " , serverID ).Msg ("Error removing MCP server via API" )
346-
350+ h .logger .Error ().Err (err ).Int64 ("serverID " , serverID ).Msg ("Error removing MCP server via API" )
351+ // Return error response for HTMX
347352 if strings .Contains (err .Error (), "not found" ) {
348- http .Redirect (w , r , "/error?error=Server not found" , http .StatusSeeOther )
353+ w .WriteHeader (http .StatusNotFound )
354+ _ , _ = w .Write ([]byte (fmt .Sprintf ("Server with ID %d not found" , serverID )))
349355 } else {
350- http .Redirect (w , r , "/error?error=Failed to remove server" , http .StatusSeeOther )
356+ w .WriteHeader (http .StatusInternalServerError )
357+ _ , _ = w .Write ([]byte ("Internal server error removing server" ))
351358 }
352359 return
353360 }
354361
355- http .Redirect (w , r , "/success" , http .StatusSeeOther )
362+ // Success: Return 200 OK. List update will happen via SSE.
363+ w .WriteHeader (http .StatusOK )
364+ // No body needed
356365}
357366
358367// --- Tool Management Handlers ---
0 commit comments