Introducing Dahua MCP Server

I built an MCP server for managing Dahua and Amcrest IP cameras. It wraps the Dahua CGI HTTP API so that AI assistants like Claude can directly query, configure, and troubleshoot cameras through natural conversation.

Why

If you’ve ever managed a fleet of Dahua or Amcrest cameras, you know the drill: open the web UI for each one, click through menus, repeat fifteen times. The cameras have a powerful CGI API under the hood, but using it directly means remembering endpoint paths and crafting curl commands with digest auth. An MCP server sits in the middle — it handles the HTTP plumbing so an AI assistant can operate the cameras on your behalf.

This follows the same pattern as my LibreNMS MCP server for network monitoring. Purpose-built for management and troubleshooting tasks: checking settings, reading logs, changing configuration across devices.

What It Does

The server exposes 20 tools organized into five categories:

Camera Discovery

  • list_cameras — Returns all configured cameras (name, host, port). Every other tool takes a camera parameter that references these names.

System Information

  • get_system_info — Full system details (device type, serial, hardware/software version)
  • get_device_type — Camera model (e.g., IPC-HDW5831R-ZE)
  • get_software_version — Firmware version and build date
  • get_machine_name — Configured device name
  • get_serial_number — Hardware serial number
  • get_hardware_version — Hardware revision
  • get_vendor — Manufacturer (Dahua, Amcrest, etc.)

Configuration

  • get_config — Generic config reader for any named section (MotionDetect, Encode, Network, NTP, VideoInMode, and hundreds more)
  • get_motion_detection — Motion detection status and settings
  • get_video_in_mode — Day/night profile mode
  • get_encoding_config — Video encoding settings (resolution, bitrate, codec)
  • get_network_config — Network configuration
  • get_ntp_config — NTP time sync settings
  • set_config — Generic config writer for any key-value pair
  • enable_motion_detection — Toggle motion detection per channel
  • set_record_mode — Set recording to Auto, Manual, or Off

System Control

  • reboot — Reboot a camera
  • take_snapshot — Capture a JPEG snapshot from any channel

Logs

  • search_logs — Search device logs by time range and type. Wraps the three-step Dahua log API (startFind/doFind/stopFind) into a single call.

Multi-Camera, Single Server

One server instance manages all your cameras. You define them in a JSON config file:

{
  "cameras": [
    {"name": "front-door", "host": "192.168.1.108", "port": 80, "username": "admin", "password": "secret"},
    {"name": "backyard",   "host": "192.168.1.109", "port": 80, "username": "admin", "password": "secret"}
  ]
}

Every tool accepts a camera parameter to target a specific device. The server handles HTTP digest authentication and CGI response parsing per camera. If you are also managing your network with LibreNMS, you can create the settings file with the prompt:
Use LibreNMS to find all my Dahua cameras and generate cameras.json

Architecture

Built with Python and FastMCP, following the same architecture as the LibreNMS MCP server:

  • httpx with built-in DigestAuth — no custom auth code needed
  • Pydantic models for configuration validation
  • Read-only mode via middleware — disable all write operations with a single env var
  • Tag-based tool filtering — selectively disable tool categories
  • Dual transport — stdio for direct CLI use, HTTP for Docker deployment

Dahua cameras return key=value text responses rather than JSON. The server parses these into structured dictionaries automatically, stripping the table. and status. prefixes that litter the raw output.

Example: Standardizing the Maintenance Reboot Schedule

Here’s a real example of what this enables. I have 15 cameras and wanted them all rebooting weekly on Tuesday between 2–4 AM with no two cameras rebooting at the same time.

I asked Claude to check the current schedules across all cameras. It pulled the AutoMaintain config from each one and found several problems:

  • Two cameras had auto-reboot disabled entirely (west-lawn-cam, garage-cam)
  • Two cameras were set to the wrong day (one on Friday, one on Wednesday)
  • Three cameras were scheduled outside the 2–4 AM window (4:19, 4:27, 4:44)
  • Two pairs of cameras had identical reboot times, risking simultaneous reboots

Claude then set all 15 cameras to reboot on Tuesday, staggered 8 minutes apart:

CameraReboot Time
deck-cam2:00 AM
driveway-cam2:08 AM
front-entry-cam2:16 AM
front-lawn-cam2:24 AM
garage-cam2:32 AM
garage-left-cam2:40 AM
garage-right-cam2:48 AM
garden-cam2:56 AM
mailbox-cam3:04 AM
peach-tree-cam3:12 AM
play-cam3:20 AM
shed-cam3:28 AM
swing-cam3:36 AM
treeline-cam3:44 AM
west-lawn-cam3:52 AM

The whole operation — audit 15 cameras, identify problems, apply a corrected schedule, verify the changes — took one conversation. No web UIs, no curl commands, no spreadsheets to track what’s been updated.

Getting Started

The server runs as a standard MCP server over stdio or as a Docker container with HTTP transport:

# stdio (for Claude Code, etc.)
uv run dahua-mcp

# Docker
docker run -v ./cameras.json:/config/cameras.json:ro -p 8000:8000 dahua-mcp

Point your MCP client at it, call list_cameras to see what’s available, and start querying.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.