# Wicklee API Reference ## Localhost Agent API Base URL: `http://localhost:7700` Auth: None required. | Method | Endpoint | Description | |--------|----------|-------------| | GET | /api/metrics | SSE stream — 1 Hz telemetry with full MetricsPayload | | GET | /ws | WebSocket — 1 Hz live telemetry (same payload as SSE, fallback transport) | | GET | /api/observations | 18 agent-evaluated patterns with routing_hint per observation + node-level routing_hint/routing_hint_source. (2 additional cloud-evaluated patterns are queryable via the cloud Observations endpoint.) | | GET | /api/history?node_id=WK-XXXX | Metric history — 1h raw samples | | GET | /api/profile?minutes=60 | Inference Profiler — correlated TTFT/KV/queue/thermal/power timeline | | GET | /api/sla?window_min=60&target_ttft_ms=500 | Inference SLA Monitor — p50/p95/p99 for TTFT, E2E latency, TPOT plus compliance vs target | | GET | /api/v1/thermal-budget?node_id=X | Thermal Budget Calculator (Pro+, cloud) — sustainable rate, push threshold, time-to-Fair, penalized rate, plain-English advice | | POST/GET/DELETE | /api/v1/webhooks[/:id[/test]] | Threshold Webhooks (Pro+) — push notifications on thermal/inference state changes and WES threshold crossings. HMAC-SHA256 signed | | GET | /api/health (localhost) | Agent diagnostic — agent version, build target, DuckDB store health, list of routes available/unavailable when store init failed. One-curl debug for "why are my routes missing?" | | GET | /api/cost-by-model?hours=24 | Cost attribution per model — daily power cost breakdown | | GET | /api/explain-slowdown?ts_ms=N | Slowdown explainer — root cause analysis for a slow request | | GET | /api/model-comparison?hours=168 | Model comparison — side-by-side efficiency for every model that has run | | GET | /api/model-switches?hours=24 | Model switching cost — swap frequency, idle gap per transition | | GET | /api/model-candidates?search=llama&limit=20 | Model discovery — GGUF models from HuggingFace scored against local hardware | | GET | /api/runtime-config?model=X | Runtime Config Surface (v0.9.0) — cached launch-time config for a named model (Ollama, vLLM, llama.cpp). 200 with JSON, 400 if `?model=` missing, 404 if not yet cached. Templates and system prompts stay local — never pushed to the fleet. | | GET | /api/traces | Proxy inference traces | | GET | /api/events/history | Node event log | | GET | /api/events/recent | Recent in-memory events | | GET | /api/export?format=json\|csv | Data export | | GET | /api/tags | Ollama model tags | | GET | /api/pair/status | Pairing status | | POST | /api/insights/dismiss | Permanently dismiss a pattern | | GET | /api/insights/dismissed | List dismissed patterns | | POST | /mcp | MCP (Model Context Protocol) JSON-RPC 2.0 endpoint | | GET | /.well-known/mcp.json | MCP server manifest | ## MCP (Model Context Protocol) The agent exposes a local MCP server for AI agents (Cursor, Claude Desktop, custom agents). **Endpoint:** `POST http://localhost:7700/mcp` **Protocol:** JSON-RPC 2.0 **Auth:** None (localhost only) ### Tools | Tool | Description | |------|-------------| | `get_node_status` | Full hardware + inference metrics snapshot | | `get_inference_state` | Live/idle/busy state with sensor context | | `get_active_models` | Running models across Ollama, vLLM, llama.cpp | | `get_observations` | Server-side pattern evaluation — 17 agent-evaluated observations (live data) | | `get_metrics_history` | 1-hour rolling telemetry buffer | ### Resources | URI | Description | |-----|-------------| | `wicklee://node/metrics` | Live MetricsPayload JSON | | `wicklee://node/thermal` | Thermal state + WES penalty values | ### Connect to Claude Desktop Open the config file in your terminal: ```bash # macOS nano "$HOME/Library/Application Support/Claude/claude_desktop_config.json" # Linux nano ~/.config/Claude/claude_desktop_config.json # Windows (PowerShell) notepad "$env:APPDATA\Claude\claude_desktop_config.json" ``` Add the `wicklee` entry inside `mcpServers` (create the file if it doesn't exist): ```json { "mcpServers": { "wicklee": { "command": "/opt/homebrew/bin/npx", "args": ["-y", "mcp-remote", "http://localhost:7700/mcp"], "env": { "HOME": "/Users/YOUR_USERNAME", "PATH": "/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin" } } } } ``` Requires Node.js. Use `which npx` to find the correct npx path. Fully quit Claude Desktop (Cmd+Q) and relaunch after editing. ### Connect to Claude Code ```bash claude mcp add -s user wicklee -- npx -y mcp-remote http://localhost:7700/mcp ``` ### Cursor Edit `~/.cursor/mcp.json` (global) or `.cursor/mcp.json` (project). Add `wicklee` to `mcpServers`: ```json "wicklee": { "command": "npx", "args": ["-y", "mcp-remote", "http://localhost:7700/mcp"] } ``` ### Windsurf Edit `~/.codeium/windsurf/mcp_config.json`. Add `wicklee` to `mcpServers`: ```json "wicklee": { "command": "npx", "args": ["-y", "mcp-remote", "http://localhost:7700/mcp"] } ``` All setups require Node.js for the mcp-remote bridge. Restart your IDE after configuration changes. ### Test with curl ```bash curl -X POST http://localhost:7700/mcp \ -H "Content-Type: application/json" \ -d '{"jsonrpc":"2.0","method":"tools/call","params":{"name":"get_inference_state"},"id":1}' ``` ## Fleet API v1 Base URL: `https://wicklee.dev/api/v1` Auth: `X-API-Key: wk_live_...` header. | Method | Endpoint | Description | Tier | |--------|----------|-------------|------| | GET | /api/v1/fleet | All nodes with full MetricsPayload | All | | GET | /api/v1/fleet/wes | WES scores ranked | All | | GET | /api/v1/nodes/{id} | Single node deep dive | All | | GET | /api/v1/route/best | Routing recommendation (latency or efficiency). Optional `?model=` for per-model routing | All | | GET | /api/v1/models/discover | Model discovery — browse catalog, `?simulate_hw=` (Pro+), `?fleet=true` (Team+) | Tiered | | GET | /api/v1/fleet/model-comparison?hours=168 | Fleet-wide per-model rollup (WES, tok/s, watts, TTFT, cost). Reads `metrics_5min`. 1–720 hour window. | All | | GET | /api/v1/fleet/model-switches?hours=24 | Cross-node model swap events (LAG window function over `metrics_raw`). 1–168 hour window, capped at 200 rows. | All | | GET | /api/v1/fleet/cost-by-model?hours=24 | Fleet-wide per-model power cost using $0.16/kWh default. 1–168 hour window. | All | | GET | /api/v1/insights/latest | Fleet intelligence snapshot | Team+ | | GET | /api/v1/fleet/chargeback?days=30 | Chargeback/showback (Clerk JWT auth) — cost + $/1M-token attribution by team tag / model / node + daily trend. `&format=csv&group=` for finance export (audited) | Team+ | | GET | /api/v1/fleet/capacity?target_tok_s=200 | Capacity planner with procurement scenarios (Clerk JWT auth) — "reach 200 tok/s: 2× RTX 4090 vs 1× H100" priced from the fleet's own measured tok/W per hardware class; every scenario states its basis | Team+ | | GET | /api/v1/fleet/migration-advisor | Cross-node model migration (Clerk JWT auth) — live WES vs peers' 7-day demonstrated WES + free memory; moves with ≥20% estimated gain and 1.2× headroom | Team+ | | GET | /api/v1/fleet/idle-waste?days=30 | Idle-waste & right-sizing report (Clerk JWT auth) — phantom-load cost + recovery actions (unload idle model, consolidate) with projected $/mo recovery | Team+ | | GET/PUT | /api/digest | Weekly idle-waste email digest settings (Clerk JWT auth) — Resend-delivered, one per tenant, audited | Team+ | | POST | /api/v1/keys | Create API key | All | | GET | /api/v1/keys | List API keys | All | | DELETE | /api/v1/keys/{id} | Revoke API key | All | | GET | /metrics | Prometheus scrape endpoint (text format) | Team+ | | GET | /api/otel/config | OpenTelemetry export configuration | Team+ | | PUT | /api/otel/config | Update OTel export settings | Team+ | ## Response Examples ### GET /api/v1/fleet/wes ```json { "nodes": [ { "node_id": "WK-XXXX", "online": true, "wes": 15.0 }, { "node_id": "WK-99E9", "online": true, "wes": 3.2 } ] } ``` ### GET /api/v1/route/best ```json { "latency": { "node": "WK-99E9", "tok_s": 31.9, "wes": 3.3, "reason": "Highest throughput" }, "efficiency": { "node": "WK-XXXX", "tok_s": 19.5, "wes": 15.0, "reason": "Highest WES" }, "default": "efficiency" } ``` ### GET /api/runtime-config?model=llama3.1:8b ```json { "model": "llama3.1:8b", "runtime": "ollama", "captured_at_ms": 1774622475195, "context_length": 131072, "n_gpu_layers": 33, "quantization": "Q4_K_M", "parameter_count": 8030261312, "template": "{{ if .System }}<|system|>{{ .System }}{{ end }}...", "system_prompt": "You are a helpful assistant." } ``` ### GET /api/v1/fleet/model-comparison?hours=168 ```json { "models": [ { "model": "llama3.1:70b", "hours_active": 18.3, "avg_tok_s": 22.5, "avg_watts": 95.0, "wes": 0.24, "avg_ttft_ms": 245, "cost_per_hour": 0.0152, "total_cost": 0.278, "sample_count": 219 }, { "model": "phi3:mini", "hours_active": 42.0, "avg_tok_s": 85.1, "avg_watts": 12.0, "wes": 7.09, "avg_ttft_ms": 34, "cost_per_hour": 0.0019, "total_cost": 0.081, "sample_count": 504 } ] } ``` ### GET /api/v1/fleet/model-switches?hours=24 ```json { "swaps": [ { "ts_ms": 1774621630223, "node_id": "WK-XXXX", "from_model": "llama3.1:70b", "to_model": "phi3:mini", "gap_ms": 3200 } ], "total_swaps": 14, "total_gap_ms": 480000, "total_gap_minutes": 8.0 } ``` ### GET /api/v1/fleet/cost-by-model?hours=24 ```json { "models": [ { "model": "llama3.1:70b", "hours_active": 6.2, "avg_watts": 95.0, "cost_usd": 0.0942, "tok_s_avg": 22.5, "sample_count": 744 } ], "total_cost_usd": 0.221 } ``` ### GET /api/v1/insights/latest ```json { "generated_at_ms": 1774624251478, "fleet": { "online_count": 3, "total_count": 3, "avg_wes": 9.9, "fleet_tok_s": 79.0 }, "findings": [{ "node_id": "WK-99E9", "hostname": "spark-c559", "severity": "low", "pattern": "wes_below_baseline", "title": "WES below fleet average", "detail": "WES 3.3 vs fleet average 9.9", "value": 3.3, "unit": "WES" }] } ``` ## Key Metrics | Field | Type | Description | |-------|------|-------------| | inference_state | string | "live" \| "idle-spd" \| "busy" \| "idle" | | ollama_tokens_per_second | f32 | tok/s from 20-token probe (≤ every 10 min) | | apple_soc_power_w | f32 | Combined CPU+GPU+ANE (Apple Silicon) | | nvidia_power_draw_w | f32 | Board power (NVIDIA) | | thermal_state | string | "Normal" \| "Fair" \| "Serious" \| "Critical" | | penalty_avg | f32 | Thermal penalty (1.0 = no penalty) | | ollama_ttft_ms | f32 | TTFT from probe baseline | | vllm_avg_ttft_ms | f32 | TTFT from production histogram | | vllm_requests_waiting | u32 | Queue depth | ## WES Formula ``` WES = tok/s / (Watts x ThermalPenalty) ``` Normal thermal (penalty=1.0): WES = tok/s / Watts = tok/W. Color scale: >10 Excellent (emerald) · 3-10 Good (green) · 1-3 Acceptable (yellow) · <1 Low (red)