aos8-mcp-server-iap
# aos8-mcp-server-IAP
A read-only MCP server for **Aruba Instant APs** (Instant AOS-8). It exposes the Instant AP
monitoring REST API as MCP tools and guided prompts, so an AI assistant can answer questions
about a swarm without being able to change it.
It follows the architecture of [`teze3808/aos8-mcp-server`](https://github.com/teze3808/aos8-mcp-server),
which targets AOS-8 **controllers**. The Instant AP API is a different API, so this is a
separate implementation rather than a fork.
## Overview
Once configured, an assistant can answer questions like:
- "Which APs in the swarm are reporting high channel utilization?"
- "Which SSIDs are still open?"
- "Which AP is the client at `00:11:22:33:44:55` connected to?"
- "Do all members of the swarm share the same config checksum?"
## Operational Scope
- Implemented: read-only `show` commands through `/rest/show-cmd`, bounded by a policy allowlist.
- Implemented: deterministic analyzers that produce findings before an AI summarizes them.
- Not implemented: any `POST` write. No Action API, no Configuration API, no `os-upgrade`,
no `ap-reboot`.
- Planned for v0.2: plan-only configuration previews that build and validate a payload
without sending it.
## Instant AP vs AOS-8 controller
| | AOS-8 controller | Instant AP (this server) |
| --- | --- | --- |
| Login | `POST /v1/api/login`, cookie + `X-CSRF-Token` | `POST /rest/login` JSON, returns `sid` |
| Auth per request | cookie + CSRF header | `sid` in the **query string** |
| Monitoring | `GET /v1/configuration/showcommand`, JSON tables | `GET /rest/show-cmd`, **raw CLI text** |
| Config read | `GET /v1/configuration/object/<name>` | not available; only `show` commands |
| Errors | HTTP status codes | HTTP 200 with `Status-code` 0–8 in the body |
| Availability | any managed node | **master or standalone AP only** |
## APIs Used
```text
POST /rest/login
POST /rest/logout
GET /rest/show-cmd?iap_ip_addr=<ipv4>&cmd=<show command>&sid=<sid>
```
## Tools
**Inventory and state** — `iap_test_connection`, `iap_get_version`, `iap_get_summary`,
`iap_get_access_points`, `iap_get_clients`, `iap_get_networks`, `iap_get_network_detail`,
`iap_get_ap_stats`, `iap_get_client_status`, `iap_get_wired_port_settings`,
`iap_get_port_status`, `iap_get_ap_env`, `iap_get_bootup_log`
**Analysis** — `iap_get_health_summary`, `iap_analyze_wlan_security`
**Escape hatch and introspection** — `iap_show_command` (allowlisted only), `iap_list_targets`
Every tool accepts an optional `iap_ip_addr`. Omit it to use the master or standalone AP;
pass a member AP's IPv4 address to read that member through the master.
Every tool also accepts an optional `cluster_name`, which picks the Instant AP cluster/swarm
to talk to (see [Multiple clusters](#multiple-clusters) below). Omit it when only one cluster
is configured; it is required when more than one is.
`iap_get_access_points`, `iap_get_clients`, and `iap_get_networks` page their results
(`limit`, default 50; `offset`; `include_extra`). A production swarm is large — 227 APs
serialize to roughly 220 KB — so each response reports `total`, `returned`, `offset`, and
`next_offset` alongside the page.
## Guided Prompts
`iap_health_overview`, `iap_troubleshoot_client`, `iap_wlan_security_review`,
`iap_swarm_review`, `iap_safe_show_command`
## Setup
### 1. Enable the REST API on the Instant AP
The REST API is **disabled by default** and is served only by the master (Virtual Controller)
or a standalone AP:
```text
(Instant AP)(config)# allow-rest-api
(Instant AP)(config)# end
(Instant AP)# commit apply
```
### 2. Configure this server
```bash
uv sync
cp .env.example .env
```
```env
IAP_BASE_URL=https://192.0.2.10:4343
IAP_USERNAME=admin
IAP_PASSWORD=your-password
IAP_VERIFY_SSL=true
```
Do not commit `.env`.
`/rest/show-cmd` requires an IPv4 `iap_ip_addr`. When `IAP_BASE_URL` uses a DNS name, set
`IAP_DEFAULT_IAP_IP_ADDR` to the master AP's IPv4 address; otherwise the server reports the
problem at the first call instead of failing on the AP.
`IAP_VERIFY_SSL=true` verifies that the AP presents a certificate trusted by the local
machine or by `IAP_CA_BUNDLE`. Instant APs commonly ship a self-signed certificate; set
`IAP_VERIFY_SSL=false` only for a temporary lab connection.
#### Multiple clusters
To reach more than one Instant AP cluster/swarm from one running server, set `IAP_CLUSTERS`
instead of `IAP_BASE_URL`/`IAP_USERNAME`/`IAP_PASSWORD` — a JSON array of cluster objects,
each with its own `name`, `base_url`, `username`, `password`, and (optionally)
`verify_ssl`, `ca_bundle`, `default_iap_ip_addr`, `allowed_iap_ips`. Call `iap_list_targets`
to see every configured cluster, then pass that cluster's `name` as `cluster_name` on
subsequent tool calls. Credentials for every cluster live in the same local `.env` file as
today, under the same trust model — do not commit it.
```env
IAP_CLUSTERS=[
{"name": "site-a", "base_url": "https://192.0.2.10:4343", "username": "admin",
"password": "change-me-a", "allowed_iap_ips": []},
{"name": "site-b", "base_url": "https://192.0.2.20:4343", "username": "admin",
"password": "change-me-b", "default_iap_ip_addr": "192.0.2.20", "allowed_iap_ips": []}
]
```
With one cluster configured, `cluster_name` may be omitted on every tool call. With more
than one, omitting it raises a clear error rather than guessing which cluster to use.
### 3. Verify
```bash
uv run iap-mcp-check
```
## Run Locally
```bash
uv run iap-mcp-server
```
With the MCP inspector:
```bash
uv run mcp dev src/aruba_iap_mcp/server.py
```
## MCP Client Configuration
### Claude Code
```bash
claude mcp add iap --env IAP_BASE_URL=https://192.0.2.10:4343 --env IAP_USERNAME=admin --env IAP_PASSWORD=your-password -- uv --directory /path/to/aos8-mcp-server-IAP run iap-mcp-server
```
### Claude Desktop, Codex, VS Code
```json
{
"mcpServers": {
"iap": {
"command": "uv",
"args": ["--directory", "/path/to/aos8-mcp-server-IAP", "run", "iap-mcp-server"],
"env": {
"IAP_BASE_URL": "https://192.0.2.10:4343",
"IAP_USERNAME": "admin",
"IAP_PASSWORD": "your-password"
}
}
}
}
```
For multiple clusters, set `IAP_CLUSTERS` in the project's `.env` file (see
[Multiple clusters](#multiple-clusters)) instead of passing it through `--env` or the `env`
block above — the server reads `.env` from its working directory at startup, so the client
config only needs `command`/`args`/`--directory`, no `env` overrides required.
## Notes
- `show running-config` is blocked by default. It is a supported command, but its output
contains WPA passphrases, RADIUS secrets, and SNMP communities. `IAP_ALLOW_RUNNING_CONFIG=true`
opts in; redaction still applies.
- The Instant AP answers HTTP 200 even for failures, so the `Status-code` in the body is the
real result. Codes 2–8 are caller or device-state problems and are never retried. Only
transport errors, HTTP 429, and HTTP 5xx are retried with exponential backoff.
- CLI output parsing is header-driven and degrades to raw text. A response with
`_meta.parsed = false` means the table shape was not recognized, not that the call failed.
- Openness is judged from **Key Management**, not Authentication Method. On a real swarm
every PSK network reports `Authentication Method: None`, so reading that field as "open"
produces false criticals.
- Parsers and field mapping were validated against a live Instant AOS-8.12.0.1 swarm
(227 APs, 407 clients, 6 networks); every column that release emits maps to a model
field. Older releases may emit different columns — unmapped ones are preserved under
`extra` (`include_extra=true`) rather than dropped. See [RUNBOOK.md](RUNBOOK.md).
- This project targets a trusted, single-user, local `stdio` deployment.
## Compatibility
| Component | Status |
| --- | --- |
| Python | 3.11, 3.12, 3.13 |
| Instant AOS-8 | verified on 8.12.0.1; 8.5.0.0+ expected (REST API introduced there) |
| Transport | local `stdio` |
| Remote / multi-user MCP | not supported |
TDQS
Scored across 17 tools
Each tool targets a distinct resource or aspect (version, summary, APs, clients, networks, ports, logs, security), with clear list/detail pairs. Minor overlap exists between iap_get_summary and iap_get_health_summary, and iap_show_command could be confused with structured getters, but descriptions make the boundaries reasonably clear.
All tools share the iap_ prefix and follow a consistent verb_noun pattern: test_connection, get_version, show_command, analyze_wlan_security, list_targets. The naming is uniformly snake_case and predictable across both collection and single-resource operations.
At 17 tools, the set is within the 16-25 range that feels heavy for a read-only monitoring/analysis surface. Each tool does have a distinct purpose, but the count is slightly more than necessary for the apparent scope.
The tool surface covers connectivity validation, version, swarm summary, AP inventory, clients, WLAN networks, port settings/status, logs, health summary, security analysis, and a raw show-command fallback. For a read-only Instant AP monitoring server, there are no obvious dead ends or missing operations.