resk-mcp · Documentation
Dashboard and audit counters
What the dashboard shows, how to enable it safely, how sessions behave, and how its assets are packaged.
On this page
Enabling the dashboard
The dashboard is not exposed unless you turn it on. While DASHBOARD_AUTH_ENABLED is false, /dashboard and both JSON endpoints answer 404 — the code fails closed so that agent interaction data is never readable without authentication.
# .env
DASHBOARD_AUTH_ENABLED="true"
DASHBOARD_USERNAME="ops"
DASHBOARD_PASSWORD="$(python -c 'import secrets; print(secrets.token_urlsafe(32))')"
Startup validation is strict: enabling the dashboard with an empty password or the literal value admin raises ValueError and the server does not start.
Then open http://localhost:8001/login (the site root / redirects there). Submitting the form posts to /api/dashboard/auth/login and sets the session_id cookie; /login then forwards you to /dashboard. Requesting /dashboard without a valid session returns HTTP 401 rather than a redirect, so a logged-out tab shows the API error, not the form.
What the UI shows
- Interaction counters per registered tool, resource and prompt, as cumulative integers since the process started.
- Server identity — the
nameandtitlegiven toSecureMCPServer. - Registered capabilities — the keys tracked at registration time (tools appear both with and without the
tool/prefix, so duplicates are normal). - Uptime, formatted as
Nd Nh Nm Nsfrom process start. - Effective security settings — auth method (
JWT), token lifetime in minutes and the configured rate limit.
There is no request history, no per-request latency and no payload capture: the dashboard shows counters and configuration, not an event log. For real observability, ship the server logs to your log stack.
JSON endpoints
| Endpoint | Method | Returns |
|---|---|---|
/api/dashboard/auth/login | POST | {"success": true} plus the session cookie, or HTTP 401 with {"success": false} |
/api/dashboard/auth/logout | POST | {"success": true} and deletes the cookie |
/api/dashboard/interactions | GET | {"tools": {...}, "resources": {...}, "prompts": {...}} |
/api/dashboard/server-info | GET | Server name/title, capability lists, uptime, auth and rate-limit settings |
Login expects a JSON body:
curl -s -c cookies.txt http://localhost:8001/api/dashboard/auth/login \
-H "Content-Type: application/json" \
-d '{"username":"ops","password":"your-password"}'
curl -s -b cookies.txt http://localhost:8001/api/dashboard/interactions
A server-info response looks like this (values depend on your server):
{
"server_name": "my-secure-mcp",
"server_title": "My Secure MCP",
"tools": ["calculator/add", "tool/calculator/add"],
"resources": ["info/version"],
"prompts": [],
"uptime": "0d 0h 4m 12s",
"auth": {"method": "JWT", "expiration_minutes": 30},
"rate_limit": "100/minute"
}
Note
These endpoints authenticate with the dashboard session cookie, not the JWT used for /mcp_secure. A bearer token from create_jwt_token() will not open them.
Sessions and cookies
- Sessions are random 16-byte hex identifiers stored in a module-level dictionary. Each has an absolute expiry set by
dashboard.auth.session_expire_minutes(default 60); there is no sliding renewal. - Expiry is enforced lazily when a session is looked up; expired entries are removed then. There is no background reaper, and a restart drops every session.
- The cookie is
HttpOnlyandSameSite=Lax. It is markedSecureonly whenSSL_CERTFILEis set — if TLS terminates at a proxy, the cookie travels without the Secure flag even though the browser connection is HTTPS. - Login compares credentials with
hmac.compare_digest, so timing is constant, but there is no lockout or rate limit on the login endpoint. Restrict reachability at the proxy.
Counter semantics
Counters are activity indicators, not exact request counts. A successful tool call is counted twice: once when the dispatcher tracks the interaction and once when the tool finishes executing. Resources and prompts are counted on dispatch only (their execution over POST is not implemented in 0.1.0). All counters reset when the process restarts.
Use the counters to spot a tool being hammered or one that never gets called, and alert on deltas over a window rather than on absolute values.
Static assets
The dashboard markup and images ship inside the package (resk_mcp/static/), so the UI is served from an installed wheel as well as from a source checkout. The routes mount /static from that directory and return “Dashboard HTML not found.” only if the assets were removed or a third-party build stripped package data.
If you hit that message on an older 0.1.0 wheel, upgrade: the original release resolved static/ as a sibling of the package, which does not exist under site-packages. As a stop-gap, copy the repository's resk_mcp/static directory next to the installed package or query the JSON endpoints, which never depended on the assets.
Production guidance
- Do not expose the dashboard on the public internet. Put it behind your VPN, an identity-aware proxy, or at minimum an IP allowlist, and use a long random password.
- Terminate TLS in front of the app and add the Secure cookie flag yourself at the proxy if you rely on cookie secrecy (for example
proxy_cookie_flags session_id secure httponly samesite=laxin nginx). - Keep a single worker if the counters matter to you; each worker keeps its own dictionary.
- Log out after use on shared machines — sessions stay valid until expiry.