Provides read-only access to Vivint home security systems, enabling monitoring of system armed states, security sensors, cameras, smart locks, thermostats, recent events, and device health status through eight comprehensive tools.
Vivint Security System MCP Server
A FastMCP server that exposes read-only access to your Vivint home security system over the Model Context Protocol (MCP) via Streamable HTTP at the /mcp endpoint.
Important: This integration uses an unofficial, reverse‑engineered API (vivintpy). Vivint has no official public API. Use at your own risk and review your Terms of Service.
Features
Eight read-only tools are exposed to MCP clients:
- get_system_status — Overall system armed state and metadata
- get_all_devices — Complete device inventory
- get_security_sensors — Motion/door/window/smoke/CO/flood sensors
- get_cameras — Camera status and capabilities
- get_locks — Smart lock states and battery level
- get_thermostats — Climate data and setpoints
- get_recent_events — Recent activity snapshots
- get_device_health — Battery/online/attention summaries
Endpoint base path: /mcp (clients must include this path).
Prerequisites
- Python 3.13+
- A Vivint account (recommend a dedicated, least‑privilege user)
- Node.js (for MCP Inspector via npx)
- Optional: Cloudflared (to expose your local server)
- macOS, Linux, or Windows. Commands below use macOS/zsh patterns.
Quick start (local)
- Clone and enter the project
- Create an environment and install dependencies
Option A: venv
Option B: conda
- Configure environment
- Enable authentication (recommended)
Generate a strong HMAC secret and add it to .env:
Generate a short‑lived JWT for local testing:
- Start the server
- Test with MCP Inspector
Then connect with:
- Transport: Streamable HTTP
- URL: http://localhost:8000/mcp
- If AUTH_ENABLED=true: add the header Authorization: Bearer
Example .env
Copy/paste and edit values as needed. Do not commit this file.
Notes:
- The server binds to HOST and PORT (defaults provided). For containers, bind‑all is recommended; for strict local, use a loopback address. The default HOST in code is redacted (*******).
- All URLs must include the /mcp base path.
Authentication options
JWT (HMAC, HS256) — recommended for single‑user/local
- Generate secret: python src/generate_token.py --type secret
- Configure .env: AUTH_ENABLED=true, AUTH_TYPE=jwt, JWT_ALGORITHM=HS256, AUTH_SECRET=...
- Create token: python src/generate_token.py --type token --hours 24 --subject local-dev
- Verify token: python src/generate_token.py --verify ""
- Use with Inspector: Authorization: Bearer
JWT (RSA, RS256) — multi‑client
- Generate keys: python src/generate_token.py --type keypair
- Configure .env: JWT_PRIVATE_KEY, JWT_PUBLIC_KEY, JWT_ALGORITHM=RS256
- Generate tokens with the private key (same script) and verify with the public key.
OAuth 2.0 — optional
- Generate a client: python src/generate_oauth_credentials.py
- Ensure OAUTH_REDIRECT_URIS includes https://claude.ai/api/mcp/auth_callback (for Claude) and any local callbacks.
- Start the server and complete the flow using the server’s OAuth endpoints. In production, consider setting OAUTH_DISABLE_NEW_CLIENTS=true.
Disable auth (development only)
Warning: Do not disable authentication if your server is reachable from the internet.
2FA/MFA setup and token persistence
Interactive (recommended)
What it does:
- Prompts for a fresh 6‑digit code when required
- Saves refresh tokens to VIVINT_REFRESH_TOKEN_FILE (default: .vivint_tokens.json)
- Validates the connection
Non‑interactive (one‑off)
Validation
Token file security: treat .vivint_tokens.json as a secret and restrict permissions (chmod 600).
Running and debugging
Start:
Explicit host/port:
Verbose logs:
Debug endpoint (when available): /debug/oauth requires DEBUG_MODE=true.
Testing with MCP Inspector
- Launch: npx @modelcontextprotocol/inspector
- Transport: Streamable HTTP
- URL: http://localhost:8000/mcp
- If auth enabled: add Authorization: Bearer
- Try tools: get_system_status, get_all_devices, get_device_health
Cloudflare tunnel (optional)
If you want to test over the internet without opening ports:
Helper scripts in repo:
OAuth redirect URIs can be updated automatically:
Manual alternative:
Deploying to Render
Use the button above or set up a Web Service that runs:
- Build: pip install -r requirements.txt
- Start: python src/server.py
Environment variables (minimum):
- ENVIRONMENT=production
- AUTH_ENABLED=true
- AUTH_TYPE=jwt (or oauth)
- For JWT HS: AUTH_SECRET=, JWT_ALGORITHM=HS256
- For JWT RS: JWT_PRIVATE_KEY, JWT_PUBLIC_KEY, JWT_ALGORITHM=RS256
- VIVINT_USERNAME, VIVINT_PASSWORD
- Optional: VIVINT_SYSTEM_ID, LOG_LEVEL=WARNING/ERROR
Your endpoint will be: https://.onrender.com/mcp
Tool reference
- get_system_status() → { armed, arm_state, is_disarmed, is_armed_stay, is_armed_away, system_id, panel_id, panel_name, timestamp, ... }
- get_all_devices() → [ { id, name, type, panel_id, system_id, state, is_online, battery_level, last_update_time, ... } ]
- get_security_sensors() → [ { id, name, sensor_type, triggered, bypassed, zone_id, ... } ]
- get_cameras() → [ { id, name, resolution, night_vision, motion_detection, rtsp_available, ... } ]
- get_locks() → [ { id, name, locked, tamper_status, battery_level, last_operated_at, ... } ]
- get_thermostats() → [ { id, name, current_temperature, target_temperature, heat_setpoint, cool_setpoint, mode, ... } ]
- get_recent_events(hours=24) → [ { id, type, description, timestamp, device_id, device_name } ]
- get_device_health() → { total_devices, online_devices, offline_devices, low_battery_devices, devices_needing_attention, ... }
Return fields are best‑effort and depend on your account/devices; errors are returned as { error, timestamp }.
Architecture
Core files
- src/server.py — FastMCP app, auth setup (JWT/OAuth), tool registration, HTTP transport on /mcp
- src/vivint_client.py — vivintpy wrapper, session lifecycle, MFA handling
- src/token_manager.py — secure token persistence and validation
- src/config.py — environment variable parsing and validation
- setup_mfa.py, test_mfa.py — interactive MFA onboarding and validation
- start_tunnel.sh, tunnel_status.sh, stop_tunnel.sh — Cloudflared helpers
- render.yaml — Render deployment config
Session notes
- Sessions are refreshed periodically; tokens auto‑refresh ~5–6 hours
- Device and state shapes come from vivintpy and can change upstream
Troubleshooting
Authentication
- “AUTH_SECRET is required” → Add AUTH_SECRET for HS* or JWT_PUBLIC_KEY for RS*
- “MFA required” → export VIVINT_MFA_CODE or run setup_mfa.py
- OAuth redirect mismatch → Ensure the exact URL is in OAUTH_REDIRECT_URIS, restart server
Connectivity
- Inspector can’t connect → Server running? Port correct? URL includes /mcp?
- Render 502 → Ensure HOST/PORT are correct for container; ENVIRONMENT=production
Devices
- No devices → Confirm account/system access; set VIVINT_SYSTEM_ID when multiple systems exist
Rate limits
- Login locked → Adjust RATE_LIMIT_* or wait for lockout to expire
Debugging
- DEBUG_MODE=true LOG_LEVEL=DEBUG for verbose logs
- /debug/oauth (if enabled) inspects OAuth configuration
Security
- Keep AUTH_ENABLED=true in production
- Rotate AUTH_SECRET/keys regularly
- Use a dedicated Vivint user
- Do not commit .env or token files; treat .vivint_tokens.json as a secret (chmod 600)
- Keep DEBUG_MODE=false in production
- Be mindful that vivintpy is unofficial and may break without notice
Limitations & disclaimers
- Unofficial API usage via vivintpy (no guarantees; subject to breakage)
- Read‑only access only; no device control
- May violate provider terms — proceed responsibly
License
MIT — see LICENSE.
This project is not affiliated with or endorsed by Vivint.
This server cannot be installed
hybrid server
The server is able to function both locally and remotely, depending on the configuration or use case.
Provides read-only access to Vivint home security systems through an unofficial API. Enables monitoring of system status, devices, sensors, cameras, locks, thermostats, and recent events through natural language.