Skip to content

feat(dashboard): complete admin panel — MCP catalog, enable/disable toggles, hook creation, system stats#36736

Merged
austinpickett merged 11 commits into
mainfrom
hermes/hermes-a963c25d
Jun 2, 2026
Merged

feat(dashboard): complete admin panel — MCP catalog, enable/disable toggles, hook creation, system stats#36736
austinpickett merged 11 commits into
mainfrom
hermes/hermes-a963c25d

Conversation

@teknium1

@teknium1 teknium1 commented Jun 1, 2026

Copy link
Copy Markdown
Contributor

Summary

Completes the dashboard admin panel so MCP, webhooks, shell hooks, and system observability are fully manageable from the browser — no CLI, no dummy data, no read-only gaps.

This is the comprehensive follow-up to #36704 after review feedback: every admin surface that was thin is now feature-complete, and the System page gains host observability.

What changed

MCP

  • New Catalog section — browse the Nous-approved optional-mcps/ catalog and install entries one-click (prompts for required env vars inline). Same catalog hermes mcp catalog / install use.
  • Per-server enable/disable toggle (writes the enabled flag; takes effect next gateway restart) — disabled servers stay in config.

Webhooks

  • Per-subscription enable/disable toggle. Disabled routes stay in the file but the gateway now rejects their events with 403 (added the gate in gateway/platforms/webhook.py); hot-reloaded, no restart.

Shell hooks

  • Create a hook (event dropdown, command, matcher, timeout) with an opt-in consent grant, plus a security warning that hooks run arbitrary commands.
  • Delete a hook (removes config entry + revokes consent).
  • List now reports accurate allowlist + executable status and the valid event set.

System

  • New Host stats section: OS/kernel, arch, hostname, Python + Hermes version, CPU cores + utilization, memory, disk (of the Hermes home), uptime, load average. From psutil when present, stdlib fallback otherwise.
  • "Backup" button relabeled Create backup (sits next to Restore).

Pairing — confirmed feature-complete vs hermes pairing (approve/revoke/clear); no change needed.

Files

  • hermes_cli/web_server.py: catalog list/install, mcp + webhook enable toggles, hook create/delete, /api/system/stats
  • gateway/platforms/webhook.py: reject disabled routes (403)
  • web/src/lib/api.ts + McpPage.tsx / WebhooksPage.tsx / SystemPage.tsx: catalog UI, toggles, hook-create modal, host stats
  • tests/hermes_cli/test_dashboard_admin_endpoints.py: +10 tests (26 total)
  • website/docs/.../web-dashboard.md: updated sections + API table + live screenshots of the rebuilt pages (real data)

Validation

Result
Admin endpoint tests 26/26 pass
Webhook gateway tests (incl. new disabled gate) 99/99 pass
Frontend tsc -b + npm run build clean
New pages eslint clean
Live capture dashboard spun up with seeded real data; every page screenshotted and self-reviewed

Update — full CLI coverage pass

Ran a complete hermes --help audit (53 commands) and closed the last in-scope gaps:

  • Curator — status + pause/resume + run-now on the System page (mirrors hermes curator)
  • Portal — Nous Portal auth + Tool Gateway routing status (read-only, mirrors hermes portal)
  • Diagnostics — prompt-size, support dump, and config-migrate added to Operations

Remaining CLI-only commands are host-bound by design (secrets/bw, proxy, lsp, acp, computer-use, postinstall, completion, uninstall, claw, debug-upload, send). 42 commands have dashboard parity; 11 are intentionally CLI-only. 31 admin tests green.

Infographic

hermes-dashboard-full-admin-control

@alt-glitch alt-glitch added type/feature New feature or request comp/cli CLI entry point, hermes_cli/, setup wizard comp/gateway Gateway runner, session dispatch, delivery platform/webhook Webhook / API server tool/mcp MCP client and OAuth P3 Low — cosmetic, nice to have labels Jun 1, 2026

