3.8 KiB
3.8 KiB
Deploy Ansible MCP server on Watchtower
Purpose
Deploy a custom Ansible MCP server on Watchtower so AI tools can query inventory, validate syntax, and run allowlisted playbooks through guarded tool calls.
Scope
- Host:
watchtowerinventory group - Playbook:
ansible/playbooks/ai/deploy_ansible_mcp_watchtower.yml - Runtime path:
/opt/ansible-mcp - Service name:
ansible-mcp - State and logs:
/var/lib/ansible-mcp
Features delivered
- MCP tools:
healthlist_inventoryvalidate_syntaxrun_playbookget_job_statuscancel_job
- Path guardrails for playbook execution (allowlisted directories only)
- Optional explicit playbook allowlist for high-trust execution scopes
- Write-mode guardrails:
- global write toggle
- explicit confirm gate for write actions
- Auth guardrail:
- bearer token required when
ANSIBLE_MCP_API_TOKENis configured
- bearer token required when
- Input guardrails:
- max
extra_varspayload size - blocked
extra_varskey list
- max
- Background run tracking with per-run logs and status records
- JSONL audit records at
/var/lib/ansible-mcp/audit/events.jsonl
Prerequisites
- Watchtower host is reachable from control node.
- Python 3 is installed on Watchtower.
- Inventory contains a valid
watchtowergroup. - Ansible control node has access to this repository at
/home/chester/homelab.
Deploy
Run from ansible/:
cd /home/chester/homelab/ansible
export ANSIBLE_MCP_API_TOKEN='set-a-strong-token-before-deploy'
ansible-playbook -i inventory/hosts.ini playbooks/ai/deploy_ansible_mcp_watchtower.yml
Validate only:
cd /home/chester/homelab/ansible
ansible-playbook -i inventory/hosts.ini playbooks/ai/deploy_ansible_mcp_watchtower.yml --check
Runtime configuration
The playbook sets these environment variables in the systemd unit:
ANSIBLE_MCP_REPO_ROOT=/home/chester/homelab/ansibleANSIBLE_MCP_INVENTORY=inventory/hosts.iniANSIBLE_MCP_ALLOWED_PLAYBOOK_DIRS=playbooksANSIBLE_MCP_ALLOWED_PLAYBOOKS=(optional comma-separated explicit allowlist)ANSIBLE_MCP_API_TOKEN=<token>(required for HTTP transport in current playbook)ANSIBLE_MCP_ALLOW_WRITE=trueANSIBLE_MCP_REQUIRE_CONFIRM=trueANSIBLE_MCP_DEFAULT_TIMEOUT=900ANSIBLE_MCP_MAX_TIMEOUT=3600ANSIBLE_MCP_MAX_EXTRA_VARS_BYTES=16384ANSIBLE_MCP_BLOCKED_EXTRA_VARS_KEYS=ansible_password,ansible_become_password,vault_passwordANSIBLE_MCP_STATE_DIR=/var/lib/ansible-mcpANSIBLE_MCP_TRANSPORT=streamable-httpANSIBLE_MCP_HOST=0.0.0.0ANSIBLE_MCP_PORT=8449
Verify
# Service state
sudo systemctl status ansible-mcp --no-pager
# Recent logs
sudo journalctl -u ansible-mcp -n 80 --no-pager
# Listening port
ss -ltnp | grep 8449
Client connection example
For MCP clients that support HTTP transport:
{
"mcpServers": {
"ansible-watchtower": {
"type": "http",
"url": "http://10.0.0.200:8449/mcp",
"headers": {
"Authorization": "Bearer ${env:ANSIBLE_MCP_API_TOKEN}"
}
}
}
}
If you terminate TLS upstream (recommended), expose this endpoint through your existing ingress and use an HTTPS URL.
Operational safety notes
- Keep
ANSIBLE_MCP_REQUIRE_CONFIRM=truein write mode. - Keep
ANSIBLE_MCP_API_TOKENset and rotate it regularly. - Prefer explicit
ANSIBLE_MCP_ALLOWED_PLAYBOOKSover broad directory allowlists. - Restrict
ANSIBLE_MCP_ALLOWED_PLAYBOOK_DIRSto known-safe playbook roots. - Do not grant broad filesystem access to the service user.
- Treat background run logs in
/var/lib/ansible-mcp/logsas audit artifacts.
Rollback
sudo systemctl disable --now ansible-mcp
sudo rm -f /etc/systemd/system/ansible-mcp.service
sudo systemctl daemon-reload
Optional cleanup:
sudo rm -rf /opt/ansible-mcp /var/lib/ansible-mcp