Version: 1.0.0
Documentation — Installation, deployment, usage across the API, CLI, and MCP interfaces, the integrated A2A agent server, and guidance on the backing Docker Hub platform are maintained in docs/.
- Overview
- Key Features
- Installation
- Usage
- Environment Variables
- Deployment
- Safety Model
- Concepts
- License
Dockerhub Api is a production-grade Agent and Model Context Protocol (MCP) server
that wraps the official Docker Hub API v2 (https://hub.docker.com): repositories
and tags, immutable tags, personal and organization access tokens, organization
members/settings/invites, teams, audit logs, and SCIM 2.0 provisioning — plus the
Registry HTTP API v2 (registry-1.docker.io: manifests, blobs, digests,
multi-arch inspection, OCI referrers, and gated push/delete) and Docker Scout
(api.scout.docker.com: CVE/SBOM/policy intelligence).
- Consolidated Action-Routed MCP Tools: Nine togglable tool modules
(
hub_auth,hub_repos,hub_org,hub_teams,hub_audit,hub_scim,hub_admin,hub_registry,hub_scout) minimize token overhead in LLM contexts. - Three API surfaces, one package: the Hub management API, the Registry v2 image API (its own host + per-repository scoped-token auth), and Docker Scout — each with the same uniform envelope, redaction, and gating.
- JWT Auth Lifecycle: Short-lived bearer minted from
POST /v2/auth/token(password, PATdckr_pat_*, or org access token), cached and refreshed before expiry, with one transparent re-mint on 401. - Rate-Limit Telemetry:
X-RateLimit-*headers surfaced in every result; HTTP 429 retried with boundedRetry-Afterbackoff. - Safety by Default: Deletes and org-settings writes are gated behind
DOCKERHUB_ALLOW_DESTRUCTIVE(defaultFalse); secrets are redacted from tool results (plaintext tokens appear exactly once — on creation). Repository creation stays enabled: it is the primary release-provisioning use case. - Integrated Graph Agent: Built-in Pydantic AI agent (
dockerhub-agent) with A2A and AG-UI web interfaces. - Native Telemetry & Tracing: Out-of-the-box OpenTelemetry exports and Langfuse tracing via agent-utilities.
pip install dockerhub-api # API client only
pip install "dockerhub-api[mcp]" # + MCP server
pip install "dockerhub-api[agent]" # + A2A agent server
pip install "dockerhub-api[all]" # everything| Extra | Adds |
|---|---|
mcp |
FastMCP server (dockerhub-mcp) via agent-utilities[mcp] |
agent |
Pydantic-AI A2A agent (dockerhub-agent) + Logfire via agent-utilities[agent,logfire] |
all |
mcp + agent |
test |
pytest toolchain for development |
# MCP server only (recommended for tool hosting — slim deps)
uv pip install "dockerhub-api[mcp]"
# Full agent runtime (Pydantic AI + epistemic-graph engine)
uv pip install "dockerhub-api[agent]"
# Everything (development)
uv pip install "dockerhub-api[all]" # or: python -m pip install "dockerhub-api[all]"One multi-stage docker/Dockerfile builds two right-sized images, selected by --target:
| Image tag | Build target | Contents | Entrypoint |
|---|---|---|---|
knucklessg1/dockerhub-api:mcp |
--target mcp |
dockerhub-api[mcp] — slim, no engine/pydantic-ai/dspy/llama-index/tree-sitter |
dockerhub-mcp |
knucklessg1/dockerhub-api:latest |
--target agent (default) |
dockerhub-api[agent] — full agent runtime + epistemic-graph engine |
dockerhub-agent |
docker build --target mcp -t knucklessg1/dockerhub-api:mcp docker/ # slim MCP server
docker build --target agent -t knucklessg1/dockerhub-api:latest docker/ # full agentdocker/mcp.compose.yml runs the slim :mcp server; docker/agent.compose.yml runs the
agent (:latest) with a co-located :mcp sidecar.
The full agent ([agent] / :latest) embeds the epistemic-graph engine (pulled in
transitively via agent-utilities[agent]). For production — or to share one knowledge graph
across multiple agents — run epistemic-graph as its own database container and point the
agent at it instead of embedding it. Deployment recipes (single-node + Raft HA), connection
config, and the full database architecture (with diagrams) are documented in the
epistemic-graph deployment guide.
The slim [mcp] server does not require the database.
from dockerhub_api.auth import get_client
api = get_client() # reads DOCKERHUB_URL / DOCKER_HUB_USER / DOCKER_HUB_TOKEN
repos = api.get_repositories(namespace="acme", ordering="-last_updated")
api.create_repository(namespace="acme", name="release-images", is_private=True)
tags = api.get_repository_tags(namespace="acme", repository="release-images")
print(api.rate_limit) # latest X-RateLimit-* snapshotEvery client method returns a uniform envelope:
{"status_code": int, "data": ..., "rate_limit": {"limit", "remaining", "reset"}}.
Auto-generated — do not edit (synced by the mcp-readme-table pre-commit hook).
| MCP Tool | Toggle Env Var | Description |
|---|---|---|
hub_admin |
ADMINTOOL |
Client diagnostics: 'rate_limit' returns the latest |
hub_audit |
AUDITTOOL |
Read a Docker Hub account's audit trail: 'logs' lists events |
hub_auth |
AUTHTOOL |
Manage Docker Hub authentication, personal access tokens (PATs), |
hub_org |
ORGTOOL |
Manage a Docker Hub organization: settings (restricted images), |
hub_registry |
REGISTRYTOOL |
Docker Registry v2 image operations (registry-1.docker.io): |
hub_repos |
REPOSTOOL |
Manage Docker Hub repositories: list/create/inspect repositories, |
hub_scim |
SCIMTOOL |
Docker Hub SCIM 2.0: service discovery (ServiceProviderConfig, |
hub_scout |
SCOUTTOOL |
Docker Scout image intelligence (api.scout.docker.com): |
hub_teams |
TEAMSTOOL |
Manage Docker Hub organization groups (teams) and their members. |
54 per-operation tools — one per public API method (click to expand)
| MCP Tool | Toggle Env Var | Description |
|---|---|---|
dockerhub_add_group_member |
GROUPSTOOL |
Add a username to a group. |
dockerhub_assign_repository_group |
REPOSITORIESTOOL |
Grant a team (group) read/write/admin on a repository. |
dockerhub_bulk_invite |
ORGSTOOL |
Invite many users/emails at once (POST /v2/invites/bulk). |
dockerhub_check_repository |
REPOSITORIESTOOL |
HEAD existence check for a repository. |
dockerhub_check_repository_tag |
REPOSITORIESTOOL |
HEAD existence check for one tag. |
dockerhub_check_repository_tags |
REPOSITORIESTOOL |
HEAD check: does the repository have any tags? |
dockerhub_create_access_token |
ACCESS_TOKENSTOOL |
Create a personal access token. |
dockerhub_create_auth_token |
AUTHTOOL |
Mint a short-lived JWT bearer from an identifier + secret. |
dockerhub_create_group |
GROUPSTOOL |
Create a group (team) in an organization. |
dockerhub_create_org_access_token |
ORG_ACCESS_TOKENSTOOL |
Create an organization access token. |
dockerhub_create_repository |
REPOSITORIESTOOL |
Create an image repository in a namespace. |
dockerhub_create_scim_user |
SCIMTOOL |
Provision a SCIM user. |
dockerhub_delete_access_token |
ACCESS_TOKENSTOOL |
Delete a personal access token. Destructive — gated. |
dockerhub_delete_group |
GROUPSTOOL |
Delete a group. Destructive — gated. |
dockerhub_delete_invite |
ORGSTOOL |
Cancel an invite. Destructive — gated. |
dockerhub_delete_org_access_token |
ORG_ACCESS_TOKENSTOOL |
Delete an organization access token. Destructive — gated. |
dockerhub_export_org_members |
ORGSTOOL |
Export the member list as CSV (GET /members/export). |
dockerhub_get_access_token |
ACCESS_TOKENSTOOL |
Get one personal access token by UUID. |
dockerhub_get_access_tokens |
ACCESS_TOKENSTOOL |
List the personal access tokens of the authenticated user. |
dockerhub_get_audit_log_actions |
AUDIT_LOGSTOOL |
List the audit-log action names available for a namespace. |
dockerhub_get_audit_logs |
AUDIT_LOGSTOOL |
List audit-log events for a namespace. |
dockerhub_get_group |
GROUPSTOOL |
Get one group. |
dockerhub_get_group_members |
GROUPSTOOL |
List a group's members. |
dockerhub_get_groups |
GROUPSTOOL |
List an organization's groups (teams). |
dockerhub_get_org_access_token |
ORG_ACCESS_TOKENSTOOL |
Get one organization access token by id. |
dockerhub_get_org_access_tokens |
ORG_ACCESS_TOKENSTOOL |
List an organization's access tokens. |
dockerhub_get_org_invites |
ORGSTOOL |
List an organization's pending invites. |
dockerhub_get_org_members |
ORGSTOOL |
List organization members (filter by search/type/role; paginated). |
dockerhub_get_org_settings |
ORGSTOOL |
Get an organization's settings (restricted images policy). |
dockerhub_get_repositories |
REPOSITORIESTOOL |
List a namespace's repositories (name filter + ordering enum). |
dockerhub_get_repository |
REPOSITORIESTOOL |
Get one repository. |
dockerhub_get_repository_tag |
REPOSITORIESTOOL |
Get one tag. |
dockerhub_get_repository_tags |
REPOSITORIESTOOL |
List a repository's tags (paginated). |
dockerhub_get_scim_resource_type |
SCIMTOOL |
Get one SCIM ResourceType by name. |
dockerhub_get_scim_resource_types |
SCIMTOOL |
List the SCIM ResourceTypes. |
dockerhub_get_scim_schema |
SCIMTOOL |
Get one SCIM Schema by id (URN). |
dockerhub_get_scim_schemas |
SCIMTOOL |
List the SCIM Schemas. |
dockerhub_get_scim_service_provider_config |
SCIMTOOL |
Get the SCIM ServiceProviderConfig. |
dockerhub_get_scim_user |
SCIMTOOL |
Get one SCIM user by id. |
dockerhub_get_scim_users |
SCIMTOOL |
List SCIM users (startIndex/count/filter/sortBy/sortOrder). |
dockerhub_login |
AUTHTOOL |
Authenticate via the legacy login endpoint. |
dockerhub_patch_group |
GROUPSTOOL |
Partially update a group (PATCH). |
dockerhub_remove_group_member |
GROUPSTOOL |
Remove a username from a group. Destructive — gated. |
dockerhub_remove_org_member |
ORGSTOOL |
Remove a member from the organization. Destructive — gated. |
dockerhub_replace_scim_user |
SCIMTOOL |
Replace a SCIM user resource (PUT). |
dockerhub_resend_invite |
ORGSTOOL |
Resend an invite (PATCH /v2/invites/{id}/resend). |
dockerhub_two_factor_login |
AUTHTOOL |
Complete a 2FA login with the TOTP code (POST /v2/users/2fa-login). |
dockerhub_update_access_token |
ACCESS_TOKENSTOOL |
Patch a personal access token's label and/or active state. |
dockerhub_update_group |
GROUPSTOOL |
Replace a group's details (PUT). |
dockerhub_update_immutable_tags |
REPOSITORIESTOOL |
Patch a repository's immutable-tags settings. |
dockerhub_update_org_access_token |
ORG_ACCESS_TOKENSTOOL |
Patch an organization access token. |
dockerhub_update_org_member |
ORGSTOOL |
Set a member's org role (owner, editor, or member). |
dockerhub_update_org_settings |
ORGSTOOL |
Replace an organization's settings. Destructive — gated. |
dockerhub_verify_immutable_tags |
REPOSITORIESTOOL |
Verify immutable-tag rules without applying them. |
9 action-routed tool(s) (default) · 54 verbose 1:1 tool(s). Each is enabled unless its <DOMAIN>TOOL toggle is set false; MCP_TOOL_MODE selects the surface (condensed default · verbose 1:1 · both). Auto-generated — do not edit.
Install the slim
[mcp]extra. All examples below installdockerhub-api[mcp]— the MCP-server extra that pulls only the FastMCP / FastAPI tooling (agent-utilities[mcp]). It deliberately excludes the heavy agent runtime (the epistemic-graph engine,pydantic-ai,dspy,llama-index,tree-sitter), souvx/container installs are dramatically smaller and faster. Use the full[agent]extra only when you need the integrated Pydantic AI agent (see Installation).
Configure your IDE's mcp.json to launch the MCP server via uvx:
{
"mcpServers": {
"dockerhub-api": {
"command": "uvx",
"args": [
"--from",
"dockerhub-api[mcp]",
"dockerhub-mcp"
],
"env": {
"DOCKER_HUB_USER": "your_dockerhub_user_here",
"DOCKER_HUB_TOKEN": "your_dockerhub_token_here"
}
}
}
}hub_registry targets a different host and auth model than the other tools.
The Hub management API (hub.docker.com) uses one JWT from /v2/auth/token; the
Registry v2 API (registry-1.docker.io) authorizes each call with a
per-repository, per-action bearer obtained from a token service via a
401 WWW-Authenticate challenge. Both reuse the same DOCKER_HUB_USER /
DOCKER_HUB_TOKEN credentials (anonymous works for public pulls). Single-segment
repository names (e.g. nginx) are normalized to their official library/ path.
_catalog (registry-wide repository listing) is intentionally not implemented:
Docker Hub does not issue the registry-scoped token it requires. The chunked push
buffers each chunk in memory — it is intended for manifests, config, and
attestation blobs, not as a replacement for docker push of large layers.
from dockerhub_api.auth import get_registry_client, get_scout_client
reg = get_registry_client()
print(reg.inspect("nginx", "latest")["data"]["platforms"]) # multi-arch list
digest = reg.resolve_digest("nginx", "latest")["data"]["digest"]
print(reg.list_referrers("nginx", digest)["data"]) # SBOM/attestations
scout = get_scout_client()
print(scout.get_cves("myorg/app", reference="v1")["data"]) # CVE listingRun the server:
export DOCKER_HUB_USER=youruser
export DOCKER_HUB_TOKEN=dckr_pat_xxx
dockerhub-mcp --transport streamable-http --host 0.0.0.0 --port 8000dockerhub-agent --mcp-url http://localhost:8000/mcp --web| Variable | Example | Description |
|---|---|---|
HOST |
0.0.0.0 |
|
PORT |
8000 |
|
TRANSPORT |
stdio |
options: stdio, streamable-http, sse |
FASTMCP_LOG_LEVEL |
ERROR |
|
NO_COLOR |
1 |
|
TERM |
dumb |
forced to "dumb" by the server to disable ANSI/color output |
ENABLE_OTEL |
True |
|
OTEL_EXPORTER_OTLP_ENDPOINT |
http://localhost:8080/api/public/otel |
|
OTEL_EXPORTER_OTLP_PUBLIC_KEY |
pk-... |
|
OTEL_EXPORTER_OTLP_SECRET_KEY |
sk-... |
|
OTEL_EXPORTER_OTLP_PROTOCOL |
http/protobuf |
|
EUNOMIA_TYPE |
none |
options: none, embedded, remote |
EUNOMIA_POLICY_FILE |
mcp_policies.json |
|
EUNOMIA_REMOTE_URL |
http://eunomia-server:8000 |
|
DOCKER_HUB_USER |
— | Official hub-tool credential names (primary): |
DOCKER_HUB_TOKEN |
— | |
DOCKERHUB_URL |
https://hub.docker.com |
Fallback aliases: DOCKERHUB_USERNAME / DOCKERHUB_TOKEN / DOCKERHUB_JWT |
DOCKERHUB_USERNAME |
your_dockerhub_username |
|
DOCKERHUB_TOKEN |
dckr_pat_your_personal_access_token |
password, PAT, or org access token |
DOCKERHUB_JWT |
— | optional pre-minted bearer (overrides the above) |
DOCKERHUB_SSL_VERIFY |
True |
|
DOCKER_REGISTRY_URL |
https://registry-1.docker.io |
|
DOCKER_REGISTRY_AUTH_URL |
https://auth.docker.io/token |
token-service realm; auto-discovered from the 401 challenge |
DOCKER_SCOUT_URL |
https://api.scout.docker.com |
|
DOCKERHUB_ALLOW_DESTRUCTIVE |
False |
|
AUTHTOOL |
True |
|
REPOSTOOL |
True |
|
ORGTOOL |
True |
|
TEAMSTOOL |
True |
|
AUDITTOOL |
True |
|
SCIMTOOL |
True |
|
ADMINTOOL |
True |
|
REGISTRYTOOL |
True |
|
SCOUTTOOL |
True |
| Variable | Example | Description |
|---|---|---|
MCP_TOOL_MODE |
condensed |
Tool surface: condensed |
MCP_ENABLED_TOOLS |
— | Comma-separated tool allow-list |
MCP_DISABLED_TOOLS |
— | Comma-separated tool deny-list |
MCP_ENABLED_TAGS |
— | Comma-separated tag allow-list |
MCP_DISABLED_TAGS |
— | Comma-separated tag deny-list |
MCP_CLIENT_AUTH |
— | Outbound MCP auth (oidc-client-credentials for fleet calls) |
OIDC_CLIENT_ID |
— | OIDC client id (service-account auth) |
OIDC_CLIENT_SECRET |
— | OIDC client secret (service-account auth) |
DEBUG |
False |
Verbose logging |
PYTHONUNBUFFERED |
1 |
Unbuffered stdout (recommended in containers) |
MCP_URL |
http://localhost:8000/mcp |
URL of the MCP server the agent connects to |
PROVIDER |
openai |
LLM provider for the agent |
MODEL_ID |
gpt-4o |
Model id for the agent |
ENABLE_WEB_UI |
True |
Serve the AG-UI web interface |
34 package + 14 inherited variable(s). Auto-generated from .env.example + the shared agent-utilities set — do not edit.
| Variable | Default | Purpose |
|---|---|---|
DOCKERHUB_URL |
https://hub.docker.com |
Docker Hub API base URL |
DOCKER_HUB_USER |
— | Account identifier (official hub-tool name, primary) |
DOCKER_HUB_TOKEN |
— | Password, PAT dckr_pat_*, or org access token (primary) |
DOCKERHUB_USERNAME / DOCKERHUB_TOKEN |
— | Legacy fallback aliases for the two above |
DOCKERHUB_JWT |
— | Optional pre-minted bearer (overrides credential exchange) |
DOCKERHUB_SSL_VERIFY |
True |
TLS certificate verification |
DOCKERHUB_ALLOW_DESTRUCTIVE |
False |
Enable deletes and org-settings writes |
AUTHTOOL … ADMINTOOL |
True |
Per-module MCP tool toggles (see table above) |
HOST / PORT / TRANSPORT |
0.0.0.0 / 8000 / stdio |
MCP server bind & transport (stdio, streamable-http, sse) |
AUTH_TYPE |
none |
MCP server auth mode (Docker image) |
MCP_URL |
— | MCP endpoint the A2A agent connects to |
ENABLE_OTEL |
True |
OpenTelemetry / Langfuse export via agent-utilities |
EUNOMIA_TYPE / EUNOMIA_POLICY_FILE / EUNOMIA_REMOTE_URL |
none / mcp_policies.json / — |
Eunomia access-governance middleware |
FASTMCP_LOG_LEVEL / NO_COLOR |
— | FastMCP logging controls |
A complete annotated template lives in .env.example.
Docker Compose definitions ship in docker/:
cp .env.example .env # fill in DOCKER_HUB_USER / DOCKER_HUB_TOKEN
docker compose -f docker/mcp.compose.yml up -d # MCP server only
docker compose -f docker/agent.compose.yml up -d # MCP server + A2A agent (port 9018)Both services expose /health endpoints; see
docs/deployment.md for transports, Caddy ingress, and
Technitium DNS guidance.
dockerhub-api can also run as a local container (Docker / Podman / uv) or be
consumed from a remote deployment. The
Deployment guide has full, copy-paste
mcp_config.json for all four transports — stdio, streamable-http,
local container / uv, and remote URL:
- Local container / uv — launch the server from
mcp_config.jsonviauvx,docker run, orpodman run, or point at a local streamable-http container byurl. - Remote URL — connect to a server deployed behind Caddy at
http://dockerhub-mcp.arpa/mcpusing the"url"key.
| Operation class | Default | Override |
|---|---|---|
| Reads (repos, tags, members, logs, SCIM) | allowed | — |
| Repository create / immutable-tag config / invites / role updates | allowed | — |
| Deletes (PATs, OATs, groups, members, invites) | blocked | DOCKERHUB_ALLOW_DESTRUCTIVE=True |
Org-settings writes (PUT /v2/orgs/{org}/settings) |
blocked | DOCKERHUB_ALLOW_DESTRUCTIVE=True |
The concept registry (CONCEPT:HUB-1.x) is documented in
docs/concepts.md.
MIT — see LICENSE.
This package can be provisioned for you — skill-guided — by the agent-os-genesis
universal skill (its single-package deploy mode): it picks your install method, seeds
secrets to OpenBao/Vault (or .env), trusts your enterprise CA, registers the MCP
server, and verifies it — the same machinery that stands up the whole Agent OS, narrowed
to just this package. Ask your agent to "deploy dockerhub-api with agent-os-genesis".
| Install mode | Command |
|---|---|
| Bare-metal, prod (PyPI) | uvx dockerhub-mcp · or uv tool install dockerhub-api |
| Bare-metal, dev (editable) | uv pip install -e ".[all]" · or pip install -e ".[all]" |
| Container, prod | deploy knucklessg1/dockerhub-api:latest via docker-compose / swarm / podman / podman-compose / kubernetes |
| Container, dev (editable) | deploy docker/compose.dev.yml (source-mounted at /src; edits live on restart) |
Secrets are read-existing + seeded via vault_sync — you are only prompted for what's missing.