@mxnstrexgl mxnstrexgl left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 Automated PR Review

Security Scan

  • ✓ No hardcoded secrets, injection sinks, unsafe deserialization, or dependency red flags found by this automated scan.

Code Quality

  • ✓ No blocking code-quality issues found by this automated scan.

Summary

Status: APPROVE — security findings: 0, quality suggestions: 0.

Automated review; raw diff content intentionally omitted.

@github-actions

github-actions Bot commented Jun 1, 2026

Copy link
Copy Markdown
Contributor

🔎 Lint report: hermes/hermes-a963c25d vs origin/main

ruff

Total: 0 on HEAD, 0 on base (➖ 0)

🆕 New issues: none

✅ Fixed issues: none

Unchanged: 0 pre-existing issues carried over.

ty (type checker)

Total: 9604 on HEAD, 9603 on base (🆕 +1)

🆕 New issues (1):

Rule Count
invalid-argument-type 1
First entries
hermes_cli/web_server.py:4066: [invalid-argument-type] invalid-argument-type: Argument to bound method `SessionDB.prune_sessions` is incorrect: Expected `str`, found `(str & ~AlwaysFalsy) | None`

✅ Fixed issues (1):

Rule Count
invalid-assignment 1
First entries
hermes_cli/web_server.py:4706: [invalid-assignment] invalid-assignment: Object of type `list[object]` is not assignable to `list[str]`

Unchanged: 4976 pre-existing issues carried over.

Diagnostics are surfaced as warnings — this check never fails the build.

teknium1 added 11 commits June 1, 2026 18:59
…reate/delete, system stats

Backend for the comprehensive admin pass:
- MCP: GET /api/mcp/catalog (browse Nous-approved optional-mcps), POST
  /api/mcp/catalog/install, PUT /api/mcp/servers/{name}/enabled
- Webhooks: PUT /api/webhooks/{name}/enabled; gateway rejects disabled routes
  with 403 (hot-reloaded, no restart)
- Hooks: POST/DELETE /api/ops/hooks — create (with consent approval) + remove;
  list now reports accurate allowlist status + valid events
- System: GET /api/system/stats — OS/arch/python/cpu + psutil memory/disk/
  uptime/process, stdlib fallback

All gated by dashboard auth; secrets never returned.
… system stats

- McpPage: catalog section (browse Nous-approved MCPs, one-click install with
  env prompts) + per-server enable/disable toggle with gateway-restart note
- WebhooksPage: per-subscription enable/disable toggle (muted + badge when off)
- SystemPage: new Host stats section (OS/arch/python/cpu/mem/disk/uptime/load),
  shell-hook create modal + delete, 'Create backup' label
- api.ts: client methods + types for catalog, toggles, hook CRUD, system stats
…hook toggle

Adds tests for the comprehensive pass: MCP enable/disable + catalog list +
catalog-install-unknown, hook create/delete with consent, system stats shape,
and webhook enable/disable. 26 tests total, all green.
…shots

Updates the MCP/Webhooks/Pairing/System sections for catalog browse+install,
enable/disable toggles, hook creation, and host system stats; adds the new
endpoints to the API table; replaces the screenshots with live captures of
the rebuilt pages (real data, no dummies) including the hook-create modal.
… ops

Closes the last in-scope CLI gaps from the coverage audit:
- Curator: GET /api/curator (status), PUT /api/curator/paused, POST
  /api/curator/run (background)
- Portal: GET /api/portal (Nous auth + Tool Gateway routing, read-only)
- Diagnostics: POST /api/ops/prompt-size, /api/ops/dump, /api/ops/config-migrate
  (backgrounded, tailed via action status)

Host-bound commands (secrets/proxy/lsp/acp/computer-use/desktop/completion/
postinstall/uninstall/claw) remain CLI-only by design.
- SystemPage: Nous Portal status section (auth + Tool Gateway routing),
  Skill curator card (status + pause/resume + run now), and three new
  Operations buttons (prompt size, support dump, migrate config)
