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) <noreply@anthropic.com>
This commit is contained in:
2026-03-27 01:25:16 -07:00
parent 5baf12e303
commit b17472122b
2 changed files with 62 additions and 52 deletions

View File

@@ -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_<NAME>` 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_<NAME>` 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_<NAME>` 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.
---

View File

@@ -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_<NAME>` | 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.