{
  "markdown": "# reolink-mcp\n\nAn open-source MCP (Model Context Protocol) server for Reolink cameras: lets\nClaude — or any MCP client — see and control Reolink cameras on the local\nnetwork. Snapshots, device state, AI detection states, PTZ presets, and\ndeterrence controls (spotlight, siren, IR/white LED). Local network only, no\ncloud.\n\n**Market gap (verified 2026-07-08):** no dedicated Reolink MCP server exists\non GitHub, npm, or PyPI. Closest prior art requires a middleman:\n`dedsxc/mcp-frigate` (needs Frigate NVR), `homeassistant-mcp` (needs Home\nAssistant). This is a first-mover standalone niche.\n\nA user with a Reolink camera adds `reolink-mcp` to their MCP client config,\nasks \"show me the front door camera,\" and gets a live snapshot — direct to\ncamera, no NVR or home-automation daemon in between.\n\n<!-- mcp-name: io.github.ed-dryha/reolink-mcp -->\n\n## Quickstart\n\nRequires a Reolink camera reachable on the local network and its admin\nusername/password.\n\n### 1. Create your camera config\n\nCopy [`config.example.yaml`](config.example.yaml) to\n`~/.config/reolink-mcp/config.yaml` (or point `RMCP_CONFIG_FILE` at a copy\nanywhere else on disk):\n\n```yaml\ncameras:\n  front_door:\n    host: 192.168.1.44\n    username: admin\n```\n\nPasswords never go in this file. Set one `RMCP_CAMERAS__<name>__PASSWORD`\nenvironment variable per camera instead — `<name>` must exactly match the\ncamera's key in the YAML above (lowercase snake_case):\n\n```bash\nRMCP_CAMERAS__front_door__PASSWORD=<camera-password>\n```\n\n> **Concurrent-session limit:** Reolink cameras allow only a limited number\n> of simultaneous sessions. `reolink-mcp` holds one `reolink-aio` session per\n> configured camera for as long as the server runs — running it alongside\n> another system that also holds sessions on the same cameras (an NVR,\n> another MCP server, etc.) can exhaust that limit. See\n> [Camera compatibility & session limits](#camera-compatibility--session-limits)\n> below.\n\n### 2. Add it to your MCP client\n\n**Claude Code:**\n\n```bash\nclaude mcp add reolink -- uvx reolink-mcp\n```\n\n**Claude Desktop** (`claude_desktop_config.json` — macOS:\n`~/Library/Application Support/Claude/claude_desktop_config.json`, Windows:\n`%APPDATA%\\Claude\\claude_desktop_config.json`):\n\n```json\n{\n  \"mcpServers\": {\n    \"reolink\": {\n      \"command\": \"uvx\",\n      \"args\": [\"reolink-mcp\"],\n      \"env\": {\n        \"RMCP_CAMERAS__front_door__PASSWORD\": \"<camera-password>\"\n      }\n    }\n  }\n}\n```\n\n**Any other MCP client** (generic stdio):\n\n```json\n{\n  \"command\": \"uvx\",\n  \"args\": [\"reolink-mcp\"]\n}\n```\n\nThat's it — ask your MCP client to \"show me the front door camera.\"\n\n## Tools\n\nBuilt on [`reolink-aio`](https://github.com/starkillerOG/reolink_aio) and the\nofficial [MCP Python SDK](https://github.com/modelcontextprotocol/python-sdk).\nEvery tool carries `readOnlyHint`/`destructiveHint` annotations so MCP\nclients can gate approvals — Observe tools are read-only, Control tools\nmutate camera state, and `set_siren` is the only tool marked destructive.\n\n| Tool | Type | Purpose | Destructive |\n|------|------|---------|-------------|\n| `list_cameras` | Observe | Enumerate every configured camera with live connection status, model, and host | No |\n| `get_device_info` | Observe | Model, firmware, hardware details for a camera | No |\n| `get_capabilities` | Observe | What a camera supports — PTZ, siren, spotlight, IR/white LED, zoom, AI detection types — in neutral feature vocabulary | No |\n| `get_states` | Observe | Current device state: day/night mode, white LED/spotlight, IR lights, siren capability, and motion | No |\n| `get_recent_events` | Observe | Current AI detection state (person/vehicle/pet plus any camera-reported extras) from an on-demand poll, plus the plain motion flag | No |\n| `get_snapshot` | Observe | Live still image from a camera, returned as an MCP image content block | No |\n| `set_siren` | Control | Sound or stop a camera's siren — ~5s safe default, 60s hard cap, over-cap requests refused not clamped | **Yes** |\n| `set_audio_alarm` | Control | Enable or disable a camera's siren/audio-alarm feature — needed when `set_siren` is accepted by the firmware but produces no sound | No |\n| `set_spotlight` | Control | Turn a camera's spotlight on or off | No |\n| `set_ir_lights` | Control | Set a camera's IR lights to `auto`, `on`, or `off` | No |\n| `set_white_led` | Control | Turn a camera's white LED on or off, with optional brightness | No |\n| `set_zoom` | Control | Zoom a camera to an absolute position (0-100) or a relative in/out step | No |\n| `list_presets` | Control | List a camera's named PTZ presets | No |\n| `ptz_move_to_preset` | Control | Move a camera to a named (or numeric) PTZ preset | No |\n| `ptz_position` | Control | Read a camera's current pan/tilt/zoom position, naming the nearest saved preset when close | No |\n| `ptz_guard` | Control | Configure a camera's PTZ guard point and auto-return (`set`/`goto`/`enable`/`disable`) | No |\n\n## Safety\n\n- **`RMCP_READ_ONLY=true`** starts the server with all 10 control tools\n  stripped at startup — they are simply never registered, not hidden. A\n  one-line notice is printed to stderr; the client sees a clean,\n  observe-only server with no control tools in its registry at all.\n- **`set_siren`** defaults to a ~5s burst when no duration is given, and\n  refuses (never silently clamps) any request over its 60-second hard cap —\n  a clear error asks for a shorter duration instead.\n- **Capability gating**: every control tool checks the target camera's\n  actual capabilities before sending any command, and refuses cleanly (e.g.\n  \"camera 'front_door' has no siren\") instead of letting a raw API error\n  from an unsupported feature reach the client.\n\n## Camera compatibility & session limits\n\nValidated live during development on:\n\n| Camera | Validated capabilities |\n|--------|-------------------------|\n| P437 | Siren, spotlight, zoom |\n| P320 | IR lights |\n\nPTZ tools (`list_presets`, `ptz_move_to_preset`, `ptz_position`,\n`ptz_guard`) are mock-validated only — real PTZ hardware validation is\npending.\n\n**Concurrent-session limit:** `reolink-aio` maintains one long-lived session\nper camera for the lifetime of the server process. Reolink cameras cap the\nnumber of simultaneous sessions a camera will accept; running `reolink-mcp`\nalongside another system that independently holds sessions on the same\ncameras (an NVR, Reolink's own app, a second automation stack) can hit that\ncap. This project's own development setup runs against cameras shared with a\nsecond, independent system and has been exercised under that exact\ncoexistence condition — if you see login/session errors, check what else\ncurrently holds a session on the camera first.\n\n## License\n\nMIT\n\n",
  "bytes": 6700,
  "sha": "4366e2ceab5c724f52ccc4e9d75a46b42876549c94550c311a35e818aa0bbb8f",
  "repo_slug": "ed-dryha/reolink-mcp",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_ed_dryha_reolink_mcp_164a82dc/readme"
}