Mist MCP Server

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.

Category
Visit Server

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:

  1. Authenticates with a permanent Bearer API token
  2. Registers a static, hand-written set of 22 curated MCP tools
  3. Serves the tools over the streamable-http MCP 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:

  1. 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.
  2. 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         │
                                        └──────────────────┘
  1. Bearer token auth — The server sends a permanent API token as Authorization: Bearer <token> on every request to api.mist.com/api/v1. The token is registered for log redaction so it never appears in logs or error messages.

  2. 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.

  3. 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, no mist_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 the HEALTHCHECK directive defined in the Containerfile; docker format keeps it for standalone podman run. The quadlet unit supplies its own HealthCmd, 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

  1. Create the systemd user directory (if it does not already exist):

    mkdir -p ~/.config/containers/systemd/
    
  2. Copy the quadlet file into that directory:

    cp mist-mcp.container ~/.config/containers/systemd/
    
  3. Create the environment file with your credentials:

    mkdir -p ~/.config/mist-mcp
    

    Edit ~/.config/mist-mcp/env with the required variables (see env.example):

    MIST_API_TOKEN=your-api-token
    MIST_ORG_ID=org_abc123
    
  4. Reload systemd and start the service:

    systemctl --user daemon-reload
    systemctl --user enable --now mist-mcp
    
  5. Check status:

    systemctl --user status mist-mcp
    
  6. 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 via ENV MIST_HOST=0.0.0.0), which is required so rootless Podman's pasta network can forward into the container on WSL2/macOS. The security boundary is the host-side port publish, pinned to loopback with PublishPort=127.0.0.1:8935:8935. The server is reachable only from the host at http://127.0.0.1:8935/mcp. Never publish the port on 0.0.0.0 host-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 EnvironmentFile in the quadlet (or set directly in the shell for development).
  • The API token is redacted from all logs and error messages — MistClient registers the token with a log redaction filter, and outgoing request headers are logged with the authorization header replaced by Bearer ***.
  • 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_WRITE flag. 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:8935 in the quadlet). The server is reachable only from the host at http://127.0.0.1:8935/mcp. Inside the container the server binds 0.0.0.0 (baked into the image via ENV MIST_HOST=0.0.0.0) so rootless Podman's pasta network can forward into the container on WSL2/macOS. Never publish the port on 0.0.0.0 host-side. For direct host runs the bind defaults to 127.0.0.1.
  • TLS verification is on by default — MIST_INSECURE_SKIP_VERIFY=true should 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

Recommended Servers

playwright-mcp

playwright-mcp

A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.

Official
Featured
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.

Official
Featured
Local
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.

Official
Featured
Local
TypeScript
VeyraX MCP

VeyraX MCP

Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.

Official
Featured
Local
graphlit-mcp-server

graphlit-mcp-server

The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.

Official
Featured
TypeScript
Kagi MCP Server

Kagi MCP Server

An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.

Official
Featured
Python
E2B

E2B

Using MCP to run code via e2b.

Official
Featured
Neon Database

Neon Database

MCP server for interacting with Neon Management API and databases

Official
Featured
Exa Search

Exa Search

A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.

Official
Featured
Qdrant Server

Qdrant Server

This repository is an example of how to create a MCP server for Qdrant, a vector search engine.

Official
Featured