Skip to main content

ansible-flow-mcp

Give agents Ansible. Not the keys.

MCP server that exposes real Ansible modules and playbooks to AI agents — and a SSH hub/spoke fabric so multi-host automation is enrolled, bastion-scoped, and check-first by default.

Hero: agent hub session and enrolled inventory rail

Track What you get
Agent loop search → schema → check → execute on allowlisted collections
Fleet fabric One hub · join tokens · SSH ForceCommand spokes · fixed inventory

OpenFlow dual-track · Campaign storyboard · Hub/spoke ops · Apache-2.0

Not affiliated with Red Hat or the Ansible project beyond using the public Ansible CLI and docs.

New here? Full step-by-step: docs/QUICKSTART.md — local MCP · compose lab · bare-metal hub/spoke · editor wiring.


Visual tour

Why it exists Agent loop
Why: god-mode control node vs enrolled bastion Agent ritual: search → schema → check → execute
Hub / spoke fabric Operators
SSH hub/spoke topology and enrollment Operator TUI, hub MCP tools, lab demo

Screenshots live in docs/images/campaign-*.png. Re-shoot from docs/campaign/ with ./capture.sh.


Why this exists

Agents on a god-mode control node invent inventory, reach for shell, and treat every worker as an entrypoint. That is not a security model.

Without a fabric vs ansible-flow-mcp controls

You need this when:

  • You want Cursor / Claude / OpenCode to run Ansible like an operator, not freestyle root across the fleet
  • Multi-host must mean bastion ops you already understand (SSH, inventory, enrollment) — not a mesh hop plane
  • Prompt injection will still ask for bad ops — policy and topology must refuse

Two tracks

1. Agent loop — search → schema → check → execute

Curated module gallery. Slim argSpec before any run. Check mode default. Free-form modules denied. Playbooks path-jailed.

Agent ritual and MCP tools

Tool Purpose
search_modules Gallery search
get_module_schema Slim argSpec for FQCN
run_module Ad-hoc Ansible (check_mode default true)
run_playbook ansible-playbook on a path-jailed .yml
list_collections Collections in gallery

Ritual (modules): search_modulesget_module_schemarun_module(..., check_mode=true) → apply only if appropriate.

Ritual (playbooks): confirm path under allowlisted roots → check → apply.

2. Hub/spoke — nothing is a target until enrolled

Secure multi-host mode: agent attaches to the hub only. Hub reaches spokes over SSH only. Spokes execute localhost and cannot lateral-move via this fabric.

SSH hub/spoke topology and enrollment

Full mesh (withdrawn) Hub/spoke (shipped)
Worker compromise Could MCP-hop fleet-wide No lateral MCP
Inventory Gossip / replicas Hub is source of truth
Agent attach Any node Hub only
Ops model Mesh OS Classic Ansible bastion

Enrollment: hub initissue-token (TTL, one-time jti) → spoke join (token + SSH identity) → hub inventory. Runtime: ForceCommand MCP session — no shell on the hub→spoke path.

Hub tools: list_nodes / hub_status, issue_token, revoke_node, groups (create_group, set_group_members, …), spoke_call, plus catalog run_* against enrolled hosts or groups only. Client-supplied -i is rejected in hub mode.

Deep ops: docs/HUB.md.


Operators

Day-2 surface matches the agent: enroll, group, hand the hub to OpenCode.

Operator TUI, hub MCP tools, lab demo

ansible-flow-mcp hub init --name ctrl-01
ansible-flow-mcp hub issue-token --name web-03 --ttl 15m
ansible-flow-mcp spoke join --token "$TOKEN" --hub user@hub:22 --public-addr web-03.example.com
ansible-flow-mcp hub session          # MCP stdio for the agent
ansible-flow-mcp tui                  # servers · groups · invite · OpenCode
ansible-flow-mcp hub spoke-call --node web-03 --tool list_collections

Lab one-shot

cd lab && ./scripts/demo.sh
# then: ./scripts/tui.sh  |  ./scripts/opencode-host.sh

See lab/README.md.


Quick start

Full guide (all paths, verify, troubleshooting): docs/QUICKSTART.md

Path Guide section
Local MCP + Cursor/Claude Path A
Compose lab (hub + 3 spokes) Path B
Bare-metal hub/spoke Path C

Single-node / dev (short form)

Requirements: Python ≥ 3.11 · ansible-core on PATH · collection ansible.posix · collections you will run.

