Ansible MCP Server

io.github.YawLabs由 GitHub 帳號 YawLabs 發布v0.1.3更新於 Oct 31, 2026

Ansible checkout truth: module specs, task args, roles, inventory, plays, upgrade impact

概覽

AI 產生的概覽

唯讀 MCP 伺服器,讓助理檢查本機 Ansible 專案:已安裝模組的參數規格、任務參數檢查、角色、清單、劇本結構與升級影響。

可以做什麼
  • 檢視專案概況:ansible-core 版本、生效設定檔、集合與角色路徑、偵測到的劇本、清單與 requirements 檔案
  • 查詢與搜尋已安裝的模組和外掛,列出精確選項、型別、預設值、可選值及提供它的集合版本
  • 依已安裝文件檢查行內 YAML、任務檔或劇本中的任務參數,包含 YAML 1.1 陷阱
  • 讀取角色介面、去識別化的清單群組主機與變數、含檔案行號與標籤的劇本結構,以及含來源的生效設定
  • 比對 requirements.yml 與實際安裝狀況,並依規則彙整離線 ansible-lint 結果
  • 評估集合升級到指定版本後本專案任務會出什麼問題,並定位到檔案行號
適用情境
適合在助理撰寫或修改 Ansible 任務時,讓它依實際安裝的集合版本核對參數,而不是憑訓練資料猜測。也適合檢視角色介面、本機清單、劇本結構、相依漂移或規劃集合升級。
執行需求
透過 npx 在本機執行,需要 Node.js 20+。ansible-core 需在 PATH 中,或放在由 ANSIBLE_MCP_BIN_DIR 指向的虛擬環境;lint 彙整另需 ansible-lint。Windows 上需在 WSL 安裝 Ansible 並設定 ANSIBLE_MCP_COMMAND_PREFIX。升級影響工具首次請求某版本時需能連線 Galaxy 或設定的伺服器。
安裝前請注意
設計上唯讀:不執行劇本、不跑 --check、不做修正,也從不提供 vault 密鑰。殘餘風險:語法檢查與 ansible-lint 會求值 play 層級 Jinja 並匯入劇本旁的 vars 外掛,應把目標目錄視為會執行 --syntax-check 的程式碼。動態清單與 play 層級 lookup 預設關閉,除非設定 ANSIBLE_MCP_ALLOW_DYNAMIC_INVENTORY 或 ANSIBLE_MCP_ALLOW_PLAY_LOOKUPS。升級影響工具會把目標集合下載到自身快取並連線 Galaxy。

安裝

在 SourceWeft 中

  1. 開啟 儀表板中的 Ansible MCP Server,將其新增到工作區。
  2. 為需要使用其工具的對話啟用該服務。

Desktop only,透過 STDIO。 STDIO 服務會啟動本機處理程序,因此需要 SourceWeft 桌面主機。

其他 MCP 客戶端

參照 儲存庫 中的啟動說明。

README

@yawlabs/ansible-mcp

[Add to Yaw MCP]

One click adds this to your local Yaw MCP config so it's available in every Yaw Terminal session. Or install manually below.

What is actually true in THIS Ansible checkout on THIS control node: the exact option specs of the modules you have INSTALLED (so coding agents stop writing options that do not exist in your collection version), task-argument checks, role interfaces, inventory structure and vars (redacted), play structure, effective config, requirements drift, and what a collection upgrade would break in your tasks. It is read-only: it never runs a play, never runs --check, never connects to a managed host and never supplies a vault secret. It complements Red Hat's servers rather than replacing them: AAP MCP answers what is true in the controller, ADT MCP takes actions (lint --fix, navigator runs, scaffolding, EE builds). Run them together.

[npm version] [License: MIT]

Built and maintained by Yaw Labs.

Why this one?

Your checkout has community.general 9.5.2; the model's training data has whatever version it saw most. Agents then write git_config: list_all: true (removed in 11.0.0), forget name (required since 12.0.0), or set 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, against what is installed.

  • Installed, not latest -- the source of truth is ansible-doc --json run against your collections paths, with redirects (ufw -> community.general.ufw) and tombstones resolved.
  • Checks what lint skips -- ansible-lint's args rule skips modules with action plugins (copy, template); ansible_check_task_args catches their unknown options and bad values, and says plainly which cross-option rules ansible-doc cannot express.
  • YAML 1.1 aware -- Ansible parses YAML 1.1, so unquoted off is false and 0755 is the integer 493. The server reads YAML the same way and says when that is probably a bug.
  • Read-only by construction -- configured vault password scripts never run (a server-owned dummy password file replaces them), script and plugin inventory sources are off by default, and play-level lookups are refused before Ansible parses a playbook (as is any playbook or lint target the pre-scan cannot fully read).
  • Collection upgrade impact -- downloads only the target version into its own cache and diffs the arg specs of the modules your tasks actually use, tied to file:line.
  • macOS, Linux, and Windows through WSL -- Ansible has no Windows control node; on Windows the server spawns it through wsl.exe --exec (no shell anywhere).

