About Beam
Beam is an MCP server published by alexballas in the Other category.
The repository has 9 stars and 4 forks, with the last commit 13 days ago. Recent commit activity is the strongest signal that reported issues will get attention.
Install
git clone https://github.com/alexballas/mcp-beamThis server has no ConduID identity, so agent calls to it are not receipted. Pin the version you install and review the source before granting it credentials.
Ask AI
Ask AI about Beam
Powered by Claude · Grounded in docs
Security checks
Static checks derived from the repository 2 days ago. Heuristics on the source, not an audit.
- ✓README presentThe repository ships documentation.
- ✓License declaredUsable under a stated license.
- ✓Tests presentA test suite exists in the repository.
- ✓Dependencies pinnedA lockfile pins dependency versions.
- ✓No dynamic code executionSource scan found no eval, dynamic Function, or shell execution.
1 check has not been run yet.
README
mcp-beam

Demo

mcp-beam is a MCP server (stdio transport) for casting local files, media URLs, and torrents to Chromecast and DLNA/UPnP devices on your LAN. It speaks both the 2026-07-28 and 2024-11-05 protocol revisions.
It exposes eight tools:
list_local_hardwareinspect_torrentbeam_mediaget_beaming_statusplay_beamingpause_beamingseek_beamingstop_beaming
Highlights
- One server for both Chromecast and DLNA/UPnP workflows.
- Stable device IDs for reliable follow-up calls.
- Protocol-aware direct play and transcoding decisions.
- Local
.torrentand magnet sources with explicit file selection and download progress. - External, sidecar, and embedded subtitles with receiver rendering or video burn-in.
- Safe-by-default path, URL, and bind policies.
- Structured errors with practical remediation hints.
Table of Contents
- Demo
- Quick Start
- Installation
- Runtime Dependencies
- Protocol Support
- Tool Reference
- Transcode Behavior
- Error Model
- Environment Variables
- Security
- Architecture
- Troubleshooting
- Development
Quick Start
Get beaming in a few minutes.
1) Add mcp-beam to your MCP host config
CLI one-liners:
# 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 using mcpServers):
{
"mcpServers": {
"mcp-beam": {
"command": "go",
"args": [
"run",
"go2tv.app/mcp-beam@latest"
]
}
}
}
Notes:
- Requires
goinPATH(Go1.26.9+). - 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
3) Run the tool flow
- Call
list_local_hardwareand pick a deviceid. - For torrent sources, call
inspect_torrentand choose a file index when the torrent contains multiple supported media files. - Call
beam_mediawithsourceandtarget_device. - Call
get_beaming_status,play_beaming,pause_beaming, orseek_beamingas needed. - Call
stop_beamingwhen done.
Minimal example flow:
{
"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"
}
}
Installation
Published module (recommended)
go run go2tv.app/mcp-beam@latest --version
go run go2tv.app/mcp-beam@latest --self-test
Local checkout
From repo root:
go run . --version
go run . --self-test
Use this MCP config to run directly from source:
macOS/Linux:
{
"mcpServers": {
"mcp-beam": {
"command": "/bin/bash",
"args": [
"-lc",
"cd /absolute/path/to/mcp-beam && go run ."
]
}
}
}
Windows PowerShell:
{
"mcpServers": {
"mcp-beam": {
"command": "powershell",
"args": [
"-NoProfile",
"-Command",
"Set-Location 'C:\\absolute\\path\\to\\mcp-beam'; go run ."
]
}
}
}
Downloaded binary
Build locally:
go build -o ./bin/mcp-beam .
./bin/mcp-beam --version
./bin/mcp-beam --self-test
Or install from releases:
https://github.com/alexballas/mcp-beam/releases
Linux/macOS checksum verify:
shasum -a 256 -c SHA256SUMS
Windows checksum verify:
Get-FileHash .\mcp-beam_<version>_windows_amd64.zip -Algorithm SHA256
Linux/macOS unpack:
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
Windows unpack:
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
MCP config for a local binary:
{
"mcpServers": {
"mcp-beam": {
"command": "/absolute/path/to/mcp-beam",
"args": []
}
}
}
Runtime Dependencies
go(Go 1.26.9+) is required when usinggo run, building locally, or packaging releases. See Go Installation below.- Downloaded release binaries do not require a local Go installation.
ffmpegandffprobeare optional for non-transcoding paths, but recommended.- If transcoding is required and
ffmpegis unavailable, calls returnFFMPEG_NOT_FOUND. - Local embedded subtitle selection and ASS/SSA subtitle conversion also require FFmpeg.
- If transcoding is required and
Go Installation
Linux
Download and install from https://go.dev/dl/ or via package manager:
- Debian/Ubuntu:
sudo apt install golang-go - Fedora:
sudo dnf install golang - Arch:
sudo pacman -S go
macOS
Download and install from https://go.dev/dl/ or use Homebrew:
brew install go
Windows
Download and install from https://go.dev/dl/
Verify Installation
go version
Should output: go1.26.9 or higher.
Install examples:
- Linux: package manager (for example
sudo apt install ffmpeg) - macOS:
brew install ffmpeg - Windows: install FFmpeg and add
bintoPATH
Verify:
- Linux/macOS:
command -v ffmpeg && command -v ffprobe - Windows:
where ffmpegandwhere ffprobe
Protocol Support
mcp-beam serves two MCP revisions concurrently and picks between them per request, so hosts on either era work against the same binary.
| Revision | Selected by | Notes |
|---|---|---|
2026-07-28 |
A request carrying io.modelcontextprotocol/protocolVersion in params._meta |
Stateless; version, identity, and capabilities travel per request. |
2024-11-05 |
An initialize handshake, or any request without that _meta |
Legacy handshake, served unchanged. |
Methods:
| Method | Revision |
|---|---|
server/discover |
2026-07-28 |
initialize |
2024-11-05 |
tools/list, tools/call |
both |
For stdio, cancel an in-progress tool call with a notifications/cancelled notification whose params.requestId matches the call's JSON-RPC ID. Cancellation stops work through the call's context and suppresses its response. Malformed notifications and unknown or completed IDs are ignored. A cancellation that arrives after a response has started may still receive that response.
When stdin closes, the server allows in-progress calls two seconds to finish, then cancels outstanding work before shutdown.
Notes for 2026-07-28 clients:
- Every request must carry
io.modelcontextprotocol/protocolVersionandio.modelcontextprotocol/clientCapabilitiesinparams._meta. A missing field is-32602. - An unsupported version returns
-32022withdata.supportedlisting the versions to retry with. server/discoverandtools/listare cacheable and carryttlMsandcacheScope.- Results are always
resultType: "complete".mcp-beamnever returnsinput_required: it needs no sampling, elicitation, or roots.
The session_id returned by beam_media is the explicit handle the stateless model calls for. Sessions are process-local and do not survive a restart; see the session lifecycle defaults under Architecture for how long they are retained.
Tool Reference
list_local_hardware
Discover Chromecast and DLNA/UPnP renderers on the local network.
Arguments:
timeout_ms(optional integer, minimum100, default5000)include_unreachable(optional boolean, defaultfalse)
Example:
{
"name": "list_local_hardware",
"arguments": {
"timeout_ms": 5000,
"include_unreachable": false
}
}
On success, structuredContent includes:
countdevices[]entries:idnametypeaddressis_audio_onlyprotocol(chromecastordlna)capabilities.supports_file_sourcecapabilities.supports_url_sourcecapabilities.supports_hls_m3u8_urlcapabilities.limitations[]
inspect_torrent
Inspect the file list in a local .torrent file or magnet URI before casting. This does not start playback.
Arguments:
source(required string): absolute local.torrentpath or magnet URItimeout_ms(optional integer,1000to120000, default60000): timeout for torrent preparation and metadata retrieval
Example:
{
"name": "inspect_torrent",
"arguments": {
"source": "/absolute/path/to/movie.torrent",
"timeout_ms": 60000
}
}
On success, structuredContent contains ok and files[] for supported media files. Each file contains index (its original zero-based torrent file index), name, and size_bytes. For a torrent containing multiple supported media files, select the desired media file and pass its index as beam_media.arguments.torrent_file_index. The index can be omitted when the torrent contains exactly one supported media file.
The text content also lists each supported file's original index, quoted name, and size_bytes, so clients that read only text can select a file. An empty list reports that the torrent contains no supported media files to beam.
Magnet URIs require peers to retrieve metadata. Increase timeout_ms when retrieval is slow; this timeout applies only to inspection. beam_media gives metadata retrieval 60 seconds. Later media preparation and device startup have separate timeouts, so the full call can take longer.
beam_media
Start playback on a selected discovered device.
Arguments:
source(required string): absolute local media path,http/httpsmedia URL, absolute local.torrentpath, or magnet URItarget_device(required string): stable device ID preferred, exact name fallbacktranscode(optional string):auto(default),always,neversubtitles_path(optional string): absolute local external subtitle file path (.srt,.vtt,.ass, or.ssa); takes precedence over sidecar and embedded subtitlestorrent_file_index(optional integer, minimum0): file index frominspect_torrent; required when a torrent contains multiple supported media filessubtitle_mode(optional string):auto(default),receiver,burn, oroffembedded_subtitle_track(optional integer, minimum0): zero-based subtitle track index in a local media filestart_seconds(optional integer, minimum0): start offset from the beginning of media
Example:
{
"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
}
}
On success, structuredContent includes:
oksession_iddevice_idmedia_urltranscodingwarnings[]- optional
torrent:file_index,file_name,downloaded_bytes,total_bytes, andprogress_percentfor the selected file
Torrent example:
{
"name": "beam_media",
"arguments": {
"source": "/absolute/path/to/movie.torrent",
"torrent_file_index": 1,
"target_device": "dev_1234abcd",
"subtitle_mode": "auto"
}
}
Protocol notes:
- 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. - When
subtitles_pathis omitted for local files, mcp-beam auto-detects sidecar subtitles using the same basename in this order:.srt,.vtt,.ass, then.ssa. An explicitembedded_subtitle_trackselects that track instead of searching for sidecars. subtitle_mode=autochooses a compatible subtitle rendering path.receiversends subtitles separately to the device and cannot render embedded bitmap tracks.burnrenders subtitles into the video and implies transcoding;offdisables subtitles.embedded_subtitle_trackselects a local embedded track; an explicitsubtitles_pathtakes precedence.- Torrent metadata retrieval requires available peers and has a 60-second timeout. Media preparation and device startup can take additional time. Torrent downloads remain active during pause and seek. Session resources and private torrent cache are released on stop, replacement, expiry, or server shutdown.
get_beaming_status
Get current playback status for an active beam session.
Arguments:
target_device(optional string)session_id(optional string)- At least one of
target_deviceorsession_idis required.
Example:
{
"name": "get_beaming_status",
"arguments": {
"session_id": "sess_abcd1234"
}
}
On success, structuredContent includes:
oksession_iddevice_iddevice_nameprotocolstate- optional
position_seconds - optional
duration_seconds - optional
title - optional
content_type media_urltranscodingwarnings[]- optional
torrent: selected file index/name, downloaded bytes, total bytes, and progress percentage
play_beaming
Resume an active beam session.
Arguments:
target_device(optional string)session_id(optional string)- At least one of
target_deviceorsession_idis required.
Example:
{
"name": "play_beaming",
"arguments": {
"session_id": "sess_abcd1234"
}
}
On success, structuredContent includes:
oksession_iddevice_idstate(playing)
pause_beaming
Pause an active beam session.
Arguments:
target_device(optional string)session_id(optional string)- At least one of
target_deviceorsession_idis required.
Example:
{
"name": "pause_beaming",
"arguments": {
"session_id": "sess_abcd1234"
}
}
On success, structuredContent includes:
oksession_iddevice_idstate(paused)
stop_beaming
Stop an active beam session.
Arguments:
target_device(optional string)session_id(optional string)- At least one of
target_deviceorsession_idis required.
Example:
{
"name": "stop_beaming",
"arguments": {
"session_id": "sess_abcd1234"
}
}
On success, structuredContent includes:
okstopped_session_iddevice_idwarnings(optional cleanup warnings after playback stopped)
seek_beaming
Seek an active beam session by absolute position, percentage, from-end offset, or relative delta.
Arguments:
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 startpercent: jump to a percentage of the total duration (0to100)from_end_seconds: jump to a point measured back from the enddelta_seconds: skip relative to the current position; negative values rewindvalue(required number): the seek amount, interpreted bymode.- At least one of
target_deviceorsession_idis required.
Example:
{
"name": "seek_beaming",
"arguments": {
"session_id": "sess_abcd1234",
"mode": "from_end_seconds",
"value": 10
}
}
On success, structuredContent includes:
oksession_iddevice_idposition_secondsrequested_moderesolved_position_seconds- optional
duration_seconds
Examples:
- 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
Note:
- Duration-relative modes (
percent,from_end_seconds) require known media duration. - Start offsets, seek positions, and reported playback positions refer to the original media timeline. Transcoded playback restarts its stream at zero and adjusts receiver subtitle cues for the selected source offset.
- Transcoded HTTP/HTTPS sources reopen the original URL for each renderer request, supporting start offsets and later seeks. Native DLNA proxy requests forward byte ranges to the source.
Transcode Behavior
beam_media.arguments.transcode values:
auto(default)alwaysnever
Behavior summary:
never: do not transcode; requesting subtitle burn-in requires transcoding.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 with
alwaysfor video sources. - DLNA URL sources: direct-first then proxy fallback; transcode forced only with
alwaysfor video.
Edge cases:
- Invalid
transcodevalues return JSON-RPC-32602(invalid params). transcode=alwayswith direct Chromecast HLS (.m3u8) URLs is rejected.- If transcoding is required/requested and
ffmpegis unavailable, the call returnsFFMPEG_NOT_FOUND. subtitle_mode=burnenables transcoding withtranscode=auto; combining it withtranscode=neverreturnsTRANSCODE_REQUIRED. Receiver subtitle rendering supports text subtitles; bitmap subtitle tracks need burn-in.- Receiver rendering converts ASS/SSA captions to text and reports a warning that styling is lost. Burn-in preserves styling through FFmpeg.
- Embedded track selection is limited to local media files. For torrent playback, Chromecast can receive automatically detected progressive text subtitles from MKV/WebM; DLNA cannot automatically send embedded torrent subtitles and returns a warning recommending burn-in.
- Results include
structuredContent.transcodingandwarnings[]so callers can verify what ran.
Error Model
Input validation failures:
- JSON-RPC error
-32602(invalid params), including a2026-07-28request missing a required_metafield - JSON-RPC error
-32022(Unsupported protocol version), withdata.supportedanddata.requested
Tool failures:
isError=truestructuredContent.errorincludes:codemessage- optional
limitations[] - optional
suggested_fixes[] - optional
details
Common tool error codes:
DEVICE_NOT_FOUNDDEVICE_UNREACHABLEFILE_NOT_FOUNDFILE_NOT_READABLEUNSUPPORTED_MEDIAUNSUPPORTED_SOURCE_FOR_PROTOCOLUNSUPPORTED_URL_PATTERNTRANSCODE_REQUIREDFFMPEG_NOT_FOUNDINVALID_ARGUMENT(unsupported argument combinations or source types)TORRENT_ERRORTORRENT_METADATA_TIMEOUTTORRENT_FILE_REQUIRED(includesdetails.filesfor explicit selection)TORRENT_FILE_INVALIDSEEK_MODE_INVALIDSEEK_POSITION_INVALIDSEEK_DURATION_UNKNOWNPROTOCOL_ERRORINTERNAL_ERROR
Environment Variables
| Variable | Default | Effect |
|---|---|---|
MCP_BEAM_STRICT_PATH_POLICY |
false |
Enables strict file/subtitle path allowlist enforcement. |
MCP_BEAM_ALLOWED_PATH_PREFIXES |
empty | Comma-separated absolute prefixes allowed in strict mode. |
MCP_BEAM_ALLOW_LOOPBACK_URLS |
false |
Allows localhost/loopback URL hosts when true. |
MCP_BEAM_ALLOW_WILDCARD_BIND |
false |
Allows wildcard bind addresses when true. |
MCP_BEAM_LOG_LEVEL |
info |
Server log level: debug, info, warn, error. |
MCP_BEAM_HANDLE_SIGINT |
false |
Handles SIGINT internally when true; by default, MCP hosts control interrupt handling. |
Security
Security controls:
- Local file paths must be absolute.
- Strict path mode enforces allowlisted prefixes and rejects path escapes.
- Media URLs accept
httpandhttps; torrent sources accept local.torrentfiles and magnet URIs. - 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.
Recommended production baseline:
- Keep
MCP_BEAM_ALLOW_LOOPBACK_URLS=falseunless explicitly needed for local-only testing. - Keep
MCP_BEAM_ALLOW_WILDCARD_BIND=false. - Enable
MCP_BEAM_STRICT_PATH_POLICY=truewith explicitMCP_BEAM_ALLOWED_PATH_PREFIXES. - Run
mcp-beamunder a least-privilege OS account.
Threat boundaries:
- MCP client input is untrusted and validated strictly.
- Source URL hosts and torrent peers 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.
Architecture
MCP Host (MCP client)
|
| stdio JSON-RPC (MCP)
v
mcp-beam (single process)
- internal/mcpserver (server/discover, 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)
Runtime model:
- Single headless binary.
- MCP over
stdin/stdoutonly. - In-process session manager is the source of truth.
- One active session per target device.
Core flow:
list_local_hardware: discover, normalize, stable IDs, optional reachability filter.inspect_torrent: retrieve torrent metadata and list file indices without starting playback.beam_media: validate source, prepare a selected torrent file when requested, resolve target, choose subtitle rendering and transcoding, 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.
Session lifecycle defaults:
idle_cleanup_after = 10mpaused_cleanup_after = 90mmax_session_age = 24h- sweep interval
5s
State sources:
- Chromecast via status polling (
GetStatus) - DLNA hybrid monitoring (callbacks + polling fallback)
Troubleshooting
Quick diagnostics:
mcp-beam --version
mcp-beam --self-test
Verbose logs:
MCP_BEAM_LOG_LEVEL=debug mcp-beam
Common issues:
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. Torrent and embedded subtitle indices must be nonnegative; inspection timeout must be between1000and120000milliseconds.TORRENT_FILE_REQUIRED: inspectdetails.filesor callinspect_torrent, then pass the desired index astorrent_file_index.TORRENT_METADATA_TIMEOUT: check peer availability and network access; retryinspect_torrentwith a largertimeout_msto inspect slow magnet sources.- Bitmap subtitles in
receivermode: usesubtitle_mode=burnand ensure FFmpeg is installed.
Discovery issues:
- If no devices are returned, increase
timeout_ms. - Set
include_unreachable=truefor debugging. - Verify firewall/network discovery access.
Startup issues:
- Verify command path and executable permissions.
- On Windows, use full path to
mcp-beam.exe. - In debug logs, check for
mcp_server_start,mcp_read_wait,mcp_message_received.
Development
The Go2TV revision pinned in go.mod includes the public torrentstream, mediasource, and castsubtitles packages and synchronized DLNA control and stream APIs. Builds use the published dependency without a local Go2TV checkout. The minimum Go version is 1.26.9, matching the upstream module.
To develop against a local Go2TV checkout, use a separate Go workspace and point GOWORK at it when building. Keep temporary checkout paths out of go.mod.
Common commands:
make test
make lint
make release
make clean
README fetched from the repository 2 days ago. The original is authoritative.