go2rtc-mcp
A production-grade Model Context Protocol (MCP) server for go2rtc (including Home Assistant's built-in go2rtc service). Designed primarily for Linux environments (Home Assistant Supervised/OS, Debian/Ubuntu, Docker, and headless media servers), go2rtc-mcp enables AI assistants and MCP clients to inspect camera streams, probe video/audio codecs, capture live JPEG snapshots, generate streaming playback URLs (WebRTC, MSE, HLS, MP4, MJPEG, RTSP), discover camera integrations, and manage streams dynamically—with strict, automated credential redaction.
Table of Contents
- Architecture & Security Guardrails
- Linux Installation & Quick Start
- Configuration
- MCP Client Configuration (Linux, macOS, Windows)
- Running as a Systemd Service (Linux)
- Usage Guide
- Project Structure
- Development & Testing
- License
Architecture & Security Guardrails
Live go2rtc API endpoints (/api/streams, /api/config, /api/hass, /api/log) regularly return plaintext or URL-encoded camera credentials and authentication tokens in RTSP producer URLs. go2rtc-mcp enforces defense-in-depth security:
1. Centralized Recursive Credential Redaction (redact_sensitive_data)
Every MCP tool return value, MCP resource response, client error message, and log record passes through redact_sensitive_data:
- Universal URI Credential Masking: Masks credentials in any URI scheme (
rtsp://,rtsps://,http://,https://,rtmp://,onvif://,dvrip://, including chained prefixes likeffmpeg:rtsp://...). - Query Parameter Token Masking: Masks sensitive query parameters (
token,access_token,auth,password,pass,pwd,secret,api_key,jwt). - Recursive Dict Key & Value Sanitization: Sanitizes both dictionary keys and values (crucial because
go2rtccreates dynamic stream keys named after raw RTSP URLs), lists, tuples, sets, Pydantic models, and multiline YAML text. - Log Stream Redaction: Attaches
RedactingLoggingFiltertohttpx,httpcore,mcp, andgo2rtc_mcploggers so credentials never reachstdout/stderrorjournald.
Example Transformation:
Raw from go2rtc:
rtsp://admin:mockpass%2A@192.0.2.10:554/Streaming/Channels/101
rtsp://stream.example.com/live?token=eyJmockToken123&tracks=v1a1
Returned by go2rtc-mcp:
rtsp://***:***@192.0.2.10:554/Streaming/Channels/101
rtsp://stream.example.com/live?token=***&tracks=v1a1
2. Command Execution Guardrail (GO2RTC_ALLOW_EXEC_STREAMS)
go2rtc allows stream sources starting with exec:, echo:, and expr: to execute host shell commands. By default (GO2RTC_ALLOW_EXEC_STREAMS=false), go2rtc-mcp rejects any add_stream or update_stream request containing exec:, echo:, or expr: (including chained forms like ffmpeg:exec:...) before any network request is issued.
Linux Installation & Quick Start
Prerequisites
- Linux (Debian, Ubuntu, Alpine, Arch, Fedora, Raspberry Pi OS, etc.)
- Python
>= 3.11 - uv package manager (recommended:
curl -LsSf https://astral.sh/uv/install.sh | sh) - Access to your
go2rtcinstance (e.g.http://localhost:1984or local network IP)
1. Clone the Repository
git clone https://github.com/gaxkalik/go2rtc-mcp.git
cd go2rtc-mcp
2. Install Dependencies with uv
uv sync
3. Configure Environment Variables
Copy .env.example to .env:
cp .env.example .env
Edit .env using your preferred editor (nano .env or vim .env):
GO2RTC_URL=http://localhost:1984
GO2RTC_USERNAME=
GO2RTC_PASSWORD=
GO2RTC_TIMEOUT=15.0
GO2RTC_ALLOW_EXEC_STREAMS=false
4. Run and Test the MCP Server
Run over stdio transport (standard for MCP clients):
uv run go2rtc-mcp
Or test interactively in your browser with the official MCP Inspector:
npx @modelcontextprotocol/inspector uv run go2rtc-mcp
Configuration
go2rtc-mcp loads settings from environment variables (and automatically reads a local .env file if present):
| Environment Variable | Default | Description |
|---|---|---|
GO2RTC_URL |
http://localhost:1984 |
Base HTTP/HTTPS URL of your go2rtc server |
GO2RTC_USERNAME |
(empty) | Optional HTTP Basic Auth username |
GO2RTC_PASSWORD |
(empty) | Optional HTTP Basic Auth password |
GO2RTC_TIMEOUT |
15.0 |
Request timeout in seconds |
GO2RTC_ALLOW_EXEC_STREAMS |
false |
Set to true only if you explicitly allow exec: / echo: / expr: sources |
MCP Client Configuration (Linux, macOS, Windows)
Linux (~/.config/Claude/claude_desktop_config.json or ~/.gemini/config/mcp_config.json)
{
"mcpServers": {
"go2rtc": {
"command": "uv",
"args": [
"--directory",
"/home/user/go2rtc-mcp",
"run",
"go2rtc-mcp"
],
"env": {
"GO2RTC_URL": "http://localhost:1984",
"GO2RTC_USERNAME": "",
"GO2RTC_PASSWORD": "",
"GO2RTC_TIMEOUT": "15.0",
"GO2RTC_ALLOW_EXEC_STREAMS": "false"
}
}
}
}
Note: Adjust
/home/user/go2rtc-mcp(or/config/go2rtc-mcpon Home Assistant) to your actual installation path. Ensureuvis in your systemPATH(e.g./home/user/.cargo/bin/uvor/usr/local/bin/uv).
macOS (~/Library/Application Support/Claude/claude_desktop_config.json)
Replace the directory path with /Users/username/go2rtc-mcp.
Windows (%APPDATA%\Claude\claude_desktop_config.json)
Replace the directory path with C:/Users/username/go2rtc-mcp.
Running as a Systemd Service (Linux)
If you wish to run go2rtc-mcp as a persistent background daemon or manage it through Linux systemctl:
Create /etc/systemd/system/go2rtc-mcp.service:
[Unit]
Description=go2rtc Model Context Protocol Server
After=network.target
[Service]
Type=simple
User=user
WorkingDirectory=/home/user/go2rtc-mcp
EnvironmentFile=/home/user/go2rtc-mcp/.env
ExecStart=/home/user/.cargo/bin/uv run go2rtc-mcp
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
Enable and start the service:
sudo systemctl daemon-reload
sudo systemctl enable --now go2rtc-mcp
sudo systemctl status go2rtc-mcp
Usage Guide
Example Natural-Language Prompts
Ask your AI assistant:
- "List all cameras configured on my go2rtc server."
- "Take a snapshot of
door_cameraand describe the current scene." - "Perform a security patrol across all active cameras."
- "Probe
garage_cameracodecs, resolution, and RTSP protocol." - "Generate WebRTC viewer, HLS (.m3u8), and RTSP playback links for
outside_camera." - "Check recent go2rtc logs for connection errors or offline feeds."
MCP Tools Reference & Examples
1. get_server_info()
Fetches go2rtc version, revision, host, and RTSP port (GET /api).
- Sample Output:
{ "config_path": "/config/go2rtc.yaml", "host": "localhost:1984", "revision": "b5948cf", "rtsp": { "default_query": "video&audio", "listen": ":554" }, "version": "1.9.14" }
2. list_streams()
Lists all configured and active streams (GET /api/streams) with credentials automatically masked.
- Sample Output:
{ "door_camera": { "producers": [ { "url": "rtsp://***:***@192.0.2.10:554/Streaming/Channels/101" } ], "consumers": [] }, "garage_camera": { "producers": [ { "url": "rtsp://***:***@192.0.2.11:554/Streaming/Channels/101" } ], "consumers": [] } }
3. get_stream_info(stream_name: str, probe: bool = False)
Fetches producer and consumer state for a specific camera (GET /api/streams?src=<stream_name>). Pass probe=True to query live codecs and SDP.
4. probe_stream(stream_name: str)
Actively queries GET /api/streams?src=<stream_name>&video=all&audio=all to inspect active codecs (H.264, H.265, AAC, PCMA, Opus), SDP tracks, protocol (rtsp+tcp), and byte counters.
5. get_stream_snapshot(stream_name: str, width: int | None = None, height: int | None = None)
Captures a live JPEG frame from stream_name (GET /api/frame.jpeg?src=<stream_name>) and returns it as a native MCP Image (image/jpeg) for multimodal vision models.
6. get_stream_urls(stream_name: str)
Generates ready-to-use streaming URLs for web, mobile, and NVR playback:
- Sample Output:
{ "stream": "door_camera", "webrtc_viewer": "http://localhost:1984/stream.html?src=door_camera&mode=webrtc", "mse_viewer": "http://localhost:1984/stream.html?src=door_camera&mode=mse", "websocket_url": "ws://localhost:1984/api/ws?src=door_camera", "hls_m3u8": "http://localhost:1984/api/stream.m3u8?src=door_camera", "mp4_stream": "http://localhost:1984/api/stream.mp4?src=door_camera", "mjpeg_stream": "http://localhost:1984/api/stream.mjpeg?src=door_camera", "snapshot_jpeg": "http://localhost:1984/api/frame.jpeg?src=door_camera", "rtsp_url": "rtsp://localhost:554/door_camera" }
7. add_stream(stream_name: str, source_url: str)
Dynamically registers or updates a stream (PUT /api/streams?name=<name>&src=<url>), validating against GO2RTC_ALLOW_EXEC_STREAMS.
8. update_stream(stream_name: str, source_url: str)
Dynamically updates an existing stream source (PATCH /api/streams).
9. delete_stream(stream_name: str)
Removes a dynamically registered stream (DELETE /api/streams?src=<name>).
10. get_config()
Retrieves sanitized go2rtc.yaml configuration (GET /api/config) with all secrets masked.
11. get_server_logs(limit: int = 50)
Fetches recent go2rtc log entries (GET /api/log) with credentials redacted.
12. discover_sources(provider: str = "hass")
Discovers stream sources from integrations (hass, onvif, dvrip, homekit, roborock, webtorrent).
MCP Resources Reference
| Resource URI | MIME Type | Description |
|---|---|---|
go2rtc://server/info |
application/json |
Server version, revision, host, and RTSP listener config |
go2rtc://streams |
application/json |
Complete dictionary of streams with redacted producer URLs |
go2rtc://streams/{stream_name} |
application/json |
Producer and consumer details for {stream_name} |
go2rtc://config |
text/yaml |
Sanitized go2rtc.yaml configuration |
MCP Prompts Reference
snapshot_all: Captures live frames from all cameras and generates a multi-camera visual security summary.security_patrol: Full security assessment combining stream health, frame capture, and log error analysis.diagnose_stream(stream_name): Guided step-by-step diagnostic workflow for troubleshooting a camera.camera_urls(stream_name): Formats all direct streaming integration links.stream_health_check: System-wide health audit of all streams, codecs, and logs.
Programmatic Python Usage
import asyncio
from go2rtc_mcp import Go2RtcClient, Go2RtcSettings, redact_sensitive_data
async def main() -> None:
settings = Go2RtcSettings.from_env()
client = Go2RtcClient(settings=settings)
# 1. Fetch server metadata
info = await client.get_server_info()
print("Server version:", info.get("version"))
# 2. List streams (credentials automatically masked)
streams = await client.list_streams()
for name, data in streams.items():
print(f"Stream: {name} -> {data}")
# 3. Capture a live JPEG snapshot
jpeg_bytes = await client.get_snapshot("door_camera", width=1280)
with open("door_snapshot.jpg", "wb") as f:
f.write(jpeg_bytes)
print("Saved door_snapshot.jpg")
if __name__ == "__main__":
asyncio.run(main())
Project Structure
go2rtc-mcp/
├── .env.example # Safe template for environment variables
├── .gitignore # Excludes .env, snapshots (*.jpg/*.png/*.mp4), and live dumps
├── LICENSE # MIT License
├── pyproject.toml # Package metadata, dependencies, pytest & ruff config
├── README.md # Project documentation and Linux usage guide
├── src/
│ └── go2rtc_mcp/
│ ├── __init__.py # Public package exports
│ ├── client.py # Async httpx Go2RtcClient with automatic redaction
│ ├── config.py # Pydantic Go2RtcSettings & dotenv loader
│ ├── models.py # Pydantic models for server & stream objects
│ ├── sanitizer.py # Alias module re-exporting security redaction utilities
│ ├── security.py # redact_sensitive_data, validate_stream_source, log filter
│ └── server.py # MCPServer tools, resources, prompts, and CLI entry point
└── tests/
├── test_client.py # respx unit tests for Go2RtcClient endpoints & error handling
├── test_security.py # Unit tests for URI schemes, recursive redaction & exec policy
└── test_server.py # Unit tests for MCP tools, resources, snapshots & prompts
Development & Testing
All unit tests use synthetic RFC 5737 (192.0.2.0/24) test fixtures and mock responses via respx so tests run offline and deterministically on Linux:
# Run unit tests
uv run python -m pytest -v
# Run ruff linter
uv run ruff check src/ tests/
License
Released under the MIT License.
Metadata
Release files for go2rtc-mcp 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| go2rtc_mcp-0.1.0.tar.gz | 16.1 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| go2rtc_mcp-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 34.5 kB
Release files / go2rtc_mcp-0.1.0.tar.gz
| Download URL | go2rtc_mcp-0.1.0.tar.gz |
|---|---|
| Size | 16.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
6bea4d34146cd59bbaa73efbb78a6fe1a5e845c7329edf242f55f3bc28b54a2c
|
|
BLAKE2b-256 checksum How to use checksums |
fa7fd2c1f48ead70c4bd5880a008982895d049a6e2f29b73ffd69dd2c9dbd29d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.13.1 {"installer":{"name":"uv","version":"0.13.1","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Release files / go2rtc_mcp-0.1.0-py3-none-any.whl
| Download URL | go2rtc_mcp-0.1.0-py3-none-any.whl |
|---|---|
| Size | 18.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
13640fb8c3522c793a1a56a98b0752c1842e472fac7598fade8b83580f2d91b0
|
|
BLAKE2b-256 checksum How to use checksums |
15ae5f67f96d5ec2bd5d888d2a4fe6ec7fbd62a897852e1c6c0995f1e9d04bc2
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.13.1 {"installer":{"name":"uv","version":"0.13.1","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|