Skip to content

Commit a47a650

Browse files
fatherlinuxclaude
andauthored
feat: update MCP server profile for distroless Hummingbird (v1.3.0) (#2)
Hummingbird runtime images are now distroless — no shell, no package manager. Updates the MCP server profile to document: - Distroless runtime constraints (no shell-form RUN) - Venv build pattern (replaces wheel-based example) - FIPS image variants in base images table - Exec-form RUN as fallback guidance Ref: https://issues.redhat.com/browse/HUM-813 Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 8543598 commit a47a650

1 file changed

Lines changed: 32 additions & 17 deletions

File tree

profiles/mcp-server.md

Lines changed: 32 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# MCP Server Profile
22

3-
> **Profile Version:** 1.2.0
3+
> **Profile Version:** 1.3.0
44
> **Applies to:** All `mcp-*-crunchtools` projects
55
66
This profile extends the [universal constitution](../constitution.md) with requirements specific to MCP (Model Context Protocol) servers in the crunchtools organization.
@@ -90,46 +90,61 @@ Every MCP server MUST support all three MCP transports:
9090

9191
MCP servers use **Hummingbird** base images (not UBI). Hummingbird images are minimal, CVE-hardened, and purpose-built for application workloads.
9292

93+
### Distroless Runtime
94+
95+
Hummingbird runtime images are **distroless** — they contain no shell (`/bin/sh`), no package manager (`dnf`), and no standard Unix utilities (`ls`, `rm`, `cat`). Only the language runtime binary (e.g., `python3`, `pip`) is present.
96+
97+
This means:
98+
- **No shell-form `RUN` commands** in the runtime stage. Shell-form `RUN` requires `/bin/sh` to interpret the command, which does not exist.
99+
- **Use the venv pattern** (preferred): build everything in the builder stage inside a Python venv, then `COPY --from=builder` the venv directory to the runtime stage. This eliminates all `RUN` commands in the runtime stage.
100+
- **Exec-form `RUN` as fallback**: if you must run a command in the runtime stage, use exec form `RUN ["pip", "install", ...]` to invoke the binary directly without a shell.
101+
93102
### Base Images
94103

95104
| Image | Use Case |
96105
|-------|----------|
97-
| `quay.io/hummingbird/python:latest` | Python runtime (no build tools, no DNF) |
98-
| `quay.io/hummingbird/python:latest-builder` | Python with build toolchain (gcc, libstdc++, DNF) |
99-
| `quay.io/hummingbird/nodejs:latest` | Node.js runtime |
106+
| `quay.io/hummingbird/python:latest` | Python runtime (distroless — no shell, no DNF) |
107+
| `quay.io/hummingbird/python:latest-builder` | Python with build toolchain (shell, gcc, DNF) |
108+
| `quay.io/hummingbird/python:latest-fips` | Python FIPS runtime (distroless) |
109+
| `quay.io/hummingbird/python:latest-fips-builder` | Python FIPS with build toolchain |
110+
| `quay.io/hummingbird/nodejs:latest` | Node.js runtime (distroless) |
100111
| `quay.io/hummingbird/core-runtime:latest` | Minimal runtime with libstdc++, glibc, ca-certificates |
101112

102-
### Multi-Stage Build Pattern
113+
### Multi-Stage Build Pattern (Venv)
103114

104115
MCP servers MUST use a multi-stage Containerfile with **builder and runtime images from the same ecosystem**:
105116

106-
1. **Builder stage**compile native wheels using the Hummingbird builder variant
107-
2. **Runtime stage**copy wheels into Hummingbird runtime, install with `pip --no-index`
117+
1. **Builder stage**create a venv, install all dependencies inside it
118+
2. **Runtime stage**`COPY` the venv from builder, set `PATH`. No `RUN` commands needed.
108119

109120
**CRITICAL: Builder and runtime images MUST be from the same base image family.** Never use Fedora, Alpine, or UBI as the builder when the runtime is Hummingbird (or vice versa). Different base images use different glibc versions — compiled artifacts and native libraries from one ecosystem are not designed or tested against the other. This creates silent ABI incompatibilities, segfaults, or subtle runtime failures.
110121

111122
Allowed builder/runtime combinations:
112123

113124
| Builder | Runtime | Status |
114125
|---------|---------|--------|
126+
| `quay.io/hummingbird/python:latest-fips-builder` | `quay.io/hummingbird/python:latest-fips` | **Allowed** |
115127
| `quay.io/hummingbird/python:latest-builder` | `quay.io/hummingbird/python:latest` | **Allowed** |
116128
| `registry.access.redhat.com/ubi10/ubi` | `registry.access.redhat.com/ubi10/ubi-minimal` | **Allowed** |
117129
| `registry.fedoraproject.org/fedora:44` | `quay.io/hummingbird/python:latest` | **Prohibited** |
118130
| `registry.access.redhat.com/ubi10/ubi` | `quay.io/hummingbird/python:latest` | **Prohibited** |
119131

120132
```dockerfile
121-
# Stage 1: Build wheels (Hummingbird builder — same ecosystem as runtime)
122-
FROM quay.io/hummingbird/python:latest-builder AS builder
123-
RUN dnf install -y gcc && dnf clean all
124-
WORKDIR /build
133+
# Stage 1: Builder (has shell, dnf, build tools)
134+
FROM quay.io/hummingbird/python:latest-fips-builder AS builder
135+
USER 0
136+
WORKDIR /app
137+
RUN python3 -m venv /app/venv
138+
ENV PATH="/app/venv/bin:$PATH"
125139
COPY pyproject.toml README.md ./
126140
COPY src/ ./src/
127-
RUN pip wheel --no-cache-dir --wheel-dir=/wheels .
141+
RUN pip install --no-cache-dir .
128142

129-
# Stage 2: Runtime (Hummingbird runtime — same ecosystem as builder)
130-
FROM quay.io/hummingbird/python:latest
131-
COPY --from=builder /wheels /wheels
132-
RUN pip install --no-cache-dir --no-index --find-links=/wheels <package-name>
143+
# Stage 2: Runtime (distroless — no shell, no package manager)
144+
FROM quay.io/hummingbird/python:latest-fips
145+
COPY --from=builder /app/venv /app/venv
146+
ENV PATH="/app/venv/bin:$PATH"
147+
ENTRYPOINT ["python", "-m", "<module_name>"]
133148
```
134149

135150
### Native Library Gap (libstdc++)
@@ -139,7 +154,7 @@ The Hummingbird Python runtime image **does not include libstdc++.so.6**. Any pi
139154
**Fix:** Copy `libstdc++` from the Hummingbird builder variant (same ecosystem):
140155

141156
```dockerfile
142-
COPY --from=quay.io/hummingbird/python:latest-builder /usr/lib64/libstdc++.so.6* /usr/lib64/
157+
COPY --from=quay.io/hummingbird/python:latest-fips-builder /usr/lib64/libstdc++.so.6* /usr/lib64/
143158
```
144159

145160
### Required Labels

0 commit comments

Comments
 (0)