Skip to content

Unifi MCP Server — 98 tools

contains code

The Unifi DADL turns Unifi's API into an MCP server that Claude, GPT or any MCP-compatible agent can consume directly. One YAML file declares all 98 tools — firewall, device, client, wlan, network, radius, and more — and ToolMesh serves them at runtime. No Python boilerplate, no per-endpoint code, no separate MCP server process.

Below: the endpoint coverage matrix, a two-block ToolMesh setup, the full tool reference grouped by Unifi feature area, required credential scopes.

Source: Ubiquiti UniFi Network Controller API

Credits: Dunkel Cloud GmbH -- maintainerUpdated: 2026-11-07

Which Unifi endpoints are covered?

61% (98 of ~160 endpoints)

Focus: Self-hosted UniFi Network Application API: devices (access points, switches, gateways, radio settings, adoption, restarts, firmware), WLANs (SSIDs, roaming, PMF, minimum data rates, AP groups), clients (active, known, blocking), firewall (rules, groups, NAT port forwarding, static routes), networks (LANs, VLANs, WAN), system log (client events, device alerts, admin activity), statistics (DPI, traffic reports, site health), hotspot (vouchers, authorizations), RADIUS, backups.

Missing: WebSocket events, v2 traffic rules and firewall policies, v2 client connection timeline, IPS/IDS management, hotspot portal config, VoIP extensions, spectrum scan results, switch port overrides, UniFi OS console login (/api/auth/login)

Last reviewed: 2026-11-07

How do you configure the Unifi DADL?

  1. Install or access your UniFi Network Controller (self-hosted or UDM/UDM Pro)
  2. Create a local admin account or use an existing one (Settings -> Admins)
  3. For dedicated API access, create a limited-admin account with read-only or site-admin role
  4. Note: UniFi uses session-based auth (username + password), not API keys
  5. Store the username and password in your ToolMesh credential store

Environment variable: CREDENTIAL_UNIFI_USERNAME / CREDENTIAL_UNIFI_PASSWORD

Authentication docs ↗

Written for the self-hosted UniFi Network Application: set url to https://<host>:8443. The file logs in at <url>/api/login. UniFi OS consoles (UDM, UCG, Cloud Key Gen2+) serve the Network API under https://<console>/proxy/network but log in at /api/auth/login on the console root, which this file does not configure; they are untested. Self-signed TLS certs are common -- configure TLS skip if needed. The health check calls GET /api/self and so tests the login with the stored credential.

How do you install the Unifi MCP server with ToolMesh?

Add to your backends.yaml:

- name: unifi
  transport: rest
  dadl: unifi.dadl
  url: "https://unifi.example.com:8443"

Set the credential:

CREDENTIAL_UNIFI_USERNAME / CREDENTIAL_UNIFI_PASSWORD=your-token-here

What 98 tools does the Unifi DADL expose?

