UniFi MCP Server API Documentation
This document provides comprehensive documentation for the Model Context Protocol (MCP) server that exposes UniFi Network Controller functionality. The server enables AI agents and other applications to interact with UniFi network infrastructure in a standardized way.Table of Contents
- Overview
- Configuration
- Connecting to the cloud API and local gateways together
- Authentication
- Performance Tracking
- MCP Tools
- MCP Resources
- MCP Prompts
- A2A Endpoints
- A2A Error Handling
- Resource Error Handling
- Rate Limiting
- Examples
Overview
The UniFi MCP Server bridges the gap between AI applications and UniFi Network Controllers by exposing network management capabilities as MCP tools and resources. It handles authentication, request formatting, and error handling, providing a clean interface for network automation. This API reference is aligned to the current implementation baseline and the forward architecture described inSPEC.md.
Operator usage
Objective
Use this reference to verify the exposed MCP surface before changing configs, writing tests, or planning a rollout.Prerequisites
- You know the target API mode and transport mode.
- You know whether you need read-only verification or a write-path review.
- You have the current phase docs open alongside this reference.
Procedure
- Start with configuration and authentication to confirm the runtime assumptions.
- Read the feature surface that matches the current deployment mode.
- Cross-check any roadmap-dependent claims against
SPEC.md,DEVELOPMENT_PLAN.md, and the phase runbooks. - Use the examples and endpoint listings to validate the intended behavior before changing production state.
Verification
- The documented endpoint or tool exists in the current implementation.
- The reference does not overstate future features as live.
- The operator can map the doc to an actual test or validation step.
Rollback
- If the API reference drifts from the implementation, restate the supported surface and move aspirational material back to roadmap docs.
Common failure modes
- Treating roadmap language as if it were an implemented guarantee.
- Skipping the phase docs and relying on the API reference alone.
- Confusing future transport or auth modes with currently shipped behavior.
Architecture
Key Features
- Device Management: List, configure, and monitor UniFi devices
- Network Configuration: Manage networks, VLANs, and subnets
- Client Information: Query connected clients and their status
- Firewall Rules: Create and manage firewall rules
- Site Management: Work with multiple UniFi sites
- Real-time Monitoring: Access device and network statistics
- Roadmap alignment: native Protect, Access, multi-controller, dry-run, RBAC, audit, metrics, A2A, and webhooks are defined in
SPEC.md
Configuration
Environment Variables
Configure the MCP server using environment variables:Note: the table below includes both currently supported settings and planned controls that will become active as Phase 5 lands. | Variable | Description | Required | Default | |----------|-------------|----------|---------| |UNIFI_API_KEY| UniFi API Key (used for both Network and Site Manager APIs) | Yes | - | |UNIFI_API_TYPE| API type:cloud-ea,cloud-v1, orlocal| No |cloud-ea| |UNIFI_MIXED_MODE| Expose the cloud and local tool modules together, for a fleet whose registry holds both cloud controllers and local gateways. Without it the exposed modules follow the singleUNIFI_API_TYPE, so local-only tools are missing on a cloud-typed server even when a local gateway is registered. Needs noUNIFI_LOCAL_HOST: the gateways come from the registry. See Connecting to the cloud API and local gateways together | No |false| |UNIFI_LOCAL_HOST| Local gateway hostname or IP (required whenUNIFI_API_TYPE=local) | No* | - | |UNIFI_LOCAL_PORT| Local gateway port | No |443| |UNIFI_LOCAL_VERIFY_SSL| Verify the local gateway’s TLS certificate. Settingfalselogs a startup warning; preferUNIFI_LOCAL_CA_FILEfor self-signed certs | No |true| |UNIFI_LOCAL_CA_FILE| CA certificate (PEM) to verify the local gateway with, in place of the default roots. Checked at startup. Can be the console’s own self-signed certificate | No | - | |UNIFI_LOCAL_TLS_SERVER_NAME| Name to check the local gateway’s certificate against, and send as SNI, when it is notUNIFI_LOCAL_HOST. UniFi OS’s own certificate namesunifi.local, not the console’s address | No | - | |UNIFI_CLOUD_API_URL| UniFi Cloud API base URL | No |https://api.ui.com| |UNIFI_DEFAULT_SITE| Default site ID | No |default| |UNIFI_RATE_LIMIT_REQUESTS| Max requests per rate limit period | No |100| |UNIFI_RATE_LIMIT_PERIOD| Rate limit period in seconds | No |60| |UNIFI_REQUEST_TIMEOUT| Request timeout in seconds | No |30| |UNIFI_MAX_RETRIES| Maximum retry attempts | No |3| |UNIFI_RETRY_BACKOFF_FACTOR| Exponential backoff factor between retries | No |2.0| |UNIFI_RETRY_TOTAL_TIMEOUT| Wall-clock budget in seconds for one request, including all retries and backoff waits | No |60| |UNIFI_PROFILE| Tool exposure profile:network,devices,security,system,minimal,protect. An unrecognised value logs a warning and falls back to all modules | No | unset | |UNIFI_READ_ONLY| Register only non-mutating tools. State-changing tools are not exposed to the client at all | No |false| |UNIFI_DRY_RUN| Change-safe mode: every tool with adry_runparameter runs as a preview, and mutating tools without one are not registered | No |false| |UNIFI_AUDIT_LOG_ENABLED| Write an audit record for mutating operations | No |true| |UNIFI_AUDIT_LOG_PATH| Append-only audit log path. Relative paths resolve against the process working directory, which is not predictable under stdio transport — prefer an absolute path. The file is created mode 0600 | No |audit.log| |UNIFI_AUDIT_FAIL_CLOSED| Refuse a mutating tool call (and a read, withUNIFI_AUDIT_READS) when its audit record cannot be written. Setfalseonly as break-glass | No |true| |UNIFI_AUDIT_READS| Also audit read tool calls:attemptand outcome records with the principal, tool, arguments and result, never the response payload | No |false| |UNIFI_AUDIT_CHAIN_KEY| HMAC key for the audit hash chain; without it the chain uses plain SHA-256, which detects edits but can be recomputed by anyone who can write the file | No | unset | |UNIFI_AUDIT_SIEM_TARGETS| Comma-separated SIEM destinations for stored audit records:syslog+tls://host:6514,https://host/path(signed webhook),otlp+https://collector:4318(see SECURITY.md). RequiresUNIFI_AUDIT_CHAIN_KEY| No | unset | |UNIFI_AUDIT_SIEM_WEBHOOK_SECRET| HMAC-SHA256 key signing webhook deliveries; required forhttps://targets | With a webhook | unset | |UNIFI_AUDIT_SIEM_OTLP_HEADERS| Extra headers for OTLP targets,key=value,key=value| No | unset | |UNIFI_AUDIT_SIEM_CA_FILE| CA bundle used to verify SIEM targets | No | system roots | |UNIFI_AUDIT_SIEM_BUFFER_DIR| On-disk buffer for undelivered records | No |siem-buffernext to the audit log | |UNIFI_AUDIT_SIEM_BUFFER_MAX_MB| Most undelivered data kept per target; the oldest is dropped beyond it | No |100| |UNIFI_AUDIT_LOG_ROTATE_MB| Rotate the JSONL audit file at this size into<log>.<UTC time>Zfiles; the chain continues across them | No | unset (never rotate) | |UNIFI_AUDIT_RETENTION_DAYS| Archive and delete audit records older than this: Postgres withpython -m src.fleet.cli audit-retention --confirm, rotated JSONL files withpython -m src.utils.audit_retention LOG --confirm(see SECURITY.md) | No | unset (keep forever) | |UNIFI_AUDIT_ARCHIVE_DIR| Where retention writes its archives | No |audit-archivenext to the audit log | |UNIFI_AUDIT_SIEM_ANCHOR_SECONDS| How often each chain’s head is sent to the SIEM as an anchor | No |300| |DATABASE_URL| Postgres URL of the fleet controller registry. When set, controllers come from Postgres instead of theUNIFI_*settings (needs the[fleet]extra andpython -m src.fleet.cli migrate) | No | unset | |UNIFI_FLEET_CREDENTIAL_KEY| Encrypts the controller API keys stored in Postgres; required withDATABASE_URL| WithDATABASE_URL| unset | |UNIFI_FLEET_REGISTRY_REFRESH_SECONDS| How often each server reloads the registry from Postgres | No |30| |UNIFI_FLEET_MAX_OPEN_CLIENTS| Most controller connections each server keeps open; least recently used idle ones are closed beyond this (controller state such as cached auth is kept) | No |256| |UNIFI_FLEET_EXPECTED_REPLICAS| How many processes (server replicas and workers) share each controller’s rate limit. While Redis is unavailable each falls back toUNIFI_RATE_LIMIT_REQUESTSdivided by this (at least 1), so together they stay near the controller’s budget | No |1| |UNIFI_FLEET_FANOUT_CONCURRENCY| Most controllers onefleet_fanoutcall reaches at once | No |20| |UNIFI_FLEET_FANOUT_TIMEOUT_SECONDS| Default per-controller timeout offleet_fanout| No |15| |UNIFI_FLEET_FANOUT_DEADLINE_SECONDS| Default overall deadline offleet_fanout; controllers not done by then are reported as timed out | No |60| |UNIFI_FLEET_WORKER_HEALTH_SECONDS| Worker (python -m src.worker): how often each controller is health-checked | No |60| |UNIFI_FLEET_WORKER_SYNC_SECONDS| Worker: how often each controller’s sites and device inventory are refreshed | No |900| |UNIFI_FLEET_WORKER_CONCURRENCY| Worker: most controller jobs one worker runs at once | No |20| |UNIFI_FLEET_WORKER_LEASE_SECONDS| Worker: how long membership and controller leases last without renewal; a dead worker’s controllers move to the others after this | No |30| |UNIFI_FLEET_WORKER_DOWN_AFTER| Worker: consecutive failed health checks before a controller isdown(earlier failures mark itdegraded) | No |3| |MIGRATION_DATABASE_URL| Used bypython -m src.fleet.cli migrate/statusinstead ofDATABASE_URL, so the schema owner can differ from the server’s least-privilege role | No | unset | |UNIFI_STDIO_ROLE| Role of the local stdio caller:viewer,operator,adminorfleet-admin| No |fleet-admin| |UNIFI_METRICS_ENABLED| Enable Prometheus metrics server | No |false| |WEBHOOK_SECRET| HMAC-SHA256 key verifyingX-UniFi-SignatureonPOST /webhooks/unifi; without it the receiver refuses every request | To receive webhooks | unset | |UNIFI_CACHE_ENABLED| Use the Redis read cache when Redis is configured; setfalseto bypass it | No |true| |REDIS_URL| Redis URL for the response cache; takes precedence overREDIS_HOST/PORT/DB/PASSWORD| No | unset | |REDIS_HOST/REDIS_PORT/REDIS_DB/REDIS_PASSWORD| Redis location for the response cache | No |localhost/6379/0/ unset | |UNIFI_SITE_MANAGER_ENABLED| Enable Site Manager API multi-site tools | No |false| |MCP_SERVER_TRANSPORT| Transport:stdio,http,sse,streamable_http| No |stdio| |MCP_SERVER_HOST| Server bind address forhttp/sse/streamable_http| No |127.0.0.1| |MCP_SERVER_PORT| Server port (http/sse transports) | No |3000| |MCP_AUTH_MAX_FAILURES| Failed bearer-token checks (401) allowed per client address withinMCP_AUTH_FAILURE_WINDOW_SECONDSon a network transport. Past that the address gets429withRetry-Afteron every route except/healthzuntil the window clears.0disables it. Behind a reverse proxy every client shares the proxy’s address unless uvicorn trusts itsX-Forwarded-For(FORWARDED_ALLOW_IPS) | No |10| |MCP_AUTH_FAILURE_WINDOW_SECONDS| Sliding window forMCP_AUTH_MAX_FAILURES| No |60| |MCP_STATELESS_HTTP| Run the HTTP transports without MCP sessions so any replica can answer any request (ignored for stdio and SSE).select_controlleris then refused: passcontroller=<name>per call. The default (stateful) mode needs per-client sticky routing across replicas, keyed on something stable frominitializeonward (seeMULTI_CONTROLLER.md) | No |false| |MCP_AUTH_TOKEN| Bearer token required to call the server over a network transport; comma-separate for several. Write an entry as<role>:<token>(viewer,operator,admin,fleet-admin) to give it a role; a bare token isfleet-admin. A misspelled or wrong-case role (Viewer:,veiwer:) stops the server instead of becoming afleet-admintoken.http/sse/streamable_httprefuse to start without it. Ignored forstdio| No | unset | |DEBUG| Registerdebug_api_request, an arbitrary GET or DELETE to any controller endpoint (destructive tier; never registered underUNIFI_READ_ONLY). Leave unset in production | No | unset | |LOG_LEVEL| Logging level:DEBUG,INFO,WARNING,ERROR| No |INFO| |LOG_API_REQUESTS| Log each controller API request | No |true| |UNIFI_CACHE_TTL| Accepted but not used: read-cache lifetimes are fixed per resource type (sites, networks and WLANs 5 min, devices 1 min, clients 30 s) | No |300| |UNIFI_BACKUP_DOWNLOAD_DIR| Directorydownload_backupwrites into; the caller names only the file | No |.| |SUPERMEMORY_ENABLED| Enable the Supermemory integration for operator notes | No |false| |SUPERMEMORY_API_KEY| Supermemory API key | WithSUPERMEMORY_ENABLED| unset |
- Required when
UNIFI_API_TYPE=local.
Configuration File
Alternatively, use aconfig.yaml file:
Connecting to the cloud API and local gateways together
One server can talk to the UniFi cloud API, to a local gateway, or to several of each at once. Three topologies are supported; which one you are in is decided by whetherDATABASE_URL is set and whether UNIFI_MIXED_MODE is on.
1. One controller, from the environment
NoDATABASE_URL. UNIFI_API_TYPE picks the backend and the UNIFI_*
variables describe it; the registry holds a single controller named default.
UNIFI_API_TYPE:
local registers the cloud and local modules, a cloud type registers only
the cloud ones.
2. Several controllers, from Postgres (fleet mode)
SetDATABASE_URL and UNIFI_FLEET_CREDENTIAL_KEY, run
python -m src.fleet.cli migrate, then register each controller. Any mix of
local gateways and cloud controllers is allowed, each with its own API key,
stored encrypted in the database — not in the environment:
credentials table as a Fernet ciphertext, encrypted
with UNIFI_FLEET_CREDENTIAL_KEY; list_controllers never returns a
credential, and rotate_fleet_credentials re-encrypts every stored key under a
new one. Calls are routed per call with controller=<name>, per session with
select_controller, or to the registry default. See MULTI_CONTROLLER.md.
3. Mixed cloud and local, in one server
Fleet mode routes to controllers of any type, but the tool modules are chosen once at start-up from the baseUNIFI_API_TYPE. On a cloud-typed
server the local-only modules (firewall zones and policies, MAC tags,
switching, QoS, RADIUS, Protect, topology and the rest) are therefore never
registered, so a registered local gateway is routable while most of its tools
do not exist.
Set UNIFI_MIXED_MODE=true to register the union instead:
- the cloud and local tool modules are both registered, so a call routed to a cloud controller reaches the cloud tools and a call routed to a local gateway reaches the local ones;
- no base
UNIFI_LOCAL_HOSTis needed — the gateways come from the registry; UNIFI_PROFILEstill narrows the union, soUNIFI_PROFILE=protectin mixed mode exposes the Protect modules only;- the start-up log names the mode and the module count, so the exposed surface is visible rather than inferred.
controller argument and are built from the process-wide
settings — so they stay gated on the base UNIFI_API_TYPE: a cloud base
exposes no local resources even with mixed mode on. Read a specific gateway
with a tool and controller=<name> instead.
Mixed mode changes which tools exist, never which controller a call reaches
or what a role may do: routing, the risk tiers, UNIFI_READ_ONLY,
UNIFI_DRY_RUN and the audit trail are unchanged.
Limitations
- A tool must be registered to be reachable. A module outside the
registered set cannot be called on any controller, whatever its type. This is
what
UNIFI_MIXED_MODEexists to fix. - MCP resources always read the default controller. The
sites://family and friends take nocontrollerargument; use the tools for a specific controller. Because they are built from the process-wide settings and cannot be routed, they stay gated on the baseUNIFI_API_TYPE— mixed mode does not expose local resources on a cloud base. - Tool modules are process-wide. A cloud-only call routed to a cloud controller still fails on a local-only endpoint, and the reverse, because the endpoint does not exist on that backend — mixed mode registers both sets, it does not make an endpoint appear on a controller that lacks it.
- One API type per registered controller. A controller entry is
local,cloud-eaorcloud-v1; to reach the same hardware both ways, register it twice under different names.
Performance Tracking
Agnost.ai Integration (Optional)
The UniFi MCP Server includes optional performance tracking powered by agnost.ai to monitor server performance, usage patterns, and identify optimization opportunities.Features
- Real-time Performance Metrics: Track tool execution times, success rates, and error patterns
- User Analytics: Monitor which tools are most frequently used and by whom
- Resource Access Patterns: Understand how MCP resources are accessed
- Error Tracking: Automatic error capture with stack traces and context
- Custom Event Tracking: Track specific business events (device adoptions, configuration changes)
- Dashboard: Visual analytics dashboard for performance insights
Configuration
Performance tracking is disabled by default and can be enabled via environment variables:Tracking Controls
The agnost integration provides granular control over what data is tracked: Input Tracking (disable_input):
- When
false(default): Tool input parameters are tracked - When
true: Input parameters are excluded from tracking - Use this to prevent sensitive configuration data from being sent
disable_output):
- When
false(default): Tool results and outputs are tracked - When
true: Output data is excluded from tracking - Use this to prevent sensitive response data from being sent
Tracked Metrics
The following metrics are automatically tracked by agnost.ai: Tool Invocation Metrics:- Tool name
- Input parameters (if
disable_input=false) - Output results (if
disable_output=false) - Execution time (milliseconds)
- Success/failure status
- Error messages (if any)
- Resource URI accessed
- Response data (if
disable_output=false) - Response size
- Access patterns
- Error type and message
- Stack trace and context
- Request metadata
- Frequency and patterns
- Average execution time per tool
- Tool usage frequency
- Peak usage times
- Success/failure rates
Privacy & Security
Data Protection:- Granular control via
disable_inputanddisable_outputflags - Sensitive data (API keys, passwords) automatically masked in logs
- All data encrypted in transit (HTTPS)
- Opt-in only (disabled by default)
- Disable input tracking to prevent parameter exposure
- Disable output tracking to prevent response data exposure
- Complete opt-out by setting
AGNOST_ENABLED=false - No personally identifiable information (PII) collected by default
- GDPR compliant data handling
- Configurable data retention policies via agnost.ai dashboard
- Transparent data collection (documented in this API guide)
- Data encrypted in transit and at rest
Example Configurations
Full Tracking (Docker):Viewing Analytics
Once configured, visit your agnost.ai dashboard at app.agnost.ai to view:- Real-time Performance Metrics: Tool execution times and latency
- Usage Trends: Most frequently used tools and resources
- Error Rates: Failure patterns and error types
- Performance Bottlenecks: Slowest operations and optimization opportunities
- Historical Data: Trends over time for capacity planning
MCP Toolbox Dashboard
For a web-based analytics dashboard with visual metrics and debugging tools, use MCP Toolbox:- Real-time performance monitoring
- Visual analytics and graphs
- Error tracking and debugging
- Historical trend analysis
- Request/response inspection
Authentication
Obtaining Your API Key
The UniFi MCP Server uses the official UniFi Cloud API with API key authentication:- Login to UniFi Site Manager
- Navigate to Settings → Control Plane → Integrations
- Create a new API Key by clicking “Create API Key”
- Save the key immediately - it’s only displayed once!
- Store the key securely in environment variables or secret management
Authentication Method
The server uses stateless API key authentication via theX-API-Key HTTP header:
API Access Modes
Cloud API (Recommended)- Base URL:
https://api.ui.com/v1/ - Access cloud-hosted UniFi instances
- Requires internet connectivity
- SSL verification recommended
- Base URL:
https://{gateway-ip}:{port}/proxy/network/integration - Access local UniFi gateway directly
- Works without internet
- May require SSL verification disabled for self-signed certificates
Current Limitations
- Read-Only Access: The Early Access API is currently read-only. Write operations will be available in future API versions and will require manual key updates.
- Rate Limiting: See Rate Limiting section below
Security Considerations
- Never hardcode API keys in your code
- Store API keys in environment variables or secure secret management systems (AWS Secrets Manager, HashiCorp Vault, etc.)
- Use HTTPS when connecting to the UniFi API (especially for cloud)
- Implement proper access controls for MCP server access
- Rotate keys regularly - API keys can be regenerated from unifi.ui.com
- Monitor API key usage for suspicious activity
- Treat API keys like passwords - they provide full access to your UniFi environment
MCP Tools
Tools are executable functions that perform actions on the UniFi Controller.Tool Categories
- Read-only Tools: Read-only operations for querying network information
- Mutating Tools: Mutating operations with safety mechanisms (confirm + dry-run)
Health Check
health_check
Verify the MCP server is running and accessible.
Parameters: None
Returns:
Server health status information.
Example:
Debug Passthrough
debug_api_request
Send a raw GET or DELETE to any controller endpoint. Registered only when DEBUG is true, 1 or yes, and never under UNIFI_READ_ONLY. Every call needs the destructive tier (admin or fleet-admin); UNIFI_DRY_RUN forces a preview.
Parameters:
endpoint(string, required): controller-relative API path starting with a single/, e.g./proxy/network/api/s/default/stat/device. Absolute (https://...) and scheme-relative (//host/...) URLs are refused, so the controller’s API key is never sent to another hostmethod(string, optional):GET(default) orDELETE; anything else is refusedconfirm(boolean, optional): must betruefor aDELETEunlessdry_runis setdry_run(boolean, optional): return the request instead of sending it
{"dry_run": true, "operation": "debug_api_request", "method": ..., "endpoint": ...}.
Example:
Controller Selection
Every controller-bound tool accepts an optionalcontroller argument naming the controller to run against. Without it, a call goes to the controller chosen with select_controller in the current MCP session, then to the server’s default. A mutating tool may not fall back to the server default when more than one controller is registered: it needs controller= or a select_controller in the same session. Until the controller registry ships (see docs/FLEET_SCALING_PLAN.md), the server has one controller, default, built from the UNIFI_* settings. MCP resources (sites:// and friends) always use the default controller.
list_controllers
List the controllers this server can reach: name, API type, host, default site and labels (never credentials), plus the default controller and this session’s selection.
Parameters: None
select_controller
Choose the controller this session’s later tool calls target. A call’s own controller argument still takes precedence.
Parameters: name (string, required) — a name from list_controllers
get_active_controller
Show which controller a call without controller would target, and whether it comes from the session (select_controller) or the default.
Parameters: None
Fleet Registry Administration
Available only whenDATABASE_URL is set, and never in read-only mode. These tools manage the controller registry rather than a controller, so they take no controller argument. They are fleet-admin tier, need confirm=true, accept dry_run, and every call is audited as an admin event with API keys redacted. A change is routable on the server that made it immediately, on other servers at once when Redis is configured (registry:changed pub/sub), and otherwise within UNIFI_FLEET_REGISTRY_REFRESH_SECONDS.
register_controller
Register a controller. Give it its own api_key (stored encrypted), or name a cloud_account to share that account’s key.
Parameters: name (required), api_type (local, cloud-ea, cloud-v1; required), local_host (required for local), local_port, local_verify_ssl, cloud_api_url, default_site, api_key, cloud_account, labels, make_default, confirm, dry_run
update_controller
Change a controller; only the fields passed change. enabled=false takes it out of routing without deleting it; make_default=true moves the default to it.
Parameters: name (required), local_host, local_port, local_verify_ssl, cloud_api_url, default_site, labels, enabled, api_key, make_default, confirm, dry_run
register_cloud_account
Register a cloud (Site Manager) API key that cloud controllers can share.
Parameters: name (required), api_key (required), api_type (default cloud-ea), cloud_api_url, labels, confirm, dry_run
rotate_fleet_credentials
Re-encrypt every stored API key under the newest UNIFI_FLEET_CREDENTIAL_KEY key. Put the new key first (new,old), run this, then remove the old key.
Parameters: confirm, dry_run
Access control
Every tool has a risk tier:read, write, destructive or fleet-admin. A caller’s role grants tiers: viewer (read), operator (+ write), admin (+ destructive), fleet-admin (+ registry, token and audit tools). Destructive tools include deletes, restores, restarts, client blocking and firewall policy changes (create_firewall_policy, update_firewall_policy, update_zbf_policy, create_firewall_rule, update_firewall_rule, assign_network_to_zone, unassign_network_from_zone), so an operator cannot change which traffic the firewall allows. A token can be narrowed further by allow_modules/deny_modules (patterns over tool module names, e.g. protect_*) and controller_labels (a controller must carry all of them). A refused call fails with Permission denied: <tool> needs the '<tier>' tier and is recorded as a denied audit event. MCP_AUTH_TOKEN tokens and stdio are break-glass fleet-admin callers (stdio’s role is set by UNIFI_STDIO_ROLE). An MCP_AUTH_TOKEN entry written <role>:<token>, for example viewer:<token>, gets that role instead, with or without the fleet registry, so a single host can issue a read-only token. Static tokens take no module or controller filters; use issued tokens for those.
create_api_token
Issue a bearer token; its value is returned only in this result (only a hash is stored). Parameters: name, role (required), expires_in_days (default 90; 0 never expires), allow_modules, deny_modules, controller_labels, confirm, dry_run
list_api_tokens
Token names, roles, filters and dates, never values. Parameters: None
revoke_api_token / update_api_token_role
Revoke a token, or change its role. Every server applies the change within 30 seconds. Parameters: name (and role), confirm, dry_run
search_audit_log
Search the Postgres audit trail, newest first, with payloads decrypted when the audit key is set. Each search is itself audited. Parameters: since, until (ISO 8601), event_type, operation, principal, controller, result, limit (max 1000), cursor
verify_audit_chain
Check every server’s hash chain for edited, missing or reordered records, that each chain ends exactly at its audit_chain_heads entry (so records deleted from the end of a chain, a whole chain, or the whole table are reported, and so is a chain whose head was deleted), and that each row’s searchable columns match its sealed record. Returns the chain heads to keep off the server. Parameters: None
export_audit_log
Export stored records (payloads still encrypted) as JSON lines, verifiable with python -m src.utils.audit_verify. Parameters: since, until, limit (max 1000)
Operator CLI (needs only DATABASE_URL, except import):
Fleet-Wide Reads
Available whenDATABASE_URL is set. All six are read tier, from the module fleet (so deny_modules: ["fleet"] removes them), take no controller argument, and cover only the controllers inside the caller’s controller_labels scope. Naming a controller that is unknown, disabled or out of scope is refused without saying which.
fleet_health, fleet_sites and fleet_inventory answer from the worker’s snapshots (python -m src.worker, see MULTI_CONTROLLER.md) with one database query and no controller calls; fleet_compare_versions and fleet_compare_sites also read those snapshots but return comparison summaries without per-entry age fields. Without a running worker, these snapshot tools return unknown health or no sites/devices as applicable.
fleet_health
Each enabled controller’s last health check: ok, degraded (failing), down (UNIFI_FLEET_WORKER_DOWN_AFTER failures in a row) or unknown (never checked), the failure detail, capabilities (network_version on local controllers), and ages. An entry is stale when its last check is more than three health intervals old. Also returns a count per state.
Network 11 / UniFi OS 6 platform compatibility. A controller with a USG gateway anywhere in its synced device inventory carries a platform_compat field: {"network_11_capable": false, "reason": "..."}. USG support ends at Network 10.6, so that site has no Network 11 target at all (DEVELOPMENT_PLAN.md §4 Phase 8, Fix 6). platform_compat is absent — not null, not true — on every other controller, including cloud controllers (the worker never inventories them) and any local controller the worker has not yet synced; absence means “no USG-gating signal found”, not an affirmative “compatible” result. There is no corresponding field for the other platform break (a classic, self-hosted Network Application Server): the Integration API’s /v1/info has no host-type field, so it cannot be auto-detected — label that controller instead (e.g. deployment=classic-server) and filter fleet_health/fleet_sites on the labels parameter. See docs/NETWORK_11_COMPATIBILITY.md for the full compatibility matrix.
health (ok, degraded, down or unknown), labels (controllers carrying all of these)
fleet_sites
Every controller’s sites: controller, site_id (UUID), short name, display name, age.
Parameters: controllers (names), labels
fleet_inventory
Devices across the fleet (local controllers; the worker does not inventory cloud controllers): controller, site, id, MAC, name, model, firmware, state, age. Also the total match count and a count per model.
Parameters: model (substring, case-insensitive, e.g. UDM), firmware_below (numeric comparison, e.g. 4.1.0; devices without a version are left out), state (e.g. OFFLINE), controllers, labels, limit (default 200, max 1000), offset
fleet_compare_versions
Compare firmware versions for one model across controllers. Returns the set of versions seen, the newest version, per-controller counts and versions, and a behind flag for each controller that does not have the newest version. Devices with no recorded version are not considered behind. Each model and controller entry also reports the age of the oldest inventory snapshot it used and a stale flag when that age exceeds three health-check intervals.
Parameters: model (substring, case-insensitive), controllers, labels
fleet_compare_sites
Compare site short names across controllers. Returns the sites common to every controller compared, the sites unique to each controller, and the full per-controller site lists. Controllers with no synced sites contribute nothing to the common set. Every site entry includes the age of its snapshot; the response also reports the oldest snapshot age per controller and overall, plus a top-level stale flag when the overall age exceeds three health-check intervals.
Parameters: controllers, labels
fleet_fanout
Run one read-tier controller tool live on many controllers: at most UNIFI_FLEET_FANOUT_CONCURRENCY at once, each with its own timeout, all under one deadline. Each controller gets its own result, so one unreachable controller never fails the call. Every per-controller call goes through the normal pipeline: the caller’s role, module filters and controller scope apply to it, and cached reads are served from the read cache. Write, destructive and fleet_* tools are refused. Prefer the snapshot tools above when they cover the question.
Parameters: tool (required, e.g. list_devices), arguments (the tool’s arguments except controller), controllers, labels, timeout_seconds (default UNIFI_FLEET_FANOUT_TIMEOUT_SECONDS), deadline_seconds (default UNIFI_FLEET_FANOUT_DEADLINE_SECONDS)
Protect Phase 3 Tools
Protect tools are exposed in local API mode and can be isolated withUNIFI_PROFILE=protect.
The currently implemented Protect MCP resources are:
protect://nvrsprotect://nvrs/{nvr_id}protect://camerasprotect://cameras/{camera_id}
update_protect_device,
update_protect_light, update_protect_sensor, update_protect_chime, update_protect_viewer,
create_protect_live_view, update_protect_live_view, and send_protect_alarm_webhook require
confirm=True and support dry_run.
Cameras
list_protect_cameras(limit=None, offset=None)get_protect_camera(camera_id)
NVRs
list_protect_nvrs()get_protect_nvr(nvr_id)
Devices, lights, sensors, and chimes
list_protect_devices(limit=None, offset=None)get_protect_device(device_id)update_protect_device(device_id, ...)list_protect_lights(limit=None, offset=None)get_protect_light(light_id)update_protect_light(light_id, ...)list_protect_sensors(limit=None, offset=None)get_protect_sensor(sensor_id)update_protect_sensor(sensor_id, ...)list_protect_chimes(limit=None, offset=None)get_protect_chime(chime_id)update_protect_chime(chime_id, ...)list_protect_device_updates(limit=None, offset=None)for device subscription messages
Views and viewers
get_protect_meta_info()list_protect_viewers(limit=None, offset=None)get_protect_viewer(viewer_id)update_protect_viewer(viewer_id, ...)list_protect_live_views(limit=None, offset=None)get_protect_live_view(live_view_id)create_protect_live_view(live_view)update_protect_live_view(live_view_id, ...)
Events and alarm webhooks
list_protect_events(limit=None, offset=None)get_protect_subscribe_events(limit=None, offset=None)compatibility aliasget_protect_event_messages(limit=None, offset=None)compatibility aliasget_protect_subscribe_devices(limit=None, offset=None)compatibility aliasget_protect_device_updates(limit=None, offset=None)compatibility aliassend_protect_alarm_webhook(webhook_id, payload=None):webhook_idis the alarm’s webhook trigger ID, one path segment of letters, digits,.,_,~,:and-
Still planned / not yet exposed
Snapshot capture, media stream helpers, talkback, and PTZ operations remain roadmap work.Device Management Tools
get_device_details
Get detailed information for a specific device.
Parameters:
site_id(string, required): Site identifierdevice_id(string, required): Device integration-API UUID (the IDs returned byget_network_topology). A legacy_idObjectId is also accepted.
/ea/ endpoints behind search_devices and
list_devices_by_type: mac_address rather than mac, ip_address rather
than ip, a string state ("ONLINE") rather than the legacy integer, and no
type field at all. Keys the controller does not report are omitted rather
than returned as null, so look keys up defensively — an absent key means “not
reported”, never “empty” or “false”.
Example:
get_device_statistics
Retrieve real-time statistics for a device.
Parameters:
site_id(string, required): Site identifierdevice_id(string, required): Device ID
list_devices_by_type
Filter devices by type (AP, switch, gateway).
Parameters:
site_id(string, required): Site identifierdevice_type(string, required): Device type filter (uap, usw, ugw, udm, uxg, etc.)
search_devices
Search devices by name, MAC, or IP address.
Parameters:
site_id(string, required): Site identifierquery(string, required): Search query string
list_pending_devices
List devices on a site that are waiting to be adopted.
Parameters:
site_id(string, required): Site identifierlimit(integer, optional): Maximum number of devices to returnoffset(integer, optional): Number of devices to skip
mac, ip, integer state),
one per device the controller reports with adopted: false. The Integration
v1 API has no pending-devices route, so this reads the legacy stat/device
endpoint and filters it.
The controller assigns a device its _id when it adopts it, so a pending
device has id: null. Key a pending device by its mac, which is the
identifier adopt_device takes. Do not pass id to any device tool for a
pending record.
Example:
null; the response above omits the remaining optional fields for brevity.
Client Management Tools
get_client_details
Get detailed information for a specific client.
Parameters:
site_id(string, required): Site identifierclient_mac(string, required): Client MAC address
get_client_statistics
Retrieve bandwidth and connection statistics for a client.
Parameters:
site_id(string, required): Site identifierclient_mac(string, required): Client MAC address
list_active_clients
List currently connected clients.
Parameters:
site_id(string, required): Site identifier
search_clients
Search clients by MAC, IP, or hostname.
Parameters:
site_id(string, required): Site identifierquery(string, required): Search query string
Network Information Tools
get_network_details
Get detailed network configuration.
Parameters:
site_id(string, required): Site identifiernetwork_id(string, required): Network ID
list_vlans
List all VLANs in a site.
Parameters:
site_id(string, required): Site identifier
get_subnet_info
Get subnet and DHCP information for a network.
Parameters:
site_id(string, required): Site identifiernetwork_id(string, required): Network ID
get_network_statistics
Retrieve network usage statistics for a site.
Parameters:
site_id(string, required): Site identifier
WAN and Dynamic DNS Tools
list_wan_connections
List WAN connections for a site.
Parameters:
site_id(string, required): Site identifier
id and name are guaranteed. The Integration v1
/sites/{site_id}/wans endpoint returns just those two fields and offers no
per-WAN detail route, so every other key — including site_id, wan_type,
interface, status, dns_servers and is_backup — may be missing. Fields
the controller does not report are omitted from the object rather than returned
as null, so consumers must look keys up defensively instead of assuming they
are always present. An absent key means “not reported”, never “empty” or
“false”.
Example:
list_dynamic_dns
List Dynamic DNS records for a site. This local API tool redacts stored password
material and returns password_configured instead.
Parameters:
site_id(string, required): Site identifier
get_dynamic_dns
Get one Dynamic DNS record by ID.
Parameters:
dynamic_dns_id(string, required): Dynamic DNS record IDsite_id(string, required): Site identifier
create_dynamic_dns
Create a Dynamic DNS record. Mutating operation; requires confirm=true unless
dry_run=true.
Parameters:
site_id(string, required): Site identifierhost_name(string, required): Hostname to updateservice(string, optional): Provider service name, defaultcustominterface(string, optional): WAN interface identifier, defaultwanlogin(string, optional): Provider login or usernamepassword(string, optional): Provider password or token, sent asx_passwordserver(string, optional): Provider server for custom configurationscustom_service(string, optional): Custom provider protocol/service labeloptions(array, optional): Provider-specific optionsconfirm(boolean/string, required for execution): Set true to applydry_run(boolean/string, optional): Preview without applying
update_dynamic_dns
Update a Dynamic DNS record. Mutating operation; requires confirm=true unless
dry_run=true.
Parameters:
dynamic_dns_id(string, required): Dynamic DNS record IDsite_id(string, required): Site identifierhost_name,service,interface,login,password,server,custom_service,options(optional): Fields to updateconfirm(boolean/string, required for execution): Set true to applydry_run(boolean/string, optional): Preview without applying
delete_dynamic_dns
Delete a Dynamic DNS record. Mutating operation; requires confirm=true unless
dry_run=true.
Parameters:
dynamic_dns_id(string, required): Dynamic DNS record IDsite_id(string, required): Site identifierconfirm(boolean/string, required for execution): Set true to applydry_run(boolean/string, optional): Preview without applying
Tagged MAC Tools
A tag is a named set of device MAC addresses (member_table). The controller
uses tags to target WiFi broadcasts at a subset of access points. These tools
read and write the local gateway’s legacy rest/tag endpoint and require
UNIFI_API_TYPE=local; list_device_tags is the read-only Integration API view.
MACs are accepted with any common separator and normalized to lowercase colon
form. Write tools compare what the controller stored against the request and
attach warnings on any difference.
list_mac_tags
List MAC tags on a site.
Parameters:
site_id(string, required): Site identifier
id, name, member_table (device MACs) and member_count.
get_mac_tag
Get one MAC tag by ID.
Parameters:
tag_id(string, required): Tag ID (24-hex ObjectId)site_id(string, required): Site identifier
create_mac_tag
Create a MAC tag. Mutating operation; requires confirm=true unless
dry_run=true. A name that matches an existing tag (case-insensitive) is
rejected instead of creating a duplicate.
Parameters:
name(string, required): Tag display namemacs(array, required): Device MAC addresses to assign (may be empty)site_id(string, required): Site identifierconfirm(boolean/string, required for execution): Set true to applydry_run(boolean/string, optional): Preview without applying
update_mac_tag
Rename a MAC tag or change its members. Mutating operation; requires
confirm=true unless dry_run=true. add_macs/remove_macs are applied to
the tag’s current members, so members added by someone else are kept. macs
replaces the member list outright ([] clears it) and cannot be combined with
add_macs/remove_macs. A dry run returns changes (added_macs,
removed_macs, name) and the merged_payload that would be sent.
Parameters:
tag_id(string, required): Tag IDsite_id(string, required): Site identifiername(string, optional): New display namemacs(array, optional): Full replacement member listadd_macs(array, optional): MACs to addremove_macs(array, optional): MACs to removeconfirm(boolean/string, required for execution): Set true to applydry_run(boolean/string, optional): Preview without applying
delete_mac_tag
Delete a MAC tag. Mutating operation; requires confirm=true unless
dry_run=true. A WLAN that broadcasts only on this tag’s access points may
stop broadcasting.
Parameters:
tag_id(string, required): Tag IDsite_id(string, required): Site identifierconfirm(boolean/string, required for execution): Set true to applydry_run(boolean/string, optional): Preview without applying
Device Migration Tools
Move a device to another site on this controller, or hand it to another controller. Local API only (UNIFI_API_TYPE=local). Each tool finds the
device in site_id first (by MAC in any common format, or by 24-hex device
ID), so a typo fails before any command is sent and a dry run names the
device that would move. All three are mutating: they require confirm=true
unless dry_run=true, and are hidden in read-only mode.
move_device_to_site
Move an adopted device to another site on the same controller
(cmd/sitemgr move-device). The device reprovisions with the target
site’s configuration, so expect a brief outage on it and anything behind it.
Parameters:
site_id(string, required): Site the device is in nowdevice_id(string, required): Device MAC or 24-hex device IDtarget_site(string, required): Destination site by short name (e.g.default), UI description, or 24-hex_id. A description shared by several sites is rejected as ambiguous.confirm(boolean/string, required for execution): Set true to applydry_run(boolean/string, optional): Preview without applying
migrate_device
Migrate a device to another controller by setting its inform URL
(cmd/devmgr migrate). The device then appears on the new controller as
pending adoption; adopt it there to finish. An offline device only receives
the command when it next checks in, and the result carries a warning.
Parameters:
site_id(string, required): Site the device is in nowdevice_id(string, required): Device MAC or 24-hex device IDinform_url(string, required):http(s)://<host>[:port]/inform, e.g.http://controller.example.net:8080/inform. Other paths, credentials, query strings, and non-HTTP schemes are rejected.confirm(boolean/string, required for execution): Set true to applydry_run(boolean/string, optional): Preview without applying
cancel_device_migration
Abort a pending migration (cmd/devmgr cancel-migrate). Only useful before
the device is adopted on the new controller.
Parameters:
site_id(string, required): Site the device was migrated fromdevice_id(string, required): Device MAC or 24-hex device IDconfirm(boolean/string, required for execution): Set true to applydry_run(boolean/string, optional): Preview without applying
Site Management Tools
get_site_details
Get detailed site information.
Parameters:
site_id(string, required): Site identifier
list_all_sites
List all accessible sites.
Parameters: None
Returns:
Array of site objects.
Example:
get_site_statistics
Retrieve site-wide statistics.
Parameters:
site_id(string, required): Site identifier
Site Manager API Tools (v0.3.0+)
Note: These tools require the Site Manager API to be enabled:- Set
UNIFI_SITE_MANAGER_ENABLED=true - The same
UNIFI_API_KEYis used for both Site Manager and Network APIs - See Site Manager API Docs for more details
api.ui.com/v1/) provides cloud-based multi-site management, ISP metrics monitoring, SD-WAN configuration, and host management capabilities.
get_isp_metrics
Get ISP performance metrics for a specific site.
Parameters:
site_id(string, required): Site identifier
query_isp_metrics
Query ISP metrics with optional filters for time range and site.
Parameters:
site_id(string, optional): Site identifier (omit for all sites)start_time(string, optional): Start time in ISO format (e.g., “2026-02-01T00:00:00Z”)end_time(string, optional): End time in ISO format
list_sdwan_configs
List all SD-WAN configurations across your organization.
Parameters: None
Returns:
List of {id, name, type} summaries from GET https://api.ui.com/v1/sd-wan-configs. The v1.0.0 SD-WAN list has no pagination parameters. An empty list is different from a 404/401/403/error, which is not converted to empty success.
Example:
get_sdwan_config
Get detailed SD-WAN configuration by ID.
Parameters:
config_id(string, required): Configuration identifier
data object from GET /v1/sd-wan-configs/{id}: id, name, type, variant, settings, hubs, spokes and unrecognized fields are preserved. This is not a typed Site Manager destination/performance-policy resource. A null/malformed detail response is an error, not a fabricated config.
Example:
get_sdwan_config_status
Get SD-WAN configuration deployment status.
Parameters:
config_id(string, required): Configuration identifier
data object from GET /v1/sd-wan-configs/{id}/status, including generation/apply states, per-hub/spoke warnings/errors, WAN state and connection/tunnel records. The documented generateStatus values are OK, GENERATING, GENERATE_FAILED; site applyStatus values are ok, creating, updating, removing, createFailed, updateFailed, removeFailed. Deployment/apply state is not a tunnel-health inference. Null/malformed known status fields are errors; unknown extension fields are preserved. This read-only Site Manager surface requires UNIFI_SITE_MANAGER_ENABLED=true and a valid cloud API key; it is registered with the site_manager module in full and system profiles across local/cloud modes, subject to RBAC and fleet routing. It is not a standalone controller endpoint.
Example:
list_hosts
List all managed UniFi hosts/consoles in your organization.
Parameters:
limit(integer, optional): Maximum number of hosts to returnoffset(integer, optional): Number of hosts to skip (for pagination)
get_host
Get detailed information about a specific managed host.
Parameters:
host_id(string, required): Host identifier
get_version_control
Get Site Manager API version control information.
Parameters: None
Returns:
Version information including current version, latest version, and deprecated versions.
Example:
Cloud Connector passthrough tools
connector_network_get, connector_network_post, connector_network_put, connector_network_patch, connector_network_delete, and the matching connector_protect_* tools forward a request to https://api.ui.com/v1/connector/consoles/{console_id}/proxy/{network,protect}/{path}. The get tools are read tier; the others need confirm=True.
Parameters: console_id, path, plus params (optional query parameters) on the get tools and body, confirm and dry_run on the mutating tools
Input rules (checked before any request is made; a bad value raises ValidationError):
console_idis the host ID fromlist_hosts, for example70A7...8EC3:1093004219. Surrounding whitespace is stripped and the stripped value is what goes into the URL. What remains must be one path segment of letters, digits,.,_,~,:and-, and cannot be only dots.pathis the sub-path under the proxy prefix, for exampleapi/s/default/stat/device. Leading slashes are stripped. Every segment uses the same character set asconsole_idand cannot be empty,.or..; one trailing slash is allowed. The whole path is capped at 2048 characters.?,#,%and\are refused: on thegettools, pass query strings throughparams.
Phase 4: Mutating Tools
All Phase 4 tools modify UniFi configuration and require safety mechanisms.Safety Mechanisms
All mutating tools implement these safety features:- Confirmation Required: Must pass
confirm=Trueto execute - Dry Run Mode: Pass
dry_run=Trueto preview without changes - Audit Logging: All operations logged to
audit.log - Input Validation: Parameters validated before execution
Firewall Management
list_firewall_rules
List all firewall rules (read-only).
Parameters: site_id
create_firewall_rule
Create a new firewall rule.
Parameters: site_id, name, action (accept/drop/reject), source, destination, protocol, port, enabled, confirm, dry_run
Example:
update_firewall_rule & delete_firewall_rule
Modify or remove firewall rules. Requires confirm=True.
Zone-Based Firewall (ZBF)
Requires: UniFi Network Application 9.0+, Local API Only Zone-Based Firewall provides modern, scalable network security by grouping networks into security zones and defining policies between zones. ⚠️ CRITICAL LIMITATIONS (Verified 2025-11-18): API Availability:- ZBF is NOT available via Cloud API - requires local gateway API access (
api_type='local') - Tested on UniFi Express 7 and UDM Pro (API v10.0.156)
- Only 2 out of 15 implemented endpoints actually exist in the UniFi API
list_firewall_zones- List all zonescreate_firewall_zone- Create new zone (untested but likely works)update_firewall_zone- Modify zone (untested but likely works)delete_firewall_zone- Delete zone (untested but likely works)assign_network_to_zone- Assign network to zone (untested but likely works)unassign_network_from_zone- Remove network from zone (untested but likely works)get_zone_networks- List networks in a zone
- ❌ Zone policy matrix operations (get/update/delete policies between zones)
- ❌ Application blocking per zone
- ❌ Zone traffic statistics
- These tools have been REMOVED - configure these features in UniFi Console UI
- Zones: Logical groups of networks (e.g., Internal, External, Gateway, VPN, Hotspot, DMZ)
- Network Assignment: Assign networks to zones for organization
- Zone-to-Zone Policies: Must be configured manually in UniFi Console UI
- Application Blocking: Use DPI categories at network level instead
Zone Management
list_firewall_zones
List all configured firewall zones.
Parameters:
site_id(string, required): Site identifier
create_firewall_zone
Create a new firewall zone.
Parameters:
site_id(string, required): Site identifiername(string, required): Zone namedescription(string, optional): Zone descriptionnetwork_ids(array, optional): Network IDs to assignconfirm(boolean, required): Must betruedry_run(boolean, optional): Preview changes
update_firewall_zone
Update an existing zone’s name, description, or networks.
Parameters:
site_id(string, required): Site identifierfirewall_zone_id(string, required): Zone IDname(string, optional): New zone namedescription(string, optional): New descriptionnetwork_ids(array, optional): Updated network listconfirm(boolean, required): Must betruedry_run(boolean, optional): Preview changes
delete_firewall_zone
Delete a firewall zone.
Parameters:
site_id(string, required): Site identifierzone_id(string, required): Zone ID to deleteconfirm(boolean, required): Must betruedry_run(boolean, optional): Preview changes
assign_network_to_zone
Dynamically assign a network to a zone.
Parameters:
site_id(string, required): Site identifierzone_id(string, required): Zone IDnetwork_id(string, required): Network ID to assignconfirm(boolean, required): Must betruedry_run(boolean, optional): Preview changes
unassign_network_from_zone
Remove a network from a zone.
Parameters:
site_id(string, required): Site identifierzone_id(string, required): Zone IDnetwork_id(string, required): Network ID to removeconfirm(boolean, required): Must betruedry_run(boolean, optional): Preview changes
get_zone_networks
List all networks assigned to a zone.
Parameters:
site_id(string, required): Site identifierzone_id(string, required): Zone ID
ZBF Usage Example
- Zone-to-zone policies must be configured in UniFi Console UI
- Application blocking per zone is not available via API - use DPI categories at network level
- Zone traffic statistics are not available - use client statistics instead
- Always use
dry_run=Trueto preview changes before applying - See
tests/verification/PHASE2_FINDINGS.mdfor complete verification details
Network Configuration
create_network
Create a new network/VLAN.
Parameters: site_id, name, vlan_id, subnet, purpose, dhcp_enabled, DHCP settings, confirm, dry_run
update_network & delete_network
Modify or remove networks. Requires confirm=True.
update_site_to_site_vpn
Update a site-to-site VPN’s networkconf entry. Requires confirm=True.
Parameters: site_id, vpn_id, name, enabled, ipsec_peer_ip, remote_vpn_subnets, x_ipsec_pre_shared_key, confirm, dry_run
vpn_id must be a 24-character hex ObjectId (or a UUID), as returned by list_site_to_site_vpns. It is lowercased before use, and anything else raises ValidationError before the controller is contacted. get_site_to_site_vpn filters the list client-side and does not apply this check.
Device Control
restart_device
Restart a UniFi device.
Parameters: site_id, device_mac, confirm, dry_run
locate_device
Enable/disable LED locate mode.
Parameters: site_id, device_mac, enabled, confirm, dry_run
upgrade_device
Trigger firmware upgrade.
Parameters: site_id, device_mac, firmware_url, confirm, dry_run
Client Management
block_client & unblock_client
Block or unblock a client from the network.
Parameters: site_id, client_mac, confirm, dry_run
reconnect_client
Force a client to reconnect.
Parameters: site_id, client_mac, confirm, dry_run
MCP Prompts
The server exposes eight parameterised UniFi operational workflows through the standard MCP prompts interface. A client discovers them withprompts/list and retrieves a rendered workflow brief with prompts/get.
Availability. A workflow is advertised only when the tools it needs are
registered on this server, so the prompt list follows the API mode, the
profile and the read-only and dry-run settings. The full catalog, with each
prompt’s arguments and the tools it depends on, is in
docs/PROMPTS.md.
Retrieving a prompt is not running it.
prompts/get returns text: a
scoped brief telling an agent which read tools to call and what to report.
The agent then calls the tools itself, and the server’s role check, the
confirm gate and the audit trail all still apply. Listing and retrieving
a prompt contacts no controller, runs no tool, reads no secret and starts
no work.
A2A Endpoints
On the network transports the server also serves an A2A-style discovery and delegation surface, behind the same bearer token as/mcp.
The card follows the AgentCard object shape of the A2A specification
version 0.3.0. The server does not implement the A2A task protocol, so the
card declares
streaming: false and pushNotifications: false. See
A2A.md for the runbook and
docs/AUDIT_A2A_SKILLS.md for what is and is not
implemented.
A delegated call runs the registered tool through its own wrapper, so the
role check, the confirm gate, the dry-run behaviour and the audit record
apply exactly as they do for an MCP client. The caller’s permissions come
from the bearer token’s role, never from the request body.
A2A Error Handling
All mutating tools raise:ConfirmationRequiredError: Ifconfirmparameter not TrueValidationError: If parameters invalidResourceNotFoundError: If resource not foundAPIError: If UniFi API returns error
Phase 5: Enterprise scale and operational excellence
Phase 5 expands the platform with WiFi management, port forwarding, DPI analytics, caching, webhook support, and enterprise-scale controls.WiFi Network (SSID) Management
list_wlans
List all wireless networks (SSIDs) in a site (read-only).
Parameters:
site_id(string, required): Site identifierlimit(integer, optional): Maximum number of WLANs to returnoffset(integer, optional): Number of WLANs to skip
create_wlan
Create a new wireless network/SSID.
Parameters:
site_id(string, required): Site identifiername(string, required): SSID namesecurity(string, required): Security type (open, wpapsk, wpaeap)password(string, optional): WiFi password (required for wpapsk)enabled(boolean, optional): Enable the WLAN immediately (default: true)is_guest(boolean, optional): Mark as guest network (default: false)wpa_mode(string, optional): WPA mode (wpa, wpa2, wpa3) (default: wpa2)wpa_enc(string, optional): WPA encryption (tkip, ccmp, ccmp-tkip) (default: ccmp)vlan_id(integer, optional): VLAN ID for network isolation (1-4094)hide_ssid(boolean, optional): Hide SSID from broadcast (default: false)confirm(boolean, required): Confirmation flag (must be True)dry_run(boolean, optional): Preview without creating
update_wlan
Update an existing wireless network.
Parameters:
site_id(string, required): Site identifierwlan_id(string, required): WLAN IDname(string, optional): New SSID namesecurity(string, optional): New security typepassword(string, optional): New WiFi passwordenabled(boolean, optional): Enable/disable the WLANis_guest(boolean, optional): Mark as guest networkwpa_mode(string, optional): New WPA modewpa_enc(string, optional): New WPA encryptionvlan_id(integer, optional): New VLAN IDhide_ssid(boolean, optional): Hide/show SSIDconfirm(boolean, required): Confirmation flagdry_run(boolean, optional): Preview without updating
delete_wlan
Delete a wireless network.
Parameters:
site_id(string, required): Site identifierwlan_id(string, required): WLAN IDconfirm(boolean, required): Confirmation flagdry_run(boolean, optional): Preview without deleting
get_wlan_statistics
Get WiFi usage statistics for a site or specific WLAN.
Parameters:
site_id(string, required): Site identifierwlan_id(string, optional): Optional WLAN ID to filter statistics
Port Forwarding Management
list_port_forwards
List all port forwarding rules in a site (read-only).
Parameters:
site_id(string, required): Site identifierlimit(integer, optional): Maximum number of rules to returnoffset(integer, optional): Number of rules to skip
create_port_forward
Create a port forwarding rule.
Parameters:
site_id(string, required): Site identifiername(string, required): Rule name/descriptiondst_port(integer, required): Destination port (external/WAN port), 1-65535fwd_ip(string, required): Forward to IPv4 address (internal/LAN), dotted quad without leading zerosfwd_port(integer, required): Forward to port (internal)protocol(string, optional): Protocol (tcp, udp, tcp_udp) (default: tcp_udp)src(string, optional): Source restriction:any, an IPv4 address, or a CIDR network such as203.0.113.0/24(host bits are cleared, so203.0.113.7/24is sent as203.0.113.0/24) (default: any)enabled(boolean, optional): Enable the rule immediately (default: true)log(boolean, optional): Enable logging for this rule (default: false)confirm(boolean, required): Confirmation flagdry_run(boolean, optional): Preview without creating
delete_port_forward
Delete a port forwarding rule.
Parameters:
site_id(string, required): Site identifierrule_id(string, required): Port forwarding rule IDconfirm(boolean, required): Confirmation flagdry_run(boolean, optional): Preview without deleting
Diagnostics and Historical Statistics
get_speed_test_history
Get historical speed test results for a site, oldest first. Reads the
stat/report/archive.speedtest report.
Parameters:
site_id(string, required): Site identifierhours(integer, optional): How far back to look (default: 168 = 7 days)
{"results": [...]}. An empty history adds statistics_note
(see the note on the statistics reset below).
get_historical_stats
Read archived time-series statistics from stat/report/{interval}.{subject}
— the only place historical airtime, per-client signal, and gateway counters
live.
Parameters:
site_id(string, required): Site identifiersubject(string, optional):site,ap,user, orgw(default:ap)interval(string, optional):5minutes,hourly,daily, ormonthly(default:hourly)hours(integer, optional): Window ending now, 1-2160 (default: 24)macs(string or array, optional): Restrict to specific devices/clientsattrs(array, optional): Report attributes; defaults per subject,timealways included
{"samples": [...]}, oldest first, each sample carrying
epoch-ms time. An empty series adds statistics_note (below).
The statistics reset note. UniFi Network 11 replaces the statistics engine and resets historical data, so an empty history immediately after the upgrade is expected — not evidence of an outage or a broken tool (DEVELOPMENT_PLAN.md §4 Phase 8, N3). Every empty response fromget_historical_stats,get_speed_test_history,get_dpi_statistics,list_top_applicationsandget_client_dpicarries astatistics_notefield saying so. The field is absent on non-empty responses.
DPI (Deep Packet Inspection) Statistics
get_dpi_statistics
Get Deep Packet Inspection statistics for a site.
Parameters:
site_id(string, required): Site identifier
stat/sitedpi report; the
endpoint accepts no time window. app and cat are the controller’s
numeric catalog ids — translate them with list_dpi_applications and
list_dpi_categories. A controller that runs traffic identification
through the flow engine reports empty lists plus a note pointing at
get_top_flows / get_flow_analytics, and the statistics_note described
above.
Example:
list_top_applications
List top applications by bandwidth usage.
Parameters:
site_id(string, required): Site identifierlimit(integer, optional): Number of top applications to return (default: 10)
statistics_note (see the statistics reset note above).
list_dpi_categories
List the DPI categories the controller recognises.
Parameters: none.
Returns:
Array of category objects. Only id and name are guaranteed, and id is a
number on the Integration v1 route (categories are numbered from zero) while
the legacy endpoint sends a string. Fields the controller does not report are
omitted rather than returned as null.
Example:
list_dpi_applications
List the DPI applications the controller recognises.
Parameters:
limit(integer, optional): Maximum number of resultsoffset(integer, optional): Starting positionfilter_expr(string, optional): Filter expression
id and name are guaranteed — the
Integration v1 route returns just those two, with a numeric id — so
category_id, category_name, enabled, protocols and ports may all be
missing. Absent keys are omitted rather than returned as null; an absent key
means “not reported”, never “empty” or “disabled”.
Example:
get_client_dpi
Get DPI statistics for a specific client.
Parameters:
site_id(string, required): Site identifierclient_mac(string, required): Client MAC addresstime_range(string, optional): Time range for statistics (default: 24h)limit(integer, optional): Maximum number of applications to returnoffset(integer, optional): Number of applications to skip
statistics_note (see the statistics reset
note above).
Traffic Flow Monitoring
Real-time traffic flow monitoring and analysis for UniFi Network 9.0+. Provides comprehensive network visibility, security quick-response capabilities, and advanced analytics.get_traffic_flows
Retrieve traffic flows with optional filtering.
By default the tool returns the 50 most-recent completed flows. Pass hours and/or
max_flows to page through a longer window instead (pageNumber / pageSize with
timestampFrom / timestampTo on the v2 endpoint); source_mac and direction are then also
sent as server-side pre-filters. The client-side filters apply in both modes.
Parameters:
site_id(string, required): Site identifiersource_mac(string, optional): Filter by source MAC address (case-insensitive)source_ip(string, optional): Filter by source IP addresssource_zone_name(string, optional): Filter by source firewall zone namesource_network_name(string, optional): Filter by source VLAN display namedestination_ip(string, optional): Filter by destination IP addressdestination_port(integer, optional): Filter by destination portdestination_zone_name(string, optional): Filter by destination zone name (useful forExternal)destination_network_name(string, optional): Filter by destination VLAN display nameprotocol(string, optional): Filter by protocol (TCP,UDP,ICMP, …)action(string, optional): Filter by firewall action (allowed,blocked)direction(string, optional): Filter by direction (outgoing,incoming,local)risk(string, optional): Filter by risk classificationmin_bytes(integer, optional): Only flows with at least this many total bytesclient_name_contains(string, optional): Substring match against the source client namelimit(integer, optional): Maximum number of flows to return (after filtering)hours(integer, optional): Page through the flows completed in the lasthours(at least 1)max_flows(integer, optional): Upper bound on flows fetched in paged mode, before client-side filtering (1-50000, default 5000)
stream_traffic_flows
⚠️ NOT SUPPORTED — This tool raisesNotImplementedError. The UniFi v2traffic-flowsendpoint returns a rolling snapshot of the 50 most-recent completed flows per call. It has no persistent connection, no pagination, and no server-push mechanism, so true streaming is not possible. Fast networks roll through the 50-flow window in under a second, making polling-based streaming impractical. Use instead: Pollget_traffic_flowson your own interval.
get_connection_states
⚠️ NOT SUPPORTED — This tool raisesNotImplementedError. The UniFi v2traffic-flowsendpoint reports completed flows with start/end timestamps. It does not expose a live connection table or track in-progress connection states (active,closed,timed_out). Use instead: Useget_traffic_flowsand inspectflow_start_time/flow_end_timefields to infer connection duration.
get_client_flow_aggregation
Get comprehensive traffic aggregation for a specific client.
Parameters:
site_id(string, required): Site identifierclient_mac(string, required): Client MAC addresshours(integer, optional): Aggregate the flows of the lasthoursinstead of the latest-50 snapshot (seeget_traffic_flows)max_flows(integer, optional): Upper bound on flows fetched in paged mode (1-50000, default 5000)
block_flow_source_ip
Block source IP address from a suspicious traffic flow.
Parameters:
site_id(string, required): Site identifierflow_id(string, required): Flow identifier to blockduration(string, optional): Block duration - “permanent” or “temporary” (default: permanent)expires_in_hours(integer, optional): Hours until expiration (for temporary blocks)confirm(boolean, required): Confirmation flag (must be true)dry_run(boolean, optional): Validate without executing (default: false)
block_flow_destination_ip
Block destination IP address from a traffic flow.
Parameters:
site_id(string, required): Site identifierflow_id(string, required): Flow identifier to blockduration(string, optional): Block duration (default: permanent)expires_in_hours(integer, optional): Hours until expirationconfirm(boolean, required): Confirmation flagdry_run(boolean, optional): Validate without executing
block_flow_application
Block application identified in a traffic flow using traditional firewall rules or DPI categories.
Parameters:
site_id(string, required): Site identifierflow_id(string, required): Flow identifier to blockconfirm(boolean, required): Confirmation flagdry_run(boolean, optional): Validate without executing
export_traffic_flows
Export traffic flows to JSON or CSV format.
Parameters:
site_id(string, required): Site identifierexport_format(string, optional): Export format - “json” or “csv” (default: json)time_range(string, optional): Time range (default: 24h)include_fields(array, optional): Specific fields to include (null = all fields)filter_expression(string, optional): Filter expressionmax_records(integer, optional): Maximum number of records
get_flow_analytics
Get comprehensive flow analytics dashboard.
Parameters:
site_id(string, required): Site identifiertime_range(string, optional): Time range (default: 24h)
get_flow_statistics
Get aggregated flow statistics.
Parameters:
site_id(string, required): Site identifiertime_range(string, optional): Time range (default: 24h)
get_traffic_flow_details
Get detailed information for a specific traffic flow.
Parameters:
site_id(string, required): Site identifierflow_id(string, required): Flow identifier
get_top_flows
Get top bandwidth-consuming flows.
Parameters:
site_id(string, required): Site identifierlimit(integer, optional): Number of top flows (default: 10)time_range(string, optional): Time range (default: 24h)sort_by(string, optional): Sort by field - “bytes”, “packets”, or “duration” (default: bytes)
get_flow_risks
Get risk assessment for traffic flows.
Parameters:
site_id(string, required): Site identifiertime_range(string, optional): Time range (default: 24h)min_risk_level(string, optional): Minimum risk level - “low”, “medium”, “high”, “critical”
get_flow_trends
⚠️ NOT SUPPORTED — This tool raisesNotImplementedError. The UniFi v2traffic-flowsendpoint provides a rolling snapshot of the 50 most-recent completed flows — it has no historical query capability and does not support time ranges or aggregation intervals. Use instead: For bandwidth time-series data, use thestat/report/*endpoints via other tools (e.g., client bandwidth history).
filter_traffic_flows
Filter flows with a comma-separated list of key=value pairs.
Parameters:
site_id(string, required): Site identifierfilter_expression(string, required): Comma-separatedkey=valuepairs using the filter parameters ofget_traffic_flows(e.g."protocol=TCP,destination_zone_name=External,min_bytes=1000")limit(integer, optional): Maximum number of flowshours(integer, optional): Page through the flows of the lasthours(seeget_traffic_flows)max_flows(integer, optional): Upper bound on flows fetched in paged mode (1-50000, default 5000)
- Security Operations: Real-time threat detection and automated blocking
- Network Monitoring: Live bandwidth and connection tracking
- Compliance: Flow data export for audit requirements
- Troubleshooting: Connection state analysis and client profiling
- Analytics: Application usage patterns and network insights
Network Topology
Retrieve and visualize your complete network topology including devices, clients, and their interconnections. Available Tools:get_network_topology: Retrieve complete topology graphget_device_connections: Device interconnection detailsget_port_mappings: Port-level connection mappingexport_topology: Export topology in multiple formatsget_topology_statistics: Topology summary statistics
Get Network Topology
Retrieve the complete network topology including all devices, clients, and their interconnections. Example:Get Device Connections
Retrieve connection details for a specific device or all devices. Bothget_device_connections and get_port_mappings accept a topology
node id, a device MAC, or a device name as device_id. An identifier
that matches none of them raises ResourceNotFoundError — distinct
from a known device with no connections, which returns an empty
result. get_port_mappings reports the resolved node id as
device_id and echoes the caller’s identifier as requested_id.
Example:
Get Port Mappings
Get detailed port-level connection mapping for a device. Each port maps to a list of peers: one physical port routinely carries several hosts — a virtualization host bridging its guests, or a downstream unmanaged switch. Example:Export Topology
Export network topology in multiple formats for visualization or documentation. Supported Formats:json: JSON format for programmatic usegraphml: GraphML (XML) format for network visualization tools (Gephi, yEd, etc.)dot: DOT format for Graphviz rendering
Get Topology Statistics
Get summary statistics about your network topology. Example:- Network Documentation: Auto-generate network diagrams
- Visualization: Export to Graphviz, yEd, or Gephi for interactive visualization
- Capacity Planning: Understand network depth and connection patterns
- Troubleshooting: Identify connection issues and network bottlenecks
- Monitoring: Track topology changes over time
- Compliance: Document network architecture for audits
Caching (Optional)
The MCP server includes optional Redis-based caching to reduce API calls and improve performance. Configuration: Install theredis client with pip install 'unifi-mcp-server[fleet]', then set these environment variables to enable caching:
REDIS_URL(optional; e.g.redis://:password@host:6379/0, takes precedence over the fields below)REDIS_HOST(default: localhost)REDIS_PORT(default: 6379)REDIS_DB(default: 0)REDIS_PASSWORD(optional)
REDIS_URL or REDIS_HOST is set explicitly (a local Redis that merely exists is never used) and UNIFI_CACHE_ENABLED is not false. It covers the inventory and configuration reads of the device, client, site, network and WLAN tools (statistics and RF-health tools are live metrics and never cached). Those tools gain an optional fresh argument that skips the cache and refreshes it. Any write to a controller, successful or not (dry runs excepted), clears that controller’s cached reads; changes made outside this server show up when entries expire. Redis errors bypass the cache instead of failing a call. Hits and misses are counted in unifi_mcp_cache_requests_total.
Independently of Redis, every server keeps one long-lived connection per controller: tool calls share it, along with the controller’s rate limiter (so UNIFI_RATE_LIMIT_REQUESTS applies across calls), its authentication probe and site map (reused for 5 minutes), and a circuit breaker that fails fast for 30 seconds after 5 consecutive calls the controller did not answer.
Cache TTL by Resource Type:
- Sites: 5 minutes
- Devices: 1 minute
- Clients: 30 seconds
- Networks: 5 minutes
- WLANs: 5 minutes
- Firewall Rules: 5 minutes
- Port Forwards: 5 minutes
- DPI Stats: 2 minutes
Liveness (GET /healthz)
On a network transport the server answers GET /healthz with
{"status": "ok"} (Cache-Control: no-store) without a bearer token, for
load balancers and container health checks. It says only that the process is
serving HTTP: no version, controller or configuration. Use the health_check
tool or /metrics (both behind the token) for more.
Webhooks (Optional)
On a network transport (http, sse, streamable_http) the server serves
POST /webhooks/unifi when WEBHOOK_SECRET is set, with the default handlers
below registered. Without the secret the route is not mounted at all; over
stdio there is no HTTP surface.
Authentication: the route does not use the MCP bearer token (UniFi cannot
send one). Each request must carry X-UniFi-Signature: the hex HMAC-SHA256 of
the raw request body, keyed with WEBHOOK_SECRET.
The receiver (src/webhooks/) is a Starlette endpoint and can also be mounted
on another app:
503).
Responses: 200 processed (or {"status": "duplicate"} for a repeated
event_id within 5 minutes), 400 invalid JSON or event, 401 missing or
invalid signature, 429 more than 100 events per site per minute, 503 no
secret configured (receiver mounted by hand only).
Supported Events:
device.online- Device came onlinedevice.offline- Device went offlineclient.connected- Client connectedclient.disconnected- Client disconnectedalert.raised- Alert raisedevent.occurred- Generic event
device.* and client.* events clear the server’s read cache (when Redis is
configured). A payload does not say which controller sent it, so the cached
reads of every controller are cleared. Custom handlers can be registered with
receiver.register_handler(event_type, handler).
Redis webhook event bus
When Redis is configured (REDIS_URL or REDIS_HOST), every verified webhook
event is also published to the pub/sub channel unifi:webhooks:v1:events after
local handlers run. Other replicas and workers can subscribe to the channel to
react to events without each process receiving the HTTP callback directly.
Payload shape:
origin matches its own instance id, so a
process does not handle an event twice.
The publish does not sit on the HTTP acknowledgement path. It is dispatched as
a background task once the local handlers have run, so a Redis that accepts
connections but stops answering cannot add the connection pool’s socket
timeout to the webhook response, and a sender with a short delivery timeout
does not retry an event whose handlers already ran. At most 1000 publishes may
be in flight at once; past that the fan-out drops events with a warning rather
than queueing without bound, and local handling is unaffected. On shutdown the
server waits up to 5 seconds for outstanding publishes, then cancels them and
logs how many never reached Redis.
MCP Resources
Resources provide read-only access to UniFi data through standardized URIs.Resource URI Scheme
Resources use a hierarchical URI scheme:Available Resources
sites://{site_id}/devices
List all devices in a site.
Example:
sites://{site_id}/devices/{mac_address}
Get a specific device by MAC address.
Example:
sites://{site_id}/networks
List all networks in a site.
Example:
sites://{site_id}/clients
List all active clients in a site.
Example:
Resource Error Handling
Error Response Format
Errors are returned in a standardized format:Common Error Codes
Rate Limiting
Official API Rate Limits
The UniFi Cloud API enforces the following rate limits:Rate Limit Response
When rate limits are exceeded, the API returns: HTTP Status:429 Too Many Requests
Headers:
Retry-After header indicates how many seconds to wait before retrying.
MCP Server Rate Limit Handling
The MCP server implements intelligent rate limit handling:- Automatic retry with exponential backoff
- Request queuing to prevent overwhelming the API
- Configurable rate limit via
UNIFI_RATE_LIMIT_REQUESTSenvironment variable - Graceful degradation when limits are reached
Best Practices
For Application Developers:- Batch operations when possible to reduce API calls
- Cache frequently accessed data (devices, networks, etc.)
- Avoid polling; use event-driven approaches when available
- Implement client-side rate limiting to stay under limits
- Monitor the
X-RateLimit-*headers (if provided by API)
- Consider the v1 Stable API when available (10,000 req/min)
- Distribute load across multiple time windows
- Use pagination efficiently to minimize requests
- Cache static data locally
Examples
Backup and Restore Operations
trigger_backup
Create a backup of the UniFi controller configuration.
Parameters:
site_id(string, required): Site identifierbackup_type(string, required): Type of backup - “network” or “system”"network": Network settings and device configurations only (~5-10 MB)"system": Complete OS, application, and device configurations (~50-100 MB)
retention_days(integer, optional): Days to retain backup (default: 30, -1 for indefinite)confirm(boolean, required): Must betrueto executedry_run(boolean, optional): Validate without creating backup
/dl/ tree —
automatic backups from dl/autobackup/, manual ones from dl/backup/.
See Download Backup.
Example:
list_backups
List all available backups for a site.
Parameters:
site_id(string, required): Site identifier
get_backup_details
Get detailed information about a specific backup.
Parameters:
site_id(string, required): Site identifierbackup_filename(string, required): Backup filename
download_backup
Download a backup file to local storage.
Parameters:
site_id(string, required): Site identifierbackup_filename(string, required): Backup filename (a single path component; separators and..are rejected)output_path(string, required): Filename to save under. Only the filename is used — any directory component is ignored and the file is written insideUNIFI_BACKUP_DOWNLOAD_DIR(default: the current working directory)verify_checksum(boolean, optional): Calculate SHA-256 checksum (default: true)
delete_backup
Delete a backup file from the controller (requires confirmation).
Parameters:
site_id(string, required): Site identifierbackup_filename(string, required): Backup filenameconfirm(boolean, required): Must betrueto executedry_run(boolean, optional): Validate without deleting
restore_backup
Restore the UniFi controller from a backup file (DESTRUCTIVE operation).
Parameters:
site_id(string, required): Site identifierbackup_filename(string, required): Backup filename to restore fromcreate_pre_restore_backup(boolean, optional): Create safety backup first (default: true, recommended)confirm(boolean, required): Must betrueto executedry_run(boolean, optional): Validate without restoring
- Controller will restart during restore process
- All current configuration will be overwritten
- Devices may temporarily disconnect
- ALWAYS create pre-restore backup for rollback capability
validate_backup
Validate a backup file before restore.
Parameters:
site_id(string, required): Site identifierbackup_filename(string, required): Backup filename
Complete Example: Network Setup
Example: Monitor Devices
Example AI Assistant Prompts
This section provides example natural language prompts you can use with AI assistants (like Claude) that have access to the UniFi MCP Server. These demonstrate real-world use cases for the current feature set.Network Topology & Visualization
Prompt: “Show me a complete map of my network topology including all devices and how they’re connected.” The assistant will useget_network_topology to retrieve the full network graph, showing devices, clients, and interconnections.
Prompt: “Export my network topology as a Graphviz DOT file so I can visualize it in a network diagram tool.”
Uses export_topology with format="dot" to generate a DOT format file compatible with Graphviz and similar visualization tools.
Prompt: “Which devices are connected to my main switch on ports 5-10?”
The assistant will use get_port_mappings to show exactly what’s plugged into specific switch ports.
Quality of Service (QoS) Management
Prompt: “My video calls stutter when someone is uploading. Turn on Smart Queues on my WAN for my 500/50 Mbps connection.” The assistant will useconfigure_smart_queue with download_mbps=500 and upload_mbps=50 to enable fq_codel shaping on the primary WAN.
Prompt: “Is Smart Queue enabled on my WAN, and what rates is it shaping to?”
Uses get_smart_queue_status to show whether the shaper is on and its download/upload rates in Mbps.
Prompt: “Which of my devices are routed through the VPN, and is the kill switch on?”
The assistant uses list_traffic_routes to read the site’s Traffic Routes, including each route’s matching target, target clients or networks, egress interface, and kill-switch setting.
Backup & Disaster Recovery
Prompt: “Create a full system backup of my UniFi controller right now and keep it for 90 days.” The assistant will usetrigger_backup with backup_type="system" and retention_days=90.
Prompt: “Show me all backups from the last 7 days and their sizes.”
Uses list_backups and filters results to show recent backups with size information.
Prompt: “Download my latest network backup to /tmp/emergency-backup.unf and verify the checksum.”
The assistant uses download_backup with checksum verification enabled for data integrity.
Prompt: “Set up automatic daily backups at 2 AM with 30-day retention.”
Uses configure_backup_schedule to establish automated backup policies with cron expressions.
Prompt: “What’s the status of my last backup? Is it complete and cloud-synced?”
The assistant uses get_backup_status to check backup completion and synchronization state.
RADIUS & Authentication
Prompt: “Set up a RADIUS server for 802.1X authentication using my FreeRADIUS server at 192.168.1.50.” The assistant will usecreate_radius_profile to configure RADIUS authentication for network access control.
Prompt: “Create a RADIUS user account ‘guest-wifi’ with password for our guest portal.”
Uses create_radius_account to provision user credentials for RADIUS authentication.
Prompt: “Configure the guest portal with a 4-hour session timeout and redirect users to our company website after login.”
The assistant uses configure_guest_portal to customize the captive portal experience.
Prompt: “Show me all active RADIUS profiles and which ones have accounting enabled.”
Uses list_radius_profiles to display authentication server configurations.
Prompt: “Create a hotspot package: ‘$5 for 24 hours’ for our café WiFi.”
The assistant uses create_hotspot_package to set up paid WiFi access
sold by duration — the controller prices packages by the hour; bandwidth
and data quotas are not part of this API surface.
Multi-Site Management
Prompt: “Compare the device count and health status across all my sites.” The assistant usesaggregate_device_stats to provide cross-site device analytics.
Prompt: “Create a new site called ‘Branch Office’ with description ‘Remote office in Austin, TX’.”
Uses create_site to provision a new UniFi site for multi-location management.
Prompt: “Move the device ‘AP-Office-2’ from the default site to the ‘Branch Office’ site.”
The assistant uses move_device_to_site for cross-site device transfers.
Prompt: “Show me aggregate client statistics across all sites - total count, by connection type, and by band.”
Uses aggregate_client_stats to provide organization-wide client analytics.
Prompt: “Set up a site-to-site VPN between my main office and branch office.”
The assistant uses configure_site_vpn to establish secure inter-site connectivity.
Firewall & Traffic Control
Prompt: “Block all BitTorrent traffic on my guest network during business hours.” The assistant will create a traffic matching list for P2P protocols and a firewall rule with schedule. Prompt: “Create an ACL that allows only IT department devices (192.168.10.0/24) to access the server VLAN (192.168.20.0/24).” Usescreate_acl to implement network segmentation and access control.
Prompt: “Show me all traffic flows where clients are using more than 10 GB per day.”
The assistant uses list_traffic_flows with filtering to identify high-bandwidth users.
Prompt: “Block the client at MAC address aa:bb:cc:dd:ee:ff for suspicious activity.”
Uses block_traffic_flow to immediately block a specific device.
Advanced Network Analysis
Prompt: “Analyze my network topology and tell me the maximum depth from the gateway and identify any bottlenecks.” The assistant usesget_topology_statistics to analyze network architecture and identify potential issues.
Prompt: “Show me all wired connections and their link speeds, highlighting any that aren’t running at 1 Gbps.”
Combines get_device_connections with filtering to identify underperforming network links.
Prompt: “Export all my site configurations for documentation purposes.”
The assistant uses export_site_config to generate comprehensive site documentation.
Troubleshooting & Monitoring
Prompt: “Why is my AP-Hallway showing as offline in the topology? Show me its last known connection details.” The assistant usesget_network_topology and filters for the specific device to diagnose connectivity issues.
Prompt: “Latency spikes whenever the link is busy. Is Smart Queue turned on, and are its rates set below my line speed?”
Uses get_smart_queue_status to check the WAN’s shaper state and rates.
Prompt: “Which backup is most recent and has it been tested for restore capability?”
The assistant uses list_backups and get_backup_details to validate backup integrity.
Prompt: “Show me all RADIUS authentication failures in the last 24 hours.”
Uses list_radius_accounts or authentication logs to troubleshoot access issues.
Combining Multiple Operations
Prompt: “I’m setting up a new branch office. Create a site, configure basic networks, enable Smart Queues on the WAN, enable RADIUS authentication, and schedule daily backups.” The assistant will orchestrate multiple MCP tools:create_site- Provision the sitecreate_network- Set up VLANsconfigure_smart_queue- Enable WAN Smart Queuescreate_radius_profile- Enable 802.1X authenticationconfigure_backup_schedule- Automate backups
get_topology_statisticsget_smart_queue_statusaggregate_client_statslist_backups+get_backup_statuslist_radius_profiles
Best Practices for Prompts
- Be Specific: Instead of “configure my network,” say “create a guest WiFi network with 4-hour timeout”
- Include Context: Mention site names, device IDs, IP ranges, or specific requirements
- Specify Timing: Use “right now,” “schedule for 2 AM,” or “during business hours”
- Request Validation: Ask for dry-run mode first: “Show me what would happen if…”
- Combine Related Tasks: Group related operations in a single prompt for better workflow
- Ask for Summaries: End with “and summarize the changes” to get a clear action report
API Changelog
Version 0.1.0 (Initial Release)
- Basic device management (list, get, restart)
- Network management (list, create)
- Client management (list, block)
- Firewall rule management (list, create)
- Site-based resource URIs
Future Enhancements
Planned features for future releases:- Port forwarding management (✅ Phase 5)
- WiFi network (SSID) management (✅ Phase 5)
- DPI (Deep Packet Inspection) statistics (✅ Phase 5)
- Webhook support for events (✅ Phase 5)
- Redis caching for performance (✅ Phase 5)
- Backup and restore operations (✅ v0.2.0 - Phase 4)
- Bulk operations for devices
- Advanced firewall rule management
- VPN configuration
- Alert and notification management
Support
For issues, questions, or contributions:- GitHub Issues: enuno/unifi-mcp-server/issues
- Documentation: See
README.mdandCONTRIBUTING.md - Security Issues: See
SECURITY.md
Last Updated: 2026-06-20 | API Version: v10.3.55