python3 -m pip install --user 'ansible-core>=2.16,<2.19'
export PATH="$HOME/.local/bin:$PATH"
ansible-galaxy collection install ansible.posix

cd ansible-flow-mcp
python -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"
pytest -q
ansible-flow-mcp

Editor snippets: examples/cursor-mcp.json, examples/claude-desktop.json.
Hub + OpenCode: examples/opencode-hub.jsonc · ansible-flow-mcp hub write-opencode-config.

{
  "mcpServers": {
    "ansible-flow": {
      "command": "/path/to/ansible-flow-mcp/.venv/bin/ansible-flow-mcp"
    }
  }
}

Security (honest)

Control Behavior
Collection allowlist Only configured collections
Module deny list command / shell / raw / script denied by default
Check mode Default true on run_module
Playbook jail Allowlisted roots · size limit · .yml/.yaml only
No shell interpolation argv-only subprocess
Hub inventory Enrolled hosts only · no client -i · host key checking on
Spoke path SSH ForceCommand · localhost exec · no peer fabric

Residual: hub compromise = fleet (same class as any Ansible control node). Harden the bastion — see docs/SECURITY.md and docs/HUB.md.


Catalog & OpenFlow

  • catalog/collections-allowlist.yml — allowlist + deny free-form modules
  • catalog/gallery.json + catalog/schemas/ — searchable gallery
  • Regenerate: python scripts/generate_catalog.py
  • Galaxy factory TUI: scripts/factory/README.md

Dual-tracked with OpenFlow Ansible canvas gallery
(plan · umbrella).

OpenFlow This MCP server
Palette Ansible gallery search_modules
Form | JSON module options get_module_schema + run_module
Playbook resource run_playbook
Control-node SSH / become Inventory + Ansible config · hub→spoke SSH in hub mode

Env (common)

Variable Meaning
ANSIBLE_FLOW_CATALOG_DIR Override catalog path
ANSIBLE_FLOW_COLLECTIONS Comma-separated allowlist override
ANSIBLE_FLOW_INVENTORY Default -i (non-hub / dev)
ANSIBLE_FLOW_TIMEOUT Seconds (default 120 module / 300 playbook)
ANSIBLE_FLOW_PLAYBOOK_ROOTS Extra playbook roots (:-separated)
ANSIBLE_FLOW_HUB_DIR Hub state (default: /var/lib/… if writable, else ~/.local/share/ansible-flow/hub)
ANSIBLE_FLOW_SPOKE_DIR Spoke state (same pattern under …/spoke)

License & publish

Apache-2.0

pip install build twine && python -m build
# twine upload dist/*
uvx --from ansible-flow-mcp ansible-flow-mcp

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

ansible_flow_mcp-0.1.2.tar.gz (7.2 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

ansible_flow_mcp-0.1.2-py3-none-any.whl (13.6 MB view details)

Uploaded Python 3

File details

Details for the file ansible_flow_mcp-0.1.2.tar.gz.

File metadata

  • Download URL: ansible_flow_mcp-0.1.2.tar.gz
  • Upload date:
  • Size: 7.2 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for ansible_flow_mcp-0.1.2.tar.gz
Algorithm Hash digest
SHA256 e3a5c52c63f9828b84757801c1826d507749b47d771992b2b0cbc4eb793f7a36
MD5 2103d9af5695c5f1822c2172265f9c97
BLAKE2b-256 aedf403f83a36aa72108fe09e369820ddd3f9e3e234d2d99d3698c7dc0c723fc

See more details on using hashes here.

Provenance

The following attestation bundles were made for ansible_flow_mcp-0.1.2.tar.gz:

Publisher: publish.yml on real-limitless/ansible-flow-mcp

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file ansible_flow_mcp-0.1.2-py3-none-any.whl.

File metadata

File hashes

Hashes for ansible_flow_mcp-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 310cba1ee7be548b309edb0b0c03709f8fb4cbc0eeabd30d5109331e42a73748
MD5 bf6a4589ead8dccc872ce6f137d6aca1
BLAKE2b-256 1c9d6522c63937b6055a133564bf72ede79fb7d88f84d94383e36eef43f3b117

See more details on using hashes here.

Provenance

The following attestation bundles were made for ansible_flow_mcp-0.1.2-py3-none-any.whl:

Publisher: publish.yml on real-limitless/ansible-flow-mcp

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page