MCP Servers for scandora.net¶
Overview¶
Model Context Protocol (MCP) servers allow AI assistants like Claude to interact with infrastructure services via their APIs. The scandora.net project uses three MCP servers:
- OPNsense MCP - Gateway management and network diagnostics
- Grafana MCP - Monitoring queries and dashboard exploration
- GitHub MCP - Issue tracking and project board management
These complement (but don't replace) Ansible IaC — they're best for interactive querying, exploratory debugging, and validating that Ansible-managed config took effect.
Use cases alongside Ansible:
- Query live state during Ansible role development (DHCP leases, firewall rules, DNS overrides, metrics)
- Verify Ansible changes applied correctly without opening web UIs
- Debug network issues interactively (ARP tables, routing, interface status, alerts)
- Security auditing of running configuration
- Explore monitoring data and create queries for dashboards
Available Servers (as of February 2026)¶
1. vespo92/OPNSenseMCP — "IaC Proxy"¶
- Repository: https://github.com/vespo92/OPNSenseMCP
- Language: TypeScript (Node.js 18+ or Bun)
- Transport: stdio
- License: MIT
- Stars: 64
- npm:
opnsense-mcp-server - Last activity: February 2026 (most active)
Tools (~35): Firewall rules, NAT (including SSH-based XML manipulation), ARP, routing diagnostics, VLANs, backups, service restarts, raw CLI execution.
Unique features:
- SSH-based NAT management (direct config.xml manipulation beyond the API)
- Auto-repair tools:
nat_fix_dmz,routing_fix_all system_execute_commandfor arbitrary CLI access- Docker deployment option
- IaC-oriented design philosophy
Auth: API key/secret + optional SSH credentials via .env or environment variables.
Best for: Hands-on firewall operations, NAT troubleshooting, interactive debugging sessions.
2. Pixelworlds/opnsense-mcp-server — "Modular Full API"¶
- Repository: https://github.com/Pixelworlds/opnsense-mcp-server
- Language: TypeScript 5.3+ (Node.js 18+)
- Transport: stdio
- License: MIT
- Stars: 63
- npm:
@richard-stovall/opnsense-mcp-server - Last activity: ~July 2025
Tools (88 modules → 2000+ methods): Entire OPNsense API surface — 752 core methods + 1,271 plugin methods across 24 core + 64 plugin modules.
Architecture: One tool per module (e.g., firewall_manage) with a method parameter. This keeps tool count manageable for the AI while covering everything.
Core modules: core_manage, interfaces_manage, firewall_manage, unbound_manage, dhcpv4_manage, openvpn_manage, ipsec_manage, wireguard_manage, firmware_manage, diagnostics_manage
Plugin modules (64): Nginx, HAProxy, Caddy, BIND, Let's Encrypt, and more.
Auth: API key/secret only (no SSH).
Best for: Comprehensive API coverage, querying any subsystem, development/exploration.
3. floriangrousset/opnsense-mcp-server — "Python + Security Auditing"¶
- Repository: https://github.com/floriangrousset/opnsense-mcp-server
- Language: Python 3.10+
- Transport: stdio
- License: AGPL 3.0
- Stars: 24
- Last activity: ~October 2025
Tools: Firewall rules, aliases, DHCP leases, VPN monitoring, system health, service control, config backups, and security auditing.
Unique features:
- Automated security auditing (identifies outdated firmware, overly permissive rules)
- Only Python implementation (easier to extend in Python ecosystems)
- AGPL license (copyleft — modifications must be open-sourced)
Auth: API key/secret.
Best for: Security-conscious environments, Python ecosystems, periodic audit checks.
4. bshandley/homelab-mcp — "Multi-Service Homelab"¶
- Repository: https://github.com/bshandley/homelab-mcp
- Language: TypeScript
- Transport: stdio + HTTP (remote with OAuth 2.0)
- Stars: 13
- Last activity: ~January 2026
OPNsense scope: Read-only monitoring + service restart only. No rule management.
Multi-service: Docker containers, OPNsense, TrueNAS, Proxmox, Home Assistant.
Unique features:
- 4 graduated capability levels: L1 (read-only) → L2 (start/stop) → L3 (read configs) → L4 (full management)
- Remote HTTP transport with OAuth (shared service, not just local stdio)
Best for: Homelab dashboarding, multi-service monitoring. Not suitable for OPNsense IaC work.
Comparison Matrix¶
| Feature | vespo92 | Pixelworlds | floriangrousset | bshandley |
|---|---|---|---|---|
| Language | TypeScript | TypeScript | Python | TypeScript |
| API methods | ~35 focused | 2000+ comprehensive | Moderate | Minimal |
| Firewall CRUD | Yes | Yes | Yes | No (read-only) |
| DHCP management | No | Yes | Yes (leases) | No |
| DNS/Unbound | No | Yes | Unknown | No |
| NAT management | Yes (SSH+API) | Yes (API) | Unknown | No |
| Security audit | No | No | Yes | No |
| SSH access | Yes | No | No | No |
| Multi-service | No | No | No | Yes |
| Remote transport | No | No | No | Yes (OAuth) |
| Activity | Very active | Stale (7mo) | Moderate | Active |
| License | MIT | MIT | AGPL 3.0 | Unknown |
Scandora.net Setup¶
All three MCP servers use automatic credential loading via wrapper scripts. No manual environment setup required!
OPNsense MCP¶
We use vespo92/OPNSenseMCP (v0.9.4, 111 tools).
Installation:
# One-time global install
npm install -g opnsense-mcp-server
# Required patch for nested KVM dev VM (firmware/info endpoint hangs):
# Edit /opt/homebrew/lib/node_modules/opnsense-mcp-server/dist/api/client.js
# In testConnection(), replace:
# const result = await this.get('/core/firmware/info');
# With:
# const result = await this.get('/diagnostics/interface/getInterfaceNames');
# This is only needed for the dev VM; production OPNsense responds normally.
Grafana MCP¶
We use @leval/mcp-grafana - a comprehensive TypeScript implementation with 43+ tools.
Installation: Automatic via npx (no global install needed)
Features:
- Dashboard queries and management
- Datasource exploration
- Alert rule inspection
- Incident management
- Logs and metrics queries
- Service account integration
GitHub MCP¶
We use github/github-mcp-server — the official GitHub MCP server for repository, issue, PR, and Projects management.
Installation: Automatic via Docker (pulled on first run)
Features:
- Issues: Create, update, search, assign, label issues
- Pull Requests: Create, review, merge PRs
- Projects: View and update GitHub Projects v2 boards (kanban items, status)
- Repositories: Browse files, check CI/CD run status
Toolsets enabled: repos,issues,pull_requests,projects
Target: https://github.com/users/scandora/projects/1 (scandora.net infrastructure project)
Unified Configuration¶
.mcp.json (project root, committed to git — no secrets):
{
"mcpServers": {
"opnsense": {
"type": "stdio",
"command": "/Users/joe/src/scandora.net/scripts/opnsense-mcp-wrapper.sh",
"env": {
"OPNSENSE_TARGET": "${OPNSENSE_TARGET:-dev}"
}
},
"grafana": {
"type": "stdio",
"command": "/Users/joe/src/scandora.net/scripts/grafana-mcp-wrapper.sh",
"env": {
"GRAFANA_TARGET": "${GRAFANA_TARGET:-dumbo}"
}
},
"github": {
"type": "stdio",
"command": "/Users/joe/src/scandora.net/scripts/github-mcp-wrapper.sh"
},
"gitlab": {
"type": "stdio",
"command": "/Users/joe/src/scandora.net/scripts/gitlab-mcp-wrapper.sh"
}
}
}
How it works:
- Each MCP server has a wrapper script that automatically loads credentials from 1Password
- Wrappers check for 1Password CLI authentication and validate connectivity
- Environment variables select which target to connect to (dev/owl/blue for OPNsense, dumbo for Grafana)
- Credentials are loaded on-demand when Claude Code starts
Usage:
Just start Claude Code from the project directory:
Default targets:
- OPNsense:
dev(opnsense-dev via localhost:8443) - Grafana:
dumbo(http://192.168.194.131:3000) - GitHub: github.com — scandora/scandora.net repo + projects/1
To connect to different targets:
# Connect to Owl production gateway
OPNSENSE_TARGET=owl claude
# Connect to Blue production gateway
OPNSENSE_TARGET=blue claude
# Shell aliases (add to ~/.bashrc or ~/.zshrc):
alias claude-dev='cd ~/src/scandora.net && claude'
alias claude-owl='cd ~/src/scandora.net && OPNSENSE_TARGET=owl claude'
alias claude-blue='cd ~/src/scandora.net && OPNSENSE_TARGET=blue claude'
1Password Items¶
OPNsense MCP:
| Item | Vault | Fields | Target |
|---|---|---|---|
| OPNsense API - Dev | Private | api key, api secret | opnsense-dev (GCE/KVM, via SSH tunnel) |
| OPNsense API - Owl | Private | api key, api secret | owl.scandora.net (via ZeroTier) |
| OPNsense API - Blue | Private | api key, api secret | blue.scandora.net (direct) |
Grafana MCP:
| Item | Vault | Fields | Target |
|---|---|---|---|
| Monitoring - Grafana Admin | scandora.net | api key | dumbo (http://192.168.194.131:3000) |
GitHub MCP:
| Item | Vault | Fields | Target |
|---|---|---|---|
| github_pat_mcp_claude | scandora-automation | credential (PAT) | github.com |
Creating GitHub PAT:
- Visit: https://github.com/settings/tokens (classic) or Fine-grained tokens
- Create token with scopes:
repo,project,read:org - Store in 1Password:
op item create --category="API Credential" \
--title="github_pat_mcp_claude" \
--vault="scandora-automation" \
--tags="scandora.net" \
"credential[password]=ghp_YOUR_TOKEN_HERE"
Creating Grafana API Key:
- Log into Grafana at http://192.168.194.131:3000
- Go to: Administration → Service Accounts
- Click "Add service account"
- Display name: "Claude Code MCP"
- Role: Viewer (or Editor for write access)
- Click "Add service account token"
- Display name: "luna-workstation"
- Expiration: No expiration (or set as needed)
- Copy the generated token (starts with "glsa_...")
- Store in 1Password:
op item edit "Monitoring - Grafana Admin" \
--vault "scandora.net" \
"api key[password]"="glsa_YOUR_TOKEN_HERE"
Access Paths¶
OPNsense:
Claude Code ──stdio──> opnsense-mcp-wrapper.sh ──1Password──> OPNsense MCP ──HTTPS──> OPNsense API
(loads credentials) (via tunnel/ZT)
For the dev VM, an SSH tunnel must be active:
For production (owl), use the ZeroTier IP: https://192.168.194.10.
Grafana:
Claude Code ──stdio──> grafana-mcp-wrapper.sh ──1Password──> Grafana MCP ──HTTP──> Grafana API
(loads api key) (via ZeroTier)
Requires ZeroTier connectivity to reach dumbo at 192.168.194.131:3000.
GitHub:
Claude Code ──stdio──> github-mcp-wrapper.sh ──1Password──> Docker (github-mcp-server) ──REST API──> GitHub
(loads PAT) (github.com)
Requires internet connectivity and Docker running locally.
Prerequisites¶
General:
- 1Password CLI (
op) installed and authenticated:eval $(op signin)
OPNsense MCP:
- For dev target: SSH tunnel to GCE active:
ssh -f -N -L 8443:10.7.0.1:443 joe@<gce-ip> - For owl/blue targets: ZeroTier connectivity to 192.168.194.x network
Grafana MCP:
- ZeroTier connectivity to reach dumbo (192.168.194.131)
- Service account token stored in 1Password (see "Creating Grafana API Key" above)
GitHub MCP:
- Internet connectivity to reach github.com
- Docker installed and running (
docker infoshould succeed) - PAT stored in 1Password (see "Creating GitHub PAT" above)
Known Issues¶
OPNsense - Dev VM firmware endpoint hang: The MCP server's testConnection() calls /api/core/firmware/info, which hangs indefinitely on nested KVM OPNsense (same issue that affects Ansible packages and monitoring tags). The workaround is to patch the globally installed client.js to use /diagnostics/interface/getInterfaceNames instead. This patch survives until the next npm update -g.
Grafana - Connection timeout: If the Grafana MCP fails to connect, verify:
- ZeroTier is connected:
zerotier-cli listnetworks(should show status: OK) - Dumbo is reachable:
ping 192.168.194.131 - Grafana API responds:
curl -H "Authorization: Bearer $GRAFANA_API_KEY" http://192.168.194.131:3000/api/health
GitHub - Authentication failures: If the GitHub MCP fails to authenticate:
- Verify PAT is valid and has
repo+project+read:orgscopes - Test manually:
curl -H "Authorization: token $(op item get github_pat_mcp_claude --vault scandora-automation --fields credential --reveal)" https://api.github.com/user - Check 1Password item
github_pat_mcp_claudehascredentialfield with the PAT - Ensure Docker is running:
docker info
Important: MCP servers are for interactive querying and debugging. Production configuration changes should always flow through Ansible (run-opnsense.sh, run-monitoring.sh) to maintain IaC as the source of truth.
Troubleshooting¶
"Not signed in to 1Password"¶
"Could not retrieve API key"¶
Verify 1Password items exist:
# List items
op item list --vault "scandora-automation" | grep -i opnsense
op item list --vault "scandora-automation" | grep -i grafana
op item list --vault "scandora-automation" | grep -i github
# Check specific items
op item get "dumbo_grafana_admin_password" --vault "scandora-automation"
op item get "github_pat_mcp_claude" --vault "scandora-automation"
Check MCP server logs¶
Claude Code logs show MCP server startup messages. Look for:
OPNsense MCP: Connecting to dev (https://localhost:8443)
Grafana MCP: Connecting to dumbo (http://192.168.194.131:3000)
GitHub MCP: Connected to github.com
Verify MCP servers in Claude Code¶
After starting Claude Code, run:
/doctor # Should show 'opnsense', 'grafana', 'github', and 'gitlab' as Ready
/mcp # Should show all four servers connected