@yawlabs/ansible-mcp answers from your checkout on your control node, not from upstream docs. The source of truth is ansible-doc --json run against your collections paths, with redirects such as ufw to community.general.ufw and tombstones resolved - so the option specs an agent checks against are the ones you actually have installed, not the ones the latest release documents. It is read-only by construction: it never runs a play, never connects to a managed host, and never supplies a vault secret. Built and maintained by Yaw Labs, MIT licensed, published on npm.

npx -y @yawlabs/ansible-mcp@latest

GitHub · npm · Add to Yaw MCP

Who it is for

Anyone who has watched an agent write a task against the wrong collection version. Your checkout has community.general 9.5.2; the model's training data has whatever version it saw most. The agent then writes git_config: list_all: true (removed in 11.0.0), forgets name (required since 12.0.0), or sets state: present on rhsm_repository (no longer accepted). The VS Code language server knows the exact specs, but only a person in the editor sees them. This server lets the agent check before it writes:

Install

1. Have ansible-core where the server can run it. On macOS and Linux, ansible-core (and optionally ansible-lint) on PATH, or in a venv you point ANSIBLE_MCP_BIN_DIR at. On Windows, inside WSL:

python3 -m venv ~/.venvs/ansible && ~/.venvs/ansible/bin/pip install ansible-core ansible-lint

A venv under $HOME survives WSL restarts; /tmp does not.

2. Add the server. Claude Code, from the project. On macOS and Linux:

claude mcp add ansible -- npx -y @yawlabs/ansible-mcp@latest

On Windows, with Ansible inside WSL:

claude mcp add ansible \ -e ANSIBLE_MCP_COMMAND_PREFIX='["wsl.exe","-d","Ubuntu","--exec"]' \ -e ANSIBLE_MCP_BIN_DIR=/home/me/.venvs/ansible/bin \ -- cmd /c npx -y @yawlabs/ansible-mcp@latest

Or add it to .mcp.json in the project. On macOS and Linux:

{ "mcpServers": { "ansible": { "command": "npx", "args": ["-y", "@yawlabs/ansible-mcp@latest"] } } }

On Windows, with Ansible inside WSL:

{ "mcpServers": { "ansible": { "command": "cmd", "args": ["/c", "npx", "-y", "@yawlabs/ansible-mcp@latest"], "env": { "ANSIBLE_MCP_COMMAND_PREFIX": "[\"wsl.exe\",\"-d\",\"Ubuntu\",\"--exec\"]", "ANSIBLE_MCP_BIN_DIR": "/home/me/.venvs/ansible/bin" } } } }

On Windows the cmd /c wrapper is required for the same reason as every other server: since Node 20, child_process.spawn cannot directly execute .cmd files, and that is what npx is on Windows. The prefix must use --exec (or -e), never --: with -- WSL re-parses the arguments with bash and a value like it's breaks the command. The server refuses a prefix without --exec.

3. Point it at the project. It uses the working directory by default; set ANSIBLE_MCP_DIR for a fixed project, or pass dir per call. On a Windows drive every folder looks world-writable to WSL and Ansible then ignores ansible.cfg - when the project has one, the server sets ANSIBLE_CONFIG to it explicitly and says so.

Running Yaw MCP? One click adds it to your local config, and it is then available in every Yaw Terminal session.

What it covers

ToolWhat it does
ansible_project_infoansible-core version, effective config file, collections and roles paths, installed ansible-* binaries, detected playbooks, inventories (with a whole-file vault count), roles and requirements files. Call this first.
ansible_module_docEvery option of one module or plugin as installed: type, required, default, choices, aliases, suboptions, deprecations, no_log, the providing collection version, [has action plugin], returns and optionally examples.
ansible_module_searchFind installed modules and plugins by name or description, ranked exact, prefix, token, then description.
ansible_check_task_argsCheck inline task YAML or a tasks file against the installed docs: unknown options, missing required ones (aliases count), bad choices and types, suboptions, mode: 0755, deprecated options, duplicate keys. Never claims "valid".
ansible_role_interfaceA role's argument-spec entry points and options, defaults (redacted, no_log honoured), undocumented defaults, dependencies, vars names and galaxy_info. Local roles and ns.collection.role.
ansible_inventoryGroups, hosts and inventory-level vars (names or values), always redacted. Whole-file vaults degrade to a per-file view instead of failing.
ansible_playbook_structure--syntax-check, then plays, matched hosts, tasks with module and file:line, tags, and the deprecation warnings Ansible printed while parsing.
ansible_configEffective config with origins (ansible.cfg, env, default); galaxy credentials always redacted; settings the server overrides for safety are flagged.
ansible_collectionsrequirements.yml vs installed: ok / VIOLATES / MISSING with file:line, galaxy constraint semantics, and shadowed copies across collections paths.
ansible_lint_summaryansible-lint --offline grouped by rule with counts, severities and locations. Never fixes.
ansible_upgrade_impactWhat breaks in this project's tasks if a collection moves to an exact version: removed or moved modules (redirects and tombstones), removed options and aliases, newly required options, dropped choices, type and default changes, requirements constraints, requires_ansible, an optional syntax-check against the target, and a verdict.

Installed, not latest, is the whole point. The source of truth is ansible-doc run against the collections paths your checkout actually uses, so a module that was renamed or removed between your version and the upstream default is described as you have it, not as the docs describe it.

Safety and control

Frequently asked questions

What does the Ansible MCP server do?

It answers what is true in your Ansible checkout on your control node, not in the upstream collection docs. The source of truth is ansible-doc --json run against your collections paths, with redirects and tombstones resolved, so the module option specs it reports are the ones you actually have installed. On top of that it checks task arguments, reads role interfaces, inspects inventory (redacted), parses play structure, resolves effective config and requirements drift, and computes what a collection upgrade would break in your tasks.

Is it safe to point at a production checkout?

It is read-only by construction. It never runs a play, never runs --check, never connects to a managed host, and never supplies a vault secret: configured vault password scripts are replaced with a server-owned dummy password file so they never execute. Script, constructed and plugin inventory sources are off by default because they run code and may call cloud APIs, and play-level lookups are refused before Ansible parses a playbook because Ansible runs those on this machine.

How is this different from ansible-lint?

It complements lint rather than replacing it. ansible-lint's args rule skips modules with action plugins, such as copy and template, so it cannot check their options at all. ansible_check_task_args covers those modules, catches unknown options and bad values, and says plainly which cross-option rules ansible-doc cannot express rather than claiming a task is valid. It also does what lint does not: role argument specs, inventory structure, effective config origins, requirements drift, and collection-upgrade impact tied to file:line.

Does Ansible run on Windows?

Ansible itself has no Windows control node, so on Windows the server reaches it through WSL with a command prefix such as wsl.exe -d Ubuntu --exec. The prefix must use --exec or -e, never --, because with -- WSL re-parses the arguments with a shell and a value like it's breaks the command; the server refuses a prefix without --exec. Windows environment variables do not cross into WSL, so variables the Ansible side needs are forwarded by name with ANSIBLE_MCP_PASS_ENV, and Windows paths are translated using the mount root wslpath reports.

What does the collection-upgrade tool actually do?

Given a collection and an exact target version, it downloads only that version into its own cache and diffs the argument specs of the modules your tasks actually use. It reports removed or moved modules via runtime.yml redirects and tombstones, removed options and aliases, newly required options, dropped choices, type and default changes, requirements constraints and requires_ansible, optionally confirms with a syntax-check against the target, and ends with a verdict tied to file:line.

Related MCP servers

Further reading

Published by Yaw Labs.