| 30 | } |
| 31 | |
| 32 | func loggingHandler(handler http.Handler) http.Handler { |
| 33 | return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { |
| 34 | start := time.Now() |
| 35 | |
| 36 | // Create a response writer wrapper to capture status code. |
| 37 | wrapped := &responseWriter{ResponseWriter: w, statusCode: http.StatusOK} |
| 38 | |
| 39 | // Sanitize user-controlled input before logging to prevent log injection |
| 40 | sanitizedPath := sanitizeForLog(r.URL.Path) |
| 41 | |
| 42 | // Log request details. |
| 43 | mcpHTTPLog.Printf("[REQUEST] %s | %s | %s %s", |
| 44 | start.Format(time.RFC3339), |
| 45 | r.RemoteAddr, |
| 46 | r.Method, |
| 47 | sanitizedPath) |
| 48 | |
| 49 | // Call the actual handler. |
| 50 | handler.ServeHTTP(wrapped, r) |
| 51 | |
| 52 | // Log response details. |
| 53 | duration := time.Since(start) |
| 54 | mcpHTTPLog.Printf("[RESPONSE] %s | %s | %s %s | Status: %d | Duration: %v", |
| 55 | time.Now().Format(time.RFC3339), |
| 56 | r.RemoteAddr, |
| 57 | r.Method, |
| 58 | sanitizedPath, |
| 59 | wrapped.statusCode, |
| 60 | duration) |
| 61 | }) |
| 62 | } |
| 63 | |
| 64 | // runHTTPServer runs the MCP server with HTTP/SSE transport |
| 65 | func runHTTPServer(server *mcp.Server, port int) error { |