The agent connects to mc-proxy via Unix socket and automatically
registers/removes routes during deploy and stop. This eliminates
manual mcproxyctl usage or TOML editing.
- New ProxyRouter abstraction wraps mc-proxy client library
- Deploy: after container starts, registers routes with mc-proxy
using host ports from the registry
- Stop: removes routes from mc-proxy before stopping container
- Config: [mcproxy] section with socket path and cert_dir
- Nil-safe: if mc-proxy socket not configured, route registration
is silently skipped (backward compatible)
- L7 routes use certs from convention path (<cert_dir>/<service>.pem)
- L4 routes use TLS passthrough (backend_tls=true)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Extends MCP to own the full build-push-deploy lifecycle. When deploying,
the CLI checks whether each component's image tag exists in the registry
and builds/pushes automatically if missing and build config is present.
- Add Build, Push, ImageExists to runtime.Runtime interface (podman impl)
- Add mcp build <service>[/<image>] command
- Add [build] section to CLI config (workspace path)
- Add path and [build.images] to service definitions
- Wire auto-build into mcp deploy before agent RPC
- Update ARCHITECTURE.md with runtime interface and deploy auto-build docs
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Phase A complete: route declarations, port allocation, $PORT env vars.
Phase B in progress: agent mc-proxy route registration.
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>
Drop uses_mcdsl, full image URLs, ports, network, user, restart.
Add route declarations and service-level version. Image names and
most config are now derived from conventions.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Service definitions now include [build] config (path, uses_mcdsl,
images) so MCP owns the full build-push-deploy lifecycle, replacing
mcdeploy.toml. Documents mcp build, mcp sync auto-build, image
versioning policy (explicit tags, never :latest), and workspace
convention.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Exposes two packages:
- default (mcp CLI) for operator workstations
- mcp-agent for managed nodes
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>
Purge removes stale registry entries — components that are no longer
in service definitions and have no running container. Designed as an
explicit, safe operation separate from sync: sync is additive (push
desired state), purge is subtractive (remove forgotten entries).
Includes safety rules (refuses to purge running containers), dry-run
mode, agent RPC definition, and rationale for why sync should not be
made destructive.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Documents Phase 6 (deployment), bugs fixed during rollout,
remaining work organized by priority (operational, quality,
design, infrastructure), and current platform state.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Token files with trailing newlines caused gRPC "non-printable ASCII
characters" errors in the authorization header.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Extract ContainerNameFor and SplitContainerName into names.go.
ContainerNameFor handles single-component services where service
name equals component name (e.g., mc-proxy → "mc-proxy" not
"mc-proxy-mc-proxy"). SplitContainerName checks known services
from the registry before falling back to naive split on "-", fixing
mc-proxy being misidentified as service "mc" component "proxy".
Also fixes podman ps JSON parsing (Command field is []string not
string) found during deployment.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Critical fixes:
- Wire monitor subsystem to agent startup (was dead code)
- Implement NodeStatus RPC (disk, memory, CPU, runtime version, uptime)
- Deploy respects active=false (sets desired_state=stopped, not always running)
Medium fixes:
- Add Started field to runtime.ContainerInfo, populate from podman inspect
- Populate ComponentInfo.started in status handlers for uptime display
- Add Monitor field to Agent struct for graceful shutdown
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Move each command function from main.go into its own file
(deploy.go, lifecycle.go, status.go, etc.) to enable parallel
development by multiple workers without file conflicts.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Agent (P2.1): Agent struct with registry DB, runtime, and logger.
gRPC server with TLS 1.3 and MCIAS auth interceptor. Graceful
shutdown on SIGINT/SIGTERM. All RPCs return Unimplemented until
handlers are built in P2.2-P2.9.
CLI (P3.1): Full command tree with all 15 subcommands as stubs
(login, deploy, stop, start, restart, list, ps, status, sync,
adopt, service show/edit/export, push, pull, node list/add/remove).
gRPC dial helper with TLS, CA cert, and bearer token attachment.
Both gates for parallel Phase 2+3 work are now open.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Go module, Makefile with standard targets, golangci-lint v2 config,
CLAUDE.md, and empty CLI/agent binaries. Build, vet, and lint all pass.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
30 discrete tasks across 5 phases, with dependency graph and
parallelism analysis. Phase 1 (5 core libraries) is fully parallel.
Phases 2+3+4 (agent handlers, CLI commands, deployment artifacts)
support up to 8+ concurrent engineers/agents. Critical path is
proto → registry + runtime → agent deploy → integration tests.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Incorporates all 14 items from DESIGN_AUDIT.md: node registry in CLI
config, container naming convention (<service>-<component>), active
state semantics, adopt by service prefix, EventInfo service field,
version from image tag, snapshot/backup timer, exec-style alert
commands, overlay-only bind address, RPC audit logging, /srv/ ownership,
rootless podman UID mapping docs.
Three minor fixes from final review: stale adopt syntax in bootstrap
section, explicit container naming in deploy flow, clarify that list/ps
query all registered nodes.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Engineering and security review of the rewritten ARCHITECTURE.md.
14 issues identified and resolved: node registry in CLI config,
active/desired_state semantics, container naming convention
(<service>-<component>), exec-style alert commands to prevent
injection, agent binds to overlay IP only (not behind MC-Proxy),
RPC audit logging, /srv/ owned by mcp user, and others.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Major design changes from the review:
- Merge agent and watcher into a single smart per-node daemon
- CLI is a thin client with no database; service definition files
are the operator's source of truth for desired state
- Registry database lives on the agent, not the CLI
- Rename containers to components; components are independently
deployable within a service (mcp deploy metacrypt/web)
- active: true/false in service definitions; desired_state values
are running/stopped/ignore
- Server-side TLS + bearer token (not mTLS)
- Dedicated mcp user with rootless podman
- CLI commands: list (registry), ps (live), status (drift+events),
sync (push desired state)
- Agent reports node resources (disk, memory, CPU) for future scheduling
- Agent is gRPC-only (deliberate exception to REST+gRPC parity rule)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Documents 12 issues found during critical review of ARCHITECTURE.md
and their resolutions: merged agent/watcher into single smart daemon,
components model for independent deploy within services, database
lives on agent not CLI, TLS+bearer (not mTLS), desired_state=ignore
for unmanaged containers, and other clarifications.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Design spec for the Metacircular Control Plane covering master/agent
architecture, service registry with desired/observed state tracking,
container lifecycle management, service definition files, single-file
transfer scoped to /srv/<service>/, and continuous monitoring via
mcp watch with event logging and alerting.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>