AI Decision System
Replayable, offline-verifiable records for AI-assisted go/no-go decisions: experiment promotions, typed model answers and human-approved actions.
MCP server for TP-Link Omada SDN: 78 read/write tools for sites, devices, clients, VLANs, firewall, Wi-Fi, switch ports and WAN
Developer toolsTypeScript · JavaScriptGitHub @realtydevSelf-installOwner unconfirmed
Paste into Claude or ChatGPT for installation instructions suited to your environment.
Have you tried it? One tap is enough. No sign-in needed.
Owners of public repositories under a personal GitHub account can sign in to verify ownership and manage the introduction themselves. No administrator approval is needed.
Sign in, generate a verification file, and commit it to this repository’s default branch within 30 minutes. Files on other branches or forks do not count. Then check the file below to manage the project without administrator approval. Keep the file to retain your access.
If needed, you will go to sign-in. After signing in, return here and press your chosen verification button again.
Installable projects can be verified without a deployment domain. Use GitHub sign-in for a personal repository, or the repository verification file above for an organization repository.
Ask about other verification options
Loading the full README. The saved excerpt is shown below.
Talk to your TP-Link Omada network. A Model Context Protocol server that lets Claude, Cursor, and any MCP client read and change your Omada SDN controller: sites, gateways, switches, access points, clients, VLANs, firewall, Wi-Fi, routing, and WAN.Read the full README ↗Talk to your TP-Link Omada network. A Model Context Protocol server that lets Claude, Cursor, and any MCP client read and change your Omada SDN controller: sites, gateways, switches, access points, clients, VLANs, firewall, Wi-Fi, routing, and WAN.
You: Why is the guest SSID slow on the upstairs AP?
Claude: (getApRadios → listClientsActivity → getSsidDetail)
The 5 GHz radio on "AP-Upstairs" is on channel 149 at 80 MHz with 23% retries…
You: Move it to 36 at 40 MHz, dry run first.
Claude: (setApRadio dryRun=true → setApRadio) Done. Read back and verified.
destructiveHint, rejects unknown fields instead of silently dropping them, and the riskiest ones (setApRadio, setLogNotifications) support dry runs and verify the result by reading it back.getServerInfo reports the exact version and git commit of the running server.In your Omada controller, go to Settings → Platform Integration → Open API, add an application in Client mode, and note the Client ID, Client Secret, and Omada ID (omadacId).
Tools that use the internal web UI API (
listRoutes, route/port-forward CRUD, firewall ACLs on OC200) also needOMADA_WEB_USERNAME/OMADA_WEB_PASSWORDfor a local controller account. Fusion gateways without Platform Integration can useOMADA_AUTH_MODE=webinstead of OAuth.
Docker (recommended), e.g. claude_desktop_config.json or .mcp.json:
{
"mcpServers": {
"omada": {
"command": "docker",
"args": [
"run", "-i", "--rm",
"-e", "OMADA_BASE_URL",
"-e", "OMADA_CLIENT_ID",
"-e", "OMADA_CLIENT_SECRET",
"-e", "OMADA_OMADAC_ID",
"-e", "OMADA_SITE_ID",
"-e", "OMADA_STRICT_SSL",
"ghcr.io/realtydev/omada-mcp:latest"
],
"env": {
"OMADA_BASE_URL": "https://omada.local:8043",
"OMADA_CLIENT_ID": "your-client-id",
"OMADA_CLIENT_SECRET": "your-client-secret",
"OMADA_OMADAC_ID": "your-omadac-id",
"OMADA_SITE_ID": "your-site-id",
"OMADA_STRICT_SSL": "false"
}
}
}
}
Claude Code:
claude mcp add omada \
-e OMADA_BASE_URL=https://omada.local:8043 \
-e OMADA_CLIENT_ID=your-client-id \
-e OMADA_CLIENT_SECRET=your-client-secret \
-e OMADA_OMADAC_ID=your-omadac-id \
-e OMADA_STRICT_SSL=false \
-- docker run -i --rm \
-e OMADA_BASE_URL -e OMADA_CLIENT_ID -e OMADA_CLIENT_SECRET -e OMADA_OMADAC_ID -e OMADA_STRICT_SSL \
ghcr.io/realtydev/omada-mcp:latest
From source:
git clone https://github.com/realtydev/omada-mcp.git && cd omada-mcp
corepack enable && yarn install && yarn build
# then point your client at: node /path/to/omada-mcp/dist/index.js
docker run -d --env-file .env \
-e MCP_SERVER_USE_HTTP=true -e MCP_HTTP_BIND_ADDR=0.0.0.0 \
-p 3000:3000 ghcr.io/realtydev/omada-mcp:latest
Endpoints: http://localhost:3000/mcp (Streamable HTTP) or /sse (SSE), with /healthz for health checks. See README.Docker.md for every HTTP option.
| Variable | Required | Default | Description |
|---|---|---|---|
OMADA_BASE_URL | Yes | - | Omada controller URL |
OMADA_AUTH_MODE | No | oauth | oauth for classic OpenAPI credentials, web for Fusion web-session auth |
OMADA_CLIENT_ID | OAuth mode | - | OAuth client ID |
OMADA_CLIENT_SECRET | OAuth mode | - | OAuth client secret |
OMADA_OMADAC_ID | Yes | - | Controller ID (omadacId) |
OMADA_SITE_ID | No | - | Default site ID |
OMADA_WEB_USERNAME | Web mode | - | Omada web UI username |
OMADA_WEB_PASSWORD | Web mode | - | Omada web UI password |
OMADA_STRICT_SSL | No | true | SSL verification (false for self-signed) |
OMADA_TIMEOUT | No | 30000 | Request timeout (ms) |
For Fusion gateways that do not expose Platform Integration OAuth credentials, set OMADA_AUTH_MODE=web and provide OMADA_WEB_USERNAME / OMADA_WEB_PASSWORD. The server logs in through /{omadacId}/api/v2/login and uses that web session for OpenAPI requests.
| Variable | Required | Default | Description |
|---|---|---|---|
MCP_SERVER_LOG_LEVEL | No | info | debug, info, warn, error, silent |
MCP_SERVER_LOG_FORMAT | No | plain | plain, json, gcp-json |
MCP_SERVER_USE_HTTP | No | false | Enable HTTP transport |
MCP_SERVER_STATEFUL | No | false | Stateful sessions |
MCP_HTTP_PORT | No | 3000 | HTTP port |
MCP_HTTP_TRANSPORT | No | stream | stream or sse |
MCP_HTTP_BIND_ADDR | No | 127.0.0.1 | Bind address |
| Tool | Description |
|---|---|
listSites | List all sites on the controller |
listDevices | List devices for a site |
listClients | List active clients for a site |
getDevice | Get details for a specific device |
getGatewayWanStatus | Live per-port WAN status: link/internet state, IPv4 lease, DNS, latency and loss |
getApRadios | AP radio configuration (channel, width, tx power per band) and radio statistics (retries, drops) |
getClientHistory | A client's association sessions over a time range, optionally with roams between APs |
getClient | Get details for a specific client |
getSwitchStackDetail | Get switch stack configuration and status |
searchDevices | Search devices globally across all sites |
listDevicesStats | Device statistics with pagination and filtering |
listMostActiveClients | Top clients sorted by traffic |
listClientsActivity | Client activity time-series data |
listClientsPastConnections | Historical client connections |
getThreatList | Security threat list with filtering |
getInternetInfo | Internet / WAN configuration |
getPortForwardingStatus | Port forwarding rules (User uses the internal web UI API when OMADA_WEB_USERNAME/OMADA_WEB_PASSWORD are set; UPnP uses the public Open API) |
getLanNetworkList | LAN networks and VLAN settings |
getLanProfileList | LAN profiles for switch ports |
getWlanGroupList | WLAN groups |
getSsidList | SSIDs in a WLAN group |
getSsidDetail | Detailed SSID configuration |
| Tool | Description |
|---|---|
createLanNetwork | Create a LAN network (VLAN, subnet, DHCP range, DNS servers, custom DHCP options) |
updateLanNetwork | Update a LAN network |
deleteLanNetwork | Delete a LAN network |
createLanProfile | Create a LAN profile |
updateLanProfile | Update a LAN profile |
updateFirewallSetting | Update firewall settings |
setIpsSetting | Enable/disable and configure IDS/IPS (mode, detection level) on a site's gateway; can reduce max throughput when enabled |
createFirewallAcl | Create a firewall ACL rule |
updateFirewallAcl | Update a firewall ACL rule |
deleteFirewallAcl | Delete a firewall ACL rule |
updateSsid | Update an SSID's basic config (name, band, security, VLAN, PSK, etc.) |
setSsidEnable | Enable or disable an SSID network-wide |
updateSwitchPort | Update switch port config (profile, PoE, speed, STP) |
updateClient | Update client settings |
setSwitchNetworks | Set switch VLAN trunking configuration |
createRoute | Create a static route (internal web UI API only) |
updateRoute | Update a static route by ID (internal web UI API only) |
deleteRoute | Delete a static route by ID (internal web UI API only) |
createPortForward | Create a port forwarding rule (internal web UI API only) |
updatePortForward | Update a port forwarding rule by ID (internal web UI API only) |
deletePortForward | Delete a port forwarding rule by ID (internal web UI API only) |
updateWanPortSetting | Update a gateway WAN port's IPv4/IPv6/MAC connection settings (e.g. DHCP client ) |
| Tool | Description |
|---|---|
setSwitchPortProfile | Assign a LAN profile to a single port |
setSwitchPortPoe | Enable/disable PoE on a single port |
setSwitchPortName | Set name on a single port |
setSwitchPortStatus | Enable/disable a single port |
setSwitchPortProfileOverride | Enable/disable profile override on a single port |
batchSetSwitchPortProfile | Batch profile override on multiple ports |
batchSetSwitchPortPoe | Batch PoE on multiple ports |
batchSetSwitchPortStatus | Batch enable/disable multiple ports |
batchSetSwitchPortName | Batch set names on multiple ports |
startCableTest | Start cable test on a switch |
| Tool | Description |
|---|---|
rebootDevice | Reboot a device |
adoptDevice | Adopt a device |
blockClient | Block a client |
unblockClient | Unblock a client |
reconnectClient | Reconnect a client |
setDeviceLed | Set device LED setting |
setLogNotifications | Turn alert/event log notification types on or off for a site; dry run supported, returns a before/after diff (live config write) |
setApRadio | Change one AP radio band: enable, channel index, width, tx power. Reads back and verifies, fails if the controller does not apply it; dry run supported (live config write, can drop clients on that band) |
startFirmwareUpgrade | Start firmware upgrade |
setGatewayWanConnect | Software-connect or disconnect a gateway WAN port |
| Tool | Description |
|---|---|
genericApiCall | Invoke any Omada OpenAPI endpoint directly |
| Tool | Description |
|---|---|
getServerInfo | Report the package version, git commit, and build time this server process was actually built from |
Omada's Link Backup can stay stuck on a dead primary WAN when the cable modem hands the gateway a private fallback lease (e.g. 192.168.100.10) and Online Detection keeps calling it "online". The optional guard polls getGatewayWanStatus and software-disconnects only the primary port after consecutive fallback observations, so Link Backup takes over.
OMADA_WAN_GUARD_ENABLED=true OMADA_WAN_GUARD_GATEWAY_MAC=AA-BB-CC-DD-EE-FF yarn wan-guard
It is disabled and dry-run by default. Read docs/wan-guard.md for configuration, testing, and where to host it.
This server can change live network configuration. Some good habits:
OMADA_STRICT_SSL=true unless your controller uses a self-signed certificate on a trusted LAN.MCP_HTTP_BIND_ADDR at 127.0.0.1 unless you put the HTTP server behind authentication. The MCP endpoint itself is unauthenticated.Found a vulnerability? See SECURITY.md.
Requires Node 24 (see .nvmrc, use nvm use) and Yarn 4 via Corepack (corepack enable).
yarn install
yarn dev # Live reload via tsx
yarn build # Compile TypeScript
yarn check # Lint + type check
yarn start # Run compiled server (stdio)
yarn docker:build # Build image
yarn docker:run # Run with .env file
For stdio transport, each session's MCP client spawns its own server subprocess when it connects,
and that process keeps running whatever code it loaded at that point. Rebuilding dist/ on disk
(yarn build) does not affect an already-connected session — only a fresh connection picks up
the new build. After merging a change and rebuilding:
/mcp in Claude Code, or
start a new session).getServerInfo tool and check gitCommit against the commit you expect to be running,
before relying on any new or changed tool behavior — especially anything billed as dry-run or
safe-by-default. A session that skips this can silently keep running stale code that ignores a
safety parameter it doesn't know about yet.Issues and pull requests are welcome. See CONTRIBUTING.md for the dev setup and conventions. Much of this codebase is written with AI assistance (Claude Code) under human review.
Maintained by realtydev.
getServerInfo, strict write validation, and many endpoint fixes.getFirewallSetting | Firewall rules and policies |
getIpsSetting | IDS/IPS (threat protection) status for a site's gateway — enabled/disabled, mode, and detection level; reports supported: false on gateway models without IDS/IPS |
getFirmwareDetails | Firmware info for a device |
listAlerts | Paginated site alerts, optionally filtered by module and resolved state |
listEvents | Paginated site events, optionally filtered by module and event key prefix |
listLogs | Paginated site logs |
listFirewallAcls | Firewall ACL rules |
listIpGroups | IP groups used by firewall ACLs (internal web UI API, requires OMADA_WEB_USERNAME/OMADA_WEB_PASSWORD) |
listRoutes | Static routes (internal web UI API only, requires OMADA_WEB_USERNAME/OMADA_WEB_PASSWORD) |
getSwitch | Full switch info including portList array (per-port status, profile, PoE) |
getCableTestResults | Cable test results for a switch |
getSwitchNetworks | Switch VLAN trunking configuration |
unicastDhcp