Omada MCP
Security-first MCP server for TP-Link Omada, with a stdio-first runtime, capability-gated tools, and OpenAPI-based network automation.
Install / Use
/learn @gaspareduard/Omada MCPQuality Score
Category
Development & EngineeringSupported Platforms
README
Safe Omada MCP
Security-focused MCP server for TP-Link Omada Open API workflows.
At a Glance
- Production-safe baseline uses
stdio - Omada credentials are environment-only
- Capability profiles and category gating control what tools are exposed
- HTTP remains in the codebase only as an explicitly unsafe, lab-only path
- Validated against live Omada Controller 6.x environments and designed around the documented 5.x/6.x Open API surface
Quick Start
Option 1: Use with Claude Desktop via Docker
-
Pull or build an image:
docker pull ghcr.io/gaspareduard/omada-mcp:latestIf you do not publish an image yet, build locally instead:
npm run docker:build -
Edit your Claude Desktop MCP config:
- macOS:
~/Library/Application Support/Claude/claude_desktop_config.json - Windows:
%APPDATA%\Claude\claude_desktop_config.json
- macOS:
-
Add the server entry:
{ "mcpServers": { "safe-omada": { "command": "docker", "args": [ "run", "-i", "--rm", "-e", "OMADA_BASE_URL=https://your-omada-controller.local", "-e", "OMADA_CLIENT_ID=your-client-id", "-e", "OMADA_CLIENT_SECRET=your-client-secret", "-e", "OMADA_OMADAC_ID=your-omadac-id", "-e", "OMADA_SITE_ID=your-site-id", "-e", "OMADA_STRICT_SSL=true", "ghcr.io/gaspareduard/omada-mcp:latest" ] } } } -
Restart Claude Desktop and verify the server by listing sites or devices.
Option 2: Run the container directly
docker run --rm -it \
--env-file .env \
ghcr.io/gaspareduard/omada-mcp:latest
Option 3: Run locally for development
npm install
npm run build
npm start
Configuration
The server reads configuration from environment variables. See .env.example for the complete reference.
Required Omada Variables
| Variable | Required | Default | Description |
| --- | --- | --- | --- |
| OMADA_BASE_URL | Yes | - | Base URL of the Omada controller |
| OMADA_CLIENT_ID | Yes | - | OAuth client ID from Omada Platform Integration |
| OMADA_CLIENT_SECRET | Yes | - | OAuth client secret |
| OMADA_OMADAC_ID | Yes | - | Omada controller ID (omadacId) |
| OMADA_SITE_ID | No | - | Optional default site ID |
| OMADA_STRICT_SSL | No | true | Enforce TLS certificate validation |
| OMADA_TIMEOUT | No | 30000 | HTTP timeout in milliseconds |
Capability and Logging
| Variable | Required | Default | Description |
| --- | --- | --- | --- |
| OMADA_CAPABILITY_PROFILE | No | safe-read | Built-in profile: safe-read, ops-write, admin, compatibility |
| OMADA_TOOL_CATEGORIES | No | profile default | Explicit category override |
| MCP_SERVER_LOG_LEVEL | No | info | debug, info, warn, error, silent |
| MCP_SERVER_LOG_FORMAT | No | plain | plain, json, or gcp-json |
Capability Profiles
| Profile | Intended use |
| --- | --- |
| safe-read | Default read-only operational visibility |
| ops-write | Limited operational write actions |
| admin | Full documented tool surface, including admin mutations |
| compatibility | Reserved for future controller-specific fallback modules |
Destructive Tool Confirmation Gate
The four restore tools (restoreController, restoreControllerFromFileServer, restoreSites, restoreSitesFromFileServer) enforce a two-step confirmation: without confirmDangerous: true the tool returns a warning explaining the action is irreversible and that a force recovery or factory reset may be required if something goes wrong.
Scope of this protection: this gate is effective in conversational AI sessions where the warning is surfaced to a human who then decides whether to confirm. It does not prevent a fully autonomous agent from passing confirmDangerous: true programmatically without human review.
True human-in-the-loop enforcement requires one or both of:
- MCP client approval mode — Claude Desktop and compatible MCP hosts can be configured to require explicit human approval before any tool call executes. This is the only reliable technical gate against autonomous execution.
- Capability profile restriction — the restore tools require
maintenance:rw, which is only granted underops-writeoradmin. Keeping the deployment on the defaultsafe-readprofile blocks all restore tools entirely.
Optional HTTP Lab Mode
HTTP is not part of the supported production baseline.
It only starts when both of these are set:
MCP_SERVER_USE_HTTP=trueMCP_UNSAFE_ENABLE_HTTP=true
Use it only for local lab/debug scenarios.
| Variable | Required | Default | Description |
| --- | --- | --- | --- |
| MCP_SERVER_USE_HTTP | No | false | Legacy lab-only switch |
| MCP_UNSAFE_ENABLE_HTTP | No | false | Explicit acknowledgement required |
| MCP_HTTP_PORT | No | 3000 | HTTP port |
| MCP_HTTP_BIND_ADDR | No | 127.0.0.1 | Loopback bind address only (127.0.0.1 or ::1) |
| MCP_HTTP_PATH | No | /mcp | MCP endpoint path |
| MCP_HTTP_ENABLE_HEALTHCHECK | No | true | Enable health check |
| MCP_HTTP_HEALTHCHECK_PATH | No | /healthz | Health check path |
| MCP_HTTP_ALLOW_CORS | No | true | Enable CORS |
| MCP_HTTP_ALLOWED_ORIGINS | No | 127.0.0.1, localhost | Allowed origins |
| MCP_HTTP_NGROK_ENABLED | No | false | Legacy placeholder; disabled in safe baseline |
| MCP_HTTP_NGROK_AUTH_TOKEN | No | - | Legacy placeholder |
Development and Validation
Common Commands
| Task | Command |
| --- | --- |
| Run dev server | npm run dev |
| Build | npm run build |
| Lint + type-check | npm run check |
| Unit tests | npm test |
| Coverage gates | npm run test:coverage |
| Symlink integrity | npm run symlinks:check |
| README/tool sync | node scripts/check-readme-sync.mjs |
| Tool/test mapping | node scripts/check-tool-tests.mjs |
Inspector
Use the MCP Inspector when you want to test the built server interactively:
npm run inspector
npm run inspector:build
Project Notes
- The safe baseline is
stdiofirst. - HTTP remains a legacy, explicitly unsafe lab path.
- The repo includes
docs/openapi/as the implementation reference for Omada endpoints. - README tool tables below are kept in sync with the registered MCP tools.
Tools
Site & Client
| Tool | Description |
| --------------------------- | ---------------------------------------------------------------------------- |
| listSites | Lists all sites configured on the controller. |
| getSiteCapacity | Get site capacity settings including maximum device and client counts. |
| getSiteDetail | Get detailed information about a site, including name, region, timezone, and configuration. |
| getSiteDeviceAccount | Get device account settings for a site. |
| getSiteNtpStatus | Get NTP server status and configuration for a site. |
| getSiteRememberSetting | Get the remember device setting for a site. |
| getSiteSpecification | Get site specification including device limits and feature capabilities. |
| getSiteUrl | Get the URL associated with a site for OpenAPI access. |
| getSiteTemplateConfig | Get configuration settings for a site template. Requires siteTemplateId. |
| getSiteTemplateDetail | Get detailed information about a site template. Requires siteTemplateId. |
| getSiteTemplateList | List all site templates configured on the controller. |
| listClients | Lists active client devices for a site. |
| getClient | [DEPRECATED] Use listClients instead. When you have a client MAC, getClientDetail is also available. This tool filters the site client list in-process. |
| listMostActiveClients | Gets the most active clients sorted by traffic usage. |
| listClientsActivity | Gets client activity statistics over time. |
| listClientsPastConnections| Gets past connection history for clients. |
| setClientRateLimit | Sets custom bandwidth limits (download/upload) for a specific client. |
| setClientRateLimitProfile | Applies a predefined rate limit profile to a specific client. |
| disableClientRateLimit | Disables bandwidth rate limiting for a specific client. |
| blockClient | Blocks a client from network access with an auditable mutation summary. |
| unblockClient | Restores a blocked client to network access with an auditable mutation summary. |
| reconnectClient | Forces a client to reconnect with an auditable mutation summary. |
| rebootDevice | Reboots a managed device with an auditable mutation summary. |
| setDeviceLed | Changes a device LED state with an auditable mutation summary. |
Device
| Tool | Description |
| ----------------------- | --------------------------------------------------------------------------------- |
| listDevices | Lists provisioned devices for a given site. |
| getDevice | [DEPRECATED] Use listDevices instead and filter results client-side. This tool filters the site device list in-process; there is no dedicated device-detail endpoint. |
| searchDevices | Searches for devices globally across all sites the user has access to. |
| listDevicesStats | Queries statistics for global adopted devices with pagination and filtering. |
| `getSwitchSt
