New agent RPCs for v2 multi-node orchestration:
- SetupEdgeRoute: provisions TLS cert from Metacrypt, resolves backend
hostname to Tailnet IP, validates it's in 100.64.0.0/10, registers
L7 route in mc-proxy. Rejects backend_tls=false.
- RemoveEdgeRoute: removes mc-proxy route, cleans up TLS cert, removes
registry entry.
- ListEdgeRoutes: returns all edge routes with cert serial/expiry.
- HealthCheck: returns agent health and container count.
New database table (migration 4): edge_routes stores hostname, backend
info, and cert paths for persistence across agent restarts.
ProxyRouter gains CertPath/KeyPath helpers for consistent cert path
construction.
Security:
- Backend hostname must resolve to a Tailnet IP (100.64.0.0/10)
- backend_tls=false is rejected (no cleartext to backends)
- Cert provisioning failure fails the setup (no route to missing cert)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Allow start/stop/restart to target a single component via
<service>/<component> syntax, matching deploy/logs/purge. When a
component is specified, start/stop skip toggling the service-level
active flag. Agent-side filtering returns NotFound for unknown
components.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The --mode flag was defined but never wired through to the RPC.
Add tls_cert and tls_key fields to AddProxyRouteRequest so L7
routes can be created via mcp route add.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
New top-level command with list, add, remove subcommands. Supports
-n/--node to target a specific node. Adds AddProxyRoute and
RemoveProxyRoute RPCs to the agent. Moves route listing from
mcp node routes to mcp route list.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
mcp dns queries MCNS via an agent to list all zones and DNS records.
mcp node routes queries mc-proxy on each node for listener/route status,
matching the mcproxyctl status output format.
New agent RPCs: ListDNSRecords, ListProxyRoutes.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Thread the linker-injected version string into the Agent struct and
return it in the NodeStatus RPC. The CLI now dials each node and
displays the agent version alongside name and address.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
New server-streaming Logs RPC streams container output to the CLI.
Supports --tail/-n, --follow/-f, --timestamps/-t, --since.
Detects journald log driver and falls back to journalctl (podman logs
can't read journald outside the originating user session). New containers
default to k8s-file via mcp user's containers.conf.
Also adds stream auth interceptor for the agent gRPC server (required
for streaming RPCs).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Implements `mcp undeploy <service>` which tears down all infrastructure
for a service: removes mc-proxy routes, DNS records, TLS certificates,
stops and removes containers, releases allocated ports, and marks the
service inactive.
This fills the gap between `stop` (temporary pause) and `purge` (registry
cleanup). Undeploy is the complete teardown that returns the node to the
state before the service was deployed.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
allocateRoutePorts() was using the route's port field (the mc-proxy
listener port, e.g. 443) as the container internal port in the podman
port mapping. For L7 routes, apps don't listen on the mc-proxy port —
they read $PORT (set to the assigned host port) and listen on that.
The mapping host:53204 → container:443 fails because nothing listens
on 443 inside the container. Fix: use hostPort as both the host and
container port, so $PORT = host port = container port.
Broke mcdoc in production (manually fixed, now permanently fixed).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
All import paths updated to git.wntrmute.dev/mc/. Bumps mcdsl to v1.2.0,
mc-proxy to v1.1.0.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Service definitions can now declare routes per component instead of
manual port mappings:
[[components.routes]]
name = "rest"
port = 8443
mode = "l4"
The agent allocates free host ports at deploy time and injects
$PORT/$PORT_<NAME> env vars into containers. Backward compatible:
components with old-style ports= work unchanged.
Changes:
- Proto: RouteSpec message, routes + env fields on ComponentSpec
- Servicedef: RouteDef parsing and validation from TOML
- Registry: component_routes table with host_port tracking
- Runtime: Env field on ContainerSpec, -e flag in BuildRunArgs
- Agent: PortAllocator (random 10000-60000, availability check),
deploy wiring for route→port mapping and env injection
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add PurgeComponent RPC to the agent service that removes stale registry
entries for components that are both gone (observed state is removed,
unknown, or exited) and unwanted (not in any current service definition).
Refuses to purge components with running or stopped containers. When all
components of a service are purged, the service row is deleted too.
Supports --dry-run to preview without modifying the database.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>