mcp-beam
About
Cast local files and media URLs to Chromecast and DLNA/UPnP devices on your LAN.
Details
- Author
- alexballas
- Categories
- Other, Media
Jump to
Setup
Install mcp-beam in your MCP client (Claude Desktop, Cursor, Windsurf, and others).
Repository: https://github.com/alexballas/mcp-beam
Follow the installation instructions in the repository README, then restart your MCP client.
mcp-beamis a MCP server (stdiotransport) for casting local files and media URLs to Chromecast and DLNA/UPnP devices on your LAN.
- list_local_hardware
- beam_media
- get_beaming_status
- play_beaming
- pause_beaming
- seek_beaming
- stop_beaming
- One server for both Chromecast and DLNA/UPnP workflows.
- Stable device IDs for reliable follow-up calls.
- Protocol-aware direct play and transcoding decisions.
- Safe-by-default path, URL, and bind policies.
- Structured errors with practical remediation hints.
- Demo
- Quick Start
- Installation
- Runtime Dependencies
# Claude Code claude mcp add --scope user mcp-beam -- go run go2tv.app/mcp-beam@latest # Codex codex mcp add mcp-beam -- go run go2tv.app/mcp-beam@latest # Gemini gemini mcp add mcp-beam go run go2tv.app/mcp-beam@latest
Generic JSON configuration (for MCP hosts usingmcpServers):
{ "mcpServers": { "mcp-beam": { "command": "go", "args": [ "run", "go2tv.app/mcp-beam@latest" ] } } }
- RequiresgoinPATH(Go1.26+).
- The first run may be slower due to module download/build.
2) Verify the server binary/module wiring
go run go2tv.app/mcp-beam@latest --version go run go2tv.app/mcp-beam@latest --self-test
- Calllist_local_hardwareand pick a deviceid.
- Callbeam_mediawithsourceandtarget_device.
- Callget_beaming_status,play_beaming,pause_beaming, orseek_beamingas needed.
- Callstop_beamingwhen done.
{ "name": "list_local_hardware", "arguments": { "timeout_ms": 3000, "include_unreachable": false } }
{ "name": "beam_media", "arguments": { "source": "/absolute/path/to/video.mp4", "target_device": "dev_1234abcd", "transcode": "auto" } }
{ "name": "get_beaming_status", "arguments": { "session_id": "sess_abcd1234" } }
{ "name": "pause_beaming", "arguments": { "session_id": "sess_abcd1234" } }
{ "name": "play_beaming", "arguments": { "session_id": "sess_abcd1234" } }
{ "name": "seek_beaming", "arguments": { "session_id": "sess_abcd1234", "mode": "percent", "value": 50 } }
{ "name": "stop_beaming", "arguments": { "session_id": "sess_abcd1234" } }
go run go2tv.app/mcp-beam@latest --version go run go2tv.app/mcp-beam@latest --self-test
Use this MCP config to run directly from source:
{ "mcpServers": { "mcp-beam": { "command": "/bin/bash", "args": [ "-lc", "cd /absolute/path/to/mcp-beam && go run ." ] } } }
{ "mcpServers": { "mcp-beam": { "command": "powershell", "args": [ "-NoProfile", "-Command", "Set-Location 'C:\\absolute\\path\\to\\mcp-beam'; go run ." ] } } }
go build -o ./bin/mcp-beam . ./bin/mcp-beam --version ./bin/mcp-beam --self-test
- https://github.com/alexballas/mcp-beam/releases
Get-FileHash .\mcp-beam_<version>_windows_amd64.zip -Algorithm SHA256
tar -xzf mcp-beam_<version>_<os>_<arch>.tar.gz ./mcp-beam_<version>_<os>_<arch>/mcp-beam --version ./mcp-beam_<version>_<os>_<arch>/mcp-beam --self-test
Expand-Archive .\mcp-beam_<version>_windows_amd64.zip -DestinationPath . .\mcp-beam_<version>_windows_amd64\mcp-beam.exe --version .\mcp-beam_<version>_windows_amd64\mcp-beam.exe --self-test
{ "mcpServers": { "mcp-beam": { "command": "/absolute/path/to/mcp-beam", "args": [] } } }
- go(Go 1.26+) is required when usinggo run, building locally, or packaging releases. SeeGo Installationbelow.
- Downloaded release binaries do not require a local Go installation.
- ffmpegandffprobeare optional for non-transcoding paths, but recommended.
- If transcoding is required andffmpegis unavailable, calls returnFFMPEG_NOT_FOUND.
Download and install fromhttps://go.dev/dl/or via package manager:
- Debian/Ubuntu:sudo apt install golang-go
- Fedora:sudo dnf install golang
- Arch:sudo pacman -S go
Download and install fromhttps://go.dev/dl/or use Homebrew:
Download and install fromhttps://go.dev/dl/
- Linux: package manager (for examplesudo apt install ffmpeg)
- macOS:brew install ffmpeg
- Windows: install FFmpeg and addbintoPATH
- Linux/macOS:command -v ffmpeg && command -v ffprobe
- Windows:where ffmpegandwhere ffprobe
Discover Chromecast and DLNA/UPnP renderers on the local network.
- timeout_ms(optional integer, minimum100, default5000)
- include_unreachable(optional boolean, defaultfalse)
{ "name": "list_local_hardware", "arguments": { "timeout_ms": 5000, "include_unreachable": false } }
- count
- devices[]entries:
- id
- name
- type
- address
- is_audio_only
- protocol(chromecastordlna)
- capabilities.supports_file_source
- capabilities.supports_url_source
- capabilities.supports_hls_m3u8_url
- capabilities.limitations[]
Start playback on a selected discovered device.
- source(required string): absolute local file path, orhttp/httpsURL
- target_device(required string): stable device ID preferred, exact name fallback
- transcode(optional string):auto(default),always,never
- subtitles_path(optional string): absolute local subtitle file path (.srtor.vtt)
- start_seconds(optional integer, minimum0): start offset from the beginning of media
{ "name": "beam_media", "arguments": { "source": "/absolute/path/to/media.mp4", "target_device": "dev_1234abcd", "transcode": "auto", "subtitles_path": "/absolute/path/to/subs.srt", "start_seconds": 60 } }
- ok
- session_id
- device_id
- media_url
- transcoding
- warnings[]
- Chromecast supports local files and URL sources.
- Chromecast supports direct.m3u8HLS URL casting.
- DLNA supports local files and URL sources with direct-first then proxy fallback behavior.
- DLNA.m3u8URLs are rejected with structured limitation details.
- Whensubtitles_pathis omitted for local files, mcp-beam auto-detects sidecar subtitles using the same basename (.srt, then.vtt).
Get current playback status for an active beam session.
- target_device(optional string)
- session_id(optional string)
- At least one oftarget_deviceorsession_idis required.
{ "name": "get_beaming_status", "arguments": { "session_id": "sess_abcd1234" } }
- ok
- session_id
- device_id
- device_name
- protocol
- state
- optionalposition_seconds
- optionalduration_seconds
- optionaltitle
- optionalcontent_type
- media_url
- transcoding
- warnings[]
- target_device(optional string)
- session_id(optional string)
- At least one oftarget_deviceorsession_idis required.
{ "name": "play_beaming", "arguments": { "session_id": "sess_abcd1234" } }
- ok
- session_id
- device_id
- state(playing)
- target_device(optional string)
- session_id(optional string)
- At least one oftarget_deviceorsession_idis required.
{ "name": "pause_beaming", "arguments": { "session_id": "sess_abcd1234" } }
- ok
- session_id
- device_id
- state(paused)
- target_device(optional string)
- session_id(optional string)
- At least one oftarget_deviceorsession_idis required.
{ "name": "stop_beaming", "arguments": { "session_id": "sess_abcd1234" } }
- ok
- stopped_session_id
- device_id
- warnings(optional cleanup warnings after playback stopped)
Seek an active beam session by absolute position, percentage, from-end offset, or relative delta.
- target_device(optional string)
- session_id(optional string)
- mode(required string): how to interpretvalue. One of:
- absolute_seconds: jump to a timestamp measured from the start
- percent: jump to a percentage of the total duration (0to100)
- from_end_seconds: jump to a point measured back from the end
- delta_seconds: skip relative to the current position; negative values rewind
- value(required number): the seek amount, interpreted bymode.
- At least one oftarget_deviceorsession_idis required.
{ "name": "seek_beaming", "arguments": { "session_id": "sess_abcd1234", "mode": "from_end_seconds", "value": 10 } }
- ok
- session_id
- device_id
- position_seconds
- requested_mode
- resolved_position_seconds
- optionalduration_seconds
- Middle of media:mode: percent,value: 50
- Ten seconds from end:mode: from_end_seconds,value: 10
- Exact second:mode: absolute_seconds,value: 120
- Skip ahead 30 seconds:mode: delta_seconds,value: 30
- Rewind 10 seconds:mode: delta_seconds,value: -10
- Duration-relative modes (percent,from_end_seconds) require known media duration.
- never: do not transcode.
- always: force transcoding for video sources; ignored for non-video sources.
- auto: protocol-aware default behavior.
- Chromecast local files: transcode only when codec compatibility requires it.
- Chromecast URL sources: direct stream by default.
- DLNA local files: transcode only withalwaysfor video sources.
- DLNA URL sources: direct-first then proxy fallback; transcode forced only withalwaysfor video.
- Invalidtranscodevalues return JSON-RPC-32602(invalid params).
- transcode=alwayswith direct Chromecast HLS (.m3u8) URLs is rejected.
- If transcoding is required/requested andffmpegis unavailable, the call returnsFFMPEG_NOT_FOUND.
- Results includestructuredContent.transcodingandwarnings[]so callers can verify what ran.
- JSON-RPC error-32602(invalid params)
- isError=true
- structuredContent.errorincludes:
- code
- message
- optionallimitations[]
- optionalsuggested_fixes[]
- optionaldetails
- DEVICE_NOT_FOUND
- DEVICE_UNREACHABLE
- FILE_NOT_FOUND
- FILE_NOT_READABLE
- UNSUPPORTED_MEDIA
- UNSUPPORTED_SOURCE_FOR_PROTOCOL
- UNSUPPORTED_URL_PATTERN
- TRANSCODE_REQUIRED
- FFMPEG_NOT_FOUND
- SEEK_MODE_INVALID
- SEEK_POSITION_INVALID
- SEEK_DURATION_UNKNOWN
- PROTOCOL_ERROR
- INTERNAL_ERROR
- Local file paths must be absolute.
- Strict path mode enforces allowlisted prefixes and rejects path escapes.
- OnlyhttpandhttpsURLs are accepted.
- Loopback hosts (localhost,127.0.0.0/8,::1) are blocked by default.
- Wildcard bind addresses (0.0.0.0,::) are blocked by default.
- Temporary media routes use random, unguessable tokens.
- Session ownership is process-local and in-memory.
- KeepMCP_BEAM_ALLOW_LOOPBACK_URLS=falseunless explicitly needed for local-only testing.
- KeepMCP_BEAM_ALLOW_WILDCARD_BIND=false.
- EnableMCP_BEAM_STRICT_PATH_POLICY=truewith explicitMCP_BEAM_ALLOWED_PATH_PREFIXES.
- Runmcp-beamunder a least-privilege OS account.
- MCP client input is untrusted and validated strictly.
- Source URL hosts are external trust boundaries.
- Media listeners are LAN-visible and should run only on trusted networks.
- Device control endpoints (Chromecast/DLNA) depend on LAN integrity.
MCP Host (MCP client) | | stdio JSON-RPC (MCP) v mcp-beam (single process) - internal/mcpserver (initialize, tools/list, tools/call) - internal/discovery (unified DLNA + Chromecast discovery) - internal/beam (session manager + lifecycle + cleanup) | +--> go2tv castprotocol (Chromecast control) +--> go2tv soapcalls (DLNA control) +--> go2tv httphandlers (temporary HTTP media serving) +--> go2tv utils (MIME/transcode/url helpers)
- Single headless binary.
- MCP overstdin/stdoutonly.
- In-process session manager is the source of truth.
- One active session per target device.
- list_local_hardware: discover, normalize, stable IDs, optional reachability filter.
- beam_media: validate source, resolve target, choose protocol, decide transcode, start playback, persist session.
- get_beaming_status: query active sessions bysession_idortarget_device.
- play_beaming/pause_beaming: resume or pause active sessions bysession_idortarget_device.
- seek_beaming: seek active sessions bysession_idortarget_device.
- stop_beaming: resolve session/device, stop protocol playback, tear down runtime resources.
- idle_cleanup_after = 10m
- paused_cleanup_after = 90m
- max_session_age = 24h
- sweep interval5s
- Chromecast via status polling (GetStatus)
- DLNA hybrid monitoring (callbacks + polling fallback)
- FFMPEG_NOT_FOUND: installffmpeg/ffprobe, then verifyPATH.
- DEVICE_NOT_FOUND: runlist_local_hardwareand reuse returnedid.
- DEVICE_UNREACHABLE: verify the target is powered on and reachable.
- UNSUPPORTED_URL_PATTERN: source must be routablehttp/https; for local loopback testing only, setMCP_BEAM_ALLOW_LOOPBACK_URLS=true.
- UNSUPPORTED_SOURCE_FOR_PROTOCOL: target Chromecast for.m3u8.
- PROTOCOL_ERRORwith bind policy: use a concrete LAN bind address; setMCP_BEAM_ALLOW_WILDCARD_BIND=trueonly in controlled environments.
- invalid params: remove unknown fields and match exact argument names/types.
- If no devices are returned, increasetimeout_ms.
- Setinclude_unreachable=truefor debugging.
- Verify firewall/network discovery access.
- Verify command path and executable permissions.
- On Windows, use full path tomcp-beam.exe.
- In debug logs, check formcp_server_start,mcp_read_wait,mcp_message_received.
Sign in to leave a review
Use Google, GitHub, or an email account so ratings stay tied to real people.
No reviews posted yet.




