Simple in-pod sidecar mode: wrap a co-located non-MCP process with spec mode #59
Labels
No labels
autonomy
async-consult
autonomy
epic
autonomy
headless
autonomy
live-collab
coherence-core
priority
P0
priority
P1
priority
P2
priority
P3
priority
P4
qa-fixture
role/ai
role/creator
role/design
role/director
role/engineer
role/exec
role/human
role/ops
role/qa
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
coilyco-flight-deck/mcp-beaver#59
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Filed by Olaf (OPS) from
coilyco-bridge/deploy. Kai's call from a design conversation on 2026-08-13; consumer context is coilyco-bridge/deploy#495.The ask
A first-class, minimal way to run a plain process beside the runtime in the same pod and wrap its HTTP surface with ordinary spec mode.
Why the existing path is not quite it
runtime.mode: upstreamplusextraContainersalready co-locates a container, and--connect-timeoutalready handles warmup. But that path is built for an upstream that is already MCP —serve-upstreamsnapshots an upstream tool list and proxies allowlisted names.The consumer case here is different and lighter: the co-located process speaks plain HTTP JSON, not MCP. Concretely, deploy#495 wants a SQLite dataset (GeoNames gazetteer, Natural Earth, OWID and friends) served over a local JSON API and wrapped with
can getgrants againstlocalhost. Datasette is the candidate. The value is that it removes an entire class of external dependency: no rate limits, no third-party uptime, no per-request caching problem, andrestrictstill bounds the surface.serve-upstreamcannot express that, because there is no upstream MCP to snapshot. Spec mode can, becausebase-urlis just a URL.This may be much smaller than it sounds — please check first
The honest version of this ask is "make it work and document it," not necessarily "build a mode." I could not determine from
README.md,docs/FEATURES.md, ordocs/chart.mdwhetherextraContainersis available inruntime.mode: specor only inupstreammode. The docs only ever discuss it under upstream mode.If it already works in spec mode, then this whole issue is likely:
examples/sidecar.values.yaml),If it does not, the chart change is probably still small.
Determining which of those it is should be the first step, not the implementation.
Readiness ordering is the one real design question
Spec mode does not connect at startup — it resolves
base-urlper request — so unlike upstream mode there is no crash-loop risk from a slow sidecar. A request arriving before the sidecar is up simply errors.That is arguably acceptable, but it means the pod can report ready while its data plane is not. Worth deciding deliberately: either a readiness gate that waits on the sidecar, or an explicit statement that early requests fail and that is fine.
Acceptance
extraContainersworks inruntime.mode: spectoday is determined and recorded on this issue before any code is written.base-urlpointing at a co-located container serves tools that reach it.serve-upstreamsemantics.Note on scope
This does not ask for multi-upstream single-spec, which Kai has ruled out as intentional (deploy#495). One guardfile, one
base-url, which here happens to belocalhost.Determination first, as the issue required:
extraContainersalready works inruntime.mode: spec.chart/templates/deployment.yamlappends.Values.extraContainersto the pod's container list at lines 124-126 with no mode condition. Only three blocks are gated on$mode: the runtime args (63-78), the/specvolumeMount (104-109), and the volumes (127-132). Nothing about co-locating a container is mode-specific.So this was the small version you hoped for. Landed in
17351e2:examples/sidecar.mcp.kdl- a Datasette-shaped gazetteer wrapped over127.0.0.1:8001.examples/sidecar.values.yaml- the pod shape.ward exec helm-template-sidecar- a tracked verb rendering it, so the shape is covered by the repo's own validation rather than only by prose.docs/chart.mdstating thatextraContainersis not mode-gated, and why the two modes co-locate for different reasons.Only upstream mode was ever documented, which is what made a supported shape look unavailable.
Readiness - decided rather than left implicit. You were right that this is the one real question, and right about the direction. Spec mode never connects at startup, so there is no crash-loop risk; the cost is the opposite failure, and it is worse than it first sounds: ward-mcp binds immediately and answers
tools/listcorrectly while the sidecar is still loading. The pod reports Ready with its data plane down.The reference values gate readiness on the sidecar's own port. Containers share a network namespace, so a probe can target it directly. Liveness stays on ward-mcp, so a wedged sidecar fails readiness and stops taking traffic rather than restarting a healthy runtime out from under itself.
Accepting the default and letting early requests fail is defensible for a fast-starting sidecar. Not chosen as the reference, because "fails briefly after every rollout" is the kind of error that gets attributed to the wrong component.
One thing worth knowing before building on this. The wrap grammar requires an
authblock and has nononescheme, so a loopback upstream needing no credential still has to name one. The example uses a pod-local shared token. Relaxing that is a umbra grammar change rather than a runtime one, so it is not taken here - flagging it because it is a small surprise waiting for whoever writes the deploy#495 guardfile.serve-upstreamsemantics untouched, and multi-upstream single-spec not touched either.Caveat on the evidence: helm is not available in this session, so the determination is from reading the template with line citations, not from a rendered manifest.
ward exec helm-template-sidecaris the one-command confirmation.