Skip to content

Access Setup

The Access module covers UniFi Access doors, credentials, visitor passes, badge-scan events, and hub / reader hardware. v0.10 ships read-only tools only. Door unlocks, credential issuance, and visitor-pass creation are deferred to a future v0.11+ that introduces session-token auth alongside the API key.

UniFi Access has a wrinkle that Network and Protect do not: mutations require a local username / password session, not the local API key. The API key only authorises GETs against the read-only endpoints.

v0.10 sticks with API-key reads (Option A in the spec) so the project’s API-key-first security posture stays intact. No admin password ever sits in env. The 18 read-only tools cover forensics, audits, summaries, and visibility, which is the bulk of LLM use cases for Access.

When write tools land in a later release, they will require setting UNIFI_ACCESS_USERNAME and UNIFI_ACCESS_PASSWORD alongside the API key and the bearer token still gates the MCP transport unchanged.

The Access module is opt-in. Add it to MCP_UNIFI_MODULES_ENABLED:

Terminal window
# All three modules
MCP_UNIFI_MODULES_ENABLED=network,protect,access
# Access only
MCP_UNIFI_MODULES_ENABLED=access

If the env var is unset, only Network loads.

If you have one UniFi controller and the Access hub is co-located or reachable from the same env, set:

Terminal window
UNIFI_HOST=192.168.1.1
UNIFI_API_KEY=<network-api-key>
UNIFI_ACCESS_HOST=192.168.1.20 # often the same as UNIFI_HOST
UNIFI_ACCESS_PORT=12445 # default; the direct Access app port
UNIFI_ACCESS_API_KEY=<access-api-key>

The Access API key is separate from the Network API key. Generate it under the Access controller’s developer settings, not Settings → Control Plane → Integrations on the gateway.

When using MCP_UNIFI_CONTROLLERS_FILE, set the per-controller access_* fields:

- name: home
host: 192.168.1.1
api_key: <home-network-key>
port: 443
access_host: 192.168.1.20
access_port: 12445
access_api_key: <home-access-key>
- name: office
host: 10.0.0.1
api_key: <office-network-key>
# No access_* fields — office controller has no Access hub.

Controllers without access_host and access_api_key simply do not register an Access backend. Calls to Access tools that target those controllers return an UnknownControllerError envelope.

Set STUB_MODE=true (the default) and the module wires an in-memory state with 2 doors, 1 door group, 1 access policy, 3 credentials (NFC / PIN / mobile), 1 visitor pass, 50 synthetic events, 3 users, 1 hub, 2 readers. No hardware required.

This is the v0.10 development substrate: real-mode integration tests are respx-mocked because Pete does not have Access hardware. A community tester (or future hardware acquisition) is what validates real mode in a v0.10.x point release.

After starting the server with MCP_UNIFI_MODULES_ENABLED including access, call any read tool. From an MCP client (Claude Desktop, n8n, etc):

list_doors(controller="default")

Expected: a JSON list of doors. If you see Access backends are not configured on this registry, you set the module name but did not provide UNIFI_ACCESS_HOST + UNIFI_ACCESS_API_KEY. Add them and restart.

Audit credentials about to expire:

audit_expiring_credentials(days_ahead=30)

Returns every credential whose expires_at falls inside the next 30 days, sorted by closest expiry first, with a computed days_until_expiry so the LLM does not have to do the math.

Find recent failed entries on the server room door:

list_failed_access_attempts(door_id="<door_id>", hours_back=24)

Each entry includes the reason (expired, off-hours, unknown_pin, etc.) so the LLM can summarise the cause distribution.

Who badged in where over the last day:

summarize_access_activity(hours_back=24)

Returns total, granted, denied, plus by_door and by_user rollups sorted by activity volume.