mcp-unifi-applications
Read-only, credential-free MCP server for querying packaged UniFi API documentation across Network, Protect, Site Manager, InnerSpace, Mobility, and Carrier Fabric.
Browse endpoints by app and HTTP method.
Fuzzy-search endpoints by name, path, method, or description.
Fetch full endpoint schemas, either folded for readability or raw JSON.
Drill into a specific field subtree instead of loading the whole endpoint.
Find where a field name appears across all endpoint schemas.
View all operations on a resource/path group.
Get runnable request examples in curl, Go, Node.js, Python, or Ansible, local or remote.
Retrieve sample JSON responses.
Read guide pages on filtering, error handling, getting started, and response formats.
Check loaded API versions, scrape dates, endpoint counts, and guide counts.
Filter several tools by application.
Provides queryable access to Ubiquiti's UniFi API documentation for Network, Protect, Site Manager, InnerSpace, Mobility, and Carrier Fabric, enabling endpoint search, schema drill-down, field lookup, guides, and code examples.
UniFi MCP Server: Queryable API Documentation
An MCP server that makes the official UniFi API documentation queryable by AI agents: endpoint search, schema drill-down, and code examples in five languages. It covers every application Ubiquiti publishes API docs for: Network, Protect, Site Manager, InnerSpace, Mobility and Carrier Fabric.
It is read-only and credential-free. It serves documentation and never talks to your controller.
Install
You need uv. The scraped docs ship inside the package, so there is nothing to scrape and no API key to set.
Claude Code
claude mcp add unifi-docs -- uvx mcp-unifi-applicationsAdd --scope user to make it available in every project.
Claude Desktop and other clients that read an mcpServers block take this entry
(Claude Desktop: claude_desktop_config.json):
{
"mcpServers": {
"unifi-docs": {
"command": "uvx",
"args": ["mcp-unifi-applications"]
}
}
}If the client reports that it cannot find uvx (GUI apps often start without your
shell's PATH), put the output of which uvx in command instead.
pip install mcp-unifi-applicationsThen use "command": "mcp-unifi-applications" with no args, or the absolute path
to that script if your client does not see your virtualenv.
What ships in the current release:
Application | API version | Scraped | Pages |
Network | v11.0.97 | 2026-11-02 | 82 |
Protect | v7.3.74 | 2026-11-02 | 81 |
Site Manager | v1.0.0 | 2026-09-10 | 12 |
InnerSpace | v1.3.23 | 2026-09-10 | 12 |
Mobility | v1.0.0 | 2026-09-10 | 9 |
Carrier Fabric | v1.0.0 | 2026-09-10 | 14 |
A workflow checks developer.ui.com every Monday and releases new API versions on its own.
Related MCP server: UniFi MCP Server
Example
"Without any context, just by using the unifi-applications MCP Server: can you tell me how to create a network with Go with the network API from UniFi, and what options do I have regarding the managed IPv4 DHCP gateway configuration?"
Claude answers that through the server, with none of the documentation in its context to begin with:
Call | What comes back |
|
|
| the request body; |
| only the DHCP subtree |
| a working request in Go |
The third call is the one that earns the server its place. Instead of the 70 KB endpoint schema, it returns just the subtree that answers the question:
# management[GATEWAY].ipv4Configuration.dhcpConfiguration (in requestBody)
- dhcpConfiguration: object (Gateway Managed IPv4 DHCP Configuration) — IPv4 DHCP …
- mode: string (required)
[RELAY]:
- dhcpServerIpAddresses: Array of string — DHCP Server IP addresses
[SERVER]:
- dnsServerIpAddressesOverride: Array of string — List of DNS servers …
- domainName: string — Domain name that can be used to access network in the browser.
- gatewayIpAddressOverride: string — Gateway IP address provided to DHCP clients. …
- ipAddressRange: object
- start: string (required)
- stop: string (required)
- leaseTimeSeconds: integer — The lease time in seconds for addresses in this range.
… ntpServerIpAddresses, option43Value, pxeConfiguration, tftpServerAddress, …Tools
Tool | What it does |
| Fuzzy search by name, path, method or description |
| Browse all endpoints, filtered by HTTP method or app |
| Full schema for one endpoint, folded to a readable summary |
| All operations on one resource, e.g. "networks" |
| One field's subtree, e.g. |
| Where a field name occurs across all endpoint schemas |
| A request in curl, Go, Node.js, Python or Ansible, local or remote |
| Example JSON response |
| Guide pages: filtering syntax, error handling, getting started |
| Which API versions are loaded, with scrape dates and counts |
Tools that return several results take an optional app filter (network,
protect, site-manager, innerspace, mobility, carrier-fabric).
How it differs
Most UniFi MCP servers are control planes: they log in to your controller and read or change live state. This one is a knowledge plane and never sees your network. The two complement each other: this one tells the model what the API looks like, a control-plane server calls it.
Ubiquiti does publish an OpenAPI spec per application, and it is a good one. But it carries no code examples and no response samples, has none of the guide pages, and at around 400 KB for Network it does not fit usefully into a context window. This server ships up to ten examples and a response sample per endpoint, and hands the model one field subtree at a time.
More
CONTRIBUTING.md: development setup, the scraper, the JSON format, releases
ROADMAP.md: what is planned, what is not, and why
Disclaimer
This project is not affiliated with, endorsed by, or sponsored by Ubiquiti Inc. The API documentation content scraped and served by this tool is the property of Ubiquiti Inc. and is sourced from their public developer portal. "UniFi" is a trademark of Ubiquiti Inc.
License
MIT
Available Tools
10 toolsfind_fieldFind FieldARead-onlyIdempotent
Locate a field by name across every endpoint, including inside discriminator variants.
Returns one line per occurrence: endpoint slug, dotted path, and which schema section it sits in (request body, parameters, or response). Common names appear hundreds of times; the reply is capped at 50 and states the true total and how many endpoints are involved, so a short list is never mistaken for a complete one. Paths from here can be passed straight to get_field_schema. A name that matches nothing returns close alternatives.
| Name | Required | Description | Default |
|---|---|---|---|
| slug | No | Optional — limit search to a specific endpoint. | |
| field_name | Yes | The field name to search for (case-insensitive). |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
get_docs_infoGet Docs InfoARead-onlyIdempotent
Report what documentation this server is serving.
Returns one line per application: API version, when it was scraped, and how many endpoints and guides it holds. Worth checking before trusting an answer about a recent API change — the documentation is a point-in-time copy, not a live view.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
get_endpointGet EndpointARead-onlyIdempotent
Get everything documented about one endpoint: method, path, description, path and query parameters, request body and response fields.
Returns readable text: a nested field list with types, required markers and descriptions, discriminator variants in brackets and enum values inline, folded at three levels deep. Large endpoints run to tens of thousands of characters — when you already know which field you need, get_field_schema returns that subtree alone. An unknown slug returns close matches rather than an error.
| Name | Required | Description | Default |
|---|---|---|---|
| slug | Yes | Endpoint identifier, app-qualified ('network/createnetwork') or bare ('createnetwork') when only one application has it. Use search_endpoints or list_endpoints to find one. | |
| summary | No | True (default) returns the folded text above. False returns the raw scraped JSON — complete and unfolded to every depth, several times larger, and only worth it when the folding hides something you need. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
get_endpoint_groupGet Endpoint GroupARead-onlyIdempotent
See every operation on one resource at once, grouped by API path.
Returns each matching resource path with its endpoints beneath it — method, slug, title and a one-line description — so the available verbs on a resource are visible together rather than found one at a time. Matching is a substring of the path, so 'networks' also finds nested paths, and one query can span applications.
| Name | Required | Description | Default |
|---|---|---|---|
| resource | Yes | Resource name or path fragment (e.g. 'networks', 'acl-rules', 'wifi/broadcasts'). |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
get_exampleGet ExampleARead-onlyIdempotent
Get a runnable request for one endpoint, in one language, as published by Ubiquiti.
Returns a heading naming the endpoint, language and mode, followed by a single code block. The request shape is authoritative; host addresses, site ids and API keys are placeholders to fill in. Bodies show the schema's default values, not a worked example — combine with get_endpoint or get_field_schema when the payload matters. If the requested language and mode pair does not exist, the reply lists the pairs that do instead of failing.
| Name | Required | Description | Default |
|---|---|---|---|
| mode | No | 'local' addresses the console directly (https://<console-ip>/proxy/…); 'remote' goes through the UniFi cloud API (api.ui.com). Defaults to 'local', except for the cloud-only applications — site-manager, mobility and carrier-fabric — which have no local form and default to 'remote'. | |
| slug | Yes | Endpoint identifier, app-qualified or bare when unambiguous. | |
| language | No | One of curl, go, nodejs, python, ansible. | curl |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
get_field_schemaGet Field SchemaARead-onlyIdempotent
Drill into a specific field's schema within an endpoint.
Instead of fetching the full 70KB endpoint schema, use this to get just the subtree you need. Paths from find_field output work directly.
| Name | Required | Description | Default |
|---|---|---|---|
| slug | Yes | Endpoint identifier (e.g. 'network/createnetwork'). | |
| field_path | Yes | Dotted path to the field, with discriminator variants in brackets. Examples: 'dhcpV4', 'management[GATEWAY].dhcpV4', 'management[GATEWAY].dhcpV4.gateway'. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
get_guideGet GuideARead-onlyIdempotent
Read a prose guide page: filtering syntax, error handling, getting started, response formats.
Returns the page as markdown with its title and source URL. Omit the topic to list what is available. Topics resolve by slug first, then by title; when the same slug exists in several applications the reply lists them and asks for an app rather than picking one. These pages carry the conventions that endpoint schemas assume but do not repeat.
| Name | Required | Description | Default |
|---|---|---|---|
| app | No | Optional app filter (network, protect, site-manager, innerspace, mobility, carrier-fabric). Omit to search all. | |
| topic | No | Guide slug or search term. Omit to list all available guides. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
get_response_sampleGet Response SampleARead-onlyIdempotent
Get the sample response body published for one endpoint.
Returns raw JSON exactly as the documentation shows it, with placeholder values. About two thirds of endpoints have one; the rest say so plainly. This is the shape of a successful reply — for the field-by-field schema including types and which fields are optional, use get_endpoint.
| Name | Required | Description | Default |
|---|---|---|---|
| slug | Yes | Endpoint identifier (e.g. 'network/getnetworksoverviewpage'). |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
list_endpointsList EndpointsARead-onlyIdempotent
Browse the endpoint catalogue: one line per endpoint with method, path, slug and title.
Returns at most 200 lines; beyond that the reply says how many were withheld and which filters would narrow it. For finding a specific endpoint, search_endpoints ranks by relevance instead. Unknown filter values are rejected by name rather than returned as an empty result.
| Name | Required | Description | Default |
|---|---|---|---|
| app | No | Optional app filter (network, protect, site-manager, innerspace, mobility, carrier-fabric). Omit to list all. | |
| method | No | Optional HTTP method filter (GET, POST, PUT, DELETE, PATCH). |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
search_endpointsSearch EndpointsARead-onlyIdempotent
Find endpoints by name, path fragment, method or description.
Returns up to ten matches ranked by relevance, each as a slug, method, path, title and a one-line description. Matching is fuzzy but floored: a query that resembles nothing returns no matches rather than the least-bad guess. Pass a result's slug to get_endpoint for the full schema. Unknown filter values are rejected by name.
| Name | Required | Description | Default |
|---|---|---|---|
| app | No | Optional app filter (network, protect, site-manager, innerspace, mobility, carrier-fabric). Omit to search all. | |
| query | Yes | Search term (endpoint name, path fragment, or keyword). | |
| method | No | Optional HTTP method filter (GET, POST, PUT, DELETE, PATCH). |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
5 tool updates
v0.5.0- Changed
find_field3 fields changed- removed
Input schema / properties / slug / anyOfRemoved value: -[ - { - "type": "string" - }, - { - "type": "null" - } -] - changed
Input schema / properties / slug / defaultPrevious value: -nullNew value: +"" - added
Input schema / properties / slug / typeAdded value: +"string"
- Changed
get_example3 fields changed- removed
Input schema / properties / mode / anyOfRemoved value: -[ - { - "type": "string" - }, - { - "type": "null" - } -] - changed
Input schema / properties / mode / defaultPrevious value: -nullNew value: +"" - added
Input schema / properties / mode / typeAdded value: +"string"
- Changed
get_guide6 fields changed- removed
Input schema / properties / app / anyOfRemoved value: -[ - { - "type": "string" - }, - { - "type": "null" - } -] - changed
Input schema / properties / app / defaultPrevious value: -nullNew value: +"" - added
Input schema / properties / app / typeAdded value: +"string" - removed
Input schema / properties / topic / anyOfRemoved value: -[ - { - "type": "string" - }, - { - "type": "null" - } -] - changed
Input schema / properties / topic / defaultPrevious value: -nullNew value: +"" - added
Input schema / properties / topic / typeAdded value: +"string"
- Changed
list_endpoints6 fields changed- removed
Input schema / properties / app / anyOfRemoved value: -[ - { - "type": "string" - }, - { - "type": "null" - } -] - changed
Input schema / properties / app / defaultPrevious value: -nullNew value: +"" - added
Input schema / properties / app / typeAdded value: +"string" - removed
Input schema / properties / method / anyOfRemoved value: -[ - { - "type": "string" - }, - { - "type": "null" - } -] - changed
Input schema / properties / method / defaultPrevious value: -nullNew value: +"" - added
Input schema / properties / method / typeAdded value: +"string"
- Changed
search_endpoints6 fields changed- removed
Input schema / properties / app / anyOfRemoved value: -[ - { - "type": "string" - }, - { - "type": "null" - } -] - changed
Input schema / properties / app / defaultPrevious value: -nullNew value: +"" - added
Input schema / properties / app / typeAdded value: +"string" - removed
Input schema / properties / method / anyOfRemoved value: -[ - { - "type": "string" - }, - { - "type": "null" - } -] - changed
Input schema / properties / method / defaultPrevious value: -nullNew value: +"" - added
Input schema / properties / method / typeAdded value: +"string"
2 tool updates
v0.3.1- Changed
get_endpoint2 fields changed- changed
Input schema / properties / slug / descriptionPrevious value: -"Endpoint identifier, app-qualified ('network/createnetwork') or bare\n ('createnetwork') when only one app has it. Use list_endpoints or\n search_endpoints to find slugs."New value: +"Endpoint identifier, app-qualified ('network/createnetwork') or bare\n ('createnetwork') when only one application has it. Use\n search_endpoints or list_endpoints to find one." - changed
Input schema / properties / summary / descriptionPrevious value: -"If True, return a compact field summary. If False, return raw JSON."New value: +"True (default) returns the folded text above. False returns the raw\n scraped JSON — complete and unfolded to every depth, several times\n larger, and only worth it when the folding hides something you need."
- Changed
get_example3 fields changed- changed
Input schema / properties / language / descriptionPrevious value: -"Programming language — one of: curl, go, nodejs, python, ansible."New value: +"One of curl, go, nodejs, python, ansible." - changed
Input schema / properties / mode / descriptionPrevious value: -"'local' (direct console access) or 'remote' (via cloud API).\n Defaults to 'local'; remote-only apps (site-manager, mobility,\n carrier-fabric) default to 'remote'."New value: +"'local' addresses the console directly (https://<console-ip>/proxy/…);\n 'remote' goes through the UniFi cloud API (api.ui.com). Defaults to\n 'local', except for the cloud-only applications — site-manager,\n mobility and carrier-fabric — which have no local form and default to\n 'remote'." - changed
Input schema / properties / slug / descriptionPrevious value: -"Endpoint identifier (e.g. 'network/createnetwork')."New value: +"Endpoint identifier, app-qualified or bare when unambiguous."
2 tool updates
v0.3.0- Changed
get_endpoint1 field changed- changed
Input schema / properties / slug / descriptionPrevious value: -"Endpoint identifier (e.g. 'createnetwork', 'listnetworks').\n Use list_endpoints or search_endpoints to find slugs."New value: +"Endpoint identifier, app-qualified ('network/createnetwork') or bare\n ('createnetwork') when only one app has it. Use list_endpoints or\n search_endpoints to find slugs."
- Changed
get_response_sample1 field changed- changed
Input schema / properties / slug / descriptionPrevious value: -"Endpoint identifier (e.g. 'listnetworks')."New value: +"Endpoint identifier (e.g. 'network/getnetworksoverviewpage')."
10 tool updates
- First observed
find_field - First observed
get_docs_info - First observed
get_endpoint - First observed
get_endpoint_group - First observed
get_example - First observed
get_field_schema - First observed
get_guide - First observed
get_response_sample - First observed
list_endpoints - First observed
search_endpoints
TDQS
Scored across 10 tools
Most tools have clearly distinct roles: list/search/get for endpoints, get_field_schema and find_field for field-level drill-down, get_guide for prose, get_docs_info for provenance. The main soft overlaps are list_endpoints vs search_endpoints vs get_endpoint_group (three different ways to browse endpoints) and get_example vs get_response_sample (request example vs response example), but each description explicitly contrasts itself with its neighbour, so an agent can pick correctly.
Every tool is snake_case and follows a verb_noun shape (get_endpoint, list_endpoints, search_endpoints, find_field, get_field_schema, get_endpoint_group). The verb choice (get/list/search/find) is meaningful rather than arbitrary, and get_docs_info is the only slightly loose noun but still fits the pattern.
Ten tools is squarely in the ideal range and each earns its place: catalogue browsing, search, per-endpoint detail, field lookup, field schema drill-down, examples, samples, guides, grouping, and docs provenance. There is no obvious padding or redundant near-duplicate.
For a documentation-browsing domain the surface is thorough: discovery (list/search/group), full endpoint schemas, targeted field drill-down and cross-endpoint field search, request examples, response samples, prose guides (with topic listing when omitted), and documentation version/provenance. I can't identify a meaningful dead end an agent would hit.
Maintenance
Related MCP Connectors
Wikimedia Enterprise API docs: search the guides, read every endpoint. Read-only, no account needed.
Scopable MSP API: clients, quotes, assessments, compliance, QBRs. OAuth 2.1, read-only or read-write
Live Steam Market API docs, schemas, products, games, markets and endpoint search.
Read-only HotAPI documentation: search integration guides and inspect OpenAPI operations.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceEnables comprehensive management of UniFi Network infrastructure through 24 tools for monitoring and controlling devices, clients, wireless networks, security, and guest access. Supports network administration tasks like device restarts, client blocking, WLAN configuration, and backup creation.11 npmMIT
- AlicenseCqualityAmaintenanceEnables AI agents to manage UniFi network infrastructure via the Model Context Protocol, supporting device management, network configuration, security, and QoS through local or cloud APIs.7132 npm1,176 PyPI343Apache 2.0
- AlicenseNot gradedqualityBmaintenanceMCP server for UniFi Network Controller enabling AI assistants to manage UniFi infrastructure via natural language. It supports firewall rules, IPv6, and uses lazy/eager tool modes to minimize context usage.6Mozilla Public 2.0
- AlicenseAqualityBmaintenanceloud-first UniFi management for AI agents. This server connects to the official UniFi Site Manager / Fabric cloud API (api.ui.com). Manage your entire UniFi fleet from anywhere through natural language.5153 PyPI5MIT