- api.ts: client methods + CuratorStatus/PortalStatus types
- tests: curator pause/resume, portal shape, system-stats shape, + auth-gate
  coverage for the new GET endpoints (31 tests total)
…System screenshots

Updates the System section for the Nous Portal status, Skill curator
controls, and the new prompt-size/dump/migrate operations; adds them to the
API table; refreshes the System screenshots (now showing Portal + Curator)
and adds a dedicated curator/gateway/memory capture.
…ints

Completes the existing tabs' backend depth (audit vs CLI):
- Sessions: GET /api/sessions/stats (store stats), GET /api/sessions/{id}/export,
  POST /api/sessions/prune. /stats is registered before /{session_id} so the
  literal path isn't captured by the parameterized route.
- Skills: GET /api/skills/hub/search — parallel multi-source hub search (threaded),
  returns installable identifiers
- (rename via PATCH and cron-edit via PUT already existed; now surfaced in UI)
…rowse, cron edit

Audited every existing tab against its CLI command and filled the gaps:
- Sessions: store stats bar, per-row rename + export (JSON download), and a
  prune-old-sessions control (mirrors hermes sessions rename/export/prune/stats)
- Skills: new 'Browse hub' view — search the skill hub across all sources,
  install by identifier with a live install log, and 'Update all' (mirrors
  hermes skills search/install/update)
- Cron: per-job Edit modal (pre-filled) calling updateCronJob (hermes cron edit)
- api.ts: renameSession/getSessionStats/exportSessionUrl/pruneSessions,
  updateCronJob, searchSkillsHub + types

Models tab was already comprehensive (provider+model picker, dynamic per-provider
lists, main + all 11 aux-task assignments, reset) — verified, no change needed.
… search

Adds the route-shadowing guard for /api/sessions/stats (must not be captured
by /api/sessions/{session_id}), rename/export/prune, and the empty-query
short-circuit for hub search. 36 tests total, all green.
Sessions: stats bar, rename, export, prune (+ screenshot). Skills: new Browse
hub view for search/install/update (+ screenshot). Cron: edit action. API
table updated with the new endpoints.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR completes the web dashboard admin panel by adding browser-based management for MCP catalog install + enable/disable, webhook enable/disable gating, shell hook create/delete, and expanded System observability (host stats, curator controls, portal status, and additional diagnostics), along with new session-management UX improvements.

Changes:

  • Add MCP catalog browsing/installation plus per-server enable/disable toggles; add per-webhook enable/disable toggles enforced by the gateway.
  • Add shell hook create/delete flows (with consent) and expand the System page with host stats, curator controls, portal status, and new backgrounded diagnostics.
  • Enhance admin UX across the dashboard (sessions stats/rename/export/prune, cron job editing modal, skills hub browsing/search/install/update) and expand backend test coverage.

Reviewed changes

