Atlas / MCP servers / sirkirby / UniFi Network

UniFi NetworkBLOCK

mcp/sirkirby/unifi-network-1

MCP servers & Graph API for the UniFi suite of applications, Network, Protect, and Access

Verdict
BLOCK
Grade
F
Trust score
33 /100
Exposed tools
20 13r · 7w · 0d
Transport
sse · stdio · streamable-http
License
MIT
Stars
853
01

Overview

From the repository's own README, as read at the audited commit. Badges and raw HTML are left out.

Leverage agents and agentic AI workflows to manage your UniFi deployment.

[](https://pypi.org/project/unifi-network-mcp/) [](https://pypi.org/project/unifi-protect-mcp/) [](https://pypi.org/project/unifi-access-mcp/) [](https://pypi.org/project/unifi-mcp-relay/) [](https://pypi.org/project/unifi-api-server/) [](https://www.npmjs.com/package/unifi-mcp-worker) [](LICENSE) [](https://www.python.org/downloads/)

Servers

Choose an integration

Read from source at commit f2db13568fa0OBSERVED · 2026-09-28
02

Connect

Built from this server's own package name, version and transport as found in its source — not copied from anyone's documentation, so it cannot drift against a page we do not control. Replace the environment placeholders with a token scoped to the least it needs.

claude-code (pypi)
claude mcp add unifi-access-mcp --env UNIFI_USERNAME=${UNIFI_USERNAME} --env UNIFI_PASSWORD=${UNIFI_PASSWORD} --env UNIFI_API_KEY=${UNIFI_API_KEY} -- None unifi-access-mcp==0.6.9
03

Exposed tools (20)

13 read · 7 write · 0 destructive.

ToolRiskDescription
get_system_inforeadGet system information
list_clientsreadList all clients
list_devicesreadList all network devices
restart_devicewriteRestart a network device
structured_innerreadreturn StructuredInnerResult(**payload)
unifi_alphareadInspect client details
unifi_batchwriteExecute multiple UniFi tools in a single request. Each call is an object with
unifi_betareadInspect client details
unifi_exact_wall_policywriteApply the wall policy update workflow
unifi_executewriteExecute a UniFi tool by name. Use unifi_tool_index to discover available tools first.
unifi_firewall_policy_updatewriteModify policy configuration
unifi_get_clientreadpass
unifi_list_clientsreadpass
unifi_list_widgetsreadreturn await widget_manager.get_widgets()
unifi_list_zebrasreadreturn await widget_manager.get_zebras()
unifi_location_timelinereadQuery events across all connected UniFi products (Network, Protect, Access)
unifi_testreadreturn StructuredResult(success=True, data={
unifi_tool_indexreadDiscover available UniFi tools. Returns names and descriptions by default.
unifi_wallwritePolicy update settings
unifi_wall_alphawriteConfigure policy update
04

Trust audit

BLOCKgrade F · trust 33/100 Do not install this without reading the findings. The audit found something that could harm you or your machine.

LayerWhat it checksResult
L0Provenance & inventoryPASS
L1Static analysis of the codeWARN
L2Instruction surface (what it tells the agent)FAIL
L3Class-specific surfacePASS
L4Behavioural (sandbox)SKIPPED

What the source does

Filesystem
declared (9 observation(s))
Network
declared (9 observation(s))
Shell
declared (2 observation(s))
Dependencies
not all pinned
Secrets in source
found

Findings (25)

HIGHPrompt injection · prompt.credential_read · CWE-94, CWE-1427
.agents/skills/claude-plugin-config-transport/SKILL.md:353
As of PR #350, all plugin tool responses redact sensitive fields by default — Wi-Fi passphrases, VPN private/preshared keys, SNMP community strings, and Access credential token/PIN values are replaced
Why it matters. asks the agent to read credentials
HIGHPrompt injection · prompt.credential_read · CWE-94, CWE-1427
.agents/skills/claude-plugin-config-transport/SKILL.md:359
**Affected workflows:** WLAN passphrase updates, VPN key rotation, SNMP community string changes, Access credential token/PIN mutations. Plugin skills that guide agents through these workflows must ex
Why it matters. asks the agent to read credentials
HIGHPrompt injection · prompt.credential_read · CWE-94, CWE-1427
.agents/skills/live-smoke-testing/SKILL.md:497
401/403 means the key was rejected. Use this to validate Access API key configuration:
Why it matters. asks the agent to read credentials
MEDIUMCode injection · code.dynamic_import · CWE-78, CWE-94, CWE-95
apps/api/src/unifi_api/serializers/_registry.py:105
product_pkg = importlib.import_module(f"unifi_api.serializers.{product}")
MEDIUMCode injection · code.dynamic_import · CWE-78, CWE-94, CWE-95
apps/api/src/unifi_api/serializers/_registry.py:111
importlib.import_module(f"unifi_api.serializers.{product}.{modname}")
MEDIUMInformation disclosure · disclose.log_secret · CWE-209, CWE-532
apps/worker/src/commands/rotate-tokens.mjs:97
console.log(`Rotating relay token for "${location.location_name}"...`);
MEDIUMInformation disclosure · disclose.log_secret · CWE-209, CWE-532
apps/worker/src/lib/display.mjs:46
console.log(`      Relay token: ${maskToken(loc.relay_token)}`);
MEDIUMInformation disclosure · disclose.log_secret · CWE-209, CWE-532
apps/worker/src/lib/display.mjs:51
console.log(`  Agent token: ${maskToken(config.agent_token)}`);
MEDIUMInformation disclosure · disclose.log_secret · CWE-209, CWE-532
apps/worker/src/lib/display.mjs:52
console.log(`  Admin token: ${maskToken(config.admin_token)}`);
MEDIUMHard-coded secrets · secret.generic · CWE-798, CWE-321
apps/api/tests/routes/resources/test_nat_writes.py:163
secret = "private-value-192.0.2.53"
MEDIUMHard-coded secrets · secret.generic · CWE-798, CWE-321
apps/api/tests/test_mdns_action_audit.py:17
SECRET = "synthetic-controller-only-secret-mdns"
MEDIUMHard-coded secrets · secret.generic · CWE-798, CWE-321
apps/api/tests/test_vpn_alternate_address.py:23
SECRET = "synthetic-controller-only-vpn-secret"
MEDIUMHard-coded secrets · secret.generic · CWE-798, CWE-321
apps/network/tests/unit/test_threat_management_update.py:19
SECRET = "private-threat-canary"
MEDIUMHard-coded secrets · secret.generic · CWE-798, CWE-321
apps/network/tests/unit/test_vpn_alternate_address.py:21
SECRET = "synthetic-private-vpn-value"
MEDIUMHard-coded secrets · secret.github · CWE-798, CWE-321
tests/test_community_issue_triage_workflow.py:2955
comment_payload = _snapshot_payload(comments=[_comment(1, "github_pat_abcdefghijklmnopqrstuvwxyz123456")])
LOWInventory / provenance · inv.hidden_file · CWE-1104
docs/.nojekyll
.nojekyll
Why it matters. hidden member outside the usual dotfiles
Fix. review its purpose
LOWCode injection · code.dynamic_import · CWE-78, CWE-94, CWE-95
apps/api/tests/unit/test_cross_layer_symmetry.py:113
pydantic_mod = importlib.import_module(f"unifi_core.{server}.models.{domain}")
LOWCode injection · code.dynamic_import · CWE-78, CWE-94, CWE-95
apps/api/tests/unit/test_cross_layer_symmetry.py:114
strawberry_mod = importlib.import_module(f"unifi_api.graphql.types.{server}.{domain}")
LOWCode injection · code.dynamic_import · CWE-78, CWE-94, CWE-95
apps/network/tests/unit/test_delete_preview_contracts.py:121
module = importlib.import_module(module_name)
LOWFilesystem / path · fs.traversal · CWE-22, CWE-59
apps/access/Makefile:50
@if [ ! -d "../../.venv" ]; then \
LOWFilesystem / path · fs.traversal · CWE-22, CWE-59
apps/access/Makefile:121
@WHEEL=$$(ls ../../dist/unifi_access_mcp-*.whl | head -1); \
LOWFilesystem / path · fs.traversal · CWE-22, CWE-59
apps/access/Makefile:150
docker run --rm --env-file ../../.env unifi-access-mcp:latest
LOWFilesystem / path · fs.traversal · CWE-22, CWE-59
apps/access/Makefile:155
rm -rf ../../dist/
LOWFilesystem / path · fs.traversal · CWE-22, CWE-59
apps/network/Makefile:56
@if [ ! -d "../../.venv" ]; then \
LOWNetwork egress · net.raw_ip · CWE-200, CWE-319
apps/access/tests/unit/test_connection_manager.py:794
assert args == ("GET", "https://192.168.1.1:12445/api/v1/developer/visitors")

Gates applied: no_behavioural_pass.

Audited 2026-09-28 · audit v0.4.1 · source sha f2db13568fa0full audit observations/trust-audit/mcp-server/sirkirby__unifi-network-1.json · Report an issue / request a re-scan
05

Audit history

Every audit this server has had. A grade with a past is a grade somebody is still checking.

DateSourceVerdictGradeScoreChange
2026-09-28f2db13568fa0BLOCKF33first audit
06

Questions

What is the UniFi Network MCP server?

MCP servers & Graph API for the UniFi suite of applications, Network, Protect, and Access

What tools does UniFi Network expose?

20 in total: 13 read-only, 7 that write, and 0 that can delete or overwrite. Every one is listed on this page with its risk.

Is UniFi Network safe to connect to an agent?

No — not without reading the findings first. The audit graded it F (33/100) and found 3 critical or high issues in the source. Each one is listed on this page with the file and line it is on.

What credentials does UniFi Network need?

It reads GH_TOKEN, GITHUB_TOKEN, UNIFI_ACCESS_API_KEY, UNIFI_API_DB_KEY, UNIFI_API_KEY, UNIFI_NETWORK_PASSWORD_COMMAND, UNIFI_PASSWORD, UNIFI_RELAY_TOKEN and UNIFI_USERNAME from the environment. Give it a token scoped to the least it needs — an agent that can be talked into calling a tool can be talked into calling it with your credentials.

How does UniFi Network run?

It speaks sse, stdio and streamable-http, so it runs as a local process your client starts. It is published on npm as unifi-mcp-worker-source at 1.0.0.

How current is this page?

The grade is for one exact copy of the source (f2db13568fa0), read on 2026-09-28. The repository is watched and re-audited when it changes.

Advertisement