obs-control-mcp
Inspects and safely controls OBS Studio over obs-websocket v5. Provides read tools for version/performance stats, scenes, inputs, filters, outputs, video settings, and timeline data; guarded write tools for switching scenes, changing filter/input settings, and starting/stopping recording; plus Source Record and IRL readiness checks, an IRL BRB auto-switcher, and a scene timeline log for correlating scene changes with VOD timestamps.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@obs-control-mcp am I ready to record with Source Record?"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
obs-control-mcp
An MCP server to inspect and safely control OBS Studio over obs-websocket v5 — built for people who let an AI assistant near the OBS they stream with.
Read everything: version and performance stats, scenes, inputs and their settings, filters with their settings, stream/recording status, output paths, video settings.
Change things only on purpose: every tool that changes OBS is a dry run unless you say otherwise, and a live guard refuses changes while OBS is streaming or recording unless you explicitly confirm.
«¿Listo para grabar?» — a readiness check for the Source Record plugin.
IRL: «¿listo para el IRL?» checks the wiring of an incoming phone/camera feed (Media Source, live and BRB scenes), and a BRB auto-switcher (NOALBS-style, with hysteresis) that runs on the command line, as a dry run until you say
--apply.Scene timeline — a JSON-lines log of which scene was on program, and when, so you can cut clips from a VOD later.
No secrets in logs or outputs — tested.
Safety design
Risk | What this server does |
A change shows up in front of your audience | Write tools default to |
The password ends up in a log | The password is read from a file (or an env var that is deleted once read). Every log line and every tool result passes through a scrubber that removes it. |
Stream keys, tokens and widget URLs leak through settings | Fields that look like credentials ( |
A redacted value is written back | Settings containing the |
You only want to look |
|
Secrets committed to this public repo |
|
Related MCP server: OBS MCP
Tools
Read (never change OBS)
Tool | What it returns |
| OBS / obs-websocket version, CPU, memory, free disk, fps, skipped frames, stream/record state, current scene, profile, scene collection, video settings, recording folder |
| Scenes top to bottom, the program (and preview) scene, the sources in each |
| Inputs and their kinds; optionally their settings (OBS defaults filled in) |
| One input's settings, which fields differ from the defaults, mute state |
| Filters of one source or of all, top to bottom, with settings |
| Stream, recording, replay buffer, virtual camera, recording folder, every output, stream service (key redacted) |
| Canvas and output resolution, fps |
| Source Record readiness verdict (see below) |
| IRL readiness verdict: live and BRB scenes, feed Media Source wiring (see below) |
| Scene timeline summary; what was live at a time or at a second of a stream |
Write (guarded: dry_run defaults to true; confirmLive=true required while live)
Tool | What it does |
| Puts a scene on program |
| Changes filter settings (Source Record included), merge or replace |
| Turns a filter on or off |
| Moves a filter in the chain (shows the order before/after) |
| Starts / stops the main recording |
| Changes input settings, merge or replace |
Source Record readiness check
check_source_record (or obs-control-mcp check on the command line) finds every
source_record_filter and checks, for each one:
the filter is enabled and its record mode (none / always / streaming / recording / streaming or recording / virtual camera), and whether it is writing a file right now;
encoder, rate control and the QP/CQP/CRF actually in use (when the filter does not set it, the encoder's OBS default), or the bitrate;
scaling and resolution, frame rate (divisor) against the canvas fps;
file names: two filters writing to the same folder with the same format collide (they start in the same second); formats without date/time codes;
output folder and container (
mp4/movare lost if OBS crashes;hybrid_mp4,mkvand fragmented formats are not);audio: own sound, another source (exists? muted?) or a mixer track; sources with no audio of their own (screen capture) give a silent file;
filter order: masks, crops and keys above Source Record are baked into the file; below it they stay out;
capture devices with «Deactivate when not showing»;
and globally: free disk (GetStats.availableDiskSpace, with an hours
estimate when bitrates are known), render fps vs canvas fps, lagged frames,
number of simultaneous encoders, and whether OBS is streaming/recording.
The verdict is ready, ready_with_warnings, not_ready or
no_source_record_filters, with a Spanish one-liner (veredicto). The command
line exits 0 / 1 / 2 accordingly (3 on connection errors).
IRL: readiness check and BRB auto-switcher
For IRL streams the phone or camera sends its feed to a relay and OBS at home
reads it with a Media Source inside a live scene; a BRB («be right
back») scene covers the dropouts. Default names, all configurable: live scene
IRL, BRB scene Ahorita regreso, feed input Señal IRL.
check_irl (MCP) / obs-control-mcp check-irl [--live S] [--brb S] [--feed I]
checks, read-only: both scenes exist and differ; the BRB scene shows
something; the feed is a Media Source (ffmpeg_source), visible in the live
scene and not in the BRB one; it reads a network input and which
protocol (the URL itself is never reported: it names the relay and, with
SRT, carries the passphrase); SRT without passphrase and plain RTMP are
flagged; the reconnect delay; «Close file when inactive» (with it on, the
Media Source is closed while BRB is on program, so the switcher could never
see the feed come back); a Source Record filter on the feed (a clean copy,
which is what clips are cut from); the stream service; render fps; free disk;
and whether the feed is playing right now. Verdict and exit codes as check.
obs-control-mcp brb watches the feed and switches between the two scenes:
obs-control-mcp brb # dry run: logs what it would do, changes nothing
obs-control-mcp brb --apply # switches for real
obs-control-mcp brb --help # every optionSignal: OBS's own media state (
GetMediaInputStatus: playing or not) and, with--stats-url http://relay:9997 --stats-path irl, the bitrate read from a mediamtx control API (bytesReceiveddeltas), so a feed that still "plays" at 200 kbps counts as bad too.Hysteresis on both sides: bad for
--downseconds (default 3) → BRB; good for--upseconds (default 5) → back; never two automatic switches within--dwellseconds (default 10); bitrate below--low(400 kbps) is bad, at or above--ok(1000 kbps) is good, in between nothing changes.It only ever moves between its two scenes. With any other scene on program it stands by. A BRB you selected by hand stays until you return (pass
--return-from-manual-brbfor NOALBS-like behaviour).--applyis the person's confirmation to act while live (that is the switcher's job); it still goes through the same guard as every write tool and is refused underOBS_READ_ONLY=1. The stats URL is treated as a secret (it may carry credentials) and never logged.
Scene timeline
When OBS_TIMELINE_FILE is set, the server subscribes to OBS events and appends
one JSON object per line:
{"t":"2026-01-01T20:02:00.000Z","type":"event","event":"CurrentProgramSceneChanged","data":{"sceneName":"Main"}}Recorded: program/preview scene changes, stream / recording / replay buffer / virtual camera state, scene item visibility (with the source name), filter and input creation, renames, enable state and settings changes (redacted), mutes. After every (re)connection it writes a snapshot of the current scene and outputs, including how long the stream has been running, so offsets stay on the stream's clock after a reconnect.
read_timeline turns it into scene segments (split where the stream/recording
starts or stops) with streamOffsetSec — seconds into the stream, which is the
VOD timestamp — time per scene, stream and recording sessions, and answers
“what was live at …” (at) or “at second N of the stream” (atStreamOffsetSec).
Only one process records a given file (a pid lock). To record without an MCP
client running, use obs-control-mcp timeline. The file grows by a few hundred
lines per stream; rotate or delete it as you see fit — nothing else reads it.
Install
Requires Node.js ≥ 22.18 and OBS 28+ (obs-websocket 5 is built in: Tools → WebSocket Server Settings).
git clone https://github.com/rjla-developer/obs-control-mcp.git
cd obs-control-mcp
npm ci && npm run buildConfiguration (environment only)
Variable | Default | |
|
| Host name or IP of the OBS machine (no scheme, no port) |
|
| |
| — | File whose first line is the password (preferred; |
| — | The password itself; removed from the environment once read |
| — | JSON-lines timeline file; enables recording and |
|
|
|
|
|
|
|
|
Claude Code
Keep the password out of the client's config: point the client at a small launcher that sets the variables, and let the server read the password file.
cat > ~/obs-control.sh <<'SH'
#!/usr/bin/env bash
export OBS_HOST=192.0.2.10 OBS_PORT=4455
export OBS_PASSWORD_FILE="$HOME/.config/obs-control/password"
export OBS_TIMELINE_FILE="$HOME/.local/share/obs-control/timeline.jsonl"
exec node /path/to/obs-control-mcp/dist/cli.js "$@"
SH
chmod 700 ~/obs-control.sh
claude mcp add obs-control -s user -- ~/obs-control.shOther MCP clients: run node dist/cli.js over stdio with the same variables.
Command line
obs-control-mcp # MCP server on stdio
obs-control-mcp check # Source Record readiness, JSON on stdout
obs-control-mcp check-irl # IRL readiness, JSON on stdout
obs-control-mcp brb # BRB auto-switcher, dry run (add --apply to switch)
obs-control-mcp timeline # only record the timeline, until Ctrl-CDevelopment
npm ci
npm run lint && npm run typecheck && npm test
npm run check-secrets # also runs as a pre-commit hook and in CITests run against a fake obs-websocket v5 server (test/fakeObs.ts) that
implements the real handshake (challenge/salt authentication) and the requests
used here. Put your own LAN address, user name or host names in a git-ignored
.forbidden-strings file (one per line) and the secret check will block them too.
License
MIT
En español
Servidor MCP para ver y controlar con cuidado OBS Studio por obs-websocket v5.
Lee todo: versión y rendimiento, escenas, fuentes y sus ajustes, filtros y sus ajustes, estado de transmisión y grabación, carpetas de salida, video.
Cambia solo a propósito: cada herramienta que cambia algo es un dry run (
dry_run=true) hasta que se pide lo contrario, y mientras OBS transmite o graba se niega a cambiar nada si no vaconfirmLive=true. Antes de confirmar en vivo, hay que preguntarle a quien transmite.«¿Listo para grabar?»:
check_source_recordrevisa cada filtro de Source Record — modo de grabación, codificador y calidad (CQP), escala, fps, nombres de archivo que chocan, carpeta y contenedor, de dónde sale el audio, si hay máscaras encima del filtro (se quedan en el archivo), cámaras con «Desactivar cuando no se muestra» y el espacio libre en disco — y da un veredicto:ready,ready_with_warningsonot_ready.IRL:
check_irlrevisa que OBS esté cableado para recibir la señal del teléfono o la cámara (escena en vivo, escena «Ahorita regreso», la Media Source con su protocolo —nunca la URL—, «cerrar cuando no se muestra», el Source Record de la señal limpia) yobs-control-mcp brbcambia solo a «Ahorita regreso» cuando la señal se cae y regresa cuando vuelve, con histéresis; sin--applysolo dice lo que haría.Línea de tiempo de escenas: con
OBS_TIMELINE_FILE, apunta en un archivo JSON-lines qué escena estaba al aire y cuándo;read_timelineresponde «¿qué se veía en el segundo 01:23:45 del directo?» para sacar clips del VOD.Ningún secreto sale del proceso: la contraseña se lee de un archivo (
OBS_PASSWORD_FILE), nunca se escribe en el log, y las claves de transmisión, tokens y URLs de widgets se muestran como[redacted]. Las pruebas corren el proceso real conDEBUG=*y fallan si aparece la contraseña o una clave.
Instalación: npm ci && npm run build, y registrar en el cliente MCP un pequeño
lanzador que ponga OBS_HOST, OBS_PORT y OBS_PASSWORD_FILE (ver arriba).
Con OBS_READ_ONLY=1 solo se registran las herramientas de lectura.
Available Tools
17 toolscheck_irlIRL: ready to go out?ARead-only
«¿Listo para el IRL?» Checks that OBS is wired for an incoming phone/camera feed: the live and BRB scenes exist, the feed is a network Media Source visible in the live scene (not in the BRB one), its URL protocol (never the URL itself), SRT passphrase, reconnect delay, «close when inactive» (would blind the BRB switcher), a Source Record filter for a clean copy, the stream service, render fps and free disk. Verdict: ready, ready_with_warnings, not_ready. Read-only.
Inputs: brbScene, feedInput, liveScene.
check_source_recordSource Record: ready to record?ARead-only
«¿Listo para grabar?» Finds every Source Record filter and checks record mode, encoder and rate control/QP, scaling, fps, file name collisions, output folder, container, audio source, filter order (masks above it get baked in), capture devices that deactivate when hidden, render fps and free disk. Returns a verdict: ready, ready_with_warnings, not_ready. Read-only.
Inputs: no named parameters.
get_input_settingsGet input settingsARead-only
Settings of one input with OBS defaults filled in, plus which fields differ from the defaults. Secret fields are redacted.
Inputs: inputName (required).
get_outputsStream and recording statusARead-only
Stream, recording, replay buffer and virtual camera status, the recording folder, every OBS output, and the stream service (server shown, key redacted).
Inputs: no named parameters.
get_overviewOBS overviewBRead-only
Version, performance stats (CPU, memory, free disk, fps, skipped frames), stream/record state, current scene, profile, scene collection, video settings and recording folder.
Inputs: no named parameters.
get_video_settingsVideo settingsBRead-only
Canvas (base) and output resolution and frame rate.
Inputs: no named parameters.
list_filtersList filtersARead-only
Filters of one source (or of every source and scene), top to bottom as in OBS, with settings (defaults filled in, secrets redacted). Filters apply top to bottom.
Inputs: kind, sourceName, includeSettings.
list_inputsList inputsARead-only
All inputs (sources) with their kind; optionally their settings with OBS defaults filled in. Secret fields are redacted.
Inputs: kind, includeSettings.
list_scenesList scenesCRead-only
Scenes in the order OBS shows them, the current program (and preview) scene, and optionally the sources in each scene.
Inputs: includeItems.
read_timelineRead the scene timelineARead-only
Summarises the scene timeline log (OBS_TIMELINE_FILE): which scene was on program and for how long, stream and recording sessions with offsets, and what was live at a given time or at a given second of a stream (e.g. a VOD timestamp).
Inputs: at, to, from, tail, +2 more.
set_filter_enabledEnable or disable a filterADestructiveIdempotent
Turns a filter on or off. Disabling a Source Record filter stops its file. Guarded: dry_run by default; needs confirmLive=true while streaming/recording.
Inputs: enabled (required), filterName (required), sourceName (required), dry_run, +1 more.
set_filter_indexMove a filterADestructiveIdempotent
Moves a filter to a position (0 = top, applied first). Shows the order before and after. Guarded: dry_run by default; needs confirmLive=true while streaming/recording.
Inputs: filterName (required), sourceName (required), filterIndex (required), dry_run, +1 more.
set_filter_settingsChange filter settingsADestructive
Changes settings of a filter (including Source Record). overlay=true (default) changes only the given fields. Shows a before/after diff. Guarded: dry_run by default; needs confirmLive=true while streaming/recording.
Inputs: settings (required), filterName (required), sourceName (required), dry_run, +2 more.
set_input_settingsChange input settingsADestructive
Changes settings of an input (source). overlay=true (default) changes only the given fields. Shows a before/after diff. Guarded: dry_run by default; needs confirmLive=true while streaming/recording.
Inputs: settings (required), inputName (required), dry_run, overlay, +1 more.
start_recordStart recordingADestructive
Starts the main OBS recording (Source Record filters in «recording» mode start with it). Guarded: dry_run by default; needs confirmLive=true while streaming.
Inputs: dry_run, confirmLive.
stop_recordStop recordingADestructive
Stops the main OBS recording and returns the file path. Always needs confirmLive=true (it only acts while recording). dry_run by default.
Inputs: dry_run, confirmLive.
switch_sceneSwitch program sceneADestructiveIdempotent
Puts a scene on program (what viewers see). Guarded: dry_run by default; needs confirmLive=true while streaming/recording.
Inputs: sceneName (required), dry_run, confirmLive.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 17 tools
Most tools target clearly distinct resources and actions, but there is some overlap between get_overview, get_outputs, and get_video_settings, all of which expose stream/record status or video settings. get_input_settings and list_inputs can also both return input settings, though the descriptions clarify the distinction.
Tool names consistently use snake_case verb_noun patterns: get_*, list_*, check_*, read_*, switch_*, set_*, start_*, and stop_*. The convention is predictable and readable throughout.
17 tools is slightly above the ideal 3-15 range, but OBS control is a broad domain involving inputs, filters, scenes, outputs, recording, and readiness checks. Each tool has a plausible role, though a few read tools could potentially be consolidated.
The server covers many read, check, and setting-modification operations, including recording start/stop and scene switching. However, notable gaps remain: there is no start_stream or stop_stream despite stream-related checks, and there are no tools to add or remove scenes, inputs, or filters, limiting full lifecycle control.
Related MCP Connectors
Query your Twitch streams, events, supporters, raids & rankings from an AI assistant via OAuth.
Connect any AI to your Foundry VTT world: actors, combat, dice, journals, tokens, compendiums.
Multistream relay control: check live status, switch destinations, manage teams, generate overlays.
Connect AI assistants to your approved computer for files, commands, browser and desktop tasks.
Related MCP Servers
- AlicenseAqualityBmaintenanceAI-driven AR lens orchestrator for live OBS streams that enables control of Streamfog face filters, AR effects, and Vtuber avatars through MCP tools via the local Streamer.bot WebSocket bridge.52MIT
- AlicenseBqualityBmaintenanceAI-powered stream and recording control for OBS Studio through the Model Context Protocol10028Apache 2.0
- AlicenseBqualityDmaintenanceEnables AI assistants to control and automate OBS Studio via natural language, covering scenes, sources, audio, recording, streaming, transitions, filters, media playback, diagnostics, and multi-step workflows over the OBS WebSocket protocol.89MIT
- AlicenseBqualityBmaintenanceEnables MCP clients to control OBS Studio through an inspectable WebSocket interface. Provides 155 tools for managing scenes, sources, audio, transitions, filters, recording, and streaming through natural language.155598 npm4MIT