Copilot reviewed 11 out of 20 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
website/docs/user-guide/features/web-dashboard.md Updates dashboard docs and API table to reflect newly completed admin surfaces and screenshots.
web/src/pages/WebhooksPage.tsx Adds enable/disable UI for webhook subscriptions and visually marks disabled routes.
web/src/pages/SystemPage.tsx Adds host stats, portal + curator sections, shell hook create/delete modal, and new diagnostics actions.
web/src/pages/SkillsPage.tsx Adds a “Browse hub” view for hub search + install/update with streamed background logs.
web/src/pages/SessionsPage.tsx Adds session stats bar, rename/export actions, and prune-old-sessions dialog.
web/src/pages/McpPage.tsx Adds MCP enable/disable, catalog listing + install flow (with required env prompt), and diagnostics display.
web/src/pages/CronPage.tsx Adds cron job edit modal and wires it to a new update endpoint.
web/src/lib/api.ts Adds typed client methods and types for all new admin endpoints (MCP catalog/toggles, webhooks toggle, hooks create/delete, system stats, curator/portal, sessions mgmt, hub search, cron update).
tests/hermes_cli/test_dashboard_admin_endpoints.py Expands backend contract tests for new admin endpoints and route-shape guarantees.
hermes_cli/web_server.py Implements new admin endpoints (system stats, curator, portal, diagnostics, sessions stats/export/prune, MCP catalog/install + enabled toggles, webhook enabled toggle, hooks create/delete, hub search).
gateway/platforms/webhook.py Enforces disabled webhook routes by rejecting incoming events with 403.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread hermes_cli/web_server.py
Comment on lines +800 to +806
try:
info["cpu_percent"] = psutil.cpu_percent(interval=0.1)
la = getattr(psutil, "getloadavg", None)
if la:
info["load_avg"] = list(la())
except Exception:
pass
Comment thread hermes_cli/web_server.py
Comment on lines +3922 to +3928
by_source: Dict[str, int] = {}
try:
for s in db.list_sessions_rich(limit=10000, include_archived=True):
src = str(s.get("source") or "cli")
by_source[src] = by_source.get(src, 0) + 1
except Exception:
pass
Comment on lines +333 to +346
const createHook = async () => {
if (!hookCommand.trim()) {
showToast("Command is required", "error");
return;
}
setCreatingHook(true);
try {
await api.createHook({
event: hookEvent,
command: hookCommand.trim(),
matcher: hookMatcher.trim() || undefined,
timeout: hookTimeout.trim() ? Number(hookTimeout) : undefined,
approve: hookApprove,
});
@austinpickett austinpickett merged commit bd8e2ec into main Jun 2, 2026
25 checks passed
@austinpickett austinpickett deleted the hermes/hermes-a963c25d branch June 2, 2026 04:16
@austinpickett austinpickett restored the hermes/hermes-a963c25d branch June 2, 2026 04:18
shuv1337 added a commit to shuv1337/hermes-agent that referenced this pull request Jun 3, 2026
changman pushed a commit to changman/hermes-agent that referenced this pull request Jun 10, 2026
…oggles, hook creation, system stats (NousResearch#36736)

* feat(dashboard): MCP catalog + enable/disable, webhook toggle, hook create/delete, system stats

Backend for the comprehensive admin pass:
- MCP: GET /api/mcp/catalog (browse Nous-approved optional-mcps), POST
  /api/mcp/catalog/install, PUT /api/mcp/servers/{name}/enabled
- Webhooks: PUT /api/webhooks/{name}/enabled; gateway rejects disabled routes
  with 403 (hot-reloaded, no restart)
- Hooks: POST/DELETE /api/ops/hooks — create (with consent approval) + remove;
  list now reports accurate allowlist status + valid events
- System: GET /api/system/stats — OS/arch/python/cpu + psutil memory/disk/
  uptime/process, stdlib fallback

All gated by dashboard auth; secrets never returned.

* feat(dashboard): MCP catalog UI, enable/disable toggles, hook create, system stats

- McpPage: catalog section (browse Nous-approved MCPs, one-click install with
  env prompts) + per-server enable/disable toggle with gateway-restart note
- WebhooksPage: per-subscription enable/disable toggle (muted + badge when off)
- SystemPage: new Host stats section (OS/arch/python/cpu/mem/disk/uptime/load),
  shell-hook create modal + delete, 'Create backup' label
- api.ts: client methods + types for catalog, toggles, hook CRUD, system stats

* test(dashboard): cover catalog, toggles, hook CRUD, system stats, webhook toggle

Adds tests for the comprehensive pass: MCP enable/disable + catalog list +
catalog-install-unknown, hook create/delete with consent, system stats shape,
and webhook enable/disable. 26 tests total, all green.

* docs(dashboard): document the comprehensive admin pass + fresh screenshots

Updates the MCP/Webhooks/Pairing/System sections for catalog browse+install,
enable/disable toggles, hook creation, and host system stats; adds the new
endpoints to the API table; replaces the screenshots with live captures of
the rebuilt pages (real data, no dummies) including the hook-create modal.

* feat(dashboard): curator, portal status, and prompt-size/dump/migrate ops

Closes the last in-scope CLI gaps from the coverage audit:
- Curator: GET /api/curator (status), PUT /api/curator/paused, POST
  /api/curator/run (background)
- Portal: GET /api/portal (Nous auth + Tool Gateway routing, read-only)
- Diagnostics: POST /api/ops/prompt-size, /api/ops/dump, /api/ops/config-migrate
  (backgrounded, tailed via action status)

Host-bound commands (secrets/proxy/lsp/acp/computer-use/desktop/completion/
postinstall/uninstall/claw) remain CLI-only by design.

* feat(dashboard): curator + portal + diagnostics UI, tests

- SystemPage: Nous Portal status section (auth + Tool Gateway routing),
  Skill curator card (status + pause/resume + run now), and three new
  Operations buttons (prompt size, support dump, migrate config)
- api.ts: client methods + CuratorStatus/PortalStatus types
- tests: curator pause/resume, portal shape, system-stats shape, + auth-gate
  coverage for the new GET endpoints (31 tests total)

* docs(dashboard): document curator, portal, and diagnostics + refresh System screenshots

Updates the System section for the Nous Portal status, Skill curator
controls, and the new prompt-size/dump/migrate operations; adds them to the
API table; refreshes the System screenshots (now showing Portal + Curator)
and adds a dedicated curator/gateway/memory capture.

* feat(dashboard): session stats/export/prune + skills hub search endpoints

Completes the existing tabs' backend depth (audit vs CLI):
- Sessions: GET /api/sessions/stats (store stats), GET /api/sessions/{id}/export,
  POST /api/sessions/prune. /stats is registered before /{session_id} so the
  literal path isn't captured by the parameterized route.
- Skills: GET /api/skills/hub/search — parallel multi-source hub search (threaded),
  returns installable identifiers
- (rename via PATCH and cron-edit via PUT already existed; now surfaced in UI)

* feat(dashboard): complete existing tabs — sessions mgmt, skills hub browse, cron edit

Audited every existing tab against its CLI command and filled the gaps:
- Sessions: store stats bar, per-row rename + export (JSON download), and a
  prune-old-sessions control (mirrors hermes sessions rename/export/prune/stats)
- Skills: new 'Browse hub' view — search the skill hub across all sources,
  install by identifier with a live install log, and 'Update all' (mirrors
  hermes skills search/install/update)
- Cron: per-job Edit modal (pre-filled) calling updateCronJob (hermes cron edit)
- api.ts: renameSession/getSessionStats/exportSessionUrl/pruneSessions,
  updateCronJob, searchSkillsHub + types

Models tab was already comprehensive (provider+model picker, dynamic per-provider
lists, main + all 11 aux-task assignments, reset) — verified, no change needed.

* test(dashboard): cover session stats/rename/export/prune + skills hub search

Adds the route-shadowing guard for /api/sessions/stats (must not be captured
by /api/sessions/{session_id}), rename/export/prune, and the empty-query
short-circuit for hub search. 36 tests total, all green.

* docs(dashboard): document enhanced Sessions, Skills hub, and Cron edit

Sessions: stats bar, rename, export, prune (+ screenshot). Skills: new Browse
hub view for search/install/update (+ screenshot). Cron: edit action. API
table updated with the new endpoints.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/cli CLI entry point, hermes_cli/, setup wizard comp/gateway Gateway runner, session dispatch, delivery P3 Low — cosmetic, nice to have platform/webhook Webhook / API server tool/mcp MCP client and OAuth type/feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants