Local, enterprise-grade Model Context Protocol (MCP) server for this repository.
It exposes the existing dashboard backend (/api/*) as MCP tools for Claude Code, Claude Desktop, and other MCP hosts.
- Overview
- Transport Modes
- Runtime Architecture
- Tool Domains
- Safety and Control Model
- Prerequisites
- Setup and Commands
- Container Runtime (Docker / Podman)
- Host Configuration
- Configuration Variables
- Enterprise File Structure
- Execution Flows
- Operational Runbook
- Troubleshooting
The MCP server supports three transport modes:
| Mode | Transport | Use case |
|---|---|---|
| stdio | JSON-RPC over stdin/stdout | MCP host integration (Claude Code, Claude Desktop) |
| http | SSE + Streamable HTTP over Express | Remote/networked MCP clients, web integrations |
| repl | Interactive CLI | Local debugging, manual tool invocation, ops tasks |
Standard MCP transport. An MCP host launches the server as a child process.
npm run mcp:start # production
npm run mcp:dev # development (tsx)Express-based HTTP server exposing both modern Streamable HTTP (protocol 2025-11-25) and legacy SSE (protocol 2024-11-05) transports on configurable port.
npm run mcp:start:http # production
npm run mcp:dev:http # development (tsx)Endpoints:
| Endpoint | Methods | Protocol |
|---|---|---|
/mcp |
POST, GET, DELETE | Streamable HTTP (2025-11-25) |
/sse |
GET | Legacy SSE stream (2024-11-05) |
/messages |
POST | Legacy SSE message endpoint |
/health |
GET | Server health check |
Interactive terminal with tab completion, colored output, and formatted results.
npm run mcp:start:repl # production
npm run mcp:dev:repl # development (tsx)REPL commands:
| Command | Description |
|---|---|
help |
Show all commands |
tools [domain] |
List tools (optionally filtered) |
domains |
List tool domains with counts |
health |
Quick dashboard health check |
stats |
Dashboard overview statistics |
status |
Full operational snapshot |
config |
Show current configuration |
clear |
Clear screen |
exit |
Quit |
<tool_name> {json} |
Invoke tool with JSON args |
<tool_name> k=v ... |
Invoke tool with key=value args |
CLI argument overrides: --transport=stdio|http|repl, --repl, --http
graph LR
HOST["MCP Host<br/>(Claude Code / Claude Desktop / IDE)"]
HTTP_CLIENT["HTTP MCP Client<br/>(remote/web)"]
REPL_USER["Operator<br/>(interactive CLI)"]
MCP_STDIO["MCP Server<br/>STDIO transport"]
MCP_HTTP["MCP Server<br/>HTTP + SSE transport<br/>Express :8819"]
MCP_REPL["MCP Server<br/>REPL transport"]
API["Dashboard API<br/>Express server /api/*"]
DB["SQLite<br/>data/dashboard.db"]
HOST -->|"stdin/stdout"| MCP_STDIO
HTTP_CLIENT -->|"HTTP POST /mcp<br/>GET /sse"| MCP_HTTP
REPL_USER -->|"interactive CLI"| MCP_REPL
MCP_STDIO -->|"HTTP (local)"| API
MCP_HTTP -->|"HTTP (local)"| API
MCP_REPL -->|"HTTP (local)"| API
API --> DB
style HOST fill:#6366f1,stroke:#818cf8,color:#fff
style HTTP_CLIENT fill:#f59e0b,stroke:#fbbf24,color:#000
style REPL_USER fill:#a855f7,stroke:#c084fc,color:#fff
style MCP_STDIO fill:#0f766e,stroke:#14b8a6,color:#fff
style MCP_HTTP fill:#0f766e,stroke:#14b8a6,color:#fff
style MCP_REPL fill:#0f766e,stroke:#14b8a6,color:#fff
style API fill:#339933,stroke:#5cb85c,color:#fff
style DB fill:#003B57,stroke:#005f8a,color:#fff
graph TD
ROOT["MCP Tool Surface"]
OBS["Observability<br/>health, stats, analytics,<br/>system info, export, snapshot"]
SES["Sessions<br/>list/get/create/update"]
AGT["Agents<br/>list/get/create/update"]
EVT["Events & Hooks<br/>list events, ingest hook events"]
PRC["Pricing & Cost<br/>rules CRUD, cost queries, reset defaults"]
MNT["Maintenance<br/>cleanup, reimport, reinstall hooks,<br/>clear-all-data (guarded)"]
ROOT --> OBS
ROOT --> SES
ROOT --> AGT
ROOT --> EVT
ROOT --> PRC
ROOT --> MNT
Read-focused tools:
dashboard_health_checkdashboard_get_statsdashboard_get_analyticsdashboard_get_system_infodashboard_export_datadashboard_get_operational_snapshotdashboard_list_sessionsdashboard_get_sessiondashboard_list_agentsdashboard_get_agentdashboard_list_eventsdashboard_get_pricing_rulesdashboard_get_total_costdashboard_get_session_cost
Mutation tools (require MCP_DASHBOARD_ALLOW_MUTATIONS=true):
dashboard_create_sessiondashboard_update_sessiondashboard_create_agentdashboard_update_agentdashboard_ingest_hook_eventdashboard_upsert_pricing_ruledashboard_delete_pricing_ruledashboard_reset_pricing_defaultsdashboard_cleanup_datadashboard_reimport_historydashboard_reinstall_hooks
Destructive tools (require mutation flag + destructive flag):
dashboard_clear_all_data- requires
confirmation_tokenexactlyCLEAR_ALL_DATA
- requires
flowchart TD
CALL["tools/call"] --> VALIDATE["zod input validation"]
VALIDATE --> MODE{"Tool type"}
MODE -->|Read-only| EXEC["Execute API request"]
MODE -->|Mutation| MUTATE_FLAG{"MCP_DASHBOARD_ALLOW_MUTATIONS=true ?"}
MUTATE_FLAG -->|No| DENY1["Reject tool call"]
MUTATE_FLAG -->|Yes| DESTRUCTIVE{"Destructive tool?"}
DESTRUCTIVE -->|No| EXEC
DESTRUCTIVE -->|Yes| DEST_FLAG{"MCP_DASHBOARD_ALLOW_DESTRUCTIVE=true ?"}
DEST_FLAG -->|No| DENY2["Reject tool call"]
DEST_FLAG -->|Yes| TOKEN{"confirmation_token == CLEAR_ALL_DATA ?"}
TOKEN -->|No| DENY3["Reject tool call"]
TOKEN -->|Yes| EXEC
EXEC --> RESULT["Return tool result"]
Core controls:
- Local dashboard host enforcement (
localhost,127.0.0.1,::1,host.docker.internal,gateway.docker.internal,host.containers.internal) - Strict schema validation per tool
- Centralized mutation/destructive policy gates
- Retry/backoff and timeout for resilient API calls
- Structured stderr logging only (stdio-safe)
flowchart TD
Q1{"Who is calling?"}
Q1 -->|"MCP host\n(Claude Code, Desktop, IDE)"| STDIO["✅ Use stdio\nnpm run mcp:start"]
Q1 -->|"Remote client\nor web app"| HTTP["✅ Use HTTP\nnpm run mcp:start:http"]
Q1 -->|"Human operator\ndebugging / admin"| REPL["✅ Use REPL\nnpm run mcp:start:repl"]
STDIO --> S_NOTE["Launch as child process\nJSON-RPC over stdin/stdout\nZero network exposure"]
HTTP --> H_NOTE["Express on :8819\nStreamable HTTP + legacy SSE\nMulti-session, /health endpoint"]
REPL --> R_NOTE["Tab completion\nColored JSON output\nDomain filtering, shortcuts"]
style STDIO fill:#6366f1,stroke:#818cf8,color:#fff
style HTTP fill:#f59e0b,stroke:#fbbf24,color:#000
style REPL fill:#a855f7,stroke:#c084fc,color:#fff
- Node.js
>= 18.18.0 - Dashboard server running:
- dev:
npm run dev - prod:
npm run build && npm start
- dev:
Recommended from repository root:
npm run mcp:install
npm run mcp:build
npm run mcp:start # stdio (default)
npm run mcp:start:http # HTTP + SSE server
npm run mcp:start:repl # interactive REPLAlternative from mcp/ directly:
cd mcp
npm install
npm run build
npm start # stdio
npm run start:http # HTTP + SSE
npm run start:repl # REPLDevelopment mode (tsx, no build needed):
npm run mcp:dev # stdio
npm run mcp:dev:http # HTTP + SSE
npm run mcp:dev:repl # interactive REPLAvailable scripts:
npm run mcp:installnpm run mcp:buildnpm run mcp:start/npm run mcp:start:http/npm run mcp:start:replnpm run mcp:dev/npm run mcp:dev:http/npm run mcp:dev:replnpm run mcp:typechecknpm run mcp:docker:build(from repo root)npm run mcp:podman:build(from repo root)
The MCP server supports all transports inside containers. For stdio mode, run as a short-lived
interactive process (-i). For HTTP mode, expose the configured port.
flowchart TD
subgraph Host["Host Machine"]
MCP_HOST["MCP Host / Client"]
end
subgraph Container["Container Runtime"]
MCP_STDIO["stdio transport\ndocker run --rm -i"]
MCP_HTTP["HTTP transport\ndocker run -p 8819:8819"]
end
subgraph Dashboard["Dashboard (host or container)"]
API["Dashboard API :4820"]
end
MCP_HOST -->|"stdin/stdout"| MCP_STDIO
MCP_HOST -->|"HTTP POST /mcp"| MCP_HTTP
MCP_STDIO -->|"MCP_DASHBOARD_BASE_URL"| API
MCP_HTTP -->|"MCP_DASHBOARD_BASE_URL"| API
style MCP_STDIO fill:#0f766e,stroke:#14b8a6,color:#fff
style MCP_HTTP fill:#0f766e,stroke:#14b8a6,color:#fff
style API fill:#339933,stroke:#5cb85c,color:#fff
Build from repository root:
# Docker
npm run mcp:docker:build
# Podman
npm run mcp:podman:buildManual build commands:
# Docker (repo root)
docker build -f mcp/Dockerfile -t agent-dashboard-mcp:local .
# Podman (repo root)
podman build -f mcp/Dockerfile -t localhost/agent-dashboard-mcp:local .Container networking options:
flowchart LR
HOST["MCP Host"]
CTR["MCP Container<br/>stdio process"]
API["Dashboard API<br/>:4820"]
HOST -->|"docker/podman run -i"| CTR
CTR -->|"MCP_DASHBOARD_BASE_URL"| API
Recommended runtime patterns:
# Docker bridge network, map host alias explicitly
docker run --rm -i --init \
--add-host=host.docker.internal:host-gateway \
-e MCP_DASHBOARD_BASE_URL=http://host.docker.internal:4820 \
agent-dashboard-mcp:local
# Podman host network (Linux/rootless): keep loopback URL
podman run --rm -i --network=host \
-e MCP_DASHBOARD_BASE_URL=http://127.0.0.1:4820 \
localhost/agent-dashboard-mcp:local
# Podman bridge mode: use built-in host alias
podman run --rm -i \
-e MCP_DASHBOARD_BASE_URL=http://host.containers.internal:4820 \
localhost/agent-dashboard-mcp:localExample MCP host config (Windows path style):
{
"mcpServers": {
"agent-dashboard": {
"command": "node",
"args": [
"C:\\ABSOLUTE\\PATH\\TO\\Claude-Code-Agent-Monitor\\mcp\\build\\index.js"
],
"env": {
"MCP_DASHBOARD_BASE_URL": "http://127.0.0.1:4820",
"MCP_DASHBOARD_ALLOW_MUTATIONS": "false",
"MCP_DASHBOARD_ALLOW_DESTRUCTIVE": "false",
"MCP_LOG_LEVEL": "info"
}
}
}
}For macOS/Linux, use POSIX paths in args.
{
"mcpServers": {
"agent-dashboard": {
"command": "docker",
"args": [
"run",
"--rm",
"-i",
"--init",
"--add-host=host.docker.internal:host-gateway",
"-e",
"MCP_DASHBOARD_BASE_URL=http://host.docker.internal:4820",
"agent-dashboard-mcp:local"
],
"env": {
"MCP_DASHBOARD_ALLOW_MUTATIONS": "false",
"MCP_DASHBOARD_ALLOW_DESTRUCTIVE": "false",
"MCP_LOG_LEVEL": "info"
}
}
}
}{
"mcpServers": {
"agent-dashboard": {
"command": "podman",
"args": [
"run",
"--rm",
"-i",
"--network=host",
"localhost/agent-dashboard-mcp:local"
],
"env": {
"MCP_DASHBOARD_BASE_URL": "http://127.0.0.1:4820",
"MCP_DASHBOARD_ALLOW_MUTATIONS": "false",
"MCP_DASHBOARD_ALLOW_DESTRUCTIVE": "false",
"MCP_LOG_LEVEL": "info"
}
}
}
}| Variable | Default | Description |
|---|---|---|
MCP_SERVER_NAME |
agent-dashboard-mcp |
MCP server name reported to host |
MCP_SERVER_VERSION |
1.0.0 |
MCP server version |
MCP_DASHBOARD_BASE_URL |
http://127.0.0.1:4820 |
Dashboard API base URL (must be local-only hostname) |
MCP_DASHBOARD_TIMEOUT_MS |
10000 |
API timeout per request |
MCP_DASHBOARD_RETRY_COUNT |
2 |
Retries for idempotent requests |
MCP_DASHBOARD_RETRY_BACKOFF_MS |
250 |
Exponential retry backoff base |
MCP_DASHBOARD_ALLOW_MUTATIONS |
false |
Enables mutating tools |
MCP_DASHBOARD_ALLOW_DESTRUCTIVE |
false |
Enables destructive tools (requires mutations) |
MCP_LOG_LEVEL |
info |
debug, info, warn, error |
MCP_TRANSPORT |
stdio |
Transport mode: stdio, http, repl |
MCP_HTTP_PORT |
8819 |
HTTP server port (only for http transport) |
MCP_HTTP_HOST |
127.0.0.1 |
HTTP server bind address |
CLI flags --transport=stdio|http|repl, --repl, --http override the env variable.
Reference file: mcp/.env.example
mcp/
src/
clients/
dashboard-api-client.ts # HTTP client with retry/backoff
config/
app-config.ts # Env/CLI config parsing
core/
logger.ts # Structured stderr logger
tool-registry.ts # MCP + collector dual registrar
tool-result.ts # Tool response formatting
policy/
tool-guards.ts # Mutation/destructive gates
tools/
schemas.ts # Shared zod schemas
domains/
observability-tools.ts
session-tools.ts
agent-tools.ts
event-tools.ts
pricing-tools.ts
maintenance-tools.ts
index.ts # MCP tool registration orchestrator
transports/
http-server.ts # Express SSE + Streamable HTTP server
repl.ts # Interactive CLI with tab completion
tool-collector.ts # Tool handler collector for REPL
types/
tool-context.ts
ui/
banner.ts # ASCII art banner + server info display
colors.ts # Zero-dep ANSI color/style helpers
formatter.ts # Tables, boxes, badges, JSON highlighting
server.ts # McpServer builder
index.ts # Entry point (transport router)
build/
Dockerfile
package.json
tsconfig.json
Tool execution flow (all transports):
sequenceDiagram
participant Host as MCP Host / REPL / HTTP Client
participant Mcp as MCP Server
participant Api as Dashboard API
Host->>Mcp: tools/call(name, args)
Mcp->>Mcp: Validate args (zod)
Mcp->>Mcp: Evaluate policy gates
Mcp->>Api: HTTP request to /api/*
Api-->>Mcp: JSON response
Mcp-->>Host: tool result (text JSON payload)
HTTP transport session lifecycle:
sequenceDiagram
participant Client as HTTP MCP Client
participant Server as MCP HTTP Server :8819
participant Session as Session Transport
Client->>Server: POST /mcp (initialize)
Server->>Session: Create StreamableHTTPServerTransport
Session-->>Server: session-id header
Server-->>Client: initialization response + session-id
Client->>Server: POST /mcp (tools/list)
Server->>Session: Route by session-id
Session-->>Client: tool list
Client->>Server: POST /mcp (tools/call)
Session-->>Client: tool result
Client->>Server: DELETE /mcp
Server->>Session: Close transport
REPL interactive flow:
flowchart LR
START["Start REPL"] --> BANNER["Print banner +\nserver info"]
BANNER --> PROMPT["Show prompt\nmcp›"]
PROMPT --> INPUT{"User input"}
INPUT -->|"help / tools / domains"| META["Show metadata"]
INPUT -->|"health / stats / status"| SHORTCUT["Invoke built-in shortcut"]
INPUT -->|"tool_name {json}"| INVOKE["Parse args → invoke handler"]
INPUT -->|"tool_name k=v"| INVOKE
INPUT -->|"exit / quit"| SHUTDOWN["Graceful shutdown"]
META --> PROMPT
SHORTCUT --> FORMAT["Format + color result"]
INVOKE --> FORMAT
FORMAT --> PROMPT
style START fill:#a855f7,stroke:#c084fc,color:#fff
style FORMAT fill:#0f766e,stroke:#14b8a6,color:#fff
style SHUTDOWN fill:#dc2626,stroke:#f87171,color:#fff
Failure handling:
flowchart LR
REQ["API request"] --> RES{"Success?"}
RES -->|No, retryable| RETRY["Retry with exponential backoff"]
RETRY --> REQ
RES -->|No, final failure| ERR["Normalize error -> tool error payload"]
RES -->|Yes| OK["Return success payload"]
flowchart TD
subgraph Daily["Daily (Read-Only)"]
D1["Start dashboard"] --> D2["Start MCP server"]
D2 --> D3["Keep mutation flags off"]
end
subgraph Admin["Admin Workflow"]
A1["Set ALLOW_MUTATIONS=true"] --> A2["Run maintenance tools"]
A2 --> A3["Revert mutations to false"]
end
subgraph Danger["High-Risk Workflow"]
H1["Set ALLOW_MUTATIONS=true\n+ ALLOW_DESTRUCTIVE=true"]
H1 --> H2["Invoke with confirmation_token"]
H2 --> H3["Immediately disable\nboth flags"]
end
Daily -.->|"need admin?"| Admin
Admin -.->|"need destructive?"| Danger
style Daily fill:#339933,stroke:#5cb85c,color:#fff
style Admin fill:#f59e0b,stroke:#fbbf24,color:#000
style Danger fill:#dc2626,stroke:#f87171,color:#fff
Read-only daily usage:
- Start dashboard (
npm run devornpm start) - Start MCP (
npm run mcp:start,mcp:start:http, ormcp:start:repl) - Keep mutation flags disabled
Admin workflow:
- Set
MCP_DASHBOARD_ALLOW_MUTATIONS=true - Run required maintenance tools (via REPL:
dashboard_cleanup_data abandon_hours=24) - Revert mutation flag to
false
High-risk workflow:
- Set both mutation and destructive flags to
true - Use destructive tool with explicit confirmation token
- Disable destructive mode immediately after operation
List tools filtered by domain:
mcp› tools observability
mcp› tools maintenance
mcp› domains
Invoke tools with JSON arguments:
mcp› dashboard_list_sessions {"limit": 5, "status": "active"}
mcp› dashboard_get_session {"session_id": "abc-123"}
Invoke tools with key=value shorthand:
mcp› dashboard_list_agents status=working limit=10
mcp› dashboard_get_session_cost session_id=abc-123
Built-in shortcuts:
mcp› health # → dashboard_health_check
mcp› stats # → dashboard_get_stats
mcp› status # → dashboard_get_operational_snapshot
mcp› config # show current configuration
- Tools fail with connection error
- Verify dashboard is reachable at
MCP_DASHBOARD_BASE_URL - Verify
GET /api/healthworks
- Verify dashboard is reachable at
- Mutation tools denied
- Set
MCP_DASHBOARD_ALLOW_MUTATIONS=true
- Set
- Destructive tool denied
- Set
MCP_DASHBOARD_ALLOW_DESTRUCTIVE=true - Pass
confirmation_token: "CLEAR_ALL_DATA"
- Set
- Host cannot start MCP
- Confirm absolute path to
mcp/build/index.js - Rebuild:
npm run mcp:build
- Confirm absolute path to
- HTTP server port already in use
- Change port:
MCP_HTTP_PORT=9819 npm run mcp:start:http - Or set
MCP_HTTP_PORTin.env
- Change port:
- REPL shows no color output
- Ensure terminal supports ANSI colors
- Set
FORCE_COLOR=1if auto-detection fails
- Docker runtime cannot reach dashboard
- Use Docker host alias +
--add-host=host.docker.internal:host-gateway - Set
MCP_DASHBOARD_BASE_URL=http://host.docker.internal:4820
- Use Docker host alias +
- Podman runtime cannot reach dashboard
- Prefer
--network=hostwithMCP_DASHBOARD_BASE_URL=http://127.0.0.1:4820 - For bridge mode, use
MCP_DASHBOARD_BASE_URL=http://host.containers.internal:4820
- Prefer
- Container image build fails
- Build from repository root so
file:..dependency resolves - Use
docker build -f mcp/Dockerfile ... .orpodman build -f mcp/Dockerfile ... .
- Build from repository root so