Files
AgentHub/docs/MCP.md
T
nntrivi2001 4a665da79e fix: a token-gated or LAN-bound dashboard works end to end (WSL mirrored)
- /ws-pty carries the dashboard token like /ws (the terminal never attached
  with DASHBOARD_TOKEN set), and so does everything that cannot send the
  header: images, downloads, exports, drops (withToken/tokenHeader). A
  refused upgrade answers 401/403 and is logged and counted by reason.
- The browser asks for a missing or wrong token (401 EUNAUTHORIZED) and takes
  ?token= from the link agenthub start prints, dropping it from the URL.
- The CLI sends the token (DASHBOARD_TOKEN, else the one the running server
  publishes 0600 in <data dir>/runtime/dashboard-token); MCP and statusline
  read the same file.
- DASHBOARD_HOST takes a list, and 127.0.0.1 is always listened on too, so a
  LAN-only bind keeps hooks and the CLI working.
- agenthub start --host/--allowed-hosts/--token are saved in
  <data dir>/network.json for every later start; a wide bind gets a token;
  every reachable URL is printed.
- tmux < 3.7 is an amber, once-per-version notice that says only the pane
  scrollbar is missing, with a ~/.local build instead of sudo make install.
- INSTALL: PATH belongs in ~/.profile for sudo -iu/ssh; WSL mirrored notes.
2026-11-06 14:59:48 +07:00

4.1 KiB

AgentHub MCP server

mcp/server.js is a small read-only Model Context Protocol server. It lets a Claude Code session (or any MCP client) ask the running AgentHub dashboard about sessions, costs, analytics, workspaces and alerts.

  • Plain Node, no build step and no dependency: JSON-RPC 2.0 over stdio, one JSON message per line (initialize, ping, tools/list, tools/call).
  • Every tool is ONE GET against the dashboard's HTTP API, so its numbers are the dashboard's own. It never opens the database and has no write tool.
  • The dashboard must be running (agenthub start). A tool called while it is down answers an isError result saying so.

Enable it

The plugin does not register the server by itself — every registered MCP server adds its tool list to every session's context, so it is opt-in:

# Plugin install or checkout with `agenthub` on PATH
claude mcp add agenthub -- agenthub mcp

# Checkout without the CLI linked
claude mcp add agenthub -- node /path/to/AgentHub/mcp/server.js

Add --scope user to make it available in every project. Remove it with claude mcp remove agenthub. On a plugin install, agenthub is the ~/.local/bin/agenthub launcher the bootstrap keeps pointed at the current build, so the registration survives plugin updates.

Which dashboard it talks to

Priority Source
1 AGENTHUB_URL (e.g. http://127.0.0.1:4821)
2 CLAUDE_DASHBOARD_PORT / DASHBOARD_PORT
3 ~/.claude/.agenthub.json — the live-dashboard discovery file the CLI uses (server/lib/dashboard-url.js)
4 http://127.0.0.1:4820

When the dashboard sets DASHBOARD_TOKEN, the MCP server sends it as Authorization: Bearer: its own DASHBOARD_TOKEN if set, else the token the running dashboard publishes for local tools in <data dir>/runtime/dashboard-token (0600, readable by the same account only). A dashboard of another account needs the variable (claude mcp add agenthub -e DASHBOARD_TOKEN=… -- agenthub mcp).

Tools

Every result is the API's JSON, pretty-printed as text. tz_offset is minutes from UTC as JavaScript's getTimezoneOffset() gives them (UTC+7 → -420); when left out, the MCP process's own time zone is used.

Tool Arguments API
get_health — GET /api/health
get_info — GET /api/settings/info
get_stats tz_offset, tool GET /api/stats
get_total_cost tz_offset, lane, tool GET /api/pricing/cost
get_session_cost session_id*, tz_offset GET /api/pricing/cost/:id
get_lane_cost lane*, tz_offset GET /api/pricing/cost?lane=
list_sessions q, status, tool, lane, limit GET /api/sessions
get_session session_id*, include_events GET /api/sessions/:id (?events=0 unless include_events)
get_session_stats session_id* GET /api/sessions/:id/stats
get_analytics tz_offset, tool GET /api/analytics
get_workflows status, tool GET /api/workflows
list_alerts unacked, limit GET /api/alerts
list_lanes — GET /api/lanes (workspaces)
list_pricing — GET /api/pricing
get_budget_status — GET /api/budgets/status

* = required. tool filters by AI CLI (claude, codex, …) on a dashboard that supports the filter and is ignored by one that does not. A route the dashboard does not have (/api/budgets/status before budgets ship, or any tool against an older AgentHub) answers Not available on this dashboard — this covers both a 404 and the production server's SPA page, which is served with 200 for any unknown path.

Errors

  • Dashboard unreachable, an API error (HTTP 404: Session not found), a missing required argument or an unknown tool → a tool result with isError: true.
  • Unknown JSON-RPC method → error -32601; a line that is not JSON → -32700.

Tests

server/__tests__/mcp-server.test.js drives the server over stdio against a fake API; server/__tests__/mcp-server-live.test.js calls every tool against a real in-test dashboard, so a tool whose path drifts from the API fails there.