Skip to main content

Docker deployment

Run HAPI MCP servers locally, in cloud environments, or in disconnected networks with the official Docker image.

Choose an image tag

TagIntended use
latestProduction-ready HAPI 0.x release line.
workflowsHAPI v1 beta with OpenAPI and HAPI Workflows (Arazzo).
arazzoAlias for workflows.
1.0.0-beta.0823A pinned HAPI v1 beta version.
HAPI v1 is a beta

Use workflows, arazzo, or a pinned 1.0.0-beta.* tag to evaluate HAPI Workflows. Keep using latest for production until HAPI v1 is stable.

Prerequisites

  • Docker
  • An OpenAPI or Arazzo document
  • Network access from the container to the documented API backend, unless all required documents and APIs are available locally

The v1 image runs as a non-root user, uses /var/lib/hapi for persistent state, and writes operational logs to standard container output.

Serve an OpenAPI document

Mount a document from the current directory and expose the MCP server on port 3000:

docker run --name hapi-openapi --rm -d \
-p 3000:3000 \
-v "$PWD:/specs:ro" \
hapimcp/hapi-cli:workflows \
serve --specs /specs/openapi.yaml \
--url https://api.example.com \
--headless \
--host 0.0.0.0 \
--public-host http://localhost:3000

The MCP endpoint is available at http://localhost:3000/mcp.

  • --specs chooses the API document.
  • --url overrides the OpenAPI document's server URL.
  • --headless exposes MCP while API requests are sent to the external backend.
  • --host 0.0.0.0 makes the service reachable through Docker port publishing.
  • --public-host is the public MCP URL advertised to OAuth clients.

Serve HAPI Workflows (Arazzo)

HAPI Workflows expose supported Arazzo workflowId values as MCP tools.

First, validate the workflow:

docker run --rm \
-v "$PWD:/specs:ro" \
hapimcp/hapi-cli:workflows \
workflows validate --specs /specs/workflow.yaml

Then serve it:

docker run --name hapi-workflows --rm -d \
-p 3000:3000 \
-v "$PWD:/specs:ro" \
hapimcp/hapi-cli:workflows \
workflows serve --specs /specs/workflow.yaml \
--port 3000 \
--host 0.0.0.0 \
--public-host http://localhost:3000

hapi arazzo serve and hapi workflows serve are exact aliases. The general hapi serve command also detects Arazzo documents automatically.

Backends in workflows

When no --url is supplied, HAPI sends each step to the server declared by the OpenAPI document referenced by that Arazzo sourceDescription. This preserves workflows that call multiple APIs.

Use --url only when you intentionally want all workflow steps to use one replacement backend, such as a staging environment:

docker run --rm \
-v "$PWD:/specs:ro" \
hapimcp/hapi-cli:workflows \
workflows serve --specs /specs/workflow.yaml \
--url https://staging.example.com

Persist HAPI state

Mount a host directory at /var/lib/hapi to retain local specifications and configuration between runs:

docker run --rm \
-v "$HOME/.hapi:/var/lib/hapi" \
hapimcp/hapi-cli:workflows plugins list

You can place documents under $HAPI_HOME/specs and refer to them by filename:

docker run --rm \
-v "$HOME/.hapi:/var/lib/hapi" \
hapimcp/hapi-cli:workflows \
serve --specs petstore.yaml

If a mounted directory is not writable by the container user, use a read-only mount for documents (:ro) or adjust the directory ownership before mounting it as HAPI home.

View logs and health

docker logs -f hapi-workflows
curl http://localhost:3000/health

Docker Compose

services:
hapi-workflows:
image: hapimcp/hapi-cli:workflows
ports:
- "3000:3000"
volumes:
- ./specs:/specs:ro
- hapi-home:/var/lib/hapi
command:
- workflows
- serve
- --specs
- /specs/workflow.yaml
- --host
- 0.0.0.0
- --public-host
- http://localhost:3000
restart: unless-stopped

volumes:
hapi-home:

Start it with:

docker compose up -d
docker compose logs -f hapi-workflows

Air-gapped deployments

Pull and save the image on a connected machine:

docker pull hapimcp/hapi-cli:1.0.0-beta.0823
docker save hapimcp/hapi-cli:1.0.0-beta.0823 -o hapi-cli-v1-beta.tar

Load it on the disconnected machine:

docker load -i hapi-cli-v1-beta.tar

Mount the Arazzo and OpenAPI documents that the workflow needs. In a fully offline environment, do not use remote --specs values or remote sourceDescriptions; use local, mounted documents instead.

References