Tools

ToolWhat it does
ansible_project_infoansible-core version, effective config file, collections and roles paths, installed ansible-* binaries, detected playbooks, inventories (with 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/plugins by name or description, ranked exact, prefix, token, then description.
ansible_check_task_argsCheck inline task YAML or a tasks file / playbook 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": it names what ansible-doc cannot check.
ansible_role_interfaceA role's argument_specs entry points and options, defaults (redacted, no_log honoured), undocumented defaults, dependencies, vars names, 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/moved modules (runtime.yml 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.

Every tool takes an optional dir (the project). Tool names carry an ansible_ prefix and never reuse ADT MCP's names (ansible_lint, ansible_navigator, ...), so both can sit behind one aggregator.

Division of authority

QuestionAuthority
Controller jobs, job templates, controller inventories, RBACAAP MCP
Scaffold content, ansible-lint --fix, run via ansible-navigator, set up a venv or EEADT MCP
Interactive editing for a personVS Code Ansible extension (language server)
Generate new content from intentAnsible Lightspeed
Execute modules against hostsnot this server
Installed specs, task-argument validity, role interfaces, local inventory, play structure, effective config, dependency drift, collection upgrade impactansible-mcp (read-only)

What is read-only, and what touches the network

  • Never run: plays, modules, --check, --diff, fact gathering. The only Ansible commands are ansible --version, ansible-config dump, ansible-doc, ansible-inventory --list/--host/--graph, ansible-playbook --syntax-check/--list-*, ansible-galaxy collection list / role list, ansible-lint --offline, and (only in ansible_upgrade_impact) ansible-galaxy collection install --no-deps -p <server cache>.
  • Never written: your project, your collections and roles paths, requirements files, and anything inside an existing ~/.ansible. Ansible's local temp, galaxy cache and (when you have none) galaxy token file are redirected to the server's cache. The one residue: Ansible creates an empty ~/.ansible when it does not exist, and ansible-lint creates empty ~/.ansible/roles / ~/.ansible/collections when they are missing.
  • Vault: no secret is ever supplied, and a vault_password_file / vault_identity_list script named in ansible.cfg never runs (it is replaced by a server-owned file holding a random password). Inline !vault values print as <vaulted>; whole-file vaults are listed, not read.
  • Dynamic inventory (script, constructed, cloud plugins) runs code and calls APIs, so it is off unless ANSIBLE_MCP_ALLOW_DYNAMIC_INVENTORY=1; skipped sources are named in the answer.
  • Residual risk, stated: ansible-playbook --syntax-check (and ansible-lint, which runs it) evaluates Jinja in play-level name, hosts and vars_files and imports playbook-adjacent vars_plugins/. Treat dir as code you would run --syntax-check on. Lookups in those fields are refused before Ansible sees them unless ANSIBLE_MCP_ALLOW_PLAY_LOOKUPS=1, and local plugin files are listed in the answer.
  • Redaction (ansible_inventory, ansible_role_interface, ansible_config, lint messages): vault markers, plus any string equal to a hidden one, plus values under secret-like names (ansible_become_password, api_token, vault_db_password, ... but not vault_addr or private_key_file), plus secret-shaped strings (private keys, JWTs, GitHub/GitLab/Slack/npm tokens; URL passwords masked in place). Galaxy server tokens and passwords are always redacted. There is no "show secrets" switch.
  • Network: only ansible_upgrade_impact, on a cache miss, to Galaxy or the servers in your ansible.cfg (openWorldHint: true). The cache is never evicted automatically; deleting it is safe.

Example ansible_check_task_args output (real docs, community.general 9.5.2):

playbooks/tasks/bad_args.yml: 7 tasks checked against installed docs (ansible-core 2.21.5): 5 problems in 3 tasks  :3 ansible.builtin.copy [has action plugin; ansible-lint skips its arguments]    unknown option owner_name (line 7)    unknown option state (line 9)    backup (line 8): expected bool, got a string that is not a boolean ('maybe')  :12 ansible.posix.mount    missing required option path (aliases: name)  :18 ansible.builtin.file (key=value form): ok (dest is an alias of path)  :21 ansible.builtin.copy: ok by docs [not checked: src and content are mutually exclusive in the module's argument_spec, which ansible-doc does not expose]  :32 ansible.builtin.apt: ok; 2 templated values not checked (state, update_cache)  :38 community.general.ufw (from short name ufw)    proto (line 41): 'tcpx' is not one of any|tcp|udp|ipv6|esp|ah|gre|igmp

Example ansible_upgrade_impact output (real 9.5.2 -> 12.0.0 docs):

upgrade community.general 9.5.2 -> 12.0.0 (major) for /work/sitetarget: requires_ansible '>=2.17.0' ok (ansible-core 2.21.5); dependencies: none; downloaded (cache: ...)constraints: requirements.yml:3 pins '>=9.0.0,<10.0.0' (change it to allow 12.0.0)used modules (7): git_config, proxmox_kvm, consul_acl, slack, rhsm_repository (playbooks/site.yml); timezone (roles/common/tasks/main.yml); ufw (roles/webapp/tasks/main.yml, via short name ufw)BREAKING (5):  playbooks/site.yml:17 community.general.git_config: option list_all removed (line 19)  playbooks/site.yml:17 community.general.git_config: name is newly required, not set  playbooks/site.yml:23 community.general.proxmox_kvm: moved to community.proxmox.proxmox_kvm; community.proxmox is not installed (add it to requirements.yml)  playbooks/site.yml:31 community.general.consul_acl: removed in 10.0.0 (tombstone): Use community.general.consul_token and/or community.general.consul_policy instead.  playbooks/site.yml:43 community.general.rhsm_repository: state=present no longer accepted (choices: enabled, disabled) (line 45)BEHAVIOR CHANGES (1):  playbooks/site.yml:37 community.general.slack: prepend_hash not set; default 'auto' -> 'never'syntax-check with 12.0.0 (playbooks/site.yml): first error playbooks/site.yml:22: couldn't resolve module/action 'community.general.proxmox_kvm' (syntax-check stops at the first error and does not check options)verdict: BREAKING (5)

Quick start

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

bash
# inside WSL (any distro); a venv under $HOME survives WSL restarts, /tmp does notpython3 -m venv ~/.venvs/ansible && ~/.venvs/ansible/bin/pip install ansible-core ansible-lint

2. Add the server. Claude Code, from the project:

bash
# macOS / Linuxclaude mcp add ansible -- npx -y @yawlabs/ansible-mcp@latest
# Windows (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 (or anywhere, and set ANSIBLE_MCP_DIR):

macOS / Linux:

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

Windows (Ansible inside WSL):

json
{  "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"      }    }  }}

Why the extra step on Windows? Since Node 20, child_process.spawn cannot directly execute .cmd files (that's what npx is on Windows). Wrapping with cmd /c is the standard workaround.

3. Restart your MCP client and ask, for example: "Add a task that opens port 8443 with ufw -- check the arguments against our installed collections first."

Windows and WSL, in detail

  • The prefix must use wsl.exe --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.
  • Nothing from the Windows environment crosses into WSL. Variables the Ansible side needs (proxies, ANSIBLE_COLLECTIONS_PATH) are forwarded by name with ANSIBLE_MCP_PASS_ENV.
  • Windows paths are translated with the mount root wslpath reports (C:\work\site -> /mnt/c/work/site). A project inside WSL works too: pass dir as \\wsl.localhost\Ubuntu\home\me\site (the distro must match the prefix's -d).
  • 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.
  • The server's Ansible-side cache lives under the WSL user's ~/.cache/ansible-mcp (never /tmp, which WSL empties on restart).

Tell your agent to use it

Paste this into the project's CLAUDE.md (or AGENTS.md):

markdown
## Ansible
Module options drift between collection versions. Use the ansible MCP server:
- Call `ansible_project_info` once per session.- Before writing or editing a task, call `ansible_module_doc` for its module, then  run `ansible_check_task_args` on the task (or the file). Fix every problem it  reports; quote values it flags as YAML 1.1 traps.- Before using a role, read `ansible_role_interface`.- Before bumping a collection in requirements.yml, run `ansible_upgrade_impact`.- Never run plays, `--check` or `ansible-lint --fix` on your own; ask first.

Configuration

All optional.

Env varDefaultPurpose
ANSIBLE_MCP_DIRthe server's working directoryProject used when a tool call passes no dir.
ANSIBLE_MCP_COMMAND_PREFIX(unset: native)JSON array prepended to every Ansible command, e.g. ["wsl.exe","-d","Ubuntu","--exec"]. A value not starting with [ is split on whitespace. Required on Windows.
ANSIBLE_MCP_BIN_DIR(unset: PATH)Ansible-side directory holding ansible-* (a venv's bin). Also put first on the child's PATH (ansible-lint needs ansible-playbook next to it).
ANSIBLE_MCP_PATH_STYLEautowsl or native. auto is wsl when the prefix starts with wsl/wsl.exe. Other prefixes (ssh, docker exec) get env -C <dir> ... and are best effort.
ANSIBLE_MCP_PASS_ENV(unset)Comma-separated names of server env vars to forward to the Ansible side in prefix mode.
ANSIBLE_MCP_TIMEOUT_MS120000Kill any Ansible command after this long (the upgrade download gets 3x).
ANSIBLE_MCP_CACHE~/.cache/ansible-mcpServer-side cache (and the Ansible-side one in native mode): the dummy vault file, local temp, upgrade targets. Safe to delete.
ANSIBLE_MCP_REMOTE_CACHE$HOME/.cache/ansible-mcp on the Ansible sideThe Ansible-side cache in prefix mode.
ANSIBLE_MCP_ALLOW_DYNAMIC_INVENTORY(unset)1 re-enables script, constructed and plugin inventory sources (they run code and may call cloud APIs).
ANSIBLE_MCP_ALLOW_PLAY_LOOKUPS(unset)1 lets playbooks with lookups in play-level name / hosts / vars_files be parsed (Ansible runs those lookups on this machine).

Runtime (oam or Node):

The ansible-mcp command prefers oam when it finds a usable one and otherwise runs on Node. It never serves on an oam older than 0.19.1.

Env varDefaultPurpose
ANSIBLE_MCP_RUNTIMEautoauto: the newest oam at 0.19.1 or newer, else Node. oam: oam or exit with an error. node: always Node -- the escape hatch when a problem only shows up under oam.
OAM_BIN(unset)Path to the oam binary to use. Otherwise the launcher checks OAM_INSTALL_DIR, the installed locations (~/.oam/bin, and %LOCALAPPDATA%\oam\bin on Windows) and PATH, and takes the newest.

An outdated oam is fixed with oam self-update. Under Yaw MCP, which runs servers on oam by default, yaw-mcp set <namespace> runtime=node switches this server to Node. There is no --permission sandbox option: the server spawns Ansible and reads whatever directory a call names, so there is nothing narrow to grant.

Requirements

  • Node.js 20+
  • ansible-core on the control node (verified with 2.21.5); ansible-lint for ansible_lint_summary (verified with 26.10.1)
  • Windows: WSL with ansible-core installed in a distro, and ANSIBLE_MCP_COMMAND_PREFIX set. Without it, only ansible_project_info (static half) and ansible_role_interface (local files) answer; the rest say what to set.
  • ansible_upgrade_impact: Galaxy (or your configured servers) reachable the first time a target version is requested; later runs for that version are offline

Contributing

bash
git clone https://github.com/YawLabs/ansible-mcp.gitcd ansible-mcpnpm installnpm run lint       # Biome checknpm run lint:fix   # Auto-fixnpm run build      # tsup bundle + declarationsnpm test           # Vitest (integration tests run only when Ansible is reachable)npm run typecheck  # oam check . when oam is installed, else tsc --noEmitnpm run check:oam-floor  # the oam floor agrees across the repo and matches the latest oam release

See CONTRIBUTING.md for the full workflow, including release process.

License

MIT

[Follow @YawLabs on X]

來源:README.md,提交 a1c1f56

工具

11

ansible_project_info

Ansible project overview

What this Ansible checkout contains and how Ansible sees it: ansible-core version, effective config file, collections and roles paths, installed ansible-* binaries, detected playbooks, inventories, roles and requirements files. Call it first. Read-only; never connects to a managed host (AAP MCP covers controller state, ADT MCP takes actions).

輸入參數dir

ansible_module_doc

Installed module/plugin spec

Exact options (type, required, default, choices, aliases, suboptions) of a module or plugin as INSTALLED here (ansible-doc), with the collection version that provides it and redirects resolved. Use before writing a task; options drift between collection versions, so training-data guesses are often wrong.

輸入參數dirname必填typeinclude_returninclude_examplesdescription_chars

ansible_check_task_args

Check task arguments

Check tasks (inline YAML, or a tasks file / playbook) against the INSTALLED module docs: unknown options, missing required ones, bad choices and types (YAML 1.1 aware: unquoted off/yes/0755), suboptions, deprecated options. ansible-doc cannot express cross-option rules (mutually_exclusive, required_if), so the answer says what it could not check; it catches action-plugin modules (copy, template) that ansible-lint's args rule skips.

輸入參數dirfilelinetask

ansible_role_interface

Role interface

A role's interface: argument_specs entry points and options (no_log honoured), defaults with redacted values, which defaults are undocumented, dependencies, vars names and galaxy_info. Works for local roles (roles_path, dir/roles, or a path) and collection roles (ns.collection.role).

輸入參數dirrole必填entry_pointdescription_chars

ansible_inventory

Inventory structure and vars

Groups, hosts and inventory-level vars (ansible-inventory --graph/--list/--host), always redacted: vault values, secret-like names and secret-shaped values are hidden, templates are shown unrendered. Script and plugin inventory sources run code, so they are skipped unless ANSIBLE_MCP_ALLOW_DYNAMIC_INVENTORY=1 (which can also call cloud APIs); vault secrets are never supplied, so whole-file vaults degrade to a per-file view.

輸入參數dirhostvarsgrouplimitinventory

ansible_playbook_structure

Playbook structure

Plays, matched hosts, tasks (with module and file:line where unambiguous) and tags of a playbook (ansible-playbook --syntax-check, then --list-hosts --list-tasks --list-tags), plus deprecation warnings Ansible printed while parsing; never runs a play. Parses playbooks with Ansible: treat dir as code you would run --syntax-check on (play-level Jinja and playbook-adjacent vars plugins are evaluated); lookups in play-level fields are refused unless ANSIBLE_MCP_ALLOW_PLAY_LOOKUPS=1.

輸入參數dirtagslimitplaybook必填inventorymax_tasksskip_tags

ansible_config

Effective Ansible config

The effective configuration for this dir (ansible-config dump) with each setting's origin (ansible.cfg, env, default); galaxy server tokens and passwords are always redacted. Settings this server overrides for safety in its other tools (vault password files, inventory and vars plugins) are flagged.

輸入參數alldirlimitfilter

ansible_collections

Collections vs requirements

requirements.yml (collections and roles) against what is installed: ok, VIOLATES (with file:line) or MISSING, using galaxy constraint rules, plus collections shadowed across collections paths (the first in COLLECTIONS_PATHS wins). Never installs anything.

輸入參數dirrequirementsinclude_extras

ansible_lint_summary

ansible-lint summary

ansible-lint (offline) grouped by rule with counts, severities and file:line locations; never fixes anything (ADT MCP's ansible_lint fixes). Parses playbooks with Ansible: treat dir as code you would run --syntax-check on (play-level Jinja and playbook-adjacent vars plugins are evaluated); lookups in play-level fields are refused unless ANSIBLE_MCP_ALLOW_PLAY_LOOKUPS=1.

輸入參數dirpathsprofilemax_locations

ansible_upgrade_impact

Collection upgrade impact

What breaks in THIS project's tasks if one collection moves to an exact version: removed or moved modules (meta/runtime.yml redirects and tombstones), removed options and aliases, newly required options, dropped choices, type and default changes, each tied to the task's file:line, plus requirements.yml constraints and a verdict. Downloads the target collection from Galaxy (or the configured servers) into this server's cache on first use; never touches dir, requirements files or your collections paths.

輸入參數dirversion必填playbookscollection必填syntax_checkinclude_unused

版本歷史

3
  1. v0.1.3最新Oct 31, 2026
  2. v0.1.2Oct 17, 2026
  3. v0.1.0Oct 16, 2026

評分

已滿足適用檢查項的 90%

該評分衡量此收錄條目的完整程度,依據註冊中心條目、端點與公開來源計算得出。它不是對伺服器本身的評價,也不表示伺服器安全或目前可用:可連通性是帶日期的檢查結果,評分也不包含安裝量或使用者評價。

  • 近 30 天內可連通25 分
  • 已宣告認證方式10 分

    請在註冊中心條目中宣告憑證請求標頭,或保持端點能夠回應探測,以便判定其認證方式。

  • 已列出工具必需15 分
  • 描述必需15 分
  • 圖示10 分
  • 文件15 分
  • 授權條款10 分