Commit Graph
3 Commits
Author SHA1 Message Date
Hermes 4a5025bea8 [pending-judge] feat(DC-166): MCP control-plane completion — 11 new tools (28 total), closing the GAP-5 scope claim
Owner decision 2026-10-09 ("Do it"): rather than only softening the site
claim "manage your ENTIRE self-hosted infrastructure", EXPAND the MCP tool
set to match what the product actually manages. 17 tools -> 28, each a thin
handler over an EXISTING, verified route (every path/method/body checked
against the route source before wiring; no new route logic):

calendar:    dashcaddy_calendar_events (days horizon -> ISO start/end
             window per routes/calendar.js contract, clamped 1..60; default
             14), dashcaddy_calendar_add_source (caldav/ics; user/pass only
             sent when provided)
security:    dashcaddy_security_events (limit/source_type/severity/since
             passthrough — only provided filters reach the query string),
             dashcaddy_security_summary (stats + perimeter fan-out; opt-out
             via withPerimeter:false)
meta:        dashcaddy_license_status, dashcaddy_capabilities (the DC-165
             ground-truth manifest — agents can now self-describe the build)
dns writes:  dashcaddy_dns_add_record (POST /dns/record body {domain,ip,
             ttl?}), dashcaddy_dns_remove_record (DELETE with encoded query,
             type default 'A')
orchestrate: dashcaddy_deploy_recipe ({recipeId, overrides->config}),
             dashcaddy_run_workflow (encodeURIComponent'd id + /run),
             dashcaddy_tailscale_status

Security posture UNCHANGED and preserved by tests: DC-162's machine-
credential gate still guards tools/call over HTTP (session-cookie callers
cannot execute tools), and the caller's credential TYPE is forwarded
downstream (apikey -> x-api-key header) — asserted for the new WRITE tools
by the credential-passthrough test. Premium-gated endpoints (recipes,
workflows) answer their own 403 envelope through the existing apiCall
error shape; nothing bypasses entitlements.

Tests: NEW __tests__/mcp/mcp-core-dc166.test.js — 15 tests (catalog
integrity: 28 unique names + required-field declarations on every write
tool; per-handler captured-fetchImpl assertions on method/URL/body/query
incl. calendar window math, security fan-out order, id encoding; unknown-
tool rejection; x-api-key passthrough). Existing MCP suites unbroken:
88 total (73 prior + 15 new); eslint 0 errors on touched files.
2026-10-09 03:44:42 -07:00
Hermes c9015b59ad [pending-judge] feat(DC-162 rev2): "Connect your AI" — spec Streamable HTTP MCP + one-click keys
Judge r1 (grade D) blockers, each fixed and tested:

1. TRANSPORT: custom POST-only JSON-RPC → MCP 2025-03-10 Streamable HTTP
   (spec-canonical; replaced HTTP+SSE). POST answers application/json for
   requests; valid notifications -> 202 empty; malformed notifications ->
   no reply (204); batching removed in this revision -> arrays rejected
   -32600. GET (server->client stream) and DELETE (session termination)
   answer 405 + Allow: POST — the spec's explicit allowance for stateless
   request/response servers; documented in /info + modal + OpenAPI.
   Origin header validated when present (DNS-rebinding MUST); Accept
   negotiation (json required, else 406); MCP-Protocol-Version header
   checked when sent. Clients needing server-initiated streams use the
   stdio bridge (unchanged, shares mcp-core).

2. CREDENTIAL TYPE PRESERVATION: routes/mcp.js now forwards the SAME
   scheme the caller authenticated with (req.auth.type from
   middleware.js:549-586): apikey -> x-api-key, jwt -> Authorization
   Bearer (NOT dk_-coerced-x-api-key as r1 did). mcp-core createToolHandler
   accepts explicit headers. Tests assert BOTH shapes downstream
   (apikey carries x-api-key & no Authorization; jwt carries Bearer & no
   x-api-key; zero downstream calls for session denial).

3. JSON-RPC VALIDATION: validateJsonRpc — jsonrpc:'2.0', non-empty string
   method, params object-or-omitted, id string|number|null. Invalid
   Request -32600 (empty body, empty array, batch); tools/call without
   string params.name -> -32602; unknown method -> -32601; error envelopes
   carry id null when unpairable. Transport primitives rejected by the
   app-wide strict JSON parser (400; asserted).

4. REPRODUCIBILITY: status/dist/features.js + sw.js regenerated and
   committed IN THE PATCH (repo convention: DC-130/131 committed bundle
   rebuilds). Verifier greps the built bundle for aiconn- (23),
   mcp/connections (1), httpConfig (2) so a clean `git am` checkout serves
   the real frontend.

Judge r1 polish, all applied:
- verifier accepts 0_PATCH.diff / PATCH.diff naming (indexed artifact);
- connections list filtered server-side to "AI connection (...)" keys
  (new GET /mcp/connections, session-only; modal switched to it);
- URL-encoded tool path params (serviceId, containerId, action,
  templateId, category, zone) in mcp-core.

Config shape: POST /mcp/config (session-only; apikey 403) returns the
standard Streamable-HTTP card {url, transport: streamable-http, headers:
{x-api-key}, mcpProtocolVersion} + per-client note (ChatGPT note states
the public-https requirement honestly; no fabricated connector claims).

Tests: 57 green (34 route incl. auth matrix/type-preservation/transport
rules/JSON-RPC errors + 23 core). Composition-root e2e (8) boots the real
createApp with the mount. eslint 0 errors. Full suite: only the
pre-existing pdf-parse billing family red (unchanged since base 470dfaa).
2026-10-08 03:46:56 -07:00
Hermes 8f4883bfcd [grade=A] DashCaddy MCP Server — AI-native self-hosting control plane
CI / Security audit (push) Canceled after 0s
CI / Test & Lint (push) Canceled after 0s
DashCaddy is now controllable by ANY AI agent via Model Context Protocol.

17 MCP tools exposed:
- Service management: list, get, health check
- Container management: list, start/stop/restart/remove
- Deployment: deploy app, wizard recommendations, catalog search, discovery
- System: health, metrics, diagnostics
- Infrastructure: DNS listing, Caddyfile generation
- Backup & Recovery: create backup, status
- Fleet: list hosts

Protocol: JSON-RPC 2.0 over stdio
Connection: DASHCADDY_URL + DASHCADDY_API_KEY env vars

Any MCP-compatible agent (Claude Desktop, Hermes, GPT) can now:
'I want to stream movies' → wizard recommends Plex/Sonarr/Radarr
'Deploy Plex' → container + Caddyfile + DNS + health check
'Why is Plex down?' → diagnostics with structured findings
'Back up everything' → full snapshot

14 tests, 1752 total pass.
2026-08-12 16:30:17 -07:00