Reverse Proxy
The reverse proxy is devtool-mcp's most powerful feature, enabling comprehensive frontend debugging through transparent HTTP interception and JavaScript instrumentation.
Overview
When you start a proxy:
- HTTP Proxy - All traffic is forwarded to your dev server
- Traffic Logging - Requests and responses are captured
- JS Injection - Diagnostic JavaScript is added to HTML pages
- WebSocket Server - Receives metrics from instrumented frontend
- Page Sessions - Groups requests by page view
Quick Start
// Start your dev server
run {script_name: "dev"}
// Create proxy in front of it
proxy {action: "start", id: "app", target_url: "http://localhost:3000", port: 8080}
Browse to http://localhost:8080 instead of port 3000. Everything works normally, but now you have:
- Complete HTTP traffic logs
- JavaScript error capture
- Performance metrics
- 50+ diagnostic primitives via
window.__devtool
Proxy Management
Start a Proxy
proxy {action: "start", id: "myapp", target_url: "http://localhost:3000", port: 8080}
→ {
"id": "myapp",
"status": "running",
"target_url": "http://localhost:3000",
"listen_addr": ":8080"
}
Auto Port Assignment
If port 8080 is busy, the proxy finds an available port:
proxy {action: "start", id: "app", target_url: "http://localhost:3000", port: 8080}
→ {
"id": "app",
"listen_addr": ":45123", // Different port assigned
"message": "Port 8080 was busy, using 45123"
}
Or explicitly request auto-assignment:
proxy {action: "start", id: "app", target_url: "http://localhost:3000", port: 0}
→ {listen_addr: ":49152"} // System assigns port
Check Status
proxy {action: "status", id: "myapp"}
→ {
"id": "myapp",
"status": "running",
"uptime": "15m32s",
"total_requests": 1542,
"log_stats": {
"http_entries": 1000,
"error_entries": 3,
"performance_entries": 45
}
}
List All Proxies
proxy {action: "list"}
→ {
"proxies": [
{"id": "frontend", "status": "running", "listen_addr": ":8080"},
{"id": "api", "status": "running", "listen_addr": ":8081"}
],
"active_count": 2
}
Stop a Proxy
proxy {action: "stop", id: "myapp"}
→ {message: "Proxy stopped"}
Traffic Logging
Query HTTP Traffic
proxylog {proxy_id: "app", types: ["http"], limit: 20}
→ {
"entries": [
{
"type": "http",
"method": "GET",
"url": "/api/users",
"status": 200,
"duration_ms": 45,
"request_headers": {...},
"response_headers": {...},
"request_body": null,
"response_body": "[{\"id\": 1, ...}]"
}
]
}
Filter by Method
proxylog {proxy_id: "app", types: ["http"], methods: ["POST", "PUT"]}
→ Only POST and PUT requests
Filter by Status Code
proxylog {proxy_id: "app", types: ["http"], status_codes: [500, 502, 503]}
→ Only server errors
Filter by URL Pattern
proxylog {proxy_id: "app", types: ["http"], url_pattern: "/api"}
→ Only requests containing "/api"
Time-Based Queries
proxylog {proxy_id: "app", types: ["http"], since: "5m"}
→ Last 5 minutes
proxylog {proxy_id: "app", since: "2024-01-15T10:00:00Z", until: "2024-01-15T10:30:00Z"}
→ Specific time range
Error Tracking
The proxy automatically captures frontend JavaScript errors:
proxylog {proxy_id: "app", types: ["error"]}
→ {
"entries": [
{
"type": "error",
"message": "Cannot read property 'map' of undefined",
"source": "http://localhost:8080/static/js/main.js",
"line": 142,
"column": 23,
"stack": "TypeError: Cannot read property 'map' of undefined\n at UserList...",
"url": "http://localhost:8080/users",
"timestamp": "2024-01-15T10:32:15Z"
}
]
}
Captures:
- Uncaught exceptions
- Unhandled promise rejections
- Error source and line/column
- Full stack trace
- Page URL where error occurred
Performance Metrics
Automatically collected on every page load:
proxylog {proxy_id: "app", types: ["performance"]}
→ {
"entries": [
{
"type": "performance",
"url": "http://localhost:8080/dashboard",
"navigation": {
"dom_content_loaded": 245,
"load_event": 892
},
"paint": {
"first_paint": 156,
"first_contentful_paint": 234
},
"resources": [
{"name": "main.js", "duration": 123, "size": 45678},
{"name": "styles.css", "duration": 45, "size": 12345}
]
}
]
}
Metrics include:
- DOM content loaded time
- Page load event time
- First paint / First contentful paint
- Resource timing (up to 50 resources)
Page Sessions
Group requests by page view for easier debugging:
currentpage {proxy_id: "app"}
→ {
"sessions": [
{
"id": "page-1",
"url": "http://localhost:8080/dashboard",
"started_at": "2024-01-15T10:30:00Z",
"resource_count": 24,
"error_count": 0
},
{
"id": "page-2",
"url": "http://localhost:8080/users",
"started_at": "2024-01-15T10:31:15Z",
"resource_count": 18,
"error_count": 2
}
]
}
Get details for a specific page:
currentpage {proxy_id: "app", action: "get", session_id: "page-2"}
→ {
"session": {
"id": "page-2",
"url": "http://localhost:8080/users",
"document": {...},
"resources": [
{"url": "/static/js/main.js", "status": 200, "duration": 123},
{"url": "/api/users", "status": 200, "duration": 456}
],
"errors": [
{"message": "Cannot read property 'map'...", "line": 142}
],
"performance": {...}
}
}
Executing Browser Code
Run JavaScript in connected browsers:
proxy {action: "exec", id: "app", code: "document.title"}
→ {result: "My App - Dashboard"}
proxy {action: "exec", id: "app", code: "window.location.href"}
→ {result: "http://localhost:8080/dashboard"}
This is how you access the Frontend Diagnostics API.
WebSocket Support
The proxy transparently handles WebSocket connections:
- Hot Module Replacement (HMR) works normally
- WebSocket upgrades are proxied to the target
- No additional configuration needed
Browser ←→ Proxy (8080) ←→ Dev Server (3000)
│
└── WebSocket for HMR
Log Statistics
proxylog {proxy_id: "app", action: "stats"}
→ {
"total_entries": 1542,
"by_type": {
"http": 1489,
"error": 8,
"performance": 45
},
"dropped": 0,
"max_entries": 1000
}
Note: The log is a circular buffer (default 1000 entries). When full, oldest entries are dropped.
Real-World Examples
Debugging API Issues
// Find failed API calls
proxylog {proxy_id: "app", types: ["http"], url_pattern: "/api", status_codes: [400, 401, 403, 404, 500]}
→ Found POST /api/users returning 400
// Get details
proxylog {proxy_id: "app", types: ["http"], url_pattern: "/api/users", methods: ["POST"]}
→ {
"request_body": "{\"email\": \"invalid\"}",
"response_body": "{\"error\": \"Invalid email format\"}"
}
Performance Investigation
// Find slow pages
proxylog {proxy_id: "app", types: ["performance"]}
→ Dashboard page: load_event = 3500ms
// Check resource loading
currentpage {proxy_id: "app", action: "get", session_id: "page-1"}
→ main.js took 2100ms to load (blocking)
Error Correlation
// See errors
proxylog {proxy_id: "app", types: ["error"]}
→ Error on /users page at line 142
// Check what API calls happened before error
currentpage {proxy_id: "app", action: "get", session_id: "page-2"}
→ GET /api/users returned 500 before the JavaScript error
Multiple Environments
// Proxy staging
proxy {action: "start", id: "staging", target_url: "https://staging.example.com", port: 8080}
// Proxy production (read-only debugging)
proxy {action: "start", id: "prod", target_url: "https://example.com", port: 8081}
// Compare behavior
proxylog {proxy_id: "staging", types: ["http"], url_pattern: "/api/users"}
proxylog {proxy_id: "prod", types: ["http"], url_pattern: "/api/users"}
Configuration
Log Size
Default: 1000 entries. Configure when starting:
proxy {action: "start", id: "app", target_url: "...", port: 8080, max_log_size: 5000}
Auto-Restart
Proxies automatically restart if the HTTP server crashes (max 5 restarts per minute). Check status for crash info:
proxy {action: "status", id: "app"}
→ {
"last_error": "bind: address already in use",
"restart_count": 2
}
Best Practices
- Use Meaningful IDs -
frontend,api,stagingnotproxy1 - Check listen_addr - Port may be auto-assigned if busy
- Clear Old Sessions -
currentpage {action: "clear"}periodically - Monitor Dropped Logs - Check stats for
droppedcount - Use Page Sessions - Easier than searching raw HTTP logs
Security Notes
- Development Only - No authentication, allows all origins
- Body Truncation - Request/response bodies limited to 10KB in logs
- Local Traffic - Only proxy trusted local development servers
Next Steps
- Explore the Frontend Diagnostics API
- See Debugging Web Apps use case
- Learn about Performance Monitoring