5825649a49
Secret scan / Scan diff for credential-shaped strings (pull_request) Successful in 2s
CI / Template validation (static) (push) Successful in 4s
CI / Adapter unit tests (pull_request) Successful in 6s
CI / Adapter unit tests (push) Successful in 5s
CI / Template validation (static) (pull_request) Successful in 8s
verify-providers-projection / Regenerate projection, fail on drift, assert registry ⊆ template (pull_request) Successful in 1m17s
CI / Template validation (runtime) (push) Successful in 1m58s
CI / T4 tier-4 conformance (live) (push) Successful in 1m57s
CI / validate (push) Successful in 2s
CI / Template validation (runtime) (pull_request) Successful in 2m3s
CI / T4 tier-4 conformance (live) (pull_request) Successful in 2m6s
CI / validate (pull_request) Successful in 1s
1.6.0 died at startup in management mode (duplicate create_request, mcp-server#63) — the image smoke gate correctly refused to publish it. 1.6.1 removes the duplicate; create_approval + create_request both serve from the composed registry. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
78 lines
4.1 KiB
Docker
78 lines
4.1 KiB
Docker
# molecule-platform-agent image
|
|
# RFC: molecule-core docs/design/rfc-platform-agent.md §5.7
|
|
#
|
|
# A dedicated image, FROM this repo's workspace-template-claude-code image, that
|
|
# bakes in the org-management MCP (@molecule-ai/mcp-server) so the org-level
|
|
# platform agent can drive the org alongside the always-on a2a MCP.
|
|
#
|
|
# Built in THIS repo (not molecule-ci) so it reuses the existing publish
|
|
# pipeline's ECR credentials, publish runners, and pin-promote — NO new secret.
|
|
# The MCP is pulled from the org's Gitea npm registry, which serves the package
|
|
# anonymously, so the build needs no token or cross-repo checkout either.
|
|
#
|
|
# Keeps the org-admin MCP OUT of ordinary workspace images (security hygiene):
|
|
# only this image installs it; ordinary workspaces declare no extra mcp_servers.
|
|
|
|
# Pin to a specific workspace-template-claude-code tag at build time via
|
|
# --build-arg BASE_IMAGE=...:sha-<7> (the publish workflow passes the sha it just
|
|
# pushed). Defaults to :latest for local builds.
|
|
ARG BASE_IMAGE=153263036946.dkr.ecr.us-east-2.amazonaws.com/molecule-ai/workspace-template-claude-code:latest
|
|
FROM ${BASE_IMAGE}
|
|
|
|
# Version of @molecule-ai/mcp-server to bake (pin for reproducible builds).
|
|
ARG MCP_VERSION=1.6.1
|
|
|
|
USER root
|
|
|
|
# Pin Node 20. The debian-slim base apt-installs `nodejs` (Node 18); the org
|
|
# MCP's @modelcontextprotocol/sdk requires >=20. Install Node 20 from NodeSource,
|
|
# replacing the apt nodejs so `node` resolves to 20 for both claude-code and the
|
|
# baked MCP.
|
|
RUN set -eux; \
|
|
apt-get update; \
|
|
apt-get install -y --no-install-recommends ca-certificates curl gnupg; \
|
|
mkdir -p /etc/apt/keyrings; \
|
|
curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key \
|
|
| gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg; \
|
|
echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_20.x nodistro main" \
|
|
> /etc/apt/sources.list.d/nodesource.list; \
|
|
apt-get update; \
|
|
apt-get install -y --no-install-recommends nodejs; \
|
|
node --version | grep -E '^v20\.'; \
|
|
rm -rf /var/lib/apt/lists/*
|
|
|
|
# Install the org-management MCP globally from the org Gitea npm registry
|
|
# (anonymous read — no auth). The package's OWN bin name (molecule-mcp)
|
|
# COLLIDES with the runtime wheel's Python a2a inbox bridge at
|
|
# /usr/local/bin/molecule-mcp, which wins on PATH — so the concierge config
|
|
# references the UNAMBIGUOUS `molecule-platform-mcp` symlink instead:
|
|
# `mcp_servers: [{name: platform, command: molecule-platform-mcp,
|
|
# env: {MOLECULE_MCP_MODE: management}}]`
|
|
# (core: conciergeMCPServersBlock). The symlink targets the package entry
|
|
# directly so it cannot be shadowed by any future bin-name squatter.
|
|
RUN set -eux; \
|
|
printf '@molecule-ai:registry=https://git.moleculesai.app/api/packages/molecule-ai/npm/\n' > /etc/npmrc; \
|
|
npm install -g --userconfig /etc/npmrc "@molecule-ai/mcp-server@${MCP_VERSION}"; \
|
|
chmod +x /usr/lib/node_modules/@molecule-ai/mcp-server/dist/index.js; \
|
|
ln -sf /usr/lib/node_modules/@molecule-ai/mcp-server/dist/index.js /usr/local/bin/molecule-platform-mcp; \
|
|
command -v molecule-platform-mcp
|
|
|
|
# Self-contain the adapter-module import path. The runtime boots via its console-script
|
|
# entrypoint, which does NOT put the working dir on sys.path — so the adapter
|
|
# module at the image's working directory is unimportable unless the working
|
|
# directory is on PYTHONPATH. Ordinary workspace images get this from the
|
|
# platform's container environment; THIS image is launched by a different
|
|
# runner that does not inject it, so the dedicated platform-agent image must
|
|
# set PYTHONPATH itself, or the runtime fails to start when the import fails.
|
|
# Putting the working directory first on PYTHONPATH also keeps the local
|
|
# modules ahead of any same-named modules under site-packages (see the base
|
|
# Dockerfile's COPY notes).
|
|
ENV PYTHONPATH=/app
|
|
|
|
# Marker so the runtime/provisioner can assert it is on the platform-agent image
|
|
# (and not an ordinary workspace image) before declaring the platform MCP.
|
|
ENV MOLECULE_PLATFORM_AGENT_IMAGE_BAKED=1
|
|
|
|
# Return to the agent uid the base image runs as.
|
|
USER agent
|