HDHomeRun MCP
CLI or API | MCP | Agent
Version: 0.1.0
Documentation — Installation, deployment, usage across the API, CLI, and MCPinterfaces, the integrated A2A agent server, and guidance for provisioning thebacking platform are maintained in theofficial documentation.
Table of Contents
- Overview
- Key Features
- Available MCP Tools
- Installation
- Usage
- MCP
- Documentation
Overview
HDHomeRun MCP MCP Server + A2A Agent
A complete client + MCP server + A2A agent for SiliconDust HDHomeRun network TVtuners, covering all four of SiliconDust's documented interfaces: the HTTP JSONAPI (device discovery, channel lineup, scan control), the DVR API(SiliconDust cloud recording rules + local record-engine operations), theDiscovery API (local UDP broadcast on port 65001 + the cloud discoveryendpoint), and the binary hdhomerun_config control protocol (TCP port65001 — a different wire protocol from the HTTP API, used for per-tunerstatus/vstatus/streaminfo/tuning/filters). Also ships a doctor diagnostictool matching this fleet's cm_doctor convention.
This repository is actively maintained - Contributions are welcome!
Key Features
- All four HDHomeRun interfaces, one package — HTTP JSON API, DVR API,Discovery API (local UDP + cloud), and the binary hdhomerun_config controlprotocol, each its own action-routed tool domain.
doctordiagnostics — one call checks device reachability, firmware/model,tuner count vs. a paired Jellyfin instance, per-channel signal strength,DeviceAuth presence/validity, and discovery-cache freshness — pass/fail with anactionable next step per check.- Action-routed MCP tools — each domain is exposed as a single MCP tool that routesto many underlying operations via an
actionargument, keeping the tool surface small. - Three interfaces, one package — use it as a Python API client, an MCP server(
stdio/streamable-http/sse), or a Pydantic-AI A2A agent. agent-utilitiesnative — built on the shared framework (auth, action router,telemetry, governance) for fleet consistency.- Per-tool toggles — enable or disable each tool domain with environment switches.
- Enterprise-ready — OTEL/Langfuse telemetry and optional Eunomia access governance.
Available MCP Tools
Each tool is action-routed: pass an action and a JSON params_json payload. Tooldomains can be toggled on or off with the listed environment variable. The table below isauto-generated from the live server by the mcp-readme-table pre-commit hook(python -m agent_utilities.mcp.readme_tools) — do not edit it by hand.
Condensed action-routed tools (MCP_TOOL_MODE=condensed)
| MCP Tool | Toggle Env Var | Description |
|---|---|---|
config_operations |
CONFIGTOOL |
Query/control a tuner via the binary hdhomerun_config TCP control |
discovery_operations |
DISCOVERYTOOL |
Discover HDHomeRun devices on the network — local UDP broadcast |
doctor_operations |
DOCTORTOOL |
Diagnose an HDHomeRun deployment: device reachability, firmware/model, |
dvr_operations |
DVRTOOL |
Manage the SiliconDust cloud DVR recording-rules API and the local |
http_operations |
HTTPTOOL |
Query the HDHomeRun device HTTP JSON API — discover.json, channel |
Verbose 1:1 API-mapped tools (MCP_TOOL_MODE=verbose or both)
57 per-operation tools — one per public API method (click to expand)
| MCP Tool | Toggle Env Var | Description |
|---|---|---|
hdhomerun_abort_scan |
GRANULARTOOL |
POST /lineup.post?scan=abort — cancel an in-progress channel scan. |
hdhomerun_add_datetime_rule |
DVRTOOL |
Add a DateTimeOnly-ChannelOnly rule (record one specific airing). |
hdhomerun_add_series_rule |
DVRTOOL |
Add a Series (or Movie) recording rule for a SeriesID. |
hdhomerun_build_live_tv_url |
DVRTOOL |
Build a record-engine buffered Live TV URL. |
hdhomerun_build_stream_url |
GRANULARTOOL |
Build a live-stream URL: /{auto|tuner}/{v|ch[-]}. |
hdhomerun_change_rule |
DVRTOOL |
Modify a rule, or reprioritize it via after_recording_rule_id. |
hdhomerun_check_device_auth |
DOCTORTOOL |
Invoke the check_device_auth operation. |
hdhomerun_check_device_reachable |
DOCTORTOOL |
Invoke the check_device_reachable operation. |
hdhomerun_check_discovery_cache_freshness |
DOCTORTOOL |
Invoke the check_discovery_cache_freshness operation. |
hdhomerun_check_firmware_model |
DOCTORTOOL |
Invoke the check_firmware_model operation. |
hdhomerun_check_signal_strength |
DOCTORTOOL |
Briefly tune each channel and sample ss/snq/seq, then release the tuner. |
hdhomerun_check_tuner_count_vs_jellyfin |
DOCTORTOOL |
Invoke the check_tuner_count_vs_jellyfin operation. |
hdhomerun_delete_recording |
DVRTOOL |
POST cmd=delete[&rerecord=1]. |
hdhomerun_delete_rule |
DVRTOOL |
Delete a Series/Movie rule (by RecordingRuleID or SeriesID) or a |
hdhomerun_disable_lineup_location |
CONFIGTOOL |
Disable the lineup-server connection (/lineup/location disabled). |
hdhomerun_discover_cloud |
DISCOVERYTOOL |
GET http://ipv4-api.hdhomerun.com/discover[?DeviceID=]. |
hdhomerun_discover_local_broadcast |
DISCOVERYTOOL |
Broadcast a DISCOVER_REQ on UDP port 65001 and collect DISCOVER_RPY replies. |
hdhomerun_discover_local_targeted |
DISCOVERYTOOL |
Send a DISCOVER_REQ directly to a known IP (works across VLANs). |
hdhomerun_get_channel |
CONFIGTOOL |
/tuner<n>/channel — current <modulation>:<frequency> or none. |
hdhomerun_get_channelmap |
CONFIGTOOL |
/tuner<n>/channelmap — the configured channel-to-frequency map. |
hdhomerun_get_discover |
GRANULARTOOL |
GET /discover.json — FriendlyName/ModelNumber/FirmwareVersion/DeviceID/ |
hdhomerun_get_filter |
CONFIGTOOL |
/tuner<n>/filter — the current PID filter (default 0x0000-0x1FFF). |
hdhomerun_get_help |
CONFIGTOOL |
get help — the list of get/set item paths this device supports. |
hdhomerun_get_ir_target |
CONFIGTOOL |
/ir/target — the configured IR-blaster target IP:port. |
hdhomerun_get_item |
CONFIGTOOL |
hdhomerun_config <id> get <item> — raw get of any supported item path. |
hdhomerun_get_lineup |
GRANULARTOOL |
GET /lineup.{json,xml,m3u} — the channel list. |
hdhomerun_get_lineup_status |
GRANULARTOOL |
GET /lineup_status.json — scan state. |
hdhomerun_get_lockkey |
CONFIGTOOL |
/tuner<n>/lockkey — current tuner lock owner (none if unlocked). |
hdhomerun_get_program |
CONFIGTOOL |
/tuner<n>/program — the current MPEG program (sub-channel) filter. |
hdhomerun_get_record_engine_status |
DVRTOOL |
GET /discover.json — FriendlyName/Version/ |
hdhomerun_get_recorded_files |
DVRTOOL |
GET (recorded_files.json) — the list of recordings |
hdhomerun_get_sys_copyright |
CONFIGTOOL |
/sys/copyright — the firmware copyright notice. |
hdhomerun_get_sys_debug |
CONFIGTOOL |
/sys/debug — device-wide debug info. |
hdhomerun_get_sys_features |
CONFIGTOOL |
/sys/features — supported channelmaps/modulations for this device. |
hdhomerun_get_sys_model |
CONFIGTOOL |
/sys/model — the device model name. |
hdhomerun_get_sys_version |
CONFIGTOOL |
/sys/version — the firmware version string. |
hdhomerun_get_target |
CONFIGTOOL |
/tuner<n>/target — the current UDP/RTP streaming target. |
hdhomerun_get_tuner_debug |
CONFIGTOOL |
/tuner<n>/debug — extended tun/dev/ts/flt/net diagnostic counters. |
hdhomerun_get_tuner_status |
CONFIGTOOL |
/tuner<n>/status — ch=... lock=... ss=... snq=... seq=... bps=... pps=.... |
hdhomerun_get_tuner_streaminfo |
CONFIGTOOL |
/tuner<n>/streaminfo — detected programs: <num>: <major>.<minor> [name]. |
hdhomerun_get_tuner_vstatus |
CONFIGTOOL |
/tuner<n>/vstatus — virtual-channel auth/CCI/CGMS status (model/firmware |
hdhomerun_list_recording_rules |
DVRTOOL |
List all recording rules for the household's DeviceAuth(s). |
hdhomerun_parse_tuner_status |
CONFIGTOOL |
Parse a ch=... lock=... ss=... snq=... seq=... bps=... pps=... status line. |
hdhomerun_poke_record_engine |
DVRTOOL |
POST /recording_events.post?sync. |
hdhomerun_restart_device |
CONFIGTOOL |
/sys/restart self — reboot the HDHomeRun. Destructive; use with care. |
hdhomerun_run_doctor |
DOCTORTOOL |
Run every check and return the aggregate report. |
hdhomerun_set_channel |
CONFIGTOOL |
/tuner<n>/channel set — e.g. auto:651000000 or auto:60; none to stop. |
hdhomerun_set_channelmap |
CONFIGTOOL |
/tuner<n>/channelmap set — e.g. us-bcast/us-cable/us-hrc/us-irc. |
hdhomerun_set_filter |
CONFIGTOOL |
/tuner<n>/filter set — e.g. 0x0000-0x1FFF or a space-separated PID list. |
hdhomerun_set_ir_target |
CONFIGTOOL |
/ir/target set — <ip>:<port>. |
hdhomerun_set_item |
CONFIGTOOL |
hdhomerun_config <id> set <item> <value> — raw set (implicit get-back). |
hdhomerun_set_lineup_location |
CONFIGTOOL |
/lineup/location set — <countrycode>:<postcode> (or set to "disabled"). |
hdhomerun_set_lockkey |
CONFIGTOOL |
/tuner<n>/lockkey set/clear — pass lock=False to release. |
hdhomerun_set_program |
CONFIGTOOL |
/tuner<n>/program set — filter to a single program (sub-channel) number. |
hdhomerun_set_target |
CONFIGTOOL |
/tuner<n>/target set — e.g. udp://192.168.1.100:5000 or rtp://.... |
hdhomerun_start_scan |
GRANULARTOOL |
POST /lineup.post?scan=start[&source=] — begin a channel scan. |
hdhomerun_stop_tuner |
CONFIGTOOL |
Set /tuner<n>/channel none — release the tuner. |
5 action-routed tool(s) · 57 verbose 1:1 tool(s). Each is enabled unless its <DOMAIN>TOOL toggle is set false; MCP_TOOL_MODE selects the surface (intent default — the six verb-tools, granular set loaded on demand · condensed action-routed · verbose 1:1 · both). Auto-generated — do not edit.
Installation
Install with uvx (no install — run on demand)
uvx --from "hdhomerun-mcp[mcp]" hdhomerun-mcp # MCP server (slim deps)
uvx --from "hdhomerun-mcp[agent]" hdhomerun-agent # A2A agent server (full runtime)
The
[mcp]extra installs only the FastMCP/FastAPI MCP-server tooling(agent-utilities[mcp]) — it excludes the heavy agent runtime (theepistemic-graph engine,pydantic-ai,dspy,llama-index), so it is farsmaller. Use[agent]only when you run the integrated agent.
Install with pip
python -m pip install hdhomerun-mcp # core (API client)
python -m pip install "hdhomerun-mcp[all]" # + MCP server + A2A agent + telemetry
Console scripts
After installation the following entry points are available on your PATH:
| Command | Description |
|---|---|
hdhomerun-mcp |
Launch the MCP server |
hdhomerun-agent |
Launch the A2A agent server |
Usage
As a Python API client
from hdhomerun_mcp.auth import get_client
client = get_client() # reads HDHOMERUN_URL / HDHOMERUN_DEVICE_AUTH
info = client.get_discover() # device identity + tuner count
lineup = client.get_lineup() # channel list
stream_url = client.build_stream_url("24.1") # http://<device>:5004/auto/v24.1
report = client.run_doctor() # full health-check sweep
As an MCP server (CLI)
# Local stdio (for IDEs)
hdhomerun-mcp
# Networked streamable-http
hdhomerun-mcp --transport streamable-http --host 0.0.0.0 --port 8000
Calling an MCP tool
Tools are action-routed — pass an action plus a JSON params_json string:
{
"tool": "http_operations",
"arguments": {
"action": "discover",
"params_json": "{}"
}
}
MCP
Using as an MCP Server
The MCP Server can be run in stdio (local), streamable-http (networked), orsse mode.
Environment Variables
Package environment variables
| Variable | Example | Description |
|---|---|---|
HOST |
0.0.0.0 |
|
PORT |
8000 |
|
TRANSPORT |
stdio |
options: stdio, streamable-http, sse |
ENABLE_OTEL |
True |
|
OTEL_EXPORTER_OTLP_ENDPOINT |
http://localhost:8080/api/public/otel |
|
OTEL_EXPORTER_OTLP_PUBLIC_KEY |
pk-... |
|
OTEL_EXPORTER_OTLP_SECRET_KEY |
sk-... |
|
OTEL_EXPORTER_OTLP_PROTOCOL |
http/protobuf |
|
EUNOMIA_TYPE |
none |
options: none, embedded, remote |
EUNOMIA_POLICY_FILE |
mcp_policies.json |
|
EUNOMIA_REMOTE_URL |
http://eunomia-server:8000 |
|
HDHOMERUN_URL |
http://hdhomerun.local |
|
HDHOMERUN_DEVICE_AUTH |
your_device_auth_here |
|
HDHOMERUN_SSL_VERIFY |
True |
|
MCP_TOOL_MODE |
condensed |
|
HTTPTOOL |
True |
|
DISCOVERYTOOL |
True |
|
DVRTOOL |
True |
|
CONFIGTOOL |
True |
|
DOCTORTOOL |
True |
Inherited agent-utilities variables (apply to every connector)
| Variable | Example | Description |
|---|---|---|
MCP_ENABLED_TOOLS |
— | Comma-separated tool allow-list |
MCP_DISABLED_TOOLS |
— | Comma-separated tool deny-list |
MCP_ENABLED_TAGS |
— | Comma-separated tag allow-list |
MCP_DISABLED_TAGS |
— | Comma-separated tag deny-list |
MCP_CLIENT_AUTH |
— | Outbound MCP child auth: oidc-client-credentials |
OIDC_CLIENT_ID |
— | OIDC client id (service-account auth) |
OIDC_CLIENT_SECRET |
— | OIDC client secret (service-account auth) |
MCP_BASIC_AUTH_USERNAME |
— | HTTP Basic username (MCP_CLIENT_AUTH=basic) |
MCP_BASIC_AUTH_PASSWORD |
— | HTTP Basic password (MCP_CLIENT_AUTH=basic) |
DEBUG |
False |
Verbose logging |
PYTHONUNBUFFERED |
1 |
Unbuffered stdout (recommended in containers) |
MCP_URL |
http://localhost:8000/mcp |
URL of the MCP server the agent connects to |
PROVIDER |
openai |
LLM provider for the agent |
MODEL_ID |
gpt-4o |
Model id for the agent |
ENABLE_WEB_UI |
True |
Serve the AG-UI web interface |
20 package + 15 inherited variable(s). Auto-generated from .env.example + the shared agent-utilities set — do not edit.
HDHOMERUN_URL: The HDHomeRun device base URL (e.g.http://10.0.132.114orhttp://hdhomerun.arpa).HDHOMERUN_DEVICE_AUTH: The device'sDeviceAuthtoken (only needed for SiliconDust cloud DVR calls; rotates on reboot/firmware update — do not hardcode).
MCP Configuration Examples
Install the slim
[mcp]extra. All examples installhdhomerun-mcp[mcp]— theMCP-server extra that pulls only the FastMCP / FastAPI tooling (agent-utilities[mcp]).It deliberately excludes the heavy agent runtime (pydantic-ai, the epistemic-graphengine,dspy,llama-index), souvx/ container installs are far smaller. Use thefull[agent]extra only when you need the integrated Pydantic AI agent.
stdio Transport (local IDEs — Cursor, Claude Desktop, VS Code)
{
"mcpServers": {
"hdhomerun-mcp": {
"command": "uvx",
"args": [
"--from",
"hdhomerun-mcp[mcp]",
"hdhomerun-mcp"
],
"env": {
"MCP_TOOL_MODE": "intent",
"CONFIGTOOL": "True",
"DISCOVERYTOOL": "True",
"DOCTORTOOL": "True",
"DVRTOOL": "True",
"HDHOMERUN_DEVICE_AUTH": "your_device_auth_here",
"HDHOMERUN_URL": "http://hdhomerun.local",
"HTTPTOOL": "True"
}
}
}
}
Streamable-HTTP Transport (networked / production)
{
"mcpServers": {
"hdhomerun-mcp": {
"command": "uvx",
"args": [
"--from",
"hdhomerun-mcp[mcp]",
"hdhomerun-mcp",
"--transport",
"streamable-http",
"--port",
"8000"
],
"env": {
"TRANSPORT": "streamable-http",
"HOST": "0.0.0.0",
"PORT": "8000",
"MCP_TOOL_MODE": "intent",
"CONFIGTOOL": "True",
"DISCOVERYTOOL": "True",
"DOCTORTOOL": "True",
"DVRTOOL": "True",
"HDHOMERUN_DEVICE_AUTH": "your_device_auth_here",
"HDHOMERUN_URL": "http://hdhomerun.local",
"HTTPTOOL": "True"
}
}
}
}
Alternatively, connect to a pre-deployed Streamable-HTTP instance by url:
{
"mcpServers": {
"hdhomerun-mcp": {
"url": "http://localhost:8000/hdhomerun-mcp/mcp"
}
}
}
Deploying the Streamable-HTTP server via Docker:
docker run -d \
--name hdhomerun-mcp-mcp \
-p 8000:8000 \
-e TRANSPORT=streamable-http \
-e HOST=0.0.0.0 \
-e PORT=8000 \
-e MCP_TOOL_MODE=intent \
-e CONFIGTOOL=True \
-e DISCOVERYTOOL=True \
-e DOCTORTOOL=True \
-e DVRTOOL=True \
-e HDHOMERUN_DEVICE_AUTH=your_device_auth_here \
-e HDHOMERUN_URL=http://hdhomerun.local \
-e HTTPTOOL=True \
knucklessg1/hdhomerun-mcp:mcp
Auto-generated from the code-read env surface (MCP_TOOL_MODE + package vars) — do not edit.
Additional Deployment Options
hdhomerun-mcp can also run as a local container (Docker / Podman / uv) or beconsumed from a remote deployment. TheDeployment guide has full,copy-paste mcp_config.json for all four transports — stdio, streamable-http,local container / uv, and remote URL:
- Local container / uv — launch the server from
mcp_config.jsonviauvx,docker run, orpodman run, or point at a local streamable-http container byurl. - Remote URL — connect to a server deployed behind Caddy at
http://hdhomerun-mcp.arpa/mcpusing the"url"key.
Container images (:mcp vs :agent)
One multi-stage docker/Dockerfile builds two right-sized images, selected by --target:
| Image tag | Build target | Contents | Entrypoint |
|---|---|---|---|
knucklessg1/hdhomerun-mcp:mcp |
--target mcp |
hdhomerun-mcp[mcp] — slim, no engine/pydantic-ai/dspy/llama-index |
hdhomerun-mcp |
knucklessg1/hdhomerun-mcp:latest |
--target agent (default) |
hdhomerun-mcp[agent] — full agent runtime + epistemic-graph engine |
hdhomerun-agent |
docker build --target mcp -t knucklessg1/hdhomerun-mcp:mcp docker/ # slim MCP server
docker build --target agent -t knucklessg1/hdhomerun-mcp:latest docker/ # full agent
Knowledge-graph database (epistemic-graph)
The full agent ([agent] / :latest) embeds the epistemic-graph engine (pulled in viaagent-utilities[agent]). For production — or to share one knowledge graph across multipleagents — run epistemic-graph as its own database container and point the agent at it.Deployment recipes (single-node + Raft HA), connection config, and the full databasearchitecture (with diagrams) are in theepistemic-graph deployment guide.The slim [mcp] server does not require the database.
Documentation
Full documentation is published to the GitHub Pages site and mirrored under docs/:
- Documentation site
- Overview
- Installation
- Usage
- Deployment
- Platform
- Concept Registry