Skip to main content
Glama
README.md
# ansible-galaxy-mcp

MCP server that exposes Ansible Galaxy collection input/output contracts. Lets AI agents discover module arguments, return values, and role facts before generating playbooks.

## Quick start

```bash
npm install
npm run build
```

### Run with stdio transport (default)

```bash
node dist/index.js
```

### Run with HTTP transport

```bash
node dist/index.js --http
# or
MCP_TRANSPORT=http node dist/index.js
```

The HTTP transport exposes the MCP Streamable HTTP endpoint at `/mcp` plus operational endpoints (`/healthz`, `/readyz`, `/metrics`).

### Build a standalone binary

Requires [Bun](https://bun.sh/):

```bash
bun build src/index.ts --compile --outfile dist/ansible-galaxy-mcp
./dist/ansible-galaxy-mcp          # stdio
./dist/ansible-galaxy-mcp --http   # HTTP on port 8080
```

The binary has no runtime dependencies — no Node.js or Bun needed on the target machine.

### Run in development

```bash
npm run dev
```

## Tools

| Tool | Description |
|------|-------------|
| `search_collections` | Search Galaxy for collections by keyword |
| `get_collection_modules` | List all modules in a collection |
| `get_collection_roles` | List all roles in a collection |
| `get_module_spec` | Get full input/output contract for a module |
| `get_role_spec` | Get full input/output contract for a role |
| `grade_collection` | Grade a collection's documentation quality (A-F) |

## MCP client configuration

### Claude Code

Add to your Claude Code settings (`~/.claude/settings.json` or project `.claude/settings.json`):

```json
{
  "mcpServers": {
    "ansible-galaxy": {
      "command": "/path/to/dist/ansible-galaxy-mcp"
    }
  }
}
```

Or with Node.js:

```json
{
  "mcpServers": {
    "ansible-galaxy": {
      "command": "node",
      "args": ["/path/to/mcp-server/dist/index.js"]
    }
  }
}
```

### Claude Desktop

Add to `claude_desktop_config.json`:

```json
{
  "mcpServers": {
    "ansible-galaxy": {
      "command": "/path/to/dist/ansible-galaxy-mcp",
      "env": {
        "LOG_LEVEL": "info"
      }
    }
  }
}
```

### Container (HTTP transport)

The Containerfile compiles a standalone binary with Bun and copies it into a UBI 10 micro image. The container starts in HTTP mode by default:

```bash
podman build -t ansible-galaxy-mcp .
podman run --rm -p 8080:8080 ansible-galaxy-mcp
```

## Configuration

All configuration is via environment variables.

| Variable | Default | Description |
|----------|---------|-------------|
| `ANSIBLE_SOURCE_TYPE` | `galaxy` | Data source: `galaxy`, `local`, or `chain` |
| `ANSIBLE_GALAXY_URL` | `https://galaxy.ansible.com` | Galaxy API base URL |
| `ANSIBLE_HUB_URL` | _(none)_ | Private Automation Hub URL (used with `chain` source) |
| `ANSIBLE_ROLES_PATH` | `./roles` | Local roles directory (used with `local` or `chain` source) |
| `ANSIBLE_GALAXY_TOKEN` | _(none)_ | Bearer token for authenticated Galaxy/Hub API access |
| `ANSIBLE_GALAXY_TIMEOUT` | `30000` | HTTP request timeout in milliseconds |
| `MCP_TRANSPORT` | `stdio` | Transport: `stdio` or `http` |
| `MCP_HTTP_PORT` | `8080` | HTTP listen port |
| `MCP_HTTP_HOST` | `::` | HTTP bind address (dual-stack by default) |
| `ANSIBLE_OUTPUT_SPECS` | `false` | Enable proposed output_specs features (see below) |
| `LOG_LEVEL` | `info` | Log verbosity: `debug`, `info`, `warn`, `error` |

### Authentication

The Galaxy/Hub API token is resolved in this order:

1. `ANSIBLE_GALAXY_TOKEN` environment variable
2. `~/.ansible/galaxy_token` file (plain text)
3. `token` field in `ansible.cfg` (`[galaxy]` or `[galaxy_server.*]` section), searched in:
   - `$ANSIBLE_CONFIG`
   - `./ansible.cfg`
   - `~/.ansible.cfg`
   - `/etc/ansible/ansible.cfg`

This follows Ansible's own precedence. In containers, use the env var or mount the token file.

### Output specs feature gate

The server supports proposed Ansible output spec features behind a feature gate. By default these are **off**, so the server works with existing collections today.

Set `ANSIBLE_OUTPUT_SPECS=true` to enable:

| Behavior | Gate off (default) | Gate on |
|----------|-------------------|---------|
| Role `output_specs.yml` lookup | Skipped | Enabled |
| Role grading | Based on `argument_specs.yml` only | Penalizes missing `output_specs.yml` |
| Module grading | Has RETURN block or not | Checks enriched fields (`contains`, `required`, `sample`) |
| `grade_collection` role scoring | Roles not factored into grade | Roles weighted at 40% of overall grade |

This lets you use the server today with any Galaxy collection, and progressively enable the proposed spec as collections adopt it.

### Source types

- **`galaxy`** (default) — Fetches data from Ansible Galaxy (or a compatible API like Private Automation Hub).
- **`local`** — Reads roles from a local directory. Useful for development or roles not published to Galaxy.
- **`chain`** — Tries local first, then Hub (if configured), then Galaxy. Useful when you have private roles that override public ones.

## Tests

```bash
npm test
```

## HTTP transport endpoints

When running with `--http`:

| Endpoint | Method | Description |
|----------|--------|-------------|
| `/mcp` | POST | MCP Streamable HTTP — send JSON-RPC messages |
| `/mcp` | GET | MCP SSE stream — receive server-initiated messages |
| `/mcp` | DELETE | Close an MCP session |
| `/healthz` | GET | Liveness probe — always returns `{"status": "ok"}` |
| `/readyz` | GET | Readiness probe — returns `{"status": "ready"}` |
| `/metrics` | GET | Prometheus-format metrics |

### Kubernetes deployment

```yaml
livenessProbe:
  httpGet:
    path: /healthz
    port: 8080
readinessProbe:
  httpGet:
    path: /readyz
    port: 8080
```

## Architecture

```
src/
  index.ts          Entry point, tool registration, transport selection
  http.ts           Streamable HTTP transport + health/metrics endpoints
  metrics.ts        Prometheus-format counter registry
  errors.ts         Typed error classes (NotFoundError, GalaxyApiError, etc.)
  logger.ts         Leveled stderr logger (debug/info/warn/error)
  cache.ts          Generic LRU cache with TTL and metrics
  types.ts          TypeScript interfaces
  galaxy/
    client.ts       Galaxy API client with caching, retry, and timeouts
    source.ts       Source abstraction (Galaxy, Local, Chain)
    parser.ts       Ansible docstring and YAML parser
```

TDQS

A4/5.0

Scored across 6 tools

Disambiguation5/5

Each tool has a clearly distinct purpose: search collections, list modules or roles in a collection, retrieve detailed specs for a specific module or role, and grade collection documentation. No overlap or ambiguity.

Naming Consistency5/5

All tool names follow a consistent verb_noun pattern in snake_case (e.g., get_collection_modules, get_module_spec). The naming is predictable and easy to understand.

Tool Count5/5

Six tools is an appropriate count for an Ansible Galaxy collection explorer—covering search, listing, specs, and grading without being excessive or insufficient.

Completeness5/5

The tool set provides comprehensive coverage for exploring and preparing to use Ansible collections: search, list modules/roles, get detailed specs, and grade documentation quality. No obvious gaps.

Maintenance

ActivityInactive
ResponsivenessNo issues