Skip to main content

ansible-jsonrpc-server

A JSON-RPC 2.0 server that executes Ansible over a stdio seam. It runs Ansible modules and action plugins, gathers facts, and installs collections, exposing them as JSON-RPC methods — so a client can drive Ansible without importing it. The server is transport- and client-agnostic: anything that can spawn a process and speak the framing can use it.

Install

pip install ansible-jsonrpc-server

Requires Python ≥ 3.11. Pulls in ansible-core, msgspec, and pebble.

Run

python -m ansible_jsonrpc_server
# or the console script
ansible-jsonrpc-server

The process is meant to be spawned by a client, not used interactively: it reads JSON-RPC requests on stdin and writes responses on stdout; all diagnostics go to stderr (fd 1 is redirected to stderr internally so a stray print — even in a forked worker — can't corrupt the frames). It exits on EOF or a shutdown notification.

Execution runs in a pebble fork pool: the parent process never imports Ansible, so it stays responsive to control messages while module runs proceed concurrently in workers.

Configuration

Env var Controls Default
ANSIBLE_JSONRPC_FORKS worker processes running Ansible concurrently (fork pool size) 5
ANSIBLE_JSONRPC_MAX_INFLIGHT dispatch threads accepting requests concurrently 64

Both must be integers >= 1; a malformed or out-of-range value aborts startup. Requests past FORKS queue until a worker frees up; MAX_INFLIGHT bounds how many can be read and queued at once.

Protocol

JSON-RPC 2.0 with Content-Length framing (LSP-style): each message is Content-Length: <n>\r\n\r\n followed by <n> bytes of UTF-8 JSON.

Methods

runAction

Run one module or action plugin on a host. If collection is given it is installed first; if host.gather_subset is set, facts are gathered (and cached) first.

Params:

Field Type Notes
host HostSpec target + connection (below)
fqcn string e.g. ansible.builtin.copy
args object module arguments (default {})
vars object task vars, e.g. ansible_python_interpreter (default {})
flags Flags check_mode, diff, no_log, verbosity, timeout
collection Collection? {name, version, source?}; omit for ansible.builtin

Result — ResultFrame:

Field Type Notes
status string ok | failed | skipped | unreachable
changed bool
result object the module's own result dict (redacted when no_log)
warnings string[]
deprecations object[]

gatherFacts

Gather facts for a host (via ansible.builtin.setup), cached per (host.id, subset). host.gather_subset selects the subset (e.g. ["min"], ["all"]).

  • Params: { host: HostSpec, vars?: object }
  • Result: the ansible_facts object (fact name → value).

Shared shapes

HostSpec   { "connection": Connection, "id"?: string,
             "become"?: object, "gather_subset"?: string[] }
Connection { "type": "local" | "ssh", "vars"?: object }   // vars → ansible_host, ansible_user, …
Flags      { "check_mode": bool, "diff": bool, "no_log": bool,
             "verbosity": int, "timeout"?: int }           // timeout seconds; 0/null → none
Collection { "name": string, "version": string, "source"?: string }

host.id keys the per-host fact and interpreter caches; host.become is a var bag (ansible_become, ansible_become_user, …). Unknown fields are ignored (forward-compatible).

Control messages (client → server, notifications)

  • shutdown — stop serving and exit.
  • $/cancelRequest — { "id": <request id> } cancels an in-flight runAction.

Notifications (server → client)

  • progress — internal activity not tied to a single reply, correlated by token:
{ "token": string, "phase": "begin" | "end",
  "kind": "collection" | "facts",
  "name"?: string, "version"?: string,   // kind=collection
  "host"?: string,  "subset"?: string[], // kind=facts
  "ok"?: bool }                           // on phase=end

Errors

Standard JSON-RPC error objects: -32601 method not found, -32602 invalid params (message carries the validation error), -32000 handler failure (data carries the Python traceback).

Example

→ {"jsonrpc":"2.0","id":1,"method":"runAction",
   "params":{"host":{"connection":{"type":"local"}},"fqcn":"ansible.builtin.ping"}}

← {"jsonrpc":"2.0","id":1,"result":{"status":"ok","changed":false,
   "result":{"ping":"pong"},"warnings":[],"deprecations":[]}}

Bootstrap script

Clients don't install the server by hand — they provision an isolated, version-keyed virtualenv with a small POSIX-sh script kept in this repo and fetched at a release tag:

https://raw.githubusercontent.com/vjrasane/ansible-jsonrpc-server/v<version>/bootstrap/v1/bootstrap.sh

It is version-agnostic (the release is an argument, not baked in), so one script serves every client and every version:

sh bootstrap.sh <version> [python]
# e.g.
sh bootstrap.sh 0.0.2

It creates $XDG_DATA_HOME/ansible-jsonrpc-server/venv/<version>, pip installs ansible-jsonrpc-server==<version>, writes a .ready marker, and prints the venv's python path on the last stdout line — the interpreter the client then spawns. It is idempotent (a provisioned venv is a fast no-op) and serialized with flock.

For server development, set ANSIBLE_JSONRPC_SERVER_SRC=<path> to install that checkout editable instead (keyed under a dev venv), so local edits are picked up live.

Module introspection

The package also ships introspect.py, used by client code generators to derive typed bindings from a collection's modules. It is a normal module in the installed package, so it runs through the same provisioned venv:

python -m ansible_jsonrpc_server.introspect '<job-json>'
  • Job: { "collection": "<ns.name>", "collectionsPath"?: "<dir>" }. collectionsPath (an ANSIBLE_COLLECTIONS_PATH root) exposes a downloaded collection to the loader; omit it for ansible.builtin.
  • Output (stdout, JSON): { "modules": [ { "fqcn", "style", "meta", "options", "returndocs" }, … ] } — one record per module, with its documented argument and return types. No module source is extracted; the server builds execution payloads itself.

License

GPL-3.0-or-later. This package depends on and embeds the execution model of ansible-core (GPL). Running it as its own process behind a JSON-RPC seam is what lets a separately licensed client drive Ansible without taking on that obligation.

Metadata

Release files for ansible-jsonrpc-server 0.0.7

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for ansible-jsonrpc-server 0.0.7
File Size Uploaded Provenance
ansible_jsonrpc_server-0.0.7.tar.gz 42.6 kB With provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for ansible-jsonrpc-server 0.0.7
File Interpreter ABI Platform
ansible_jsonrpc_server-0.0.7-py3-none-any.whl Python 3 none any Details

Total release size: 81.7 kB

Release files / ansible_jsonrpc_server-0.0.7.tar.gz

Download URL ansible_jsonrpc_server-0.0.7.tar.gz
Size 42.6 kB
Tags Source
SHA-256 checksum
How to use checksums
6e09db5a474d9a87683b8ce3ec05e1eafb8a021cdcd799bf17019e57260973f6
BLAKE2b-256 checksum
How to use checksums
b8cbf00c795785651a8e5de8199d9b7af1e5f893bc0e31967a451f85ec2998e4
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 23, 2026.

Transparency log

Release files / ansible_jsonrpc_server-0.0.7-py3-none-any.whl

Download URL ansible_jsonrpc_server-0.0.7-py3-none-any.whl
Size 39.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
99348944a150abbdecd54f10870d10ffdc6bcbf3679b7583216a94489cfdd7a9
BLAKE2b-256 checksum
How to use checksums
005eeb57010c0654caafd218f36276ac259ef9e41bd3d824fe5805cbabcbe4ae
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 23, 2026.

Transparency log

Security for ansible-jsonrpc-server 0.0.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for ansible_jsonrpc_server-0.0.7.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 23, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page