The XcodeMCPWrapper Web UI Dashboard provides real-time monitoring, metrics visualization, and audit logging for your MCP tool usage.
- Real-time Metrics Dashboard: Live RPS counter, latency percentiles (p50, p95, p99), error rates
- Tool Usage Analytics: Visual charts showing most frequently used tools
- Request Timeline: Time-series visualization of requests and errors
- Per-Tool Latency Statistics: Detailed latency breakdown by tool
- Audit Logging: Persistent log of all MCP tool calls with export capabilities
- Optional Authentication: Basic auth support for secure access
pip install mcpbridge-wrapper[webui]Or using the install script:
./scripts/install.sh --webuiOr install the extras manually:
pip install fastapi uvicorn websockets httpx python-multipart# Start with Web UI on default port 8080
xcodemcpwrapper --web-ui
# Start with custom port
xcodemcpwrapper --web-ui --web-ui-port 9090
# Start with custom config file
xcodemcpwrapper --web-ui --web-ui-config /path/to/config.json# Install with Web UI dependencies
make install-webui
# Start Web UI dashboard
make webui
# Check Web UI health and metrics
make webui-health
# Run Web UI tests
make test-webuiIf you cloned the repo and installed via make install-webui in a virtual environment:
# Start with Web UI on default port 8080
/path/to/XcodeMCPWrapper/.venv/bin/mcpbridge-wrapper --web-ui
# Start with custom port
/path/to/XcodeMCPWrapper/.venv/bin/mcpbridge-wrapper --web-ui --web-ui-port 9090Replace /path/to/XcodeMCPWrapper with the actual path to your cloned repository.
xcodemcpwrapper enables the dashboard only when --web-ui is provided.
There is no MCP_WRAPPER_WEB_UI* runtime toggle.
# Web UI is enabled by the CLI flag
xcodemcpwrapper --web-uiThe Web UI dashboard is hosted by the wrapper process that successfully binds the configured host:port.
- Only one process can listen on a single
host:port(for example127.0.0.1:8080). - If another wrapper process starts with the same Web UI port, MCP can keep working while dashboard startup is skipped for that process.
- This is expected behavior in multi-agent setups and can look like: tools are available, but
http://127.0.0.1:8080is unreachable. - Ownership is decided at wrapper-process startup by successful port binding.
Recommended patterns:
- Single owner (recommended): enable
--web-uifor one designated client process only. - Unified broker config (multi-agent): use
--broker --web-ui --web-ui-config <shared-path>across Cursor/Zed/Claude/Codex so the first auto-spawn host owns one shared dashboard endpoint. - Separate ports per process: if you truly need multiple dashboards, give each process its own port.
Broker-mode note:
--broker-daemon --web-uistarts the dashboard in the broker host process.--broker --web-uican start the dashboard when it has to spawn the broker host.- When
--brokerattaches to an already-running host, it does not change that host's dashboard state. - If dashboard bind fails, broker MCP transport still runs and dashboard startup is skipped.
For full single-config examples by client (Cursor, Zed, Claude Code, Codex CLI), see Broker Mode Guide.
Once started, open your browser to:
http://localhost:8080
Create a webui.json configuration file:
{
"host": "127.0.0.1",
"port": 8080,
"auth": {
"enabled": false,
"username": "admin",
"password": "changeme"
},
"metrics": {
"window_seconds": 3600,
"max_datapoints": 3600,
"capture_params": false
},
"audit": {
"enabled": true,
"log_dir": "logs/audit",
"max_file_size_mb": 10.0,
"max_files": 10,
"capture_payload": false
},
"dashboard": {
"refresh_interval_ms": 1000,
"chart_history_seconds": 300
}
}| Option | Description | Default |
|---|---|---|
host |
Server bind address | 127.0.0.1 |
port |
Server port | 8080 |
auth.enabled |
Enable basic authentication | false |
auth.username |
Auth username | admin |
auth.password |
Auth password | changeme |
metrics.window_seconds |
Metrics rolling window | 3600 |
metrics.max_datapoints |
Max data points per series | 3600 |
metrics.capture_params |
Record parameter key names per tool call for pattern analysis | false |
audit.enabled |
Enable audit logging | true |
audit.log_dir |
Audit log directory (relative paths resolve from the config-file directory; otherwise from current process working directory) | logs/audit |
audit.max_file_size_mb |
Max log file size | 10.0 |
audit.max_files |
Max rotated log files | 10 |
audit.capture_payload |
Capture full request/response payloads in the ring buffer | false |
dashboard.refresh_interval_ms |
WebSocket update interval | 1000 |
dashboard.chart_history_seconds |
Chart history duration | 300 |
You can override config values via environment variables (when Web UI is enabled via --web-ui):
export WEBUI_HOST=0.0.0.0
export WEBUI_PORT=9000
export WEBUI_AUTH_ENABLED=true
export WEBUI_AUTH_USERNAME=myuser
export WEBUI_AUTH_PASSWORD=mypass
xcodemcpwrapper --web-uiNote: Environment variables only cover
host,port, andauth.*. Options likemetrics.capture_paramsandaudit.capture_payloadhave no env var equivalent and must be set via a config file passed with--web-ui-config.
If you configure the wrapper via mcp.json (e.g. Cursor, Claude Desktop), pass the config file path as an argument:
{
"xcode-tools": {
"command": "/Users/YOUR_USERNAME/bin/xcodemcpwrapper",
"args": ["--web-ui", "--web-ui-config", "/Users/YOUR_USERNAME/.config/xcodemcpwrapper/webui.json"],
"env": {}
}
}Then create the config file at the specified path with your desired settings, for example to enable parameter capture:
{
"metrics": {
"capture_params": true
}
}Precedence note: If you pass both
--web-ui-portand--web-ui-config, the CLI port overrides the config file port. In MCP client setups this can cause Web UI startup to be skipped if the forced port is already in use.
The top section displays key metrics:
- Uptime: How long the wrapper has been running
- Total Requests: Cumulative request count
- Requests/sec: Current throughput (60s window)
- Error Rate: Percentage of failed requests
- Total Errors: Cumulative error count
- In Flight: Currently active requests
- Tool Usage (Bar): Bar chart of tool call frequency
- Tool Distribution (Pie): Pie chart showing tool usage breakdown
- Request Timeline: Time-series of requests and errors
- Latency: Latency trends over time
A table showing detailed latency metrics per tool:
- Calls: Total number of calls
- Avg/P50/P95/P99: Latency percentiles
- Min/Max: Latency range
A paginated table of recent tool calls with:
- Timestamp (ISO format)
- Tool name
- Direction (request/response)
- Request ID
- Latency (ms)
- Error message (if any)
Features:
- Filter by tool name: Type in the filter box
- Pagination: Navigate through history
- Export JSON: Download full audit log as JSON
- Export CSV: Download as CSV for spreadsheet analysis
When multiple wrapper processes write to the same audit log directory (for example, frequent Cursor reconnects), the dashboard uses this model:
- Audit data is shared through on-disk JSONL files in
audit.log_dir. /api/auditrefreshes from those files when they change, so entries from sibling processes become visible without restarting the dashboard process./api/sessionsis computed from the same refreshed audit entry set used by/api/audit.- Tool charts/KPIs are sourced from
SharedMetricsStore(SQLite) and remain process-shared.
Known limitation:
- Session ordering/duration edge cases are tracked separately under
BUG-T20.
The Web UI exposes a REST API:
| Endpoint | Method | Description |
|---|---|---|
/api/health |
GET | Health check (no auth) |
/api/metrics |
GET | Current metrics summary |
/api/metrics/timeseries |
GET | Time-series data for charts |
/api/metrics/reset |
POST | Reset all metrics |
/api/audit |
GET | Query audit logs (with pagination) |
/api/audit/export/json |
GET | Export audit as JSON |
/api/audit/export/csv |
GET | Export audit as CSV |
/api/config |
GET | Current configuration (masked) |
/ws/metrics |
WebSocket | Real-time metrics stream |
Enable basic authentication by setting auth.enabled: true in config or using the environment variable:
export WEBUI_AUTH_ENABLED=true
export WEBUI_AUTH_USERNAME=admin
export WEBUI_AUTH_PASSWORD=your-secure-passwordNote: The dashboard binds to 127.0.0.1 (localhost only) by default for security. Only change to 0.0.0.0 if you understand the security implications.
Audit logs contain MCP tool call data. Ensure:
- Log directory has appropriate permissions
- Log files are rotated to prevent disk exhaustion
- Sensitive data in requests/responses is sanitized before logging
Error: Web UI dependencies not installed. Install with: pip install mcpbridge-wrapper[webui]
Install the webui extras:
pip install mcpbridge-wrapper[webui]Address already in use
Change the port:
xcodemcpwrapper --web-ui --web-ui-port 9090Or set via environment:
export WEBUI_PORT=9090- Check that the wrapper is still running
- Refresh the page
- Check browser console for WebSocket errors
- The dashboard falls back to HTTP polling if WebSocket fails
Adjust retention settings in config:
{
"metrics": {
"window_seconds": 1800,
"max_datapoints": 1800
},
"audit": {
"max_file_size_mb": 5.0,
"max_files": 5
}
}The Web UI is designed for minimal impact on wrapper performance:
- Metrics collection adds < 1% overhead
- WebSocket updates every 1 second
- Audit logging is asynchronous
- Memory-bounded data structures
- All heavy operations run in separate threads
To remove Web UI support:
pip uninstall fastapi uvicorn websockets httpx python-multipartOr reinstall without extras:
pip install mcpbridge-wrapper --force-reinstall