Arcane MCP
AI-powered Docker management server that enables natural language control of environments, containers, images, networks, volumes, and more through a unified Arcane API interface.
README
Arcane MCP
TypeScript MCP server for the Arcane Docker management API. Exposes a single arcane tool that routes all Docker environment, project, container, image, network, volume, system, registry, image-update, vulnerability, and GitOps operations through the Arcane service.
Overview
Arcane MCP wraps the Arcane REST API behind a Model Context Protocol interface. An AI agent calls the arcane tool with an action and subaction. The server authenticates the request, enforces a confirmation gate on destructive operations, routes to the appropriate backend service, and returns JSON.
The server ships two MCP tools:
| Tool | Purpose |
|---|---|
arcane |
Unified action/subaction router for all Arcane API operations |
arcane_help |
Returns the full action/subaction reference as formatted text |
Tools
arcane
Call this tool with action, subaction, and optional envId, id, and params.
{
"action": "container",
"subaction": "list",
"envId": "env-abc123"
}
Parameter rules
| Parameter | Type | Description |
|---|---|---|
action |
string (enum) | Resource family: environment, project, container, image, network, volume, system, image-update, vulnerability, registry, gitops |
subaction |
string (enum) | Operation to perform (see per-family tables below) |
envId |
string (optional) | Target environment ID. Required by all families except registry. For environment subactions, envId and id are interchangeable for single-resource ops. |
id |
string (optional) | Resource ID for single-resource operations (get, delete, etc.) |
params |
object (optional) | Operation-specific payload. Pass { "confirm": true } to authorize a destructive operation without elicitation. |
Destructive operation gate
Any operation in the DESTRUCTIVE set (listed per family below) is blocked unless one of three conditions is met:
ARCANE_MCP_ALLOW_DESTRUCTIVE=true— all destructive ops auto-confirm, no re-call needed.ARCANE_MCP_ALLOW_YOLO=true— skips the interactive elicitation prompt; the tool must still be re-called withparams: { "confirm": true }to proceed.- Default — if the MCP client supports elicitation forms, the server prompts the user interactively. If the client does not support elicitation, the server returns a prompt asking for a re-call with
params: { "confirm": true }.
Action families
environment
Top-level Docker host connections. envId and id are interchangeable for single-resource operations.
| Subaction | Description | Destructive |
|---|---|---|
list |
List all environments | |
get |
Get an environment by ID | |
create |
Create a new environment; pass params with apiUrl, apiKey, and optional name, enabled, isEdge |
|
update |
Update environment settings; pass params with fields to change |
|
delete |
Permanently delete an environment | yes |
test |
Test the environment's API connection |
Example:
{"action": "environment", "subaction": "list"}
{"action": "environment", "subaction": "get", "id": "env-abc123"}
{"action": "environment", "subaction": "create", "params": {"apiUrl": "https://host.example.com", "apiKey": "..."}}
{"action": "environment", "subaction": "delete", "id": "env-abc123", "params": {"confirm": true}}
project
Docker Compose stacks running inside an environment. Requires envId.
| Subaction | Description | Destructive |
|---|---|---|
list |
List all projects in the environment | |
get |
Get a project by ID | |
create |
Create a project; pass params with name, composeContent, and optional envContent |
|
update |
Update a project; pass params with composeContent, envContent, or name |
|
up |
Start a project (docker compose up) | |
down |
Stop a project (docker compose down) | yes |
restart |
Restart all containers in the project | yes |
pull |
Pull latest images without restarting | |
destroy |
Stop and remove containers, networks, volumes created by the compose file | yes |
redeploy |
Pull images and recreate the project | yes |
build |
Build images for the project; pass optional params with services, provider, push, load |
Example:
{"action": "project", "subaction": "list", "envId": "env-abc123"}
{"action": "project", "subaction": "up", "envId": "env-abc123", "id": "my-stack"}
{"action": "project", "subaction": "down", "envId": "env-abc123", "id": "my-stack", "params": {"confirm": true}}
{"action": "project", "subaction": "build", "envId": "env-abc123", "id": "my-stack", "params": {"services": ["web"], "push": true}}
container
Individual Docker containers inside an environment. Requires envId.
Note: container logs are not available via the Arcane REST API. Use the Arcane web UI or docker logs directly.
| Subaction | Description | Destructive |
|---|---|---|
list |
List all containers | |
get |
Get a container by ID | |
create |
Create a container; pass params with name, image, and optional cmd, env, ports, volumes, restartPolicy, labels, memory, cpus, privileged |
|
start |
Start a stopped container | |
stop |
Stop a running container | yes |
restart |
Restart a container | yes |
update |
Re-pull the container's image and recreate it using its existing config. No params accepted. | |
delete |
Remove a container | yes |
stats |
Get CPU, memory, and network stats for all containers in the environment |
Example:
{"action": "container", "subaction": "list", "envId": "env-abc123"}
{"action": "container", "subaction": "stats", "envId": "env-abc123"}
{"action": "container", "subaction": "stop", "envId": "env-abc123", "id": "container-id", "params": {"confirm": true}}
{"action": "container", "subaction": "create", "envId": "env-abc123", "params": {"name": "nginx", "image": "nginx:latest", "ports": {"80/tcp": [{"HostPort": "8080"}]}}}
image
Docker images available in an environment. Requires envId.
| Subaction | Description | Destructive |
|---|---|---|
list |
List all images | |
get |
Get an image by ID | |
pull |
Pull an image; pass params with imageName and optional tag |
|
delete |
Delete an image by ID | yes |
prune |
Remove all unused images | yes |
scan |
Scan an image for vulnerabilities (triggers Trivy scan) |
Example:
{"action": "image", "subaction": "list", "envId": "env-abc123"}
{"action": "image", "subaction": "pull", "envId": "env-abc123", "params": {"imageName": "nginx", "tag": "latest"}}
{"action": "image", "subaction": "scan", "envId": "env-abc123", "id": "sha256:abc..."}
{"action": "image", "subaction": "prune", "envId": "env-abc123", "params": {"confirm": true}}
network
Docker networks in an environment. Requires envId.
| Subaction | Description | Destructive |
|---|---|---|
list |
List all networks | |
get |
Get a network by ID | |
create |
Create a network; pass params with name and options (driver, internal, enableIPv6, labels) |
|
delete |
Delete a network by ID | yes |
prune |
Remove all unused networks | yes |
Example:
{"action": "network", "subaction": "list", "envId": "env-abc123"}
{"action": "network", "subaction": "create", "envId": "env-abc123", "params": {"name": "my-net", "options": {"driver": "bridge"}}}
{"action": "network", "subaction": "prune", "envId": "env-abc123", "params": {"confirm": true}}
volume
Docker volumes in an environment, with full backup and restore support. Requires envId.
| Subaction | Description | Destructive |
|---|---|---|
list |
List all volumes | |
get |
Get a volume by name | |
create |
Create a volume; pass params with name and optional driver, driverOpts, labels |
|
delete |
Delete a volume by name | yes |
prune |
Remove all unused volumes | yes |
browse |
Browse a volume's directory tree; pass optional params.path (relative, no .. allowed) |
|
list-backups |
List all backups for a volume; requires id (volume name) |
|
create-backup |
Create a new backup snapshot; requires id (volume name) |
|
delete-backup |
Delete a backup by ID; pass params.backupId |
yes |
restore |
Restore a volume to a backup state; requires id (volume name) and params.backupId |
yes |
restore-files |
Restore specific files from a backup; requires id, params.backupId, and params.paths (string array) |
yes |
Volume backup/restore workflow
- List available backups:
subaction=list-backups,id=<volumeName> - Create a new snapshot:
subaction=create-backup,id=<volumeName> - Inspect a backup's contents: use
list-backupsto get the backup ID, thenrestore-fileswithparams.paths - Full restore:
subaction=restore,id=<volumeName>,params: { backupId: "...", confirm: true } - Partial restore:
subaction=restore-files,id=<volumeName>,params: { backupId: "...", paths: ["data/config.json"], confirm: true } - Remove old snapshot:
subaction=delete-backup,params: { backupId: "...", confirm: true }
Example:
{"action": "volume", "subaction": "list-backups", "envId": "env-abc123", "id": "my-data-vol"}
{"action": "volume", "subaction": "create-backup", "envId": "env-abc123", "id": "my-data-vol"}
{"action": "volume", "subaction": "restore", "envId": "env-abc123", "id": "my-data-vol", "params": {"backupId": "bkp-xyz", "confirm": true}}
{"action": "volume", "subaction": "restore-files", "envId": "env-abc123", "id": "my-data-vol", "params": {"backupId": "bkp-xyz", "paths": ["etc/app.conf"], "confirm": true}}
{"action": "volume", "subaction": "browse", "envId": "env-abc123", "id": "my-data-vol", "params": {"path": "etc"}}
system
Docker daemon-level operations for an environment. Requires envId.
| Subaction | Description | Destructive |
|---|---|---|
docker-info |
Get Docker daemon info (version, runtime, resources) | |
start-all |
Start all projects in the environment | |
stop-all |
Stop all projects in the environment | yes |
prune |
Prune unused Docker resources; pass params with boolean flags: containers, images, networks, volumes, buildCache, dangling |
yes |
convert |
Convert a docker run command to Docker Compose YAML; pass params.dockerRunCommand |
Example:
{"action": "system", "subaction": "docker-info", "envId": "env-abc123"}
{"action": "system", "subaction": "prune", "envId": "env-abc123", "params": {"containers": true, "images": true, "networks": true, "volumes": false, "buildCache": true, "dangling": true, "confirm": true}}
{"action": "system", "subaction": "convert", "envId": "env-abc123", "params": {"dockerRunCommand": "docker run -d -p 80:80 nginx"}}
image-update
Check whether images have newer versions available. Requires envId. Long-running checks use a 120-second timeout.
| Subaction | Description |
|---|---|
check-all |
Check all images in the environment for updates; pass optional params.credentials for private registries |
check |
Check a single image; pass either id (Arcane image ID) or params.imageRef (e.g. nginx:latest) |
check-batch |
Check multiple images; pass params.imageRefs (string array) and optional params.credentials |
summary |
Get a summary count: total images, images with updates, digest-only updates, errors |
The check subaction resolves the target in this order: id (Arcane internal imageId) → params.imageRef (image reference string). Passing both is undefined behavior; use one or the other.
Example:
{"action": "image-update", "subaction": "summary", "envId": "env-abc123"}
{"action": "image-update", "subaction": "check", "envId": "env-abc123", "params": {"imageRef": "nginx:latest"}}
{"action": "image-update", "subaction": "check", "envId": "env-abc123", "id": "img-abc123"}
{"action": "image-update", "subaction": "check-batch", "envId": "env-abc123", "params": {"imageRefs": ["nginx:latest", "redis:7"]}}
{"action": "image-update", "subaction": "check-all", "envId": "env-abc123"}
vulnerability
Image vulnerability scanning powered by Trivy. Requires envId.
| Subaction | Description |
|---|---|
summary |
Get counts by severity (critical, high, medium, low, unknown) across all scanned images |
list |
List all vulnerability entries with full CVE detail |
scanner-status |
Get the Trivy scanner's current operational status |
ignore |
Add a vulnerability to the ignore list; pass params with imageId, vulnerabilityId, pkgName, and optional installedVersion, reason |
unignore |
Remove an ignore entry; pass id (ignoreId) |
list-ignored |
List all active ignore entries |
Example:
{"action": "vulnerability", "subaction": "summary", "envId": "env-abc123"}
{"action": "vulnerability", "subaction": "list", "envId": "env-abc123"}
{"action": "vulnerability", "subaction": "ignore", "envId": "env-abc123", "params": {"imageId": "img-abc", "vulnerabilityId": "CVE-2024-1234", "pkgName": "openssl", "reason": "mitigated"}}
{"action": "vulnerability", "subaction": "unignore", "envId": "env-abc123", "id": "ignore-entry-id"}
registry
Container registry credentials. Global resource — envId is not required and is ignored.
| Subaction | Description | Destructive |
|---|---|---|
list |
List all configured registries | |
get |
Get a registry by ID | |
create |
Add a registry; pass params with url, username, token, and optional description, enabled, insecure |
|
update |
Update a registry; pass id and params with fields to change (url, username, token, description, enabled, insecure) |
|
delete |
Remove a registry | yes |
test |
Test connectivity to the registry |
Example:
{"action": "registry", "subaction": "list"}
{"action": "registry", "subaction": "create", "params": {"url": "registry.example.com", "username": "myuser", "token": "...", "enabled": true}}
{"action": "registry", "subaction": "test", "id": "reg-abc123"}
{"action": "registry", "subaction": "delete", "id": "reg-abc123", "params": {"confirm": true}}
gitops
Git-backed Compose deployment syncs. Requires envId.
Warning: gitops:sync pulls from a remote repository and applies changes. This is a supply chain risk if the repository is compromised. Always confirm the sync target before proceeding.
| Subaction | Description | Destructive |
|---|---|---|
list |
List all GitOps sync configurations | |
get |
Get a sync configuration by ID | |
create |
Create a sync config; pass params with name, repositoryId, branch, composePath, and optional autoSync, syncInterval, projectName |
|
update |
Update a sync config; pass id and params with fields to change |
|
delete |
Delete a sync configuration | yes |
sync |
Trigger an immediate sync from the remote repository | yes |
status |
Get the sync's last run status, commit, and next scheduled run | |
browse |
Browse the repository's file tree; pass optional params.path |
GitOps workflow
- List existing syncs:
subaction=list - Check a sync's state:
subaction=status,id=<syncId> - Inspect repository contents:
subaction=browse,id=<syncId> - Trigger a sync:
subaction=sync,id=<syncId>,params: { confirm: true }
Example:
{"action": "gitops", "subaction": "list", "envId": "env-abc123"}
{"action": "gitops", "subaction": "status", "envId": "env-abc123", "id": "sync-abc123"}
{"action": "gitops", "subaction": "browse", "envId": "env-abc123", "id": "sync-abc123"}
{"action": "gitops", "subaction": "sync", "envId": "env-abc123", "id": "sync-abc123", "params": {"confirm": true}}
{"action": "gitops", "subaction": "create", "envId": "env-abc123", "params": {"name": "prod-stack", "repositoryId": "repo-abc", "branch": "main", "composePath": "stacks/web/docker-compose.yml", "autoSync": true, "syncInterval": 300}}
Destructive operations reference
The following 22 operations require confirmation before execution:
| Action | Subaction |
|---|---|
environment |
delete |
project |
down, restart, destroy, redeploy |
container |
stop, restart, delete |
image |
delete, prune |
network |
delete, prune |
volume |
delete, prune, delete-backup, restore, restore-files |
system |
prune, stop-all |
registry |
delete |
gitops |
delete, sync |
Installation
Plugin marketplace
/plugin marketplace add jmagar/claude-homelab
/plugin install arcane-mcp @jmagar-claude-homelab
Local development
npm install
npm run build
npm start
For watch mode:
just dev
Docker
just up
just logs
Configuration
Copy .env.example to .env and fill in the required values:
cp .env.example .env
chmod 600 .env
Environment variables
| Variable | Required | Default | Description |
|---|---|---|---|
ARCANE_API_URL |
yes | — | Base URL of your Arcane instance, e.g. https://arcane.example.com |
ARCANE_API_KEY |
yes | — | API key from Arcane Settings > API |
ARCANE_MCP_TOKEN |
yes | — | Bearer token for MCP server auth. Generate with: openssl rand -hex 32 |
ARCANE_MCP_BIND_PORT |
no | 3000 |
Internal container port the server binds to |
ARCANE_MCP_PORT |
no | 44332 |
Host-side Docker port mapping |
ARCANE_MCP_TRANSPORT |
no | http |
Transport mode: http or stdio |
ARCANE_MCP_AUTH_ENABLED |
no | true |
Set to false to disable Bearer auth (use only behind a trusted proxy) |
ARCANE_MCP_ALLOW_YOLO |
no | false |
true skips elicitation prompts; re-call with params: { confirm: true } is still required |
ARCANE_MCP_ALLOW_DESTRUCTIVE |
no | false |
true auto-confirms all destructive operations. Use only in fully trusted automated environments. |
LOG_LEVEL |
no | info |
Pino log level: trace, debug, info, warn, error |
Safety flag behavior
ARCANE_MCP_ALLOW_YOLO and ARCANE_MCP_ALLOW_DESTRUCTIVE control the confirmation gate independently:
- Both
false(default): destructive ops show an elicitation dialog (if the MCP client supports it) or return a prompt to re-call withparams: { confirm: true }. ALLOW_YOLO=true: skips the elicitation dialog. The agent must still re-call withparams: { confirm: true }.ALLOW_DESTRUCTIVE=true: bypasses the gate entirely. No re-call needed. Use in CI or fully automated pipelines only.
Authentication
All MCP endpoints require a Bearer token unless ARCANE_MCP_AUTH_ENABLED=false.
The following paths bypass authentication:
GET /health— health check, always unauthenticated/.well-known/*— RFC 9728 OAuth discovery endpoint; reserved for future OAuth resource metadata
All other paths, including /mcp, require Authorization: Bearer <ARCANE_MCP_TOKEN>.
Token comparison uses timingSafeEqual to prevent timing attacks.
Session management
The HTTP transport maintains per-session MCP server instances (up to 200 concurrent sessions). Sessions idle for more than 30 minutes are evicted. When the session cap is reached, the least-recently-used idle session is evicted first.
Clients that do not send an initialize request are bootstrapped into a pre-initialized session. These clients cannot use elicitation (the confirmation dialog) — they will always receive the "re-call with params: { confirm: true }" response for destructive operations.
Development commands
just dev # Start with watch-mode TypeScript compilation
just build # Compile TypeScript to dist/
just typecheck # Type-check without emitting
just lint # Run Biome linter
just fmt # Run Biome formatter
just test # Run unit tests with Vitest
just up # Start Docker Compose service
just down # Stop Docker Compose service
just logs # Tail container logs
just health # Check /health endpoint
just setup # Create .env from .env.example
just gen-token # Generate a random Bearer token
just clean # Remove dist/, .cache/, coverage/
Verification
After starting the server:
just typecheck
just lint
just test
just health
The health endpoint returns:
{"status": "ok", "service": "arcane-mcp"}
Related plugins
| Plugin | Category | Description |
|---|---|---|
| homelab-core | core | Core agents, commands, skills, and setup/health workflows for homelab management. |
| overseerr-mcp | media | Search movies and TV shows, submit requests, and monitor failed requests via Overseerr. |
| unraid-mcp | infrastructure | Query, monitor, and manage Unraid servers: Docker, VMs, array, parity, and live telemetry. |
| unifi-mcp | infrastructure | Monitor and manage UniFi devices, clients, firewall rules, and network health. |
| gotify-mcp | utilities | Send and manage push notifications via a self-hosted Gotify server. |
| swag-mcp | infrastructure | Create, edit, and manage SWAG nginx reverse proxy configurations. |
| synapse-mcp | infrastructure | Docker management (Flux) and SSH remote operations (Scout) across homelab hosts. |
| syslog-mcp | infrastructure | Receive, index, and search syslog streams from all homelab hosts via SQLite FTS5. |
| plugin-lab | dev-tools | Scaffold, review, align, and deploy homelab MCP plugins with agents and canonical templates. |
License
MIT
推荐服务器
Baidu Map
百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。
Playwright MCP Server
一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。
Magic Component Platform (MCP)
一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。
Audiense Insights MCP Server
通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。
VeyraX
一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。
graphlit-mcp-server
模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。
Kagi MCP Server
一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。
e2b-mcp-server
使用 MCP 通过 e2b 运行代码。
Neon MCP Server
用于与 Neon 管理 API 和数据库交互的 MCP 服务器
Exa MCP Server
模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。