Mist MCP Server
Exposes Juniper Mist REST API as 22 curated MCP tools, enabling AI agents to query and manage network resources like sites, devices, WLANs, and Marvis AI insights through natural language.
README
Mist MCP Server
An MCP (Model Context Protocol) server that exposes the
Juniper Mist REST API (api.mist.com/api/v1, Bearer token auth) as a
curated set of MCP tools for AI agents.
Overview
This project bridges AI assistants (such as Claude, Copilot, or any MCP-compatible agent) with Juniper Mist's REST API. At startup, the server:
- Authenticates with a permanent Bearer API token
- Registers a static, hand-written set of 22 curated MCP tools
- Serves the tools over the
streamable-httpMCP transport
The result: an AI agent can query organizations, sites, devices, WLANs, RF templates, networks, alarms, events, maps, and insights, execute Marvis AI queries, and perform targeted write operations, all through natural-language conversations — without any hand-written API glue.
Why curated tools? The Mist REST API is a large OpenAPI surface. The curated tool set provides safe, conveniently-shaped wrappers for the most common operations. Unlike other MCP servers in this family, there are no escape hatches — the 22 curated tools are the complete surface. There is also no write gating — the Mist API token's RBAC permissions are the sole access control.
Prerequisites
Before using this server, you must configure Juniper Mist for API access:
-
Create an API token
- Navigate to Organization > Administrators > API Tokens in the Mist Console.
- Create a new token and copy the generated value — this is your
MIST_API_TOKEN.
-
Find your Organization ID
- Navigate to Organization > Settings in the Mist Console.
- The organization ID appears in the URL or on the settings page — this is your
MIST_ORG_ID.
Important: The token's effective permissions are entirely determined by the Mist RBAC profile assigned to the token. The MCP server does not perform any additional access control. Write tools are exposed by the server but their actual reach is enforced by Mist via the token's RBAC permissions. Mist validates all write operations and rejects unauthorized ones.
How It Works
┌──────────────┐ streamable-http ┌──────────────────┐
│ AI Agent │ ◄──────────────────────► │ Mist MCP │
│ (Claude, │ tools/list │ Server │
│ Copilot…) │ tools/call │ (FastMCP) │
└──────────────┘ └────────┬─────────┘
│
Authorization: Bearer <token>
│
▼
┌──────────────────┐
│ Juniper Mist │
│ REST API │
│ api.mist.com │
│ /api/v1 │
└──────────────────┘
-
Bearer token auth — The server sends a permanent API token as
Authorization: Bearer <token>on every request toapi.mist.com/api/v1. The token is registered for log redaction so it never appears in logs or error messages. -
Curated tool set — The server registers a fixed, hand-written set of 22 tools defined in
src/mist_mcp/curated_tools.py. The set is:- Read tools (15):
mist_orgs,mist_sites,mist_site,mist_devices,mist_device,mist_device_stats,mist_inventory,mist_wlans,mist_rf_templates,mist_networks,mist_alarms,mist_events,mist_maps,mist_insights,mist_marvis_query - Write tools (7):
mist_marvis_suggest,mist_marvis_action,mist_create_wlan,mist_update_wlan,mist_delete_wlan,mist_claim_devices,mist_restart_device
All 22 tools are always registered and always available. There are no escape hatches — no raw request tool, no introspection tool, no generic "pull anything" tool. Access control is enforced entirely by the Mist API token's RBAC permissions.
- Read tools (15):
-
Retry & error handling — HTTP 429 and 5xx responses are retried with exponential backoff (1s, 2s, 4s). Timeouts are retried once. The API token is redacted from all log output and error messages.
Tool Catalog
Read tools (15)
| Tool | Description |
|---|---|
mist_orgs |
Return all organizations accessible with the configured API token |
mist_sites |
Return all sites in an organization |
mist_site |
Return a single site's full details by its site ID |
mist_devices |
Return all devices (APs, switches, gateways) at a site |
mist_device |
Return a single device's full details by its device ID |
mist_device_stats |
Return real-time device statistics and health for a site |
mist_inventory |
Return the device inventory for an organization |
mist_wlans |
Return all WLAN configurations at a site |
mist_rf_templates |
Return all RF templates in an organization |
mist_networks |
Return all network definitions at a site |
mist_alarms |
Return current alarms for an organization |
mist_events |
Return events for a site, optionally filtered by event type |
mist_maps |
Return all maps (floor plans) at a site |
mist_insights |
Return wireless or client insights for an organization |
mist_marvis_query |
Ask a natural language question to Marvis, the Mist AI engine |
Write tools (7)
| Tool | Description |
|---|---|
mist_marvis_suggest |
Return suggested questions that Marvis can answer |
mist_marvis_action |
Ask Marvis for an actionable remediation recommendation |
mist_create_wlan |
Create a new WLAN at a site with the given SSID and JSON configuration |
mist_update_wlan |
Update an existing WLAN configuration at a site (partial update) |
mist_delete_wlan |
Delete a WLAN from a site by its WLAN ID |
mist_claim_devices |
Claim and assign devices to an organization's inventory using a claim code or MAC addresses |
mist_restart_device |
Restart (reboot) a device by its device ID |
Note: There are no escape hatches (no
mist_get, nomist_raw_request). The 22 curated tools are the complete surface. Write tools have no server-side gate — Mist RBAC is the sole access control. Mist validates all writes and rejects unauthorized operations.
Environment Variables
| Variable | Required | Default | Description |
|---|---|---|---|
MIST_API_TOKEN |
Yes | — | Mist API token from Organization > Administrators > API Tokens |
MIST_ORG_ID |
Yes | — | Default organization ID from Organization > Settings |
MIST_HTTP_TIMEOUT |
No | 30 |
HTTP request timeout in seconds for outbound calls to api.mist.com |
MIST_INSECURE_SKIP_VERIFY |
No | (unset) | Set to true to skip TLS verification (development only; Mist cloud API always uses valid TLS) |
MIST_HOST |
No | 0.0.0.0 (container) / 127.0.0.1 (direct run) |
Server bind address. The container image sets 0.0.0.0 so rootless Podman's pasta network can forward into the container on WSL2/macOS; the host-side port publish stays loopback-only. Direct host runs (python -m mist_mcp) default to 127.0.0.1; set 0.0.0.0 only when running inside a container. |
MIST_PORT |
No | 8935 |
Server bind port |
MIST_LOG_LEVEL |
No | INFO |
Log level: DEBUG, INFO, WARNING, ERROR |
See env.example for a documented template.
Build
Build the container image with Podman:
podman build --format docker -t ghcr.io/adam5isalive/mist-mcp-server:latest -f Containerfile .
Note: Build with
--format docker. The default OCI image format does not preserve theHEALTHCHECKdirective defined in the Containerfile;dockerformat keeps it for standalonepodman run. The quadlet unit supplies its ownHealthCmd, so this only matters outside quadlet.
Deploy with Podman Quadlet
Quadlet lets you run containers as systemd user services. This is the recommended deployment method for production use.
Step-by-step
-
Create the systemd user directory (if it does not already exist):
mkdir -p ~/.config/containers/systemd/ -
Copy the quadlet file into that directory:
cp mist-mcp.container ~/.config/containers/systemd/ -
Create the environment file with your credentials:
mkdir -p ~/.config/mist-mcpEdit
~/.config/mist-mcp/envwith the required variables (seeenv.example):MIST_API_TOKEN=your-api-token MIST_ORG_ID=org_abc123 -
Reload systemd and start the service:
systemctl --user daemon-reload systemctl --user enable --now mist-mcp -
Check status:
systemctl --user status mist-mcp -
View logs:
journalctl --user -u mist-mcp
Example quadlet file (mist-mcp.container)
[Unit]
Description=Mist MCP Server
Documentation=https://github.com/adam5isalive/mist-mcp-server
[Container]
Image=localhost/mist-mcp:latest
EnvironmentFile=%h/.config/mist-mcp/env
PublishPort=127.0.0.1:8935:8935
Restart=always
HealthCmd=/usr/bin/curl -fsS -o /dev/null -X POST http://127.0.0.1:8935/mcp -H "Content-Type: application/json" -H "Accept: application/json, text/event-stream" -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"healthcheck","version":"1"}}}'
HealthInterval=30s
HealthTimeout=10s
HealthStartPeriod=30s
HealthRetries=3
AutoUpdate=registry
Label=io.containers.autoupdate=registry
[Service]
Restart=on-failure
TimeoutStartSec=60
[Install]
WantedBy=default.target
Host binding / pasta: The container binds
0.0.0.0(baked into the image viaENV MIST_HOST=0.0.0.0), which is required so rootless Podman'spastanetwork can forward into the container on WSL2/macOS. The security boundary is the host-side port publish, pinned to loopback withPublishPort=127.0.0.1:8935:8935. The server is reachable only from the host athttp://127.0.0.1:8935/mcp. Never publish the port on0.0.0.0host-side.
Verify
List the available tools using any MCP client, or test directly with curl. The server is
reachable at http://127.0.0.1:8935/mcp from the host. The MCP streamable-http transport
requires a full handshake (initialize → capture Mcp-Session-Id → notifications/initialized
→ tools/list) and the proper Accept header.
For a manual check, first establish a session and capture the session ID:
curl -i -X POST http://127.0.0.1:8935/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{},"clientInfo":{"name":"curl","version":"1.0"}}}'
Then, using the Mcp-Session-Id header from the response, list the tools:
curl -X POST http://127.0.0.1:8935/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-H "Mcp-Session-Id: <session-id>" \
-d '{"jsonrpc":"2.0","id":2,"method":"tools/list"}'
A successful response lists all 22 tools, for example:
{
"jsonrpc": "2.0",
"id": 2,
"result": {
"tools": [
{
"name": "mist_orgs",
"description": "Return all organizations accessible with the configured API token, including org id, name, and metadata.",
"inputSchema": { "type": "object", "properties": {} }
},
{
"name": "mist_sites",
"description": "Return all sites in an organization, including site id, name, address, and configuration.",
"inputSchema": { "type": "object", "properties": { "org_id": { "type": "string" } } }
},
{
"name": "mist_devices",
"description": "Return all devices (APs, switches, gateways) at a site, including id, mac, model, name, type, and status.",
"inputSchema": { "type": "object", "properties": { "site_id": { "type": "string" } } }
},
{
"name": "mist_marvis_query",
"description": "Ask a natural language question to Marvis, the Mist AI engine. Supports questions about network health, client experience, device status, and more.",
"inputSchema": { "type": "object", "properties": { "query": { "type": "string" }, "org_id": { "type": "string" } } }
},
{
"name": "mist_create_wlan",
"description": "Create a new WLAN at a site with the given SSID and JSON configuration.",
"inputSchema": { "type": "object", "properties": { "site_id": { "type": "string" }, "ssid": { "type": "string" }, "config": { "type": "string" } } }
},
…
]
}
}
Hermes Registration
To register this MCP server with an AI agent that supports the Hermes MCP configuration format, add the following to the agent's MCP config:
{
"mcpServers": {
"mist-mcp": {
"url": "http://127.0.0.1:8935/mcp"
}
}
}
Security Notes
- Secrets come from environment variables only — The API token and org ID are never baked
into the container image. They are provided at runtime via the
EnvironmentFilein the quadlet (or set directly in the shell for development). - The API token is redacted from all logs and error messages —
MistClientregisters the token with a log redaction filter, and outgoing request headers are logged with the authorization header replaced byBearer ***. - No escape hatches — Unlike other MCP servers in this family, this server has no raw request tool, no introspection tool, and no generic "pull anything" tool. The 22 curated tools are the complete surface. Agents cannot bypass the curated tool set.
- No write gating — All 7 write tools are always registered and always available. There is no
ALLOW_WRITEflag. Access control is enforced entirely by the Mist API token's RBAC permissions. Mist validates all writes and rejects unauthorized operations. - Loopback-only exposure — The security boundary is the host-side port publish, pinned to
loopback (
PublishPort=127.0.0.1:8935:8935in the quadlet). The server is reachable only from the host athttp://127.0.0.1:8935/mcp. Inside the container the server binds0.0.0.0(baked into the image viaENV MIST_HOST=0.0.0.0) so rootless Podman'spastanetwork can forward into the container on WSL2/macOS. Never publish the port on0.0.0.0host-side. For direct host runs the bind defaults to127.0.0.1. - TLS verification is on by default —
MIST_INSECURE_SKIP_VERIFY=trueshould only be used in development or test environments. The Mist cloud API always uses valid TLS certificates. - Rootless operation — The quadlet runs under
systemctl --user, meaning the container runs without root privileges. This follows the principle of least privilege.
Development
Run the server locally without a container. The curated tool set is registered by
register_curated_tools() in src/mist_mcp/curated_tools.py:
# Create and activate a virtual environment
python -m venv .venv && . .venv/bin/activate
# Install the package in editable mode
pip install -e .
# Run with required environment variables
MIST_API_TOKEN=your-api-token \
MIST_ORG_ID=org_abc123 \
python -m mist_mcp
Or use the installed console script:
MIST_API_TOKEN=your-api-token \
MIST_ORG_ID=org_abc123 \
mist-mcp
The server will start on 127.0.0.1:8935 by default. You can override the bind address, port,
log level, timeout, and TLS verification via the environment variables listed above.
Updating
If the container image is published to a registry, and the quadlet includes AutoUpdate=registry,
you can update to the latest image with:
podman auto-update
This pulls the latest image and restarts the container gracefully. Check the status afterwards:
systemctl --user status mist-mcp
Architecture
mist-mcp-server/
├── env.example # Documented environment variable template
├── pyproject.toml # Project metadata, dependencies, entrypoint
├── src/
│ └── mist_mcp/
│ ├── __main__.py # Entrypoint: env loading, init, server start
│ ├── rest_client.py # Async REST client for api.mist.com/api/v1
│ └── curated_tools.py # Static, hand-written MCP tool set (22 tools)
└── tests/ # Test suite (see test files)
Module responsibilities
| Module | Role |
|---|---|
__main__.py |
Reads environment variables, validates required ones (MIST_API_TOKEN, MIST_ORG_ID), initialises MistClient, creates the FastMCP server, calls register_curated_tools(), and starts the streamable-http transport. |
rest_client.py |
Async HTTP client for api.mist.com/api/v1. Sends Authorization: Bearer <token>, provides get(), post(), put(), delete() methods, retries on 429/5xx with exponential backoff (1s, 2s, 4s), retries once on timeout, redacts the API token from all log output, and raises typed exceptions (MistError, MistHttpError). |
curated_tools.py |
Registers the static, hand-written tool set (register_curated_tools(mcp, mist_client)): 15 read tools and 7 write tools. No escape hatches, no write gating. Returns the number of tools registered (22). |
Skills
skills/mist-tools.skill.md— Per-tool reference for all 22 tools: exact names, argument signatures, return shapes, and read/write status.skills/mist-api.skill.md— Reference for the Juniper Mist REST API itself: endpoint, auth, URL paths, and RBAC.skills/podman-deploy.skill.md— Rootless Podman quadlet build and deployment of the server.
推荐服务器
Baidu Map
百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。
Playwright MCP Server
一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。
Magic Component Platform (MCP)
一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。
Audiense Insights MCP Server
通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。
VeyraX
一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。
graphlit-mcp-server
模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。
Kagi MCP Server
一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。
e2b-mcp-server
使用 MCP 通过 e2b 运行代码。
Neon MCP Server
用于与 Neon 管理 API 和数据库交互的 MCP 服务器
Exa MCP Server
模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。