Command Palette

Search for a command to run...

UnylyUnyly
Browse all

Unifi Codemode

FreeNot checked

codemode MCP for LLM interactions with the UniFi Networking API

GitHubEmbed

About

codemode MCP for LLM interactions with the UniFi Networking API

README

A Model Context Protocol (MCP) server for LLM-assisted network management.

This server implements Anthropic's Code Execution pattern. Instead of accessing the typical MCP "tools", the LLM writes Python code that executes directly against an API. This approach (described by Cloudflare as "Code Mode") is more token-efficient and enables more complex multi-step analyses in a single execution.

Get an API key

In your UniFi console UI: Settings -> Control Plane -> Integrations -> Create API Key. Copy it immediately; it is shown only once.

Older UniFi OS versions put this under Settings -> Admins & Users -> (your admin) -> Create API Key.

[!CAUTION] The Integration API does not provide fine-grained access to the console. It only provides full-access, so use with care.

Install

The sandbox ships as prebuilt wheels, so there is no build toolchain to setup:

python3 -m venv .venv
.venv/bin/pip install -e .

Register with Claude Code

Use the absolute path to venv's interpreter and to main.py so it works from any directory:

claude mcp add unifi-codemode-mcp \
  -e UNIFI_HOST=https://<your-console-ip>:11443 \
  -e UNIFI_API_KEY=<your-api-key> \
  -- /fully/qualified/path/to/unifi-codemode-mcp/.venv/bin/python3 /fully/qualified/path/to/unifi-codemode-mcp/main.py

This registers the server for the current project. Add -s user before -- to make it available in every project.

To verify that Claude sees the tool, run:

claude mcp list

If you want to test this MCP before adding it to claude, you can throw the below line into your terminal. Be sure to change <your-console-ip> and <your-api-key>:

echo '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"execute_python","arguments":{"code":"print(get_sites())"}}}' \
  | UNIFI_HOST=https://<your-console-ip>:11443 UNIFI_API_KEY=<your-api-key> .venv/bin/python3 main.py

A working setup prints a result containing your site list. Any failure prints a traceback naming the cause.

What the LLM can call

41 read-only methods, generated from the console's own OpenAPI spec: sites, devices (plus per-device statistics), clients, networks, WiFi broadcasts, firewall zones and policies, ACL rules, DNS policies, switching (LAGs, stacks, MC-LAG), VPN, WANs, RADIUS profiles, hotspot vouchers, traffic matching lists, and DPI application data.

List methods return plain lists, fully paginated. site_id defaults to your first site, so single-site consoles can ignore it.

Three of the methods are for discovery rather than data which help keep the tool description small. The LLM pulls an endpoint's schema only when it actually needs it:

Method Returns
search_api(query) Endpoints matching a keyword, as operationIds
describe(operation_id) One endpoint's full description, filterable properties, schemas
filtering_guide() The console's documentation for the filter syntax

Many list endpoints accept filter=, which filters on the console instead of in Python:

get_clients(filter="type.eq('WIRED')")
get_devices(filter="and(model.eq('U6 Pro'), state.ne('OFFLINE'))")

Calls that don't depend on each other can run concurrently:

parallel([("get_device_statistics", {"device_id": d["id"]}) for d in get_devices()])

Try asking:

  • What's connected to my network right now?
  • Which of my UniFi devices are offline?
  • Group my clients by the access point they're connected to.
  • What configurations can I change to better secure my network?

Sandboxing

The LLM's code runs inside Monty, a sandboxed Python interpreter, not in this process. Sandboxed code cannot read files, reach the network, see the environment (including UNIFI_API_KEY), or call eval/exec — the generated API methods are its only way out. Each call gets a fresh namespace with a 30 second and 512 MB ceiling.

The trade is that only part of the standard library exists in there: json, re, math, collections, itertools, datetime, dataclasses and typing, among a few others, but not functools, statistics or ipaddress. The tool description tells the LLM which calls are available.

Regenerating the API surface

The console serves the OpenAPI spec for its own API docs UI, authenticated with the same API key:

UNIFI_HOST=https://<your-console-ip>:11443 UNIFI_API_KEY=<your-api-key> scripts/fetch-spec.sh
python3 scripts/generate_client.py

fetch-spec.sh saves the spec to unifi_codemode_mcp/spec/integration-<version>.json, named for the Network application version it describes, so a git diff after a console upgrade shows exactly what Ubiquiti changed. It lives inside the package so it ships with an ionstall instead of depending on the repo layout. generate_client.py rewrites unifi_codemode_mcp/generated.py from it.

generated.py is committed, so regenerating is a reviewable diff rather than something that changes under you at import time. Method names come from the spec's operationIds, with an override table in the generator for the ones that read badly (getSiteOverviewPage -> get_sites).

Read-only, for now

Only the spec's GET operations are generated. The other 32 operations (create, update, and delete for firewall policies, ACL rules, DNS policies, networks, and device adoption) are visible through search_api() and describe() but are not callable.

Eventually, modifications to the UniFi Networking devices will be enabled through the UNIFI_ALLOW_WRITES=1 environment variable, but for now its just a thought. The default stays read-only and the tool description can tell the LLM which mode it is in.

Notes

  • Getting an HTML login page back means you're on port 443. The Integration API is on 11443.
  • UNIFI_LOG_LEVEL=DEBUG logs every HTTP request to stderr.
  • New public methods on UbiquitiClient are advertised to the LLM automatically. The tool description is generated from the class.
  • The LLM's code runs in-process and unsandboxed, with the same access as whoever started the server.

License

MIT

from github.com/akrutsinger/unifi-codemode-mcp

Installing Unifi Codemode

This server has no published package — it is built from source. Open the repository and follow its README.

▸ github.com/akrutsinger/unifi-codemode-mcp

FAQ

Is Unifi Codemode MCP free?

Yes, Unifi Codemode MCP is free — one-click install via Unyly at no cost.

Does Unifi Codemode need an API key?

No, Unifi Codemode runs without API keys or environment variables.

Is Unifi Codemode hosted or self-hosted?

Self-hosted: the server runs locally on your machine via the install command above.

How do I install Unifi Codemode in Claude Desktop, Claude Code or Cursor?

Open Unifi Codemode on unyly.org, pick your client tab (Claude Desktop, Claude Code, Cursor) and press Install — the config is generated automatically, no JSON editing.

Related MCPs

Compare Unifi Codemode with

Not sure what to pick?

Find your stack in 60 seconds

Author?

Embed badge for your README

Browse similar

All ai MCPs