Skip to main content

Every Ansible module as a typed MCP tool

Project description

Rocannon

Rocannon turns any Ansible control node into an MCP server: it registers every installed module as a typed tool. It reads ansible-doc -j for each module at startup and builds a Pydantic-validated function signature, then exposes the result over the MCP protocol (stdio or HTTP). The tool surface is whatever you have installed, from one collection to a hundred. Any MCP client (Claude Code, Cursor, mcphost, custom agents) calls the same tools an operator would call from a REPL.

Each registered tool carries the module's own ansible-doc metadata: a JSON output schema for structured results, and MCP safety hints derived from the module's attributes (read-only for fact modules, destructive and open-world for command, shell, script, and raw).

Every module is also a top-level CLI subcommand:

rocannon ansible.builtin.command --target h1 --cmd 'uptime'
rocannon ansible.builtin.copy    --target h1 --src /etc/hosts --dest /tmp/h

Append --record path/to/runbook.yml to any invocation and Rocannon writes each call as a new play in a real Ansible playbook. The resulting file runs directly under ansible-playbook -i <inv> path/to/runbook.yml.

Add --check to preview a change without applying it (Ansible check mode) and --diff to see what would change. Each is offered per module according to its declared check-mode support, both on the CLI and as a parameter on the matching MCP tool. rocannon playbook run <name> --check previews an entire saved runbook.

Sessions driven via the MCP server save the same way: as Ansible playbooks under .rocannon/playbooks/. Rocannon also loads them back on next startup as MCP prompts.

demo

Claude Haiku, via the Claude Agent SDK, driving Rocannon's typed Ansible-module tools against a real RHEL 9 host in natural language.

Case studies

  • examples/case-study drives natural language into ad-hoc Ansible on a real RHEL 9 host: facts, a command, a config change, plus --check and replay as standard ansible-playbook.
  • examples/containerlab runs the same agent against a two-node Arista cEOS fabric, where the arista.eos modules become MCP tools.
  • examples/execution-environment bakes Rocannon into an Ansible Execution Environment for a frozen, reproducible tool set.

Install

pip install rocannon

This brings ansible-core and ansible-runner with it. rocannon doctor reports anything missing from the environment.

Quickstart

rocannon quickstart

This scaffolds a localhost profile (ansible_connection=local) under .rocannon/ and prints the exact wiring for your MCP client (Claude Code, Claude Desktop, Cursor) plus a rocannon mcp doctor command to confirm the tools register. Then ask your assistant something like "Gather facts from localhost and tell me the OS and kernel version."

To explore from a shell instead of an MCP client:

rocannon mcp doctor --profile .rocannon/quickstart.yml   # list registered tools
rocannon repl       --profile .rocannon/quickstart.yml   # operator shell

Inside the REPL:

rocannon> .target localhost
rocannon> ping
rocannon> command cmd="uptime"
rocannon> .save my_session
rocannon> .exit

.save writes .rocannon/playbooks/my_session.yml as a standard Ansible playbook. Run it directly with ansible-playbook -i hosts my_session.yml, or let Rocannon load it back as an MCP prompt next time the server starts.

CLI

rocannon quickstart    scaffold a localhost profile and print client wiring
rocannon <fqcn>        invoke a module: rocannon ansible.builtin.copy ...
                       optional --record FILE appends each call to a playbook
rocannon mcp serve     start the MCP server (stdio or http)
rocannon mcp doctor    list registered tools, resources, prompts
rocannon repl          interactive shell on the same MCP server
rocannon run           legacy ad-hoc form (module FQCN + -a key=value)
rocannon doctor        system health (binaries, env, inventory)
rocannon doc <module>  print parsed schema for a module
rocannon search <q>    find modules by name or description
rocannon ls            list hosts/groups/modules from a profile
rocannon playbook      list/show/run saved playbooks

Per-module help (typed flags, defaults, descriptions from ansible-doc): rocannon ansible.builtin.copy --help. Modules that support check mode also accept --check and --diff.

Profiles

A profile is a YAML file declaring inventory + modules:

inventories:
  - ./hosts
modules:
  - ansible.builtin
  - ibm.ibm_zos_core
ansible_cfg: ./ansible.cfg          # optional
vault_password_file: ~/.vault_pass  # optional
extra_envvars:                      # optional
  ZOAU_HOME: /usr/lpp/IBM/zoautil

modules accepts a specific module (ansible.builtin.copy), a collection (ansible.builtin), or a namespace (community).

Multiple profiles can live under .rocannon/profiles/:

.rocannon/profiles/
├── box1.yml
├── box2.yml
└── default.yml -> box1.yml
rocannon mcp serve                     # uses default.yml
rocannon mcp serve --profile box2

The active profile can be switched at runtime via three MCP tools: rocannon_list_profiles, rocannon_current_profile, rocannon_use_profile. The tool surface is the union of every profile's modules; a call to a module that isn't in the active profile returns a structured error pointing at rocannon_use_profile.

MCP clients

A working .mcp.json ships at the repo root. Per-client snippets are in examples/clients/.

Client Config location
Claude Code .mcp.json at project root, or claude mcp add
Claude Desktop macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
Cursor .cursor/mcp.json or ~/.cursor/mcp.json
mcphost ~/.mcphost.yml or --config <path>
IBM Bob .bob/mcp.json or ~/.bob/mcp_settings.json

All share the standard mcpServers envelope pointing at rocannon mcp serve --profile <your-profile.yml>.

Development

git clone https://github.com/msradam/rocannon.git
cd rocannon
uv sync
./tests/check.sh                # ruff format + lint + mypy + pytest
uv run pytest -m integration    # opt-in: spins up a real UBI9 container

See ARCHITECTURE.md for how the pieces fit together.

Rocannon is developed with AI assistance.

The name

Ursula K. Le Guin coined the word "ansible" in her 1966 novel Rocannon's World. The gryphon is a nod to the Windsteeds that Rocannon and his companions ride.

Credits

Project details


Download files

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

Source Distribution

rocannon-0.1.1.tar.gz (45.7 kB view details)

Uploaded Source

Built Distribution

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

rocannon-0.1.1-py3-none-any.whl (51.6 kB view details)

Uploaded Python 3

File details

Details for the file rocannon-0.1.1.tar.gz.

File metadata

  • Download URL: rocannon-0.1.1.tar.gz
  • Upload date:
  • Size: 45.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.21 {"installer":{"name":"uv","version":"0.11.21","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for rocannon-0.1.1.tar.gz
Algorithm Hash digest
SHA256 b6233334af02161d418eeb011c427548c1f35d21551d52a9ace07d51c0423f70
MD5 2d63929ba4efc4250a8668312d634d4f
BLAKE2b-256 f426a802615c6fb49d1171f99c19390a0b3d85c8255c572c3551b04ca69cfb51

See more details on using hashes here.

File details

Details for the file rocannon-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: rocannon-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 51.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.21 {"installer":{"name":"uv","version":"0.11.21","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for rocannon-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 99b948fba98c1e33e50cd8f8d7259795c896c2521fd8e509e32ce534f1aa6bb3
MD5 0b6ba4bf0d1c6d0854ce99965d98e562
BLAKE2b-256 b145888dd450af5745b4b59a00491e67eaffbe354c2dc0c5a726e105ac5ed05e

See more details on using hashes here.

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