Docker Cloud CI MCP Bridge
Runs allowlisted CI builds and tests in Docker Cloud Sandboxes via the Docker Sandboxes SDK, including job startup, status polling, and bounded log retrieval using Docker ID and PAT credentials.
This server does not currently have a deployable release on Glama. Follow the repository's setup instructions to install and configure it for your MCP client, including any required credentials and local dependencies.
Docker Cloud CI MCP Bridge
A small single-user fallback CI execution bridge. Not a proxy for Docker's MCP Gateway. Cloud Container (i.e. Perplexity Computer) -> HTTPS /mcp (Bearer API key) -> Docker Sandboxes SDK (Docker ID + PAT). No Docker socket, host shell execution, OAuth callback, model API key or sbx installation required.
Quick start (Node 22+, one replica only)
Extract archive and enter directory. Run
npm install(internet required). Review the resolved Docker SDK version and commit package-lock.json before production; Docker SDK is deliberately not version-guessed. MCP SDK is pinned to the official v1 API reviewed via Context7.cp .env.example .env; cp projects.example.json projects.json; chmod 600 .envGenerate a key:
openssl rand -hex 32. Put it in BRIDGE_API_KEY. Never paste the Docker PAT into a chat or connector form.Create Docker PAT with Allow Cloud Sandboxes access; set DOCKER_ID and DOCKER_PAT. Requires active Agentic Platform subscription; compute is separately billed.
Edit projects.json to allow only repositories and scripts you trust. Only exact 40-character commit SHAs accepted. Caller cannot choose a URL, shell command, kit or secret.
npm test. For a no-cost transport test set MOCK_DOCKER=1, thennpm start. In another terminal runnode --env-file=.env scripts/smoke.mjs.Set MOCK_DOCKER=0 and restart for real execution. Use a disposable repository for the first build. Shell kit must have git and your build tools; example task checks node/npm and fails if missing. This package does NOT assume shell kit contains a full language toolchain. Customize scripts to bootstrap trusted pinned tooling, or adapt the SDK launch to a reviewed image/kit using Docker's image documentation.
Deploy on Railway (below). It terminates HTTPS for you, so no reverse proxy is needed.
Related MCP server: MCP Build Environment Service
Deploy on Railway
Requires the Railway CLI (railway login). Run from this directory. railway.json sets the start command, /healthz healthcheck, restart policy and a single replica.
railway init # or: railway link
railway add --service docker-ci-bridge
railway volume add --mount-path /data # persistent job records; REQUIRED (the app refuses to start on Railway without one)
railway variables --set "BRIDGE_API_KEY=$(openssl rand -hex 32)" --set "MOCK_DOCKER=1"
railway up # first deploy in mock mode (no billable sandboxes)
railway domain # public HTTPS URL -> https://<domain>/mcpThen validate: BRIDGE_URL=https://<domain>/mcp BRIDGE_API_KEY=<key> node scripts/smoke.mjs.
For real execution set the Docker credentials in the Railway dashboard (so they never enter shell history or chat): DOCKER_ID, DOCKER_PAT, and MOCK_DOCKER=0, then redeploy. Optional: ALLOWED_ORIGIN, PROJECTS_FILE.
Railway notes:
The app binds
0.0.0.0and$PORTautomatically whenRAILWAY_ENVIRONMENT_NAMEis set; locally it stays on127.0.0.1.DATA_DIRdefaults toRAILWAY_VOLUME_MOUNT_PATH. KeepnumReplicasat 1: the one-build-at-a-time lock andrequest_iddedupe are in-process.Services with a volume redeploy with brief downtime, and a redeploy kills any running build. On restart that job is marked
interrupted; check Docker Console for the orphaned sandbox before retrying. Avoid deploying while a build is running.projects.jsonis committed and shipped with the deploy, so edit the allowlist (repo URLs and scripts) beforerailway up.
Agent skill
skills/docker-cloud-bridge/SKILL.md teaches coding agents how to run builds through the bridge and how to deploy and debug it. The same file is checked in where each tool looks for project skills:
Tool | Location |
Universal ( |
|
Claude Code |
|
Codex (also read by OpenCode) |
|
OpenCode |
|
skills/ is the canonical copy. If you edit it, copy the file to the other three locations so they don't drift.
Private repos, secret forwarding, artifacts and status reports
All four are configured by the operator in projects.json. The caller (an agent) can only pick among what was declared, and it never sees or supplies a secret value.
{
"my-app": {
"repo": "https://github.com/OWNER/PRIVATE_REPO.git",
"auth": { "tokenEnv": "GH_CLONE_TOKEN" },
"status": { "provider": "github", "tokenEnv": "GH_STATUS_TOKEN" },
"tasks": {
"build": {
"script": "npm ci --ignore-scripts\nnpm test\nnpm run build",
"artifacts": ["dist/", "coverage/lcov.info"],
"forward": {
"NPM_TOKEN": { "mode": "inject", "hosts": ["registry.npmjs.org"], "header": "Authorization", "format": "Bearer %s" },
"DEPLOY_ENV": { "mode": "env" }
}
}
}
}
}A task may still be a plain string (the script), exactly as before.
Private repositories (auth). tokenEnv names a bridge environment variable holding a read-only token (a fine-grained GitHub token with Contents: read on that one repo, or a GitLab deploy/project token with read_repository). For each build the bridge stores it as a Docker stored secret and attaches it to the sandbox; Docker's proxy adds the credential to requests for the repo host only, so the token is never written into the sandbox. GitHub uses Docker's native github secret type (Docker rejects custom injection for managed hosts). Other forges get a custom Authorization injection (scheme basic (default, user oauth2 on gitlab.com or username) or bearer). Repo hosts default to github.com,gitlab.com; set ALLOWED_GIT_HOSTS (comma separated) to use others. It replaces the default list, so include github.com/gitlab.com if you still need them. The stored secret is deleted when the build ends, and any bridge-* secret left by a crash is purged at startup.
Forwarding environment variables (forward + forward_env). The agent calls start_build with forward_env: ["NPM_TOKEN"]: names only. A name is accepted only if the operator listed it under that task's forward; the value is read from the bridge's own environment (for example a Railway variable), never from the caller. Two modes:
inject(preferred): Docker's proxy adds the value to the named header on requests to the listed exact hosts. The sandbox only sees a placeholder in$NPM_TOKEN, so a build script cannot print or exfiltrate the real value, but it can still make requests to those hosts. Hosts must be exact lowercase DNS names (max 10).formathas exactly one%s.github.comis not allowed here; useauth.env: the raw value is placed in the build process environment. Use only for non-sensitive settings or when you accept that the commit's code can read it.
BRIDGE_API_KEY, DOCKER_ID, DOCKER_PAT and any variable used as auth.tokenEnv, status.tokenEnv or status.secretEnv can never be forwarded. At most 16 names per build.
Artifacts (artifacts). Up to 8 relative paths per task (files, or directories ending in /) inside the checkout. After the script finishes (pass or fail) the bridge lists them with the sandbox's own tools, drops anything that resolves outside the work dir (symlinks) and reads each file under caps: ARTIFACT_MAX_FILES (20), ARTIFACT_MAX_FILE_BYTES (5 MiB), ARTIFACT_MAX_TOTAL_BYTES (20 MiB). Files are hashed (sha256) and stored under DATA_DIR/artifacts/<job id>/. The get_build_artifacts tool lists them; with index it returns files up to ARTIFACT_INLINE_MAX_BYTES (256 KiB) as base64; anything can be fetched with GET /artifacts/<job id>/<index> using the same Authorization header. Contents are untrusted data.
Status reports (status). The bridge itself posts the build state to the forge (so these tokens never enter a sandbox) when a build starts and when it finishes. Logs are never sent. Failures are recorded on the job (statusReport) and never fail the build.
github: commit status API; the token needs Commit statuses: write on the repo. GitHub Enterprise: setbaseUrlto the API root.gitlab: commit status API with aPRIVATE-TOKEN(scopeapi). Self-hosted: setbaseUrl.webhook: any other git host or CI glue.POSTof a small JSON document (project,task,repo,commit,jobId,status,exitCode,finishedAt) to an httpsurl, signed withX-Bridge-Signature: sha256=<hmac>whensecretEnvis set.
Config is validated at startup and the bridge refuses to start with a message listing every problem. In MOCK_DOCKER=1 mode nothing is posted to forges.
Connect Perplexity
Plugins -> Add custom -> Add MCP connector -> Remote.
URL: https://YOUR_DOMAIN/mcp
Transport: Streamable HTTP. Authentication: API Key, not OAuth.
API key: BRIDGE_API_KEY. Server expects Authorization: Bearer <key>.
The official Perplexity guide does not specify the API Key field's exact wire encoding. Validate this with smoke.mjs and connector setup; if your client sends a different standard authorization format, adjust the auth middleware deliberately, not by disabling auth. There is no arbitrary custom-header field in the connector form.
Tools: list_projects, start_build, get_build_status, get_build_logs. Example request: list approved tasks, then ask me to approve a test of project my-app at exact commit SHA. Start only after approval, generate a UUID request_id, and poll status. Reuse the SAME request_id when retrying a timed-out start call. Read logs after completion.
Behavior and limitations
Uses official SDK PAT exchange, shell kit launch, waitUntilRunning, processes.run, refresh/delete/waitUntilDeleted.
start_build returns a job ID immediately; poll status. Results and bounded tail logs persist in data/. Logs are collected on process completion, not live streamed. The SDK can buffer more output before truncation here; constrain noisy build output in your trusted script.
One active job, one process/replica. request_id deduplication retained on disk. No distributed lock or queue. Local disk must persist across restarts. Manually prune old job records when idle; there is no retention scheduler.
Process timeout is ten minutes; launch/wait timeouts two minutes each. Timeout is not a billing cap. Cleanup attempted in finally, including failed builds. SDK timeouts or a crash can orphan resources. On restart active records become interrupted; inspect Docker Console and delete orphans before retrying. A creation timeout can occur before the sandbox name reaches the bridge. Set account budget alerts and review Console resources. No claim of crash-safe cleanup or auto-expiry.
Default SDK small compute: 2 CPUs/4 GiB. No network policy is configured by this implementation (Docker rejected inline network policies on the account used for verification; use Docker governance policies if you need egress control). Private repos, forwarded variables, artifacts and status reports are opt-in per project in
projects.json(see the section above). Do not put PATs in repo URLs or scripts.Default workflow is CI (test/build). No deployment/registry credentials, prod deploy, rollback, cancellations or automatic failover scheduler. Add a fixed allowlisted deployment task only after designing narrowly scoped credentials, independent approval enforcement and rollback. Exported artifacts accumulate on the volume (capped per build, no retention scheduler); prune
DATA_DIR/artifacts/when idle.Task execution is a billable, side-effecting operation, even for tests. Tool description instructs client to request approval, but does NOT provide a server-side human approval gate. Possession of bridge API key permits running ANY allowlisted task/commit. Use only trusted connector owners. Do not add production deployment credentials unless you implement an independent approval gate.
An allowlisted repo is not a security boundary against malicious code within that repo. Tests/package scripts execute code from the selected commit. Do not execute unreviewed fork/PR code with secrets. npm ci --ignore-scripts only disables installation lifecycle scripts; npm test/build still execute code.
Logs are untrusted and may include secrets deliberately printed by code. The bridge key, Docker PAT, the repo token and every forwarded value are redacted from logs, job records, error messages and artifact names; this is not a generic secret scanner and artifact contents are not scanned. The Docker PAT remains on the bridge host and is never injected into a sandbox.
Railway provides HTTPS only; there is no rate limiting, so keep the API key secret (32+ chars enforced) and rotate credentials. Origin-bearing requests rejected unless ALLOWED_ORIGIN matches; non-browser MCP requests normally omit Origin.
Verification status
Policy tests can run offline with Node. Dependency installation, MCP smoke testing and real Docker execution require network access/credentials and have NOT been performed by the artifact generator. No live cloud resources were created. Dependency compatibility is based on official examples, not a live integration certification.
Official references consulted
https://docs.docker.com/ai/sandboxes-api/ https://docs.docker.com/ai/sandboxes-api/authentication/ https://docs.docker.com/ai/sandboxes-api/get-started/ https://docs.docker.com/ai/sandboxes-api/concepts/ https://docs.docker.com/ai/sandboxes-api/cookbook/create-your-first-sandbox/ https://docs.docker.com/ai/sandboxes-api/cookbook/run-your-first-command/ https://docs.docker.com/ai/sandboxes-api/limits/ https://github.com/modelcontextprotocol/typescript-sdk/tree/1.32.2 https://www.perplexity.ai/help-center/en/articles/13915507-adding-custom-remote-connectors
Docker CLI cloud secret store and web Agentic Platform secrets are separate. Earlier chat advice implying they are interchangeable was inaccurate. This bridge authenticates directly through the documented SDK API, not by borrowing the Gateway's OAuth session.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
This server cannot be deployed
Maintenance
Related MCP Connectors
Build, test, publish, and run Kovca workflows from AI agents over remote MCP.
Secure Linux sandboxes for AI agents, as MCP tools.
Verified component catalog over remote MCP: agents pick component ids and get a stamped project repo that builds. Connect at https://www.botkelp.com/mcp. Auth: MCP OAuth 2.1, or a Bearer bk_live_ API key; initialize and tools/list are open.
Sandboxes, storage, secrets, queues, timers, locks, inboxes and run ledger for AI bots. One MCP.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceEnables secure Docker command execution from isolated environments like containers through MCP protocol. Provides tools for managing Docker containers, images, and Docker Compose services with security validation and async operation support.MIT
- AlicenseAqualityDmaintenanceProvides secure access to containerized build environments for software projects, enabling AI assistants to execute builds, run tests, manage git operations, and inspect build artifacts without requiring local installation of dependencies.6MIT
- FlicenseNot gradedqualityDmaintenanceProvides MCP tools for managing disposable Docker sandboxes that let AI agents safely execute commands in isolated, ephemeral environments.-
- -licenseNot gradedqualityNot gradedmaintenanceEnables MCP clients to securely execute bounded coding tasks through registered backends, with idempotent job submission, status polling, and artifact retrieval. It isolates each job in Git worktrees and supports optional branch publishing and pull request creation under strict policy constraints.-