macharpe/meraki-mcp-cloudflare
If you are the rightful owner of meraki-mcp-cloudflare and would like to certify it and/or have it hosted online, please leave a comment on the right or send an email to dayong@mcphub.com.
The Cisco Meraki MCP Server is a Model Context Protocol server that integrates AI assistants with Cisco Meraki network management capabilities, running on Cloudflare Workers.
🌐 Cisco Meraki MCP Server
A production-ready, enterprise-grade Model Context Protocol (MCP) server that provides AI assistants with comprehensive access to Cisco Meraki network management capabilities. Built on Cloudflare Workers with Durable Objects, OAuth 2.1 authentication with PKCE, intelligent KV caching, and full RFC-compliant OAuth discovery support.
Inspiration: This implementation was inspired by Censini/mcp-server-meraki and mkutka/meraki-magic-mcp - credits to both original works for API method ideas and implementation approaches.
📑 Table of Contents
- Prerequisites
- Features
- Architecture
- Authentication
- Performance & Caching
- Environment Variables
- Project Structure
- Installation & Deployment
- Claude Configuration
- Usage Examples
- Testing
- Troubleshooting
- Contributing
- License
- Acknowledgments
📋 Prerequisites
Before deploying the server, ensure you have:
- 🌐 Cloudflare Account: Free account at cloudflare.com with a domain configured
- 🔑 Cisco Meraki Account: With API access enabled
- 🎫 Meraki API Key: Generated from your Meraki Dashboard
- Navigate to Organization > Settings > Dashboard API access
- Enable API access and generate a new API key
- 💻 Node.js: Version 18 or higher
- 📦 Git: For cloning the repository
- 🔐 Cloudflare Access for SaaS: Configured identity provider (Okta, Google Workspace, Azure AD, etc.)
✨ Features
🛠️ Available Tools
The server provides 27 comprehensive Meraki management tools organized across multiple categories:
🏢 Organization & Network Management (6 tools)
get_organizations,get_organization,get_networks,get_network,get_network_traffic,get_network_events
📱 Device Management (5 tools)
get_devices,get_device,get_device_statuses,get_clients,get_management_interface
🔗 Switch Management (4 tools)
get_switch_ports,get_switch_port_statuses,get_switch_routing_interfaces,get_switch_static_routes
📡 Wireless Management (8 tools)
get_wireless_radio_settings,get_wireless_status,get_wireless_latency_stats,get_wireless_rf_profilesget_wireless_channel_utilization,get_wireless_signal_quality,get_wireless_connection_stats,get_wireless_client_connectivity_events
🛡️ Appliance Management (4 tools)
get_appliance_vpn_site_to_site,get_appliance_content_filtering,get_appliance_security_events,get_appliance_traffic_shaping
🏗️ Architecture
┌──────────────────┐ ┌─────────────────────┐ ┌──────────────────┐
│ MCP Client │ │ Cloudflare Worker │ │ Meraki API │
│ (AI Playground) │◄────►│ Durable Object MCP │◄────►│ Dashboard │
│ (Claude) │ │ + OAuth Handler │ │ │
└──────────────────┘ └─────────────────────┘ └──────────────────┘
│ │
│ │
└──────────────────────────┘
Cloudflare Access
(OAuth 2.1 + Enterprise SSO)
Architecture Highlights:
- Durable Objects: Stateful MCP agent with SQLite storage for session management
- Multi-Layer Caching: KV caching for organizations, networks, clients, and JWKS keys
- Global Edge: Deployed across 300+ Cloudflare data centers for low latency
- Zero Trust: Every request authenticated and verified via Cloudflare Access JWT tokens
🔐 Authentication
The server implements OAuth 2.1 with PKCE integrated with Cloudflare Access for SaaS for enterprise-grade authentication and authorization. All MCP endpoints (/mcp and /sse) are protected and require valid Cloudflare Access JWT tokens.
📋 Detailed Documentation: See for the complete authentication architecture with detailed sequence diagrams.
🎯 Authentication Flow Overview
sequenceDiagram
participant User as User
participant Client as MCP Client<br/>(AI Playground)
participant Worker as Meraki MCP<br/>Worker
participant Access as Cloudflare<br/>Access
participant SSO as Enterprise<br/>SSO (Okta)
Note over User,SSO: 📱 User Connects to MCP Server
Client->>Worker: 1. Connect to /mcp
Worker-->>Client: 2. 401 Unauthorized<br/>(Need authentication)
Note over User,SSO: 🔐 OAuth Flow Begins
Client->>Worker: 3. Start OAuth flow
Worker-->>User: 4. Show approval dialog
User->>Worker: 5. Click "Approve"
Worker->>Access: 6. Redirect to Access login
Note over User,SSO: 👤 Enterprise SSO Authentication
Access->>SSO: 7. SAML/OIDC login
User->>SSO: 8. Enter credentials
SSO-->>Access: 9. User authenticated
Note over User,SSO: 🎫 Token Exchange
Access-->>Worker: 10. Return auth code
Worker->>Access: 11. Exchange code for JWT
Access-->>Worker: 12. Cloudflare Access JWT
Worker-->>Client: 13. Return access token
Note over User,SSO: ✅ Authenticated Access
Client->>Worker: 14. MCP requests with Bearer token
Worker->>Worker: 15. Verify JWT signature
Worker-->>Client: 16. Return Meraki data
Note over User,SSO: Subsequent requests use cached token
Key Takeaways:
- 🔐 Users authenticate once via their enterprise SSO (Okta, Google, Azure AD, etc.)
- 🎫 Cloudflare Access issues a JWT token valid for 1 hour
- ✅ All subsequent MCP requests include the Bearer token
- ⚡ Token verification is cached for performance (~5ms vs ~100ms)
🔍 OAuth Infrastructure
The server provides RFC-compliant OAuth 2.1 endpoints:
| Endpoint | Purpose | Specification |
|---|---|---|
/.well-known/oauth-authorization-server | OAuth metadata discovery | RFC 8414 |
/.well-known/oauth-protected-resource | Resource server metadata | RFC 8707 |
/.well-known/jwks.json | JSON Web Key Set for token verification | RFC 7517 |
/register | Dynamic client registration | RFC 7591 |
/authorize | Authorization endpoint (with PKCE) | RFC 7636 |
/callback | OAuth callback handler | OAuth 2.1 |
/token | Token exchange endpoint | OAuth 2.1 |
/mcp | Protected MCP JSON-RPC endpoint | MCP Spec |
/sse | Protected Server-Sent Events transport | MCP Spec |
⚡ Performance & Caching
The server implements intelligent multi-layer KV caching to optimize performance and reduce API calls to Meraki Dashboard:
🗄️ Cache Strategy
| Data Type | Cache TTL | Rationale |
|---|---|---|
| Organization Lists | 30 minutes | Organizations rarely change |
| Network Lists | 15 minutes | Moderate update frequency |
| Client Lists | 5 minutes | Clients connect/disconnect frequently |
| JWKS Keys | 1 hour | JWT verification keys are stable |
🌍 Environment Variables
The server uses the following environment variables:
Required Secrets
Set these using npx wrangler secret put <SECRET_NAME>:
| Secret | Description | How to Get |
|---|---|---|
MERAKI_API_KEY | Cisco Meraki Dashboard API key | Generate from Meraki Dashboard → Organization > Settings > API |
ACCESS_CLIENT_ID | Cloudflare Access client ID | From Access for SaaS application configuration |
ACCESS_CLIENT_SECRET | Cloudflare Access client secret | From Access for SaaS application configuration |
ACCESS_TOKEN_URL | Cloudflare Access token endpoint | From Access for SaaS application configuration |
ACCESS_AUTHORIZATION_URL | Cloudflare Access authorization endpoint | From Access for SaaS application configuration |
ACCESS_JWKS_URL | Cloudflare Access JWKS endpoint | From Access for SaaS application configuration |
COOKIE_ENCRYPTION_KEY | 32-byte hex key for cookie encryption | Generate with: openssl rand -hex 32 |
📁 Project Structure
meraki-mcp-cloudflare/
├── src/
│ ├── index.ts # Main Durable Object MCP Agent
│ ├── access-handler.ts # OAuth 2.1 authentication handler
│ ├── oauth-helpers.ts # OAuth utility functions
│ ├── workers-oauth-utils.ts # Workers OAuth utilities
│ ├── middleware/
│ │ └── auth.ts # Authentication middleware
│ ├── services/
│ │ ├── merakiapi.ts # Meraki API service layer with caching
│ │ └── cache.ts # KV caching service
│ ├── types/
│ │ ├── env.ts # Environment variable type definitions
│ │ └── meraki.ts # Meraki API type definitions
│ └── tests/
│ ├── index.test.ts # MCP agent tests
│ └── auth.test.ts # Authentication tests
├── docs/
│ ├── oauth-authentication-flow.md # Complete OAuth flow documentation
│ └── authentication-flow.md # Legacy authentication docs
├── scripts/
│ └── pre-deploy.sh # Pre-deployment validation script
├── wrangler.jsonc # Cloudflare Workers configuration
├── package.json # Dependencies and npm scripts
├── tsconfig.json # TypeScript configuration
├── biome.json # Biome linter configuration
├── .claude/ # Claude Code project instructions
│ └── CLAUDE.md
└── README.md # This file
🚀 Installation & Deployment
1. Clone the Repository
git clone https://github.com/macharpe/meraki-mcp-cloudflare.git
cd meraki-mcp-cloudflare
2. Install Dependencies
npm install
3. Create a SaaS App
Follow the Cloudflare Access for SaaS MCP Server guide to create your Access for SaaS application.
Important: Make note of these values - you'll need them later:
- ✅ Client ID
- ✅ Client Secret
- ✅ Token Endpoint
- ✅ Authorization Endpoint
- ✅ Key Endpoint (JWKS URL)
Access Control: When creating the SaaS App, configure an Access policy to control who can authenticate and access your MCP server. This policy determines which users (based on email, group membership, identity provider, etc.) are authorized to connect. Only users who match your policy will be able to authenticate via enterprise SSO and use the MCP server.
4. Create KV Namespaces
Create two KV namespaces for OAuth session storage and API response caching:
# Create OAuth session storage namespace
npx wrangler kv:namespace create "OAUTH_KV"
# Output: id = "abc123..." - SAVE THIS
# Create cache storage namespace
npx wrangler kv:namespace create "CACHE_KV"
# Output: id = "def456..." - SAVE THIS
5. Configure Custom Domain
Update wrangler.jsonc with your domain and KV namespace IDs:
{
"name": "meraki-mcp-cloudflare",
"main": "src/index.ts",
"compatibility_date": "2025-03-07",
// KV namespaces - UPDATE THESE WITH YOUR IDS FROM STEP 4
"kv_namespaces": [
{
"binding": "OAUTH_KV",
"id": "YOUR_OAUTH_KV_ID_HERE" // From step 4
},
{
"binding": "CACHE_KV",
"id": "YOUR_CACHE_KV_ID_HERE" // From step 4
}
],
// Custom domain routing - UPDATE WITH YOUR DOMAIN
"routes": [
{
"pattern": "meraki-mcp.yourdomain.com", // Change to your domain
"custom_domain": true
}
],
// Security: Disable public endpoints
"workers_dev": false,
"preview_urls": false
}
Note: The KV namespace IDs shown above are placeholders. Replace them with the actual IDs from step 4.
6. Set Required Secrets
First, generate a cookie encryption key:
openssl rand -hex 32
Copy the output - you'll need it in the next step.
Reference: See Cloudflare's Configure a cookie encryption key documentation for more details.
Configure all required secrets using Wrangler:
# Meraki API authentication
npx wrangler secret put MERAKI_API_KEY
# Enter your Meraki API key when prompted
# Cloudflare Access for SaaS credentials (from step 3)
npx wrangler secret put ACCESS_CLIENT_ID
npx wrangler secret put ACCESS_CLIENT_SECRET
npx wrangler secret put ACCESS_TOKEN_URL
npx wrangler secret put ACCESS_AUTHORIZATION_URL
npx wrangler secret put ACCESS_JWKS_URL
# Cookie encryption key (paste the output from openssl command above)
npx wrangler secret put COOKIE_ENCRYPTION_KEY
7. Configure Local Development (Optional)
For local testing with wrangler dev, create a .dev.vars file:
echo "MERAKI_API_KEY=your_meraki_api_key_here" > .dev.vars
Note: The
.dev.varsfile is git-ignored for security. This is useful for local development but not required for production deployment.
8. Deploy to Cloudflare Workers
Authenticate with Cloudflare (first time only):
npx wrangler login
Deploy the server:
npx wrangler deploy
Your server will be available at: https://meraki-mcp.yourdomain.com
⚙️ Claude Configuration
📊 Client Compatibility Summary
The following table summarizes OAuth-protected MCP server compatibility based on testing with this server:
| Client | Status | OAuth Flow | MCP Handshake | Tools Available | Notes |
|---|---|---|---|---|---|
| Workers AI Playground | ✅ Works | ✓ Complete | ✓ Complete | ✓ All 27 tools | Built by Cloudflare for OAuth MCP |
| Claude Code (CLI) | ✅ Works | ✓ Complete | ✓ Complete | ✓ All 27 tools | Recommended - Tested and verified working |
| Claude.ai (Web) | ⚠️ Partial | ✓ Complete | ✗ Incomplete | ✗ No tools | OAuth succeeds, handshake stalls after initialize |
| Claude Desktop | ❌ Fails | ✗ Callback error | ✗ N/A | ✗ N/A | mcp-remote can't resolve callback URI |
✅ Claude Code (CLI)
Claude Code has full OAuth support for remote MCP servers and works reliably.
Add via CLI:
claude mcp add --transport http --scope user meraki-mcp https://meraki-mcp.yourdomain.com/mcp
Or manually add to ~/.claude.json:
{
"mcpServers": {
"meraki-mcp": {
"url": "https://meraki-mcp.yourdomain.com/mcp",
"transport": "http"
}
}
}
When you start a new Claude Code session, it will automatically initiate the OAuth flow via your browser.
💻 Claude Desktop
⚠️ Compatibility Issue: Based on testing, Claude Desktop has compatibility issues with OAuth-protected remote MCP servers. The
mcp-remotepackage encounters callback URI resolution errors.Error:
Cannot find localhost callback URI from existing client informationWorkaround: Use Workers AI Playground or Claude Code CLI instead.
Configuration (for future compatibility)
-
Locate your Claude Desktop config file:
- macOS:
~/Library/Application Support/Claude/claude_desktop_config.json - Windows:
%APPDATA%\Claude\claude_desktop_config.json - Linux:
~/.config/Claude/claude_desktop_config.json
- macOS:
-
Add the Meraki MCP server configuration:
{
"mcpServers": {
"meraki-mcp": {
"command": "npx",
"args": [
"-y",
"mcp-remote@latest",
"https://meraki-mcp.yourdomain.com/mcp"
]
}
}
}
- Restart Claude Desktop completely (quit and relaunch)
🌐 Claude.ai (Website)
⚠️ Compatibility Issue: Based on testing, Claude.ai's web interface has compatibility issues with OAuth-protected MCP servers. OAuth authentication completes successfully, but the MCP handshake stalls after the
initializecall - it never progresses totools/list, resulting in no tools being available.Observed Behavior:
- ✓ OAuth discovery works
- ✓ User authentication succeeds
- ✓ JWT token obtained
- ✓
initializerequest completes- ✗ Connection reinitializes repeatedly instead of calling
tools/listWorkaround: Use Workers AI Playground or Claude Code CLI, which have full OAuth MCP support.
Configuration (for reference)
- Navigate to claude.ai
- Click on your profile → Settings
- Go to Integrations → Model Context Protocol
- Click Add Server
- Enter:
- Name: Meraki MCP Server
- URL:
https://meraki-mcp.yourdomain.com
- Click Connect
- Authenticate via your enterprise SSO when prompted
🔧 Claude Code (CLI)
Add to your MCP settings configuration:
{
"mcpServers": {
"meraki-mcp": {
"url": "https://meraki-mcp.yourdomain.com",
"oauth": {
"discoveryUrl": "https://meraki-mcp.yourdomain.com/.well-known/oauth-authorization-server"
}
}
}
}
💡 Usage Examples
Once connected to Claude, you can use natural language to interact with your Meraki infrastructure:
🏢 Organization Management
"Show me all my Meraki organizations"
"Get details for organization 123456"
🌐 Network Operations
"List all networks in my main organization"
"Get network traffic statistics for the office network"
📱 Device Management
"Show me all devices in the SF office network"
"Get wireless status for access point Q2XX-YYYY-ZZZZ"
🔍 Client Information
"List all connected clients on the guest network"
"Show me connectivity events for MAC address XX:XX:XX:XX:XX:XX"
🔗 Switch Configuration
"Get switch port statuses for device ABC-123-DEF"
"Show routing interfaces on the core switch"
🧪 Testing & API Endpoints
🏥 Health Check
Test basic connectivity:
curl https://meraki-mcp.yourdomain.com/health
Expected Response:
{
"status": "OK",
"service": "Cisco Meraki MCP Server",
"timestamp": "2025-01-23T10:30:00.000Z",
"oauthEnabled": true,
"version": "1.0.0",
"endpoints": [...]
}
🔍 OAuth Discovery
Test OAuth metadata discovery:
curl https://meraki-mcp.yourdomain.com/.well-known/oauth-authorization-server
🛠️ Development Commands
Local Development:
npm run dev # Start development server
npm run build # Compile TypeScript
npm run lint # Run code linting
npm run lint:fix # Auto-fix linting issues
npm run typecheck # Type checking only
npm run pre-deploy # Complete pre-deployment checks
Deployment:
npm run deploy # Deploy to Cloudflare Workers
npm run types # Generate Cloudflare types
Monitoring:
npx wrangler tail --format pretty # Real-time logs
🔧 Troubleshooting
Common Issues:
-
OAuth Authentication Failures
- Verify Cloudflare Access configuration matches secrets
- Check redirect URI matches exactly (no trailing slash)
- Ensure domain is properly configured in Cloudflare
-
KV Namespace Errors
- Verify KV namespace IDs in
wrangler.jsoncmatch those fromkv:namespace create - Check KV namespaces exist in Cloudflare dashboard
- Verify KV namespace IDs in
-
Meraki API Errors
- Verify API key is valid and not expired
- Check API key has proper organization access
- Ensure rate limits aren't exceeded (5 req/sec)
-
CORS Issues
- Server includes proper CORS headers automatically
- Check browser console for specific CORS errors
- Verify
mcp-protocol-versionheader is allowed
Debug Mode:
Enable detailed logging:
npx wrangler tail --format pretty | grep '\[AUTH\]' # Authentication logs
npx wrangler tail --format pretty | grep '\[CACHE\]' # Cache performance
🤝 Contributing
Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.
📄 License
This project is licensed under the GPL-3.0 License - see the file for details.
🙏 Acknowledgments
- Cloudflare Workers: For providing an excellent serverless platform
- Model Context Protocol: For creating the MCP specification
- Cisco Meraki: For their comprehensive API
- Censini/mcp-server-meraki: Original inspiration for this implementation
- mkutka/meraki-magic-mcp: Additional inspiration for API methods and implementation approaches
Built with ❤️ using Cloudflare Workers and the Model Context Protocol