GETget_server_statusGet controller server status (unauthenticated). Returns server version, UUID, up status.
GETget_selfGet currently logged-in admin user info
GETget_sysinfoGet controller system info: version, hostname, uptime, memory
GETget_healthGet site health status for all subsystems (wan, wlan, lan, vpn)
GETget_dashboardGet dashboard metrics. Optional scale param for time granularity.
GETlist_sitesList all sites accessible to current admin (basic info)
GETlist_sites_statsList all sites with health data, device counts, and alerts
POSTsite_commandSite management commands: add-site, delete-site, update-site, get-admins, move-device, delete-device
GETlist_adminsList all administrators across all sites with permissions
POSTadmin_commandAdmin commands: invite-admin, assign-existing-admin, update-admin, revoke-admin, delete-admin
GETlist_devices_basicList all adopted devices with limited fields (fast)
POSTlist_devicesList adopted devices (APs, switches, gateways) as a compact projection: _id, mac, name, type (uap, usw, ugw, udm), model, state (1 = connected), version, ip, uptime, traffic rates, num_sta, satisfaction, plus per radio the settings (radio_table: radio, name, channel, ht, tx_power_mode, tx_power, min_rssi_enabled, min_rssi) and the live radio stats (radio_table_stats: radio, channel, tx_power, num_sta, satisfaction, cu_total, cu_self_rx, cu_self_tx, tx_retries_pct). Switches have empty radio arrays. Port tables, LLDP, uplink and the remaining radio fields are not included: use get_device (one MAC) or get_device_detail for the full raw document. Optional macs (array) filters by MAC.
POSTget_device_detailFull raw device documents, no projection: port_table, lldp_table, uplink, vap_table, radio_table (all fields), radio_table_stats, config_network and more, about 30 kB per access point. Pass macs as an ARRAY, also for a single device: {macs: ["00:00:5e:00:53:01"]} returns exactly that device. There is no singular mac parameter; without macs the controller returns every device of the site. For one device get_device (GET by MAC) returns the same document. Returns an array of devices. The documents contain device keys (x_authkey, x_vwirekey): do not copy them into output.
GETget_deviceGet one device by MAC address: the full raw document (same content as get_device_detail with one MAC), including radio_table and radio_table_stats for access points and port_table for switches. Returns an array with one element. Works on self-hosted controllers (verified on Network 10.6). The document contains device keys (x_authkey, x_vwirekey): do not copy them into output.
PUT_update_device_rawInternal: raw device update. Sends only the fields given. radio_table REPLACES the whole radio array: a partial array loses the settings of the radios left out. Use the update_device composite instead, which reads the current radio_table and merges. Every call re-provisions the device (its clients drop briefly).
POSTdevice_commandDevice management commands: adopt, restart, force-provision, power-cycle, upgrade, set-locate, unset-locate, speedtest, speedtest-status, migrate, cancel-migrate, spectrum-scan
GETlist_active_clientsList all currently connected clients
GETget_clientGet details of a single connected client by MAC
GETget_userGet client/user details including offline clients
GETlist_known_clientsList all known/configured clients (including offline)
POSTlist_all_usersList all users (active and historical). Filter by type and time range.
POSTlist_guestsList guest clients within a time range
POSTclient_commandClient management commands: block-sta, unblock-sta, kick-sta, forget-sta
PUTupdate_clientUpdate client: name, note, fixed IP, network_id, usergroup_id
GETlist_networksList all networks (LANs, VLANs, WAN)
POSTcreate_networkCreate a new network
PUTupdate_networkUpdate network configuration
DELETEdelete_networkDelete a network. WARNING: may disconnect clients on this network.
GETlist_wlansList all WLAN configurations (SSIDs)
POSTcreate_wlanCreate a new WLAN (SSID)
PUTupdate_wlanUpdate a WLAN (SSID): pass only the fields to change; top-level fields not sent stay as they are. Array fields (wlan_bands, ap_group_ids) are replaced as a whole, so pass the complete list. Read the current values with list_wlans first. Every update re-provisions all APs that broadcast this SSID (clients drop briefly). Roaming: bss_transition (802.11v), fast_roaming_enabled (802.11r). Security: pmf_mode, wpa_mode, wpa3_support, wpa3_transition. Bands: wlan_bands. AP selection: ap_group_mode + ap_group_ids (list_ap_groups). The minrate_* values are used when minrate_setting_preference is manual. Returns the updated WLAN document, which includes x_passphrase: do not copy it into output.
DELETEdelete_wlanDelete a WLAN. All clients on this SSID will be disconnected.
GETlist_wlan_groupsList WLAN groups (radio profiles)
GETlist_ap_groupsList AP groups (v2 API): each entry has _id, name and device_macs (the member APs). A WLAN with ap_group_mode groups is broadcast only by the APs in the groups listed in its ap_group_ids (see update_wlan). Returns a bare array.
GETlist_firewall_rulesList all user-defined firewall rules
POSTcreate_firewall_ruleCreate a new firewall rule
PUTupdate_firewall_ruleUpdate a firewall rule
DELETEdelete_firewall_ruleDelete a firewall rule
GETlist_firewall_groupsList firewall groups (address groups, port groups)
POSTcreate_firewall_groupCreate a firewall group (address-group, port-group, ipv6-address-group)
PUTupdate_firewall_groupUpdate firewall group members
DELETEdelete_firewall_groupDelete a firewall group
GETlist_port_forwardsList all port forwarding rules
POSTcreate_port_forwardCreate a port forwarding rule
PUTupdate_port_forwardUpdate a port forwarding rule (enable/disable, change ports)
DELETEdelete_port_forwardDelete a port forwarding rule
GETlist_routesList user-defined static routes
GETget_active_routesGet active routing table from gateway device
POSTcreate_routeCreate a static route
PUTupdate_routeUpdate a static route
DELETEdelete_routeDelete a static route
GETget_dpi_statsGet site-wide Deep Packet Inspection stats
POSTget_site_dpiGet filtered site DPI stats by application or category
POSTget_client_dpiGet per-client DPI stats. Filter by MAC addresses.
POSTstat_report_siteGet site-level traffic report for a time interval
POSTstat_report_deviceGet per-AP traffic report for a time interval
POSTstat_report_userGet per-user traffic report for a time interval
POSTstat_report_gatewayGet gateway/WAN traffic report for a time interval
POSTclear_dpiClear/reset DPI counters
POSTlist_system_logRead the controller's system log (v2 API), where Network 10.x keeps the event history: client connects, disconnects and roams, device alerts and state changes, WAN and update events, admin activity, threat alerts. Replaces list_events and list_alarms, which Network 10.6 no longer serves. The POST is a query and changes nothing. timestampFrom and timestampTo are Unix epoch MILLISECONDS and are required, for the last 24 hours e.g. timestampFrom: Date.now() - 86400000, timestampTo: Date.now(). Results are paged and newest first: pageNumber starts at 0, pageSize sets the entries per page. Returns the raw page object {data: [...], page_number, total_element_count, total_page_count}. Entries carry key (e.g. a client-connected key), category, severity, timestamp (ms), a message template (message_raw, e.g. "{CLIENT} connected to {WLAN}") and parameters with the referenced CLIENT, DEVICE, WLAN etc. Class all returns every entry and can be narrowed with categories; the UniFi UI sends class-specific filter arrays for the other classes (see the params).
GETlist_eventsLegacy: list events from stat/event (newest first, max 3000) on older controllers. Network 10.6 answers HTTP 404; use list_system_log there. Use _limit and _start for paging.
GETlist_alarmsLegacy: list alarms from stat/alarm (newest first, max 3000) on older controllers. Network 10.6 answers HTTP 404; use list_system_log (class device-alert or critical) there.
GETlist_alarms_unarchivedLegacy: list unarchived alarms from rest/alarm (oldest first) on older controllers. Network 10.6 answers HTTP 400 api.err.InvalidObject; use list_system_log there.
POSTarchive_all_alarmsArchive all active alarms of the legacy alarm store (older controllers, where list_alarms works). Untested on Network 10.6, which no longer serves the alarm list.
POSTcreate_backupGenerate a controller backup
POSTlist_backupsList available auto-backups
POSTdelete_backupDelete a backup file by filename
POSTauthorize_guestAuthorize a guest client for network access
POSTunauthorize_guestRevoke guest authorization
POSTcreate_voucherCreate hotspot voucher(s) for guest access
POSTrevoke_voucherRevoke a voucher by its _id
POSTlist_vouchersList all vouchers. Optionally filter by creation timestamp.
GETlist_paymentsList hotspot payment history
POSTlist_sessionsList client sessions with time range and optional MAC filter
GETlist_user_groupsList user groups (bandwidth profiles)
POSTcreate_user_groupCreate a user group with bandwidth limits
PUTupdate_user_groupUpdate user group bandwidth limits
DELETEdelete_user_groupDelete a user group
GETget_settingsGet all site settings (country, locale, mgmt, guest_access, etc.)
PUTupdate_settingUpdate a specific site setting by key (country, locale, snmp, mgmt, guest_access, ntp, connectivity)
POSTset_ledToggle site-wide device LED on/off
GETlist_radius_profilesList RADIUS profiles
POSTcreate_radius_profileCreate a RADIUS profile
GETlist_radius_accountsList RADIUS user accounts
POSTcreate_radius_accountCreate a RADIUS user account
GETlist_tagsList all tags (MAC address groups)
POSTcreate_tagCreate a tag to group MAC addresses
PUTupdate_tagUpdate tag members
DELETEdelete_tagDelete a tag
POSTlist_rogue_apsList neighboring/rogue APs detected within a time range
GETlist_known_roguesList known/acknowledged rogue APs
GETget_ddns_statusGet Dynamic DNS status (current IP, last change)
GETget_ddns_configGet Dynamic DNS configuration
PUTupdate_ddns_configUpdate Dynamic DNS configuration
GETlist_port_profilesList switch port profiles (native VLAN, tagged VLANs, PoE mode)
GETget_country_codesList available country codes
GETget_wifi_channelsList available WiFi channels for the site's country setting
GETget_sdn_statusGet UniFi SDN/Cloud connection status

What composite workflows does the Unifi DADL provide? ⚠ contains code

FNupdate_deviceUpdate a device (AP, switch, gateway): name, led_override, disabled, and per-radio settings of an access point. Pass only what should change. For radio_table pass one entry per radio you want to change, keyed by radio (ng = 2.4 GHz, na = 5 GHz, 6e = 6 GHz), with only the fields to change, e.g. [{radio: "ng", channel: 11, ht: 20}, {radio: "na", min_rssi_enabled: true, min_rssi: -80}]. The controller replaces the whole radio_table on every write, so the composite reads the device (get_device), merges the changes into the current entries and sends the complete array; other radios and fields keep their values. Settable radio fields: channel ("auto" or a channel number), ht (20, 40, 80, 160, 240, 320), tx_power_mode (auto, high, medium, low, custom, disabled; disabled switches the radio off), tx_power (dBm, with custom), min_rssi_enabled, min_rssi (-90 to -67 dBm), sens_level_enabled, sens_level (-90 to -50), antenna_gain, antenna_id, vwire_enabled, hard_noise_floor_enabled, loadbalance_enabled, maxsta, dfs. Unknown fields are rejected before anything is sent. If nothing differs from the current state, no write happens. dry_run true returns the PUT body without writing. Every write re-provisions the device: its clients drop for a few seconds. Returns {_id, written, changed, radio_table (settings after the merge), result} or, with dry_run, {_id, written: false, dry_run: true, changed, body}.