Skip to main content
Glama

meraki-mcp

A read-only, production-shaped Model Context Protocol server for the Cisco Meraki Dashboard, built for infra/delivery teams (MR / MS / MX). It exposes a small, high-signal set of tools an LLM can select reliably — the tool design rationale lives in ../docs/; the code architecture is in ARCHITECTURE.md.

Built on the MCP Python SDK (FastMCP) and the official async meraki library.

What makes it enterprise-shaped

  • One response contract. Every tool returns ToolResult{summary, data, meta, error}. Nobody hand-rolls output; tools project Meraki payloads to declared fields (no raw blobs) and cap arrays. meta carries scope, count, truncated, elapsed_ms, partial/warnings (a partially-failed call declares what's missing), and note.

  • Response-size budget. The registrar runs enforce_budget on every result: if it serializes past MERAKI_MCP_MAX_RESPONSE_CHARS (~15k tokens) the largest arrays are shrunk to fit and the result is flagged (meta.truncated + meta.note) — so a response can never overflow the Copilot/agent context.

  • One lifecycle owner. register_tool wraps every tool with timeout, exception→ToolResult normalization, elapsed_ms, and structured logging. A raw exception never crosses the MCP boundary.

  • One SDK seam. All Meraki calls flow through MerakiGateway (concurrency limit, per-call timeout, error normalization, logging) — applied once, not per tool.

  • Names in, IDs never invented. Tools accept "Rome DC"; the cached Resolver turns it into an ID (ambiguity returns the candidate list for the model to pick).

  • Testable by construction. Tools depend on the gateway interface, so tests/fakes.FakeGateway exercises real tool logic offline, no API key.

  • Read-only by default. The sole non-GET tool (live_diagnostics) is behind a flag and annotated readOnlyHint=false.

Related MCP server: Unimus MCP Server

Layout

src/meraki_mcp/
  server.py         FastMCP app + lifespan (builds gateway, resolver, settings once)
  config.py         env Settings (validated; timeouts, concurrency, feature flags)
  context.py        AppContext handed to every tool (gateway, resolver, settings)
  core/
    gateway.py      the ONE Meraki SDK seam: concurrency + timeout + error normalization
    response.py     ToolResult / Meta / Collector / Response  (the output contract)
    errors.py       ResolutionError + GatewayError hierarchies (each carries an ErrorKind)
    resolver.py     name/serial/MAC -> IDs, TTL-cached
    observability.py logging setup
    pagination.py   aggregate (all pages) vs firehose (capped)
    formatting.py   small trim helpers
  tools/
    _registry.py    register_tool: the single lifecycle wrapper (ctx->app, timeout, errors, logging)
    _shared.py      one-import toolkit for tool modules
    <domain>.py     pure handlers + one-line register() each
    optional/       reports.py (P2) + live.py (non-GET, flagged)
  prompts/playbooks.py   13 packaged playbooks (register_prompts)
tests/
  fakes.py          FakeGateway/FakeSection — the DIP payoff
  test_core.py test_gateway.py test_response.py test_selection.py

Implementation status

All 18 tools are implemented — 13 core (find, health_overview, list_problems, site_status, device_status, client_status, troubleshoot_client, triage_site, site_turnup_readiness, wireless_status, switch_status, security_events, config_review) plus 5 optional/off-by-default (change_audit, firmware_compliance, license_inventory_report, usage_summary, and live_diagnostics — the only non-GET tool, a create→poll job runner). Also 3 resources (meraki://organizations, meraki://networks, meraki://devices) and 13 prompts. Multi-org is supported: MERAKI_ORG_ID is an optional default, every tool takes an optional org, and find() lists orgs/networks for discovery.

Field-shape parsing is based on the Meraki OpenAPI spec and unit-tested with a FakeGateway, but not yet run against a live org — do one smoke test with a read-only key before production (see REVIEW.md B2).

Run

pip install -e ".[dev]"
cp .env.example .env      # set a READ-ONLY MERAKI_DASHBOARD_API_KEY (+ MERAKI_ORG_ID for single-org)
meraki-mcp               # transport from .env (streamable-http by default)

How to test it

  1. Unit tests (offline, no key): pytest -q — 36 tests (gateway, response/budget, resolver, all tools via FakeGateway). Lint: ruff check src tests scripts.

  2. Live smoke (needs a read-only key in .env): python scripts/smoke_test.py — runs find/health_overview/list_problems against your real org and prints each summary + any meta.warnings (field-shape/licensing issues). Add a site name to also exercise site_status/wireless_status: python scripts/smoke_test.py "Rome DC".

  3. In VS Code / Copilot (stdio): .vscode/mcp.json (in the workspace root) launches this server for VS Code's MCP client — open it and start the meraki server.

  4. Over HTTP (Copilot Studio / MCP Inspector):

    MERAKI_MCP_TRANSPORT=streamable-http meraki-mcp     # serves http://127.0.0.1:8000/mcp

    or containerised: docker build -t meraki-mcp . && docker run --rm -p 8000:8000 -e MERAKI_DASHBOARD_API_KEY=... -e MERAKI_ORG_ID=... meraki-mcp. Expose via a dev tunnel and register the https://…/mcp URL in Copilot Studio (No authentication for now — see CONNECT-COPILOT-STUDIO.md).

Never commit a real key. .env is git-ignored; .env.example holds a placeholder only.

meraki-mcp

meraki-mcp

F
license - not found
-
quality - not tested
B
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/reshif/meraki-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server