From b17472122b971af2603613754260b591ba3946c0 Mon Sep 17 00:00:00 2001 From: Kyle Isom Date: Fri, 27 Mar 2026 01:25:16 -0700 Subject: [PATCH] Mark Phase A complete, document $PORT convention, update next steps PLATFORM_EVOLUTION.md: mark gaps #2 and #9 as done, Phase A complete, Phase B in progress. Update sequencing and next steps. engineering-standards.md: add Port Assignment and $PORT Convention section documenting how MCP-deployed services receive assigned ports via environment variables. Co-Authored-By: Claude Opus 4.6 (1M context) --- PLATFORM_EVOLUTION.md | 92 +++++++++++++++++----------------------- engineering-standards.md | 22 ++++++++++ 2 files changed, 62 insertions(+), 52 deletions(-) diff --git a/PLATFORM_EVOLUTION.md b/PLATFORM_EVOLUTION.md index f378464..ff8ed94 100644 --- a/PLATFORM_EVOLUTION.md +++ b/PLATFORM_EVOLUTION.md @@ -5,7 +5,7 @@ from its current manually-wired state to fully declarative deployment. It is a living design document — not a spec, not a commitment, but a record of where we are, where we want to be, and what's between. -Last updated: 2026-03-27 +Last updated: 2026-03-27 (Phase A complete) --- @@ -188,21 +188,19 @@ mcdsl is already properly versioned and released: - Docker builds use standard `go mod download` - `uses_mcdsl` eliminated from service definitions and docs -#### 2. MCP Agent: Port Assignment +#### 2. MCP Agent: Port Assignment — DONE -**Gap**: agent doesn't manage host ports. Service definitions specify -them manually. - -**Work**: -- Agent picks free host ports at deploy time (random + availability - check). -- Agent records assignments in its registry. -- Agent passes `$PORT` / `$PORT_` to containers. -- Agent releases ports on container stop/removal. -- New service definition format drops `ports` field, adds - `[[components.routes]]`. - -**Depends on**: nothing (can be developed standalone). +Agent allocates host ports automatically at deploy time: +- Service definitions declare `[[components.routes]]` with name, port, + mode, and optional hostname +- Agent picks random free ports (10000-60000, availability check, + mutex-serialized), records assignments in `component_routes` table +- Containers receive `$PORT` / `$PORT_` env vars +- Backward compatible: old-style `ports` strings still work unchanged +- 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 generation #### 3. MCP Agent: mc-proxy Route Registration @@ -287,19 +285,16 @@ is no API for dynamic record management. wrapper, not a full service. This may be the right time to build the real MCNS. -#### 9. Application $PORT Convention +#### 9. Application $PORT Convention — DONE -**Gap**: applications read listen addresses from their config files. -They don't check `$PORT` env vars. - -**Work**: -- Each service's config layer checks `$PORT` / `$PORT_` and - overrides the configured listen address if set. -- This fits naturally into the existing `$SERVICENAME_*` env override - convention — it's just one more env var. -- Small change per service, but touches every service. - -**Depends on**: nothing (can be done incrementally). +mcdsl v1.1.0 adds `$PORT` and `$PORT_GRPC` env var support: +- `config.Load` checks `$PORT` → overrides `Server.ListenAddr` +- `config.Load` checks `$PORT_GRPC` → overrides `Server.GRPCAddr` +- Takes precedence over TOML and generic env overrides + (`$MCR_SERVER_LISTEN_ADDR`) — agent-assigned ports are authoritative +- Handles both `config.Base` embedding (MCR, MCNS, MCAT) and direct + `ServerConfig` embedding (Metacrypt) via struct tree walking +- MCR, Metacrypt, MCNS upgraded to mcdsl v1.1.0 --- @@ -308,15 +303,15 @@ They don't check `$PORT` env vars. The dependencies form a rough order: ``` -Phase A — Independent groundwork (parallel): +Phase A — Independent groundwork: ✓ COMPLETE #1 mcdsl proper module versioning ✓ DONE - #2 MCP agent port assignment + #2 MCP agent port assignment ✓ DONE #5 mc-proxy route persistence ✓ DONE - #9 $PORT convention in applications + #9 $PORT convention in applications ✓ DONE -Phase B — MCP route registration: +Phase B — MCP route registration: ← IN PROGRESS #3 Agent registers routes with mc-proxy - (depends on #2 + #5) + (depends on #2 + #5 — both done) Phase C — Automated TLS: #7 Metacrypt cert issuance policy @@ -329,31 +324,24 @@ Phase D — DNS: (depends on #8) ``` -Phase A is partially complete. mcdsl (#1) and mc-proxy route -persistence (#5) are done. The remaining Phase A work (#2, #9) can -proceed in parallel. +**Phase A is complete.** Services can be deployed with agent-assigned +ports and `$PORT` env vars. mc-proxy routes must still be registered +manually via `mcproxyctl` or the gRPC API. -After Phase A, services can be deployed with agent-assigned ports -(manually registered in mc-proxy). +**Phase B is next.** The agent will call mc-proxy's gRPC API to +register/remove routes automatically during deploy/stop. This +eliminates the last manual networking step — no more `mcproxyctl` +or TOML editing. -After Phase B, the manual steps are: cert provisioning and DNS. This -is the biggest quality-of-life improvement — no more manual port -picking or mc-proxy TOML editing. - -After Phase C, only DNS remains manual. - -After Phase D, `mcp deploy` is fully declarative. - -Each phase is independently useful and deployable. +After Phase C, cert provisioning is automatic. After Phase D, +`mcp deploy` is fully declarative. ### Immediate Next Steps -1. **MCP agent port assignment (#2)** — new service definition parser, - port allocation, `$PORT_*` injection. With #5 done, this is the - remaining blocker for Phase B. -2. **$PORT convention (#9)** — small per-service config change. Can - start incrementally now, but only useful once #2 is deployed. -3. **mcdoc implementation** — fully designed, no platform evolution +1. **Phase B: MCP agent route registration (#3)** — agent connects to + mc-proxy via Unix socket, registers routes on deploy, removes on + stop. TLS certs are pre-provisioned (Phase C automates this later). +2. **mcdoc implementation** — fully designed, no platform evolution dependency. Deployable with a manually assigned port today. --- diff --git a/engineering-standards.md b/engineering-standards.md index aa2f468..8c7b843 100644 --- a/engineering-standards.md +++ b/engineering-standards.md @@ -810,6 +810,28 @@ registry. If a tag is missing and the source tree is available, it builds and pushes automatically. If the source tree is not available, it fails with a clear error directing the operator to build first. +### Port Assignment and $PORT Convention + +When deployed via MCP, the agent assigns host ports automatically and +passes them to containers via environment variables: + +| Env var | When set | Example | +|---------|----------|---------| +| `$PORT` | Component has a single route | `PORT=8913` | +| `$PORT_` | Component has multiple routes | `PORT_REST=8913`, `PORT_GRPC=9217` | + +Route names come from the `name` field in `[[components.routes]]`. +Names are uppercased for the env var (e.g., `name = "rest"` → +`$PORT_REST`). + +Services using mcdsl v1.1.0+ get this automatically — `config.Load` +checks `$PORT` and `$PORT_GRPC` and overrides `Server.ListenAddr` and +`Server.GRPCAddr` respectively. These take precedence over TOML values +and generic env overrides (`$MCR_SERVER_LISTEN_ADDR`). + +Services not using mcdsl must check `$PORT` manually in their config +loading. + ### TLS - **Minimum TLS version: 1.3.** No exceptions, no fallback cipher suites.