Skip to main content
Glama

OBS MCP

CI

OBS MCP helps agents and operators inspect OBS Studio, plan scene changes, and supervise recordings. Preview a change before taking it to program, watch a bounded take as it records, and retain operation receipts when a command's outcome needs review.

Start with obs-observe, resolve a layout with obs-plan-scene-template, then stage and inspect the preview before calling obs-take-scene. The observation tool and obs://status resource share their consistency checks and missing-evidence contract. See production workflows and Linux support for examples, platform boundaries, and verification limits.

The server uses MCP 2026-07-28 and accepts legacy 2025-era clients. Tool discovery remains available while OBS is closed.

Native runtime and qualification

The executable runs the retained Rust service directly over stdio or loopback HTTP. The native MCPB layout contains no Node runtime, JavaScript SDK or TypeScript server payload. TypeScript remains a development oracle.

Production is the default immutable profile and exposes up to 165 ordinary tools with approved host/media adapters. Advanced exposes 163 and excludes guarded Take, media, Stage and recovery owners. Their union contains 179 ordinary names; stdio dynamic mode can add three group controllers. Filters, read-only mode and available adapters narrow discovery. See native profiles.

Core checkpoint d3bb516 (PRs #26 and #27) passed ten CI jobs. Its physical-Mac qualification passed 736 Source unit cases, 21 Source transport cases, 1,050 default-feature Rust cases, 214 all-feature bin/library cases, four resolver process contracts, seven component checks and 1,016 public cases with no skips. The public suite includes 17 actual HTTP-entry and 58 TCP cases. These suites overlap; their counts are not a unique-test total.

The matching extracted Mac MCPB passed three package checks and the bounded OBS 32.2.2 fixture journey. Its 2.837-second silent A/B clip passed strict decoding, sampled content and exact presented-frame cadence checks. Conflict-preserving recovery, manual Restore and an offline snapshot restart passed; the original, restored and final state snapshots were byte-identical and all owned helpers closed. The fractional-FPS export correction is merged.

A separate tester ran focused cadence, HTTP, raw stdio and method-header checks on the exact Linux main executable. That VM had no Source oracle or package qualification; Linux CI has separate results. Real XComposite capture remains unqualified because the software display lacks EGL_KHR_image_pixmap; an XShm whole-display control does not establish exact-window capture.

Default TLS remains off. The opt-in TLS evaluation passed seven optimized/extracted Mac read-only WSS cases against actual OBS through an owned proxy, including DNS/IP custom-CA TLS1.2/1.3 and early trust refusals. Its qualification is separate from the core checkpoint and does not establish general production TLS admission. Cutover status binds both compositions to exact artifacts and limits; native distribution gives normal setup and the explicit evaluation pack command. Each delivered archive needs its own source and artifact binding; installed-client activation remains separate.

Related MCP server: obs-mcp-server

How it works

MCP clients  <-- stdio or loopback HTTP -->  Rust OBS MCP  <-- WebSocket v5 -->  OBS Studio

OBS MCP runs as a separate MCP server process using the native executable. It does not patch OBS or require an OBS plugin; it uses the WebSocket server built into OBS Studio. MCP handles tool discovery, schemas, results, and approval hints. OBS WebSocket handles the live application state.

What is covered

The 179-name ordinary catalog spans both profiles; it is not a promise of 179 simultaneous tools in one process.

  • Descriptions for all 147 request types in the pinned OBS WebSocket protocol; profile policy controls dispatch

  • Explicit read-only, destructive, idempotent, and open-world annotations on every tool

  • Runtime capability checks against the requests advertised by the connected OBS instance

  • Structured MCP results for automation, with readable text retained for people and older clients

  • Source screenshots returned as MCP image content instead of clipped base64 text

  • Protocol inspection through obs-describe-request

  • Advanced-profile raw, batch, vendor and hotkey tools with explicit policy and durable guarded-reentry barriers

  • A host-specific .mcpb built from checked native assets and corresponding Rust source, with profile-conditional inventory

Use the explicit tools for normal workflows. Advanced raw tools accept the bundled request names and retain destructive/open-world policy even when a wrapped request is a read. They do not borrow Production Take, Stop, file or recovery authority.

Requirements

  • A qualified native executable for your host (or the pinned Rust toolchain to build it)

  • An existing approved private state directory; optional recording root and trusted FFmpeg/ffprobe for local media workflows

  • OBS Studio 28 or newer with the WebSocket server enabled

  • An MCP client that supports MCP 2026-07-28 or the compatible legacy protocol

OBS includes WebSocket v5. Enable it under Tools > WebSocket Server Settings. Newer OBS requests are available only when the connected version advertises them; unsupported calls return a descriptive error.

Install from source

Build the runtime directly from its checked native inputs; Node and a TypeScript build are unnecessary:

cd native
RUSTUP_AUTO_INSTALL=0 cargo build --locked --offline --release --bin obs-mcp-native

The pinned toolchain and Cargo sources must already be available. A missing cache is an explicit prerequisite, not permission for an automatic fetch. Create and approve a safe state directory inside your chosen project, then configure the absolute native executable and OBS_MCP_STATE_DIR in your MCP client. Native distribution gives the complete setup, optional recording/media paths and immutable profile behavior. No home directory is initialized or history erased as part of source qualification.

Verify the connection

Open OBS, start a new agent session, and ask:

Check the OBS connection. Report the OBS version, current scene, stream status, and recording status. Do not change anything.

The client should request only read-only tools and return live values from OBS. If discovery works while OBS is closed, start OBS and request the read-only connection check again. Native operation history never authorizes automatic mutation replay; a lost owned session may require a fresh MCP process while retained unknown effects remain refused.

Install the MCPB package

With the explicit development archive tools installed, node scripts/pack.mjs builds dist/obs-studio-native.mcpb for the build host. It compiles from checked native assets, keeps corresponding Rust source/configuration and notices, and uses no staging dependency install or Source server build. Node/MCPB CLI are development packaging tools; the installed extension contains no Node, JavaScript SDK or server payload.

The MCPB setup requires an existing approved private state directory and exposes profile and optional recording/media paths. Discovery works while OBS is offline after valid local startup. The 2 November macOS candidate passed extraction and a bounded live journey; a changed artifact or another platform needs its own checks. Package contents alone prove neither production TLS nor Linux desktop support. See native distribution.

Configuration

Variable

Required

Default

Purpose

OBS_WEBSOCKET_URL

No

ws://localhost:4455

Address of the OBS WebSocket server

OBS_WEBSOCKET_PASSWORD

Only when OBS authentication is enabled

None

Password configured in OBS

OBS_MCP_READ_OBS_CONFIG

No

false

When OBS_WEBSOCKET_PASSWORD is unset, read the password OBS saved in its own obs-websocket/config.json. Only for a server on the same machine and user account as OBS

OBS_MCP_MAX_SCREENSHOT_BYTES

No

4194304

Maximum decoded size of a screenshot returned through MCP; the hard ceiling is 6 MiB

OBS_MCP_TOOLSETS

No

all tools

Comma-separated tool groups to register: all, core, or any group listed under Choosing tools

OBS_MCP_TOOLS

No

none

Comma-separated tool names to register in addition to OBS_MCP_TOOLSETS

OBS_MCP_READ_ONLY

No

false

Register only read-only tools; overrides both lists

OBS_MCP_DYNAMIC_TOOLSETS

No

false

Start with only the OBS_MCP_TOOLSETS groups (default general) and let the model turn others on and off (see Choosing tools)

OBS_MCP_CONFIRM_LIVE

No

false

Ask before starting a stream/output or stopping or toggling a stream, recording, or output (see Confirming live actions)

OBS_MCP_HTTP_PORT

No

none (stdio)

Serve MCP over Streamable HTTP at http://127.0.0.1:<port>/mcp instead of stdio, so several agents share one server (see Sharing one server); 0 picks a free port

OBS_MCP_HTTP_TOKEN

No

none

With OBS_MCP_HTTP_PORT, require Authorization: Bearer <token> on every request

OBS_MCP_STATE_DIR

An existing approved namespace is required

Prefer an explicit canonical path

Endpoint-bound snapshots, recovery journals and receipts; startup does not create an unsolicited namespace or clear history

OBS_MCP_NATIVE_PROFILE

No

production

Immutable production or advanced capability profile

OBS_MCP_NATIVE_RECORDING_ROOT

For Production recording/file workflows

None

Existing approved recording directory; does not grant recording or file authority

OBS_MCP_NATIVE_FFMPEG / OBS_MCP_NATIVE_FFPROBE

For media workflows

Trusted executable on PATH

Explicit existing media-tool bindings; the package installs neither

OBS_MCP_TLS_CA_FILE

TLS evaluation build

None

Optional absolute safe certificate-only PEM file adding process-local trust anchors; requires the feature-on evaluation build

Passwords and HTTP tokens are not printed. Stdio reserves stdout for MCP; HTTP keeps it empty and announces its loopback endpoint on stderr. Default builds refuse encrypted wss: OBS endpoints before connection. Conditional macOS Network.framework and Linux GnuTLS backends remain behind platform-tls-evaluation; see transport status.

Tool surface

The profile-conditional tool catalog covers:

  • server status, version information, statistics, hotkeys, and studio mode

  • scenes, groups, sources, filters, and scene items

  • input settings, audio tracks, volume, mute state, media controls, and deinterlacing

  • recording, streaming, replay buffer, virtual camera, and output settings

  • transitions, transition overrides, the transition cursor, and the T-Bar

  • canvases, screenshots, profiles, scene collections, and persistent data

  • a recording preflight (obs-preflight) that catches the conditions under which OBS silently refuses or botches a recording

  • obs-audit-scene, which inspects one selected scene for missing or hidden required items, incomplete observations, and structural problems without changing OBS

  • obs-record-clip, which preflights, records up to 50 seconds with chapter markers, stops, and checks the file's length and audio with ffprobe/ffmpeg when they are installed. While it records, it watches the take (see Watching a take)

  • obs-take-start, obs-take-mark, obs-take-status, and obs-take-stop for watched recordings, with chapters and duration policy (see Watching a take)

  • obs-trim-take, which cuts dead time out of a recording, and obs-contact-sheet, which tiles frames from it into one image (see Trimming a take)

  • obs-apply-scene, which takes a description of a scene and makes OBS match it (see Describing a scene)

  • obs-snapshot and obs-restore, which save the state of inputs and scene items and later undo changes to them (see Undoing changes)

  • obs-capture-window, which plans or selects macOS or Linux X11 windows from an existing capture inventory, or fits an existing user-authorized Wayland portal capture

  • input and transform changes that return the resulting settings, size, and an optional screenshot, warning when a source renders at 0×0

  • protocol description and Advanced raw/batch tools, which send several requests in one message, in order or one per rendered frame (so a change to two sources lands on the same frame), with Sleep between them. OBS's parallel mode is not offered: in obs-websocket 5.7, concurrent parallel batches deadlock its WebSocket server until OBS restarts

Tools that send a single OBS request declare an outputSchema generated from the pinned protocol, so clients receive typed structuredContent with the documented response fields. Fields are optional and nullable because OBS omits newer fields in older versions and returns undocumented nulls.

Tool discovery works without an OBS connection. Calls that need OBS return an MCP error until the WebSocket connection is ready.

Choosing tools

Every available tool in the selected profile is registered by default. Clients load these definitions into the model's context, so a smaller set is cheaper and easier to choose from. Filters cannot enable a tool excluded by its profile or missing adapter.

Group

Covers

general

status, version, statistics, hotkeys, vendor requests, custom events, sleep, control of a shared server

scenes

scenes, canvases, program and preview scene, obs-apply-scene, obs-audit-scene

scene-items

scene items, groups, transforms, ordering, locking, blend modes, obs-snapshot, and obs-restore

sources

source screenshots and active state

inputs

inputs, input settings and properties, audio, deinterlacing, and obs-capture-window

media

media input playback

filters

source filters

transitions

transitions, overrides, the T-Bar

record

recording, chapters, obs-preflight, obs-record-clip, the obs-take-* tools, obs-trim-take, and obs-contact-sheet

stream

streaming and captions

outputs

virtual camera, replay buffer, and generic outputs

config

profiles, scene collections, video settings, persistent data

ui

studio mode, dialogs, projectors

protocol

obs-describe-request, the generic obs-call-request, and obs-batch

core expands to general, scenes, scene-items, sources, inputs, and record. Add OBS_MCP_READ_ONLY=true for inspection-only discovery. Counts depend on profile and adapters. Unknown groups or names refuse at startup.

With OBS_MCP_DYNAMIC_TOOLSETS=true, every group is registered but only the groups in OBS_MCP_TOOLSETS (by default just general) and the tools in OBS_MCP_TOOLS start enabled. Three more tools manage the rest: obs-list-toolsets shows each group and how many of its tools are on, and obs-enable-toolset and obs-disable-toolset switch groups for the session. Each change sends notifications/tools/list_changed, so clients that support it (Claude Code, VS Code, Cursor) reload the list. Read-only mode still applies: enabling a group adds only its read-only tools.

Resources and prompts

Resources give clients that support them a live view without tool calls. Each one duplicates a read-only tool, since many clients read resources rarely or not at all.

URI

Contents

Updated on

obs://status

connection, recording, streaming, program scene

output and scene changes

obs://scenes

GetSceneList

scenes added, removed, renamed, or switched

obs://scene/{sceneName}/items

GetSceneItemList

items added, removed, reordered, shown, hidden, locked

obs://scene/{sceneName}/screenshot

960px JPEG of the scene

(read on demand)

obs://take/current

the running take: audio levels, skipped frames, black or unchanging picture, chapters, warnings

a warning or chapter

Legacy stdio clients receive updates for subscribed URIs; modern clients choose updates on their subscriptions/listen stream. Legacy HTTP requests do not retain initialize offers or subscription state as authority for later exchanges.

Three prompts appear as slash commands in clients that show MCP prompts: record-demo (capture a window silently, preflight, record a clip), software-demo (the bounded demo recipe below), and pre-stream-check (a read-only go/no-go review).

Confirming live actions

With OBS_MCP_CONFIRM_LIVE=true, obs-start-stream, generic StartStream/StartOutput requests, obs-stop-stream, obs-toggle-stream, obs-stop-record, obs-toggle-record, obs-take-stop, obs-stop-output, and obs-toggle-output ask before they run, as do obs-call-request and obs-batch when they carry one of those requests. The generic output tools are included because the stream and the recording are outputs too. Clients that support elicitation (Claude Code, VS Code, Cursor) show the user a confirmation, and confirm: true from the model does not skip it. Other clients get an error asking the model to get the user's agreement and call again with confirm: true. These tools are also marked destructive, so clients that ask before destructive tools already prompt without this setting.

Confirmation never enables a profile-excluded tool or bypasses a durable barrier. Native grants are single-use and bound to the caller and original request; re-enabling a hidden tool cannot revive a consumed grant.

Where it fits

OBS MCP is well suited to operational work that already has a clear outcome: inspecting a scene collection, creating or arranging sources, changing audio state, switching scenes, taking screenshots, checking output status, or carrying out a repeatable recording setup.

It does not replace visual or editorial judgment. Framing, color, transition timing, audio balance, and the decision to go live still need a person watching and listening to the result.

Safety and approvals

Every tool publishes all four MCP behavior hints. Read-only inspection is separated from state changes, and actions with broader consequences are marked destructive or open-world as appropriate.

Get explicit user permission before capture, recording, streaming, file publication or destructive changes. Keep qualification bounded to an approved collection and fixture. Tool hints and a successful preflight are not permission. Pay particular attention to tools that:

  • start or stop streaming, recording, virtual camera, replay buffer, or another output

  • switch profiles or scene collections

  • trigger hotkeys or interact with OBS UI elements

  • invoke vendor requests

  • save files or use Advanced obs-call-request

In Advanced, obs-call-request and obs-batch accept only request types in the bundled OBS protocol, but their payloads are intentionally generic. With OBS_MCP_CONFIRM_LIVE=true, they ask before sending StartStream, StartOutput, StopStream, ToggleStream, StopRecord, ToggleRecord, StopOutput, or ToggleOutput. Both are always advertised as destructive and open-world so a client does not silently treat an unfamiliar operation as safe.

Watching a take

obs-record-clip records up to 50 seconds in one call. For anything longer, or a demo whose steps happen while it records, use a take:

  1. obs-take-start runs the preflight, starts recording, and waits for OBS to confirm. Only one take runs at a time.

  2. obs-take-mark adds a named chapter before each step, both in the file (Hybrid MP4/MOV) and in the take log.

  3. obs-take-status reports what the take has seen so far.

  4. obs-take-stop stops recording, checks the file, and reports.

While a locked take records, profile, collection and output-setting changes refuse. Use the owned Take Stop for that recording. Explicit Stop admission is separately bounded; unavailable storage or uncertain ownership can still refuse it. lock: false changes the take lock, not immutable profile rules or durable barriers. Advanced raw/batch tools cannot be used to bypass those rules in a guarded Production process.

While a take records, the server watches OBS instead of waiting for the file:

  • Audio: it subscribes to OBS's InputVolumeMeters events for the length of the take and records each input's loudest level after volume and mute. An input on a recorded track that rises above −60 dBFS is logged, and with expectSilent it is a problem. Muted inputs and inputs on unrecorded tracks are not.

  • Frames: it polls GetStats every 2 seconds and warns when OBS misses frames rendering or the encoder skips them.

  • Picture: once a second it takes a 96-pixel-wide PPM screenshot of the program scene. Two black samples in a row raise a warning (a capture that lost its window or permission looks like this). Stretches of 3 seconds or more where the picture holds still are recorded as stills, which mark dead time to trim. A spinner or a shimmering "thinking" label counts as still; text that appears and stays does not (see below).

The result lists the findings, and when OBS records to this machine the server writes them next to the recording as <name>.take.json, with chapter times and OBS events (scene switches, mutes, output state) in seconds from the start. obs://take/current shows the same data while the take runs.

Bounded software demos

The software-demo MCP prompt and obs-demo agent skill use the version 1 recipe. The skill remains in the development checkout and native MCPB source bundle. Open this checkout in your agent host and explicitly load the linked skill, or request the software-demo prompt through MCP. Merely installing an MCPB does not install a skill into every host. Automatic host discovery and real rendered OBS output have not been qualified by the hermetic checks.

V1 uses local OBS on macOS or Linux, an existing current scene, and one enabled, preconfigured window capture. Linux supports XComposite on X11 and an existing portal-authorized PipeWire capture on Wayland. A portal selection still needs visual inspection for window identity. Video-only Linux capture sources have no mute or audio tracks to change; preflight checks the complete recording audio path. The capture must appear exactly once in a collection without groups or nested scenes. The tools require stable OBS object identifiers and complete state; they refuse unsupported setups rather than create or retarget sources. Streaming, recording, virtual camera, replay buffer, and every listed generic output must be inactive during preparation and recovery. Missing or failed output status blocks the operation. OBS code 604 explicitly reporting an unavailable virtual camera or replay buffer is accepted as an unavailable feature; named output statuses must still establish inactivity.

  1. Plan with obs-prepare-demo and exact sceneCollection, sceneName, and inputName. After authorization, repeat with apply: true. It mutes the capture, clears its audio tracks, fits it to the canvas, and returns an operationId when changes require recovery.

  2. Inspect a screenshot for the intended window and framing. Run silent preflight and require every check named in the recipe to pass. A required unknown or missing check blocks this workflow.

  3. Start a take with maxDurationSeconds (120 by default in the prompt, at most 3600), mark steps, and stop it when finished. The server attempts to stop its own take at the deadline and retains the result for obs-take-stop to read. The deadline requires a running server; process death and sleep prevent an unattended cleanup guarantee.

  4. Inspect the final file and contact sheet. Chapters may be in the .take.json sidecar. After trimming, verify the exported copy and its remapped chapters. Use the local verifier below to bind measurements to the delivered file hash.

  5. Plan obs-recover-demo with the retained operationId; apply recovery when requested. It restores only the preparation's changed fields after checking collection/object identity and expected values. A conflict stops recovery. It does not lock OBS's UI or other processes; incomplete recovery needs operator inspection. Existing obs-restore remains a manual tool for legacy snapshots.

node scripts/verify-demo.mjs --file /path/demo.mp4 --reference /path/expected.png --seconds 30 --chapter Intro --checkpoint 10=/path/step-two.png --report /path/demo.verification.json

The verifier uses local ffmpeg and ffprobe; it never contacts OBS. It reports strict full-file decoding separately from metadata and sampled pictures. A decode timeout is unavailable evidence. It checks duration within 2 seconds, a video stream, every audio track at or below -60 dB, requested chapters, and reference frames scaled to 160×90 grayscale (mean absolute error at most 12). These frame comparisons test selected checkpoints, not semantic recognition or every frame. Use reference images from the intended scene. Missing tools or evidence produce unavailable; failed requirements produce fail. The report must be a new file. Synthetic-media tests cover the verifier; a real recording still needs visual review.

Trimming a take

obs-trim-take finds dead time: stretches where the picture holds still (and, if the recording has sound, where it is also silent). It samples the video twice a second at 96 pixels wide and looks for steps: pixels whose median over the three samples before a moment differs from their median over the three after it. Text that appears and stays is a step. A spinner, a shimmering "thinking" label, or a blinking cursor comes and goes, so waiting on one still counts as dead time. On a 1080p ChatGPT recording, this separated waiting from streaming answers where ffmpeg's freezedetect could not with any single noise threshold.

By default, a still stretch of 4 seconds or more loses its middle, keeping 1 second at each side. Nothing is cut from 3 seconds before to 1.5 seconds after each chapter start, or in the last 3 seconds, so each step's finished result stays on screen long enough to read. Chapters come from the file, or from the take log when the file has none, and are moved to their new times.

Without apply: true it returns only the plan: the cuts, the new length, and the new chapter times. With it, the tool validates a staged copy before publishing <name>.trimmed.mp4 next to the original. Validation checks the planned duration, video dimensions, audio stream count, remapped chapters, and strict full-file decoding. Publication refuses an existing destination. Cancellation before publication discards the staged copy; after publication, optional contact-sheet failure retains the output path and SHA-256 in the result.

Exports retain the first audio track and use H.264 with yuv420p. Other audio tracks are omitted; choose a separate workflow when they must remain independent. High bit depth and explicitly tagged PQ/HLG HDR inputs are refused; no implicit tone mapping occurs. Missing color tags remain unknown, so a successful export does not establish color fidelity. The contact sheet shows frames on either side of each seam for review.

obs-contact-sheet tiles frames from a recording into one JPEG: one second after each chapter start by default, or at the times you give. Both tools work only on files inside OBS's recording directory, and need ffmpeg and ffprobe on PATH.

Auditing a scene

obs-audit-scene reads one scene in the current collection without changing OBS. The selected scene can be off program. It is available in the scenes group and in read-only mode:

{
  "sceneCollection": "Demo collection",
  "sceneName": "Demo",
  "requiredItems": [{ "sourceName": "Application" }],
  "includeScreenshot": false
}

For a secondary canvas, add canvasUuid from obs-get-canvas-list. The audit uses that canvas for scene discovery, item and group reads, transform rereads, and the optional screenshot. Omitting it keeps OBS's default-canvas behavior. The report includes the supplied canvas UUID in its target.

The report lists individual source occurrences with their container, source UUID, scene-item ID, and containment path. A required source that is missing or hidden fails its check. Repeated occurrences need a more specific selector: add sourceUuid, containerUuid, or sceneItemId to the required item. Ambiguous selectors remain unknown.

Checks report pass, fail, or unknown, with observation times and evidence. Missing fields, unreadable state, cycles, traversal limits, unsupported geometry, or detected changes during collection make the affected evidence unknown. Nested scene and group membership can be inspected, but composed geometry is not qualified. The report covers a sampling interval; it is not an atomic snapshot or a promise that OBS will stay unchanged.

Zero-size media sources remain unknown: a filename extension does not prove that a file has no video. Inputs whose source kind establishes audio-only capture are exempt from visual dimension checks.

Set includeScreenshot: true to request a bounded scene image for inspection. An unavailable image is reported as unknown. The tool does not save screenshots or reports to disk. A structural pass leaves renderedContent as unverified: it does not establish the intended capture content, readability, freedom from occlusion, audio policy, or readiness to record. Continue to use the recording preflight and inspect the rendered picture separately.

Describing a scene

obs-apply-scene takes the scene you want instead of the steps to build it:

{
  "sceneName": "Review",
  "sources": [
    { "name": "Background", "kind": "color_source_v3", "settings": { "color": 4278190080 }, "locked": true },
    { "name": "ChatGPT Window", "kind": "screen_capture", "settings": { "type": 1 }, "muted": true, "audioTracks": [], "fit": "canvas" }
  ],
  "order": true,
  "apply": true
}

Sources are listed back to front. The tool reuses existing inputs (including ones shown in other scenes), creates missing scenes, inputs, and items, and changes only the settings, visibility, lock, mute, volume, audio tracks, transforms, and order that differ. fit: "canvas" scales a source to fit the canvas, centered. removeOthers: true removes unlisted items from the scene; their inputs remain.

Without apply: true it returns the plan. When applying, it creates what is missing in one request batch, then plans again with the new items' IDs and makes the remaining changes in a second. It then plans a third time to confirm OBS matches, and warns about any listed source that renders at 0×0. For an existing scene it first saves a snapshot, so obs-restore can undo the changes to existing sources.

Undoing changes

obs-snapshot saves the settings, mute, volume, and audio tracks of inputs, and the transform, visibility, lock, and order of scene items: by default the program scene and the inputs in it. obs-restore compares OBS with a snapshot and sends only what differs, in one request batch; dryRun: true lists the changes first. It cannot recreate a removed input or item, and leaves items added since in place; it reports both. obs-capture-window takes a snapshot automatically before it changes an existing capture.

Snapshots are saved in the server's state directory (the last 20 you take, plus the last 10 taken automatically before a change, readable only by you), so obs-restore works after a restart and from another agent's session. Each server lists only the snapshots of the OBS instance it connects to. They contain input settings, such as file paths and browser source URLs. OBS's own scene collection file is not a substitute: OBS rewrites it while running.

Sharing one server

By default, each stdio client starts its own server and OBS owner. To share one retained service, start the native executable in HTTP mode:

OBS_MCP_STATE_DIR=/absolute/canonical/approved-state \
OBS_MCP_HTTP_PORT=8765 \
native/target/release/obs-mcp-native
# Point each MCP client at http://127.0.0.1:8765/mcp?client=its-name

The server binds only to 127.0.0.1 and checks Host and Origin headers. Set an opaque OBS_MCP_HTTP_TOKEN through approved secret configuration to require bearer authentication; without it, local programs can reach the server. HTTP uses static tool groups and ignores OBS_MCP_DYNAMIC_TOOLSETS.

The port accepts trimmed decimal digits from 0 through 65535, including leading zeros. 0 chooses a free port. An absent, empty or JavaScript-whitespace-only value selects stdio; signed, fractional, exponent and hexadecimal forms refuse. HTTP ignores stdin EOF and joins its service and drivers on SIGINT or SIGTERM. Closing one client does not shut down peer work or a Take.

While agents share a server, obs-claim-control gives one of them control of OBS for a set time (30 minutes by default). Until it calls obs-release-control or the time runs out, tools that change OBS refuse calls from other clients. Read-only inspection and explicitly admitted Stop routes retain their own policy and capacity limits. obs-control-status shows who holds control. obs-take-start claims control for the length of the take. Clients are told apart by name: the client parameter of the URL they connect with, or else the name a 2026-07-28 client sends with each request. Clients using the 2025 protocol over HTTP send each request without a name, so give each agent its own ?client= name. An unnamed client cannot claim control and is refused while another client holds it. Two agents given the same name share control. The names are not credentials; control is for agents cooperating on one machine, not for keeping out someone who can reach the server.

Troubleshooting

Tools appear, but OBS calls fail: make sure OBS is open and its WebSocket server is enabled. Discovery is local; the shared OBS connection starts lazily. A failed or lost owned session can require a fresh MCP process. Keep its receipts and do not replay an uncertain mutation.

Authentication fails: copy the password from Tools > WebSocket Server Settings into OBS_WEBSOCKET_PASSWORD, then restart the MCP server process. When the server runs on the same machine as OBS, OBS_MCP_READ_OBS_CONFIG=true reads the saved password instead, so it never has to be copied into an agent's configuration. The server logs which file it used, never the password.

The agent cannot see the tools: restart the agent session or the MCP host so it creates a fresh stdio connection and reloads the tool list.

A request is unsupported: the connected OBS build did not advertise that WebSocket request. Use an operation supported by that version or update OBS.

The process exits or emits protocol errors: inspect stderr. stdio stdout is reserved for MCP traffic; HTTP stdout stays empty. Keep ordinary logs on stderr.

Verified replay files use obs-save-replay-verified; see verification and naming limits. Multitrack trim preserves qualified tracks independently; see the workflow matrix.

Development

After approving the project-scoped dependency fetch, install the pinned development tooling and run the native gate:

npm ci --ignore-scripts --no-audit
npm run native:check

The gate uses the checked Rust toolchain/assets and explicit TypeScript/SDK oracles. It runs default and all-feature Rust checks, path-crate and resolver lifetime controls, then both MCP eras, actual HTTP entry and TCP controls against a pinned optimized executable and fake OBS. License and migration checks also run. This command does not record live OBS. npm run check remains the development Source-oracle gate; Node tooling is not part of the native runtime.

Test the file users will actually install with:

npm run test:package

That command builds the host-specific dist/obs-studio-native.mcpb, extracts it, and checks its manifest, corresponding source and native entry. Verify profile-conditional inventories rather than treating the 179-name union as one runtime. The recorded macOS artifact passed all three package checks; later artifacts and other platforms need their own receipts.

Live OBS tests

The development live suite is separate from CI and native release acceptance. It exercises the explicit Source oracle; the extracted native Mac journey recorded above has its own receipts. Changed executables, other platforms and additional live workflows need the relevant authorized checks. By default this development suite is skipped. With OBS open and the standard WebSocket environment variables already available to the process, run the read-only checks with:

OBS_MCP_LIVE_TEST=1 npm run test:obs-live

The read-only lane checks the OBS version, scenes, active scene collection, streaming state, recording state, resources, and read-only request batches through the compiled MCP stdio server. On the machine running OBS, add OBS_MCP_READ_OBS_CONFIG=1 instead of exporting the password.

There is also a narrowly bounded mutation test. Use a disposable scene collection, select it in OBS first, and make sure streaming and recording are stopped. Then run:

OBS_MCP_LIVE_TEST=1 \
OBS_MCP_LIVE_MUTATION=1 \
OBS_MCP_LIVE_SCENE_COLLECTION="OBS MCP Test" \
npm run test:obs-live

The suite refuses to mutate if the selected collection does not exactly match OBS_MCP_LIVE_SCENE_COLLECTION or if either output is active. It creates one uniquely named scene and removes it in a finally block.

Add OBS_MCP_LIVE_RECORD=1 to the mutation command to also record a one-second clip. It checks that obs-start-record reports success only after OBS confirms the output is active, then stops the recording in a finally block. The clip is saved to the profile's recording directory and captures whatever the selected collection shows, so select a collection whose sources are safe to record.

Scenario tests

Scenario tests build a real use case through MCP tools, record it, and check the file with ffmpeg and ffprobe instead of trusting what OBS reports. They need both tools on PATH, a disposable scene collection, and stopped outputs. The first scenario checks multi-track recording for editing: two tones stand in for a microphone and a game on tracks 2 and 3, and a flash-and-beep clip on track 1 measures audio/video sync. It fails if a track carries the wrong source or if any flash and its beep are more than 100 ms apart. The pulses are unevenly spaced, so a beep matched to the wrong flash shows up as an error. Correcting sync with an audio sync offset is not covered yet: on OBS 32.2.2, changing the offset on a playing media source did not move the recorded audio by the requested amount.

Set the profile used with the disposable collection to record audio tracks 1, 2 and 3 (Settings > Output > Recording), restart OBS, then run:

OBS_MCP_LIVE_TEST=1 \
OBS_MCP_LIVE_SCENARIOS=1 \
OBS_MCP_LIVE_SCENE_COLLECTION="OBS MCP Test" \
npm run test:obs-live -- test/live/obs-scenarios.test.ts

While it runs, the test mutes every other audio input, points the recording directory at a temporary folder, and switches the program scene to its own scene. Afterwards it puts all three back and removes its scene and inputs. OBS_MCP_LIVE_SERVER=native runs the same scenario against native/target/release/obs-mcp-native (or OBS_MCP_LIVE_NATIVE_BIN) in the Advanced profile, with a temporary OBS_MCP_STATE_DIR so its operation receipts never reach a real state namespace. The signal checks have hermetic tests in test/unit/media-analysis.test.ts.

Persona tests

Six personas each pursue their goals end to end against a real OBS, through native/target/release/obs-mcp-native (or OBS_MCP_LIVE_NATIVE_BIN) in the Production profile:

  • a streamer with overlays

  • a vlogger editing in Resolve

  • a consultant using the virtual camera

  • a competitive gamer saving replays

  • a lecturer switching layouts

  • a founder recording a product demo

Each check reads what OBS produced: a recording, a replay, what a local RTMP server received, or a screenshot.

Profile setup. Use a disposable collection with a 1920×1080 canvas. Its profile needs:

  • Simple output mode, with recording format Hybrid MP4

  • audio tracks 1, 2 and 3

  • the replay buffer enabled

Restart OBS after changing the profile.

Requirements.

  • ffmpeg and ffprobe must be on PATH.

  • The product-demo persona runs on macOS only. It needs Python with tkinter, and Screen Recording permission for OBS.

  • OBS_MCP_LIVE_VCAM_FRAMES=1 also reads frames from the OBS Virtual Camera device. That needs camera permission for the process running the tests.

OBS_MCP_LIVE_TEST=1 \
OBS_MCP_LIVE_PERSONAS=1 \
OBS_MCP_LIVE_SCENE_COLLECTION="OBS MCP Test" \
npx vitest run --config vitest.live.config.ts test/live/personas.test.ts

What changes while it runs. Each persona creates and removes its own scenes and inputs. It stops any output it started, leaves Studio Mode, and puts back the program scene and recording directory. The streamer persona points the profile's stream service at a temporary local RTMP server, and restores the original settings if they were not empty.

Pull-request CI checks the dependency policy before installation. Native-default delivery must run the hermetic development gate on a supported pinned Node toolchain and separately exercise the extracted executable with Node unavailable. Historical Node20 matrix results are not native-only distribution acceptance. Dependency auditing checks the lockfile in a separate weekly workflow so registry advisories do not make otherwise reproducible pull-request checks flaky.

Dependency safety

Direct dependencies use exact versions. npm run check:dependencies checks that the lockfile matches the manifest, uses npm registry HTTPS tarballs with SHA-512 integrity, and contains no production dependency install scripts. The check runs offline and requires no installed packages:

node scripts/check-dependencies.mjs

The private development project disables dependency lifecycle scripts through .npmrc; native MCPB staging installs no npm dependencies. Explicit commands such as npm run build still run. Dependabot proposes weekly npm and GitHub Actions updates for review. CI actions are pinned to verified commit hashes. The residual development advisory and published SDK license findings are recorded in docs/dependency-security.md.

For a dependency update, inspect its release notes and changes to the lockfile, retain exact direct versions, then run npm run check and npm run test:package. Check current advisories with npm audit --package-lock-only --ignore-scripts --audit-level=low. An audit reports known registry advisories; the offline policy check validates the dependency graph's packaging constraints.

The private development toolchain is pinned in package.json/package-lock.json. The current Vitest5 range supports Node22.12+,24 or26+, independently of the installed native runtime, which requires no Node.

TypeScript policy

The development oracle builds with TypeScript 7.0.2 and does not import the TypeScript compiler API. If a future generator, linter, or build tool needs programmatic compiler access, keep that tool on TypeScript 6 while the application compiler remains on TypeScript 7. TypeScript 7.0 does not ship a programmatic API; Microsoft documents the side-by-side TypeScript 6 compatibility package in the TypeScript 7.0 release notes.

Historical protocol baseline

On October 14, 2026, this revision was compared with local modelcontextprotocol, mcp-typescript-sdk, and obs-studio reference checkouts. Those checkouts were read without modification. The exact reference sources are:

  • MCP specification: 5ea99602

  • MCP TypeScript server and client SDKs: 2.3.1; reference checkout 9bc40e90

  • OBS Studio: f082210c

  • OBS WebSocket: e28f8497, the revision pinned by that OBS Studio checkout

The refreshed OBS WebSocket revision has the same 147 requests, 60 events, and 7 enums as the previous baseline; its protocol JSON is byte-for-byte identical. MCP 2026-07-28 remains the released protocol baseline.

The generated protocol files live under docs/. Tests compare every request used by the tool modules with the bundled protocol, so obsolete request names and missing wrappers fail locally.

Project history

This project began with Roy Shilkrot's obs-mcp, including upstream work by Zeke Sikelianos. It also preserves Jag-k's MCPB packaging and registerTool migration work. Their original commits and authorship remain in the Git history.

License

OBS MCP is licensed under the MIT License. The generated OBS WebSocket protocol data under docs/protocol* remains under obs-websocket's GPL-2.0 terms (licenses/obs-websocket/GPL-2.0.txt). The native MCPB layout retains the Rust source, native assets, pinned build inputs and notices. TypeScript remains development oracle code. See LICENSE and NOTICE.md.

Native implementation notes

Native architecture describes retained service, journal, connection and shutdown ownership. Full Rust cutover records the optimized, package and bounded Mac evidence alongside the remaining release gates. Earlier 83/166/167 checkpoint configuration, timings and Mac recordings are artifact-bound historical evidence; their compatibility/opt-in commands are superseded by the current native setup.

Available Tools

155 tools
obs-broadcast-custom-eventBroadcast Custom EventA

Broadcasts a CustomEvent to all WebSocket clients

Inputs: eventData (required).

obs-call-requestCall OBS RequestA
Destructive

Call any request in the pinned OBS WebSocket protocol; inspect it with obs-describe-request first

Inputs: requestType (required), requestData.

obs-call-vendor-requestCall Vendor RequestC
Destructive

Call a request registered to a vendor

Inputs: vendorName (required), requestType (required), requestData.

obs-create-inputCreate InputA

Creates a new input, adding it as a scene item to the specified scene

Inputs: inputKind (required), inputName (required), sceneName (required), canvasUuid, +2 more.

obs-create-profileCreate ProfileA

Creates a new profile, switching to it in the process

Inputs: profileName (required).

obs-create-record-chapterCreate Record ChapterA

Adds a new chapter marker to the file currently being recorded

Inputs: chapterName.

obs-create-sceneCreate SceneB

Create a new scene in OBS

Inputs: sceneName (required), canvasUuid.

obs-create-scene-collectionCreate Scene CollectionA

Creates a new scene collection, switching to it in the process

Inputs: sceneCollectionName (required).

obs-create-scene-itemCreate Scene ItemB

Create a scene item for a source in a scene

Inputs: enabled, sceneName, sceneUuid, canvasUuid, +2 more.

obs-create-source-filterCreate Source FilterA

Creates a new filter, adding it to the specified source

Inputs: filterKind (required), filterName (required), sourceName (required), canvasUuid, +1 more.

obs-describe-requestDescribe OBS RequestA
Read-onlyIdempotent

Inspect the exact fields and constraints of requests in the pinned OBS WebSocket protocol

Inputs: category, requestType.

obs-duplicate-scene-itemDuplicate Scene ItemA

Duplicate a scene item while preserving its transform and crop

Inputs: sceneItemId (required), sceneName, sceneUuid, canvasUuid, +2 more.

obs-get-canvas-listGet Canvas ListA
Read-onlyIdempotent

Get all canvases available in OBS

Inputs: no named parameters.

obs-get-current-sceneGet Current SceneB
Read-onlyIdempotent

Get the current active scene in OBS

Inputs: no named parameters.

obs-get-current-transitionGet Current TransitionA
Read-onlyIdempotent

Get the name of the currently active transition

Inputs: no named parameters.

obs-get-filter-default-settingsGet Filter Default SettingsB
Read-onlyIdempotent

Gets the default settings for a filter kind

Inputs: filterKind (required).

obs-get-filter-kind-listGet Filter Kind ListA
Read-onlyIdempotent

Gets an array of all available source filter kinds

Inputs: no named parameters.

obs-get-group-listGet Group ListA
Read-onlyIdempotent

Get all OBS groups

Inputs: no named parameters.

obs-get-group-scene-itemsGet Group Scene ItemsC
Read-onlyIdempotent

Get the scene items contained in an OBS group

Inputs: sceneName, sceneUuid, canvasUuid.

obs-get-hotkey-listGet Hotkey ListA
Read-onlyIdempotent

Gets an array of all hotkey names in OBS

Inputs: no named parameters.

obs-get-input-audio-balanceGet Input Audio BalanceC
Read-onlyIdempotent

Gets the audio balance of an input

Inputs: inputName (required).

obs-get-input-audio-monitor-typeGet Input Audio Monitor TypeC
Read-onlyIdempotent

Gets the audio monitor type of an input

Inputs: inputName (required).

obs-get-input-audio-sync-offsetGet Input Audio Sync OffsetA
Read-onlyIdempotent

Gets the audio sync offset of an input

Inputs: inputName (required).

obs-get-input-audio-tracksGet Input Audio TracksA
Read-onlyIdempotent

Get the enabled audio tracks for an input

Inputs: inputName, inputUuid.

obs-get-input-default-settingsGet Input Default SettingsA
Read-onlyIdempotent

Gets the default settings for an input kind

Inputs: inputKind (required).

obs-get-input-deinterlace-field-orderGet Input Deinterlace Field OrderC
Read-onlyIdempotent

Get the deinterlace field order of an asynchronous input

Inputs: inputName, inputUuid.

obs-get-input-deinterlace-modeGet Input Deinterlace ModeA
Read-onlyIdempotent

Get the deinterlace mode of an asynchronous input

Inputs: inputName, inputUuid.

obs-get-input-kind-listGet Input Kind ListA
Read-onlyIdempotent

Gets an array of all available input kinds in OBS

Inputs: unversioned.

obs-get-input-listGet Input ListA
Read-onlyIdempotent

Gets an array of all inputs in OBS

Inputs: inputKind.

obs-get-input-muteGet Input Mute StateB
Read-onlyIdempotent

Gets the audio mute state of an input

Inputs: inputName (required).

obs-get-input-property-list-itemsGet Input Property List ItemsA
Read-onlyIdempotent

Get the selectable items for a dynamic input list property

Inputs: propertyName (required), inputName, inputUuid.

obs-get-input-settingsGet Input SettingsC
Read-onlyIdempotent

Gets the settings of an input

Inputs: inputName (required).

obs-get-input-volumeGet Input VolumeA
Read-onlyIdempotent

Gets the current volume setting of an input

Inputs: inputName (required).

obs-get-last-replay-buffer-replayGet Last Replay Buffer FileA
Read-onlyIdempotent

Gets the filename of the last replay buffer save file

Inputs: no named parameters.

obs-get-media-input-statusGet Media Input StatusC
Read-onlyIdempotent

Gets the status of a media input

Inputs: inputName (required).

obs-get-monitor-listGet Monitor ListA
Read-onlyIdempotent

Gets a list of connected monitors and information about them

Inputs: no named parameters.

obs-get-output-listGet Output ListA
Read-onlyIdempotent

Gets the list of available outputs

Inputs: no named parameters.

obs-get-output-settingsGet Output SettingsB
Read-onlyIdempotent

Gets the settings of an output

Inputs: outputName (required).

obs-get-output-statusGet Output StatusC
Read-onlyIdempotent

Gets the status of an output

Inputs: outputName (required).

obs-get-persistent-dataGet Persistent DataA
Read-onlyIdempotent

Gets the value of a slot from the selected persistent data realm

Inputs: realm (required), slotName (required).

obs-get-preview-sceneGet Preview SceneA
Read-onlyIdempotent

Get the current preview scene in OBS Studio Mode

Inputs: no named parameters.

obs-get-profile-listGet Profile ListA
Read-onlyIdempotent

Gets an array of all profiles

Inputs: no named parameters.

obs-get-profile-parameterGet Profile ParameterA
Read-onlyIdempotent

Gets a parameter from the current profile's configuration

Inputs: parameterName (required), parameterCategory (required).

obs-get-record-directoryGet Record DirectoryA
Read-onlyIdempotent

Gets the current directory that the record output is set to

Inputs: no named parameters.

obs-get-record-statusGet Record StatusB
Read-onlyIdempotent

Gets the status of the record output

Inputs: no named parameters.

obs-get-replay-buffer-statusGet Replay Buffer StatusB
Read-onlyIdempotent

Gets the status of the replay buffer output

Inputs: no named parameters.

obs-get-scene-collection-listGet Scene Collection ListA
Read-onlyIdempotent

Gets an array of all scene collections

Inputs: no named parameters.

obs-get-scene-item-blend-modeGet Scene Item Blend ModeB
Read-onlyIdempotent

Get the blend mode of a scene item

Inputs: sceneItemId (required), sceneName, sceneUuid, canvasUuid.

obs-get-scene-item-enabledGet Scene Item EnabledA
Read-onlyIdempotent

Get whether a scene item is enabled

Inputs: sceneItemId (required), sceneName, sceneUuid, canvasUuid.

obs-get-scene-item-idGet Scene Item IDA
Read-onlyIdempotent

Get the ID of a scene item by its source name

Inputs: sceneName, sceneUuid, canvasUuid, sourceName, +2 more.

obs-get-scene-item-indexGet Scene Item IndexC
Read-onlyIdempotent

Get the index position of a scene item

Inputs: sceneItemId (required), sceneName, sceneUuid, canvasUuid.

obs-get-scene-item-lockedGet Scene Item LockedA
Read-onlyIdempotent

Get whether a scene item is locked

Inputs: sceneItemId (required), sceneName, sceneUuid, canvasUuid.

obs-get-scene-itemsGet Scene ItemsA
Read-onlyIdempotent

Get a list of all scene items in a scene

Inputs: sceneName, sceneUuid, canvasUuid.

obs-get-scene-item-sourceGet Scene Item SourceA
Read-onlyIdempotent

Get the source associated with a scene item

Inputs: sceneItemId (required), sceneName, sceneUuid, canvasUuid.

obs-get-scene-item-transformGet Scene Item TransformA
Read-onlyIdempotent

Get the position, rotation, scale, or crop of a scene item

Inputs: sceneItemId (required), sceneName, sceneUuid, canvasUuid.

obs-get-scene-listGet Scene ListB
Read-onlyIdempotent

Get a list of scenes in OBS

Inputs: canvasUuid.

obs-get-scene-transition-overrideGet Scene Transition OverrideA
Read-onlyIdempotent

Get the transition override configured for a scene

Inputs: sceneName, sceneUuid, canvasUuid.

obs-get-source-activeGet Source Active StateB
Read-onlyIdempotent

Gets the active and show state of a source

Inputs: canvasUuid, sourceName, sourceUuid.

obs-get-source-filterGet Source FilterC
Read-onlyIdempotent

Gets the info for a specific source filter

Inputs: filterName (required), sourceName (required), canvasUuid.

obs-get-source-filter-listGet Source Filter ListA
Read-onlyIdempotent

Gets an array of all of a source's filters

Inputs: sourceName (required), canvasUuid.

obs-get-source-screenshotGet Source ScreenshotA
Read-onlyIdempotent

Gets a Base64-encoded screenshot of a source

Inputs: imageFormat (required), canvasUuid, imageWidth, sourceName, +3 more.

obs-get-special-inputsGet Special InputsB
Read-onlyIdempotent

Gets the names of all special inputs

Inputs: no named parameters.

obs-get-statsOBS StatisticsB
Read-onlyIdempotent

Gets statistics about OBS, obs-websocket, and the current session

Inputs: no named parameters.

obs-get-statusOBS Server StatusA
Read-onlyIdempotent

Get the current status of the OBS MCP server and OBS connection

Inputs: no named parameters.

obs-get-stream-service-settingsGet Stream Service SettingsA
Read-onlyIdempotent

Gets the current stream service settings

Inputs: no named parameters.

obs-get-stream-statusGet Stream StatusA
Read-onlyIdempotent

Get the current streaming status

Inputs: no named parameters.

obs-get-studio-modeGet Studio ModeA
Read-onlyIdempotent

Gets whether studio mode is enabled

Inputs: no named parameters.

obs-get-transition-cursorGet Transition CursorB
Read-onlyIdempotent

Get the current scene transition cursor position

Inputs: no named parameters.

obs-get-transition-durationGet Transition DurationA
Read-onlyIdempotent

Get the duration of the current transition in milliseconds

Inputs: no named parameters.

obs-get-transition-kindGet Transition KindA
Read-onlyIdempotent

Get the kind/type of the current transition

Inputs: no named parameters.

obs-get-transition-kind-listGet Transition Kind ListA
Read-onlyIdempotent

Get all available OBS transition kinds

Inputs: no named parameters.

obs-get-transition-listGet Transition ListA
Read-onlyIdempotent

Get a list of available transitions in OBS

Inputs: no named parameters.

obs-get-transition-settingsGet Transition SettingsB
Read-onlyIdempotent

Get the settings of the current transition

Inputs: no named parameters.

obs-get-versionOBS Version InfoA
Read-onlyIdempotent

Get OBS Studio version information

Inputs: no named parameters.

obs-get-video-settingsGet Video SettingsA
Read-onlyIdempotent

Gets the current video settings

Inputs: no named parameters.

obs-get-virtual-cam-statusGet Virtual Camera StatusA
Read-onlyIdempotent

Gets the status of the virtualcam output

Inputs: no named parameters.

obs-offset-media-input-cursorOffset Media Input CursorA

Offsets the current cursor position of a media input

Inputs: inputName (required), mediaCursorOffset (required).

obs-open-input-filtersOpen Input FiltersA
Idempotent

Opens the filters dialog of an input

Inputs: inputName, inputUuid.

obs-open-input-interactOpen Input InteractA
Idempotent

Opens the interact dialog of an input

Inputs: inputName, inputUuid.

obs-open-input-propertiesOpen Input PropertiesB
Idempotent

Opens the properties dialog of an input

Inputs: inputName, inputUuid.

obs-open-source-projectorOpen Source ProjectorC
Idempotent

Opens a projector for a source

Inputs: canvasUuid, sourceName, sourceUuid, monitorIndex, +1 more.

obs-open-video-mix-projectorOpen Video Mix ProjectorB
Idempotent

Opens a projector for a specific output video mix

Inputs: videoMixType (required), monitorIndex, projectorGeometry.

obs-pause-recordPause RecordingA
Idempotent

Pauses the record output

Inputs: no named parameters.

obs-press-input-property-buttonPress Input Property ButtonC
Destructive

Press a button exposed by an input property

Inputs: propertyName (required), inputName, inputUuid.

obs-remove-inputRemove InputA
DestructiveIdempotent

Removes an existing input

Inputs: inputName (required).

obs-remove-profileRemove ProfileA
DestructiveIdempotent

Removes a profile. If the current profile is chosen, it will change to a different profile first

Inputs: profileName (required).

obs-remove-sceneRemove SceneA
DestructiveIdempotent

Remove a scene from OBS

Inputs: sceneName (required), canvasUuid.

obs-remove-scene-itemRemove Scene ItemA
DestructiveIdempotent

Remove a scene item from a scene

Inputs: sceneItemId (required), sceneName, sceneUuid, canvasUuid.

obs-remove-source-filterRemove Source FilterA
DestructiveIdempotent

Removes a filter from a source

Inputs: filterName (required), sourceName (required), canvasUuid.

obs-resume-recordResume RecordingB
Idempotent

Resumes the record output

Inputs: no named parameters.

obs-save-replay-bufferSave Replay BufferA

Saves the contents of the replay buffer output

Inputs: no named parameters.

obs-save-source-screenshotSave Source ScreenshotC
Destructive

Saves a screenshot of a source to the filesystem

Inputs: imageFormat (required), imageFilePath (required), canvasUuid, imageWidth, +4 more.

obs-send-stream-captionSend Stream CaptionB

Sends CEA-608 caption text over the stream output

Inputs: captionText (required).

obs-set-current-profileSet Current ProfileA
Idempotent

Switches to a profile

Inputs: profileName (required).

obs-set-current-sceneSet Current SceneB
Idempotent

Set the current active scene in OBS

Inputs: sceneName (required).

obs-set-current-scene-collectionSet Current Scene CollectionC
Idempotent

Switches to a scene collection

Inputs: sceneCollectionName (required).

obs-set-current-transitionSet Current TransitionA
Idempotent

Set the current transition in OBS

Inputs: transitionName (required).

obs-set-input-audio-balanceSet Input Audio BalanceA
Idempotent

Sets the audio balance of an input

Inputs: inputName (required), inputAudioBalance (required).

obs-set-input-audio-monitor-typeSet Input Audio Monitor TypeA
Idempotent

Sets the audio monitor type of an input

Inputs: inputName (required), monitorType (required).

obs-set-input-audio-sync-offsetSet Input Audio Sync OffsetC
Idempotent

Sets the audio sync offset of an input

Inputs: inputName (required), inputAudioSyncOffset (required).

obs-set-input-audio-tracksSet Input Audio TracksB
Idempotent

Set the enabled audio tracks for an input

Inputs: inputAudioTracks (required), inputName, inputUuid.

obs-set-input-deinterlace-field-orderSet Input Deinterlace Field OrderA
Idempotent

Set the deinterlace field order of an asynchronous input

Inputs: inputDeinterlaceFieldOrder (required), inputName, inputUuid.

obs-set-input-deinterlace-modeSet Input Deinterlace ModeB
Idempotent

Set the deinterlace mode of an asynchronous input

Inputs: inputDeinterlaceMode (required), inputName, inputUuid.

obs-set-input-muteSet Input MuteA
Idempotent

Sets the audio mute state of an input

Inputs: inputName (required), inputMuted (required).

obs-set-input-nameRename InputA
Idempotent

Sets the name of an input (rename)

Inputs: inputName (required), newInputName (required).

obs-set-input-settingsSet Input SettingsC
Idempotent

Sets the settings of an input

Inputs: inputName (required), inputSettings (required), overlay.

obs-set-input-volumeSet Input VolumeB
Idempotent

Sets the volume setting of an input

Inputs: inputName (required), inputVolumeDb, inputVolumeMul.

obs-set-media-input-cursorSet Media Input CursorA
Idempotent

Sets the cursor position of a media input

Inputs: inputName (required), mediaCursor (required).

obs-set-output-settingsSet Output SettingsC
Idempotent

Sets the settings of an output

Inputs: outputName (required), outputSettings (required).

obs-set-persistent-dataSet Persistent DataB
Idempotent

Sets the value of a slot from the selected persistent data realm

Inputs: realm (required), slotName (required), slotValue (required).

obs-set-preview-sceneSet Preview SceneB
Idempotent

Set the current preview scene in OBS Studio Mode

Inputs: sceneName (required).

obs-set-profile-parameterSet Profile ParameterA
Idempotent

Sets the value of a parameter in the current profile's configuration

Inputs: parameterName (required), parameterValue (required), parameterCategory (required).

obs-set-record-directorySet Record DirectoryA
Idempotent

Sets the current directory that the record output writes files to

Inputs: recordDirectory (required).

obs-set-scene-item-blend-modeSet Scene Item Blend ModeC
Idempotent

Set the blend mode of a scene item

Inputs: sceneItemId (required), sceneItemBlendMode (required), sceneName, sceneUuid, +1 more.

obs-set-scene-item-enabledSet Scene Item VisibilityB
Idempotent

Show or hide a scene item

Inputs: enabled (required), sceneItemId (required), sceneName, sceneUuid, +1 more.

obs-set-scene-item-indexSet Scene Item IndexC
Idempotent

Set the index position of a scene item

Inputs: sceneItemId (required), sceneItemIndex (required), sceneName, sceneUuid, +1 more.

obs-set-scene-item-lockedSet Scene Item LockedB
Idempotent

Set whether a scene item is locked

Inputs: sceneItemId (required), sceneItemLocked (required), sceneName, sceneUuid, +1 more.

obs-set-scene-item-transformSet Scene Item TransformB
Idempotent

Set the position, rotation, scale, or crop of a scene item

Inputs: sceneItemId (required), scaleX, scaleY, cropTop, +10 more.

obs-set-scene-nameSet Scene NameA
Idempotent

Rename an OBS scene

Inputs: newSceneName (required), sceneName, sceneUuid, canvasUuid.

obs-set-scene-transition-overrideSet Scene Transition OverrideA
Idempotent

Set or clear the transition override for a scene

Inputs: sceneName, sceneUuid, canvasUuid, transitionName, +1 more.

obs-set-source-filter-enabledSet Source Filter EnabledA
Idempotent

Sets the enable state of a source filter

Inputs: filterName (required), sourceName (required), filterEnabled (required), canvasUuid.

obs-set-source-filter-indexSet Source Filter IndexB
Idempotent

Sets the index position of a filter on a source

Inputs: filterName (required), sourceName (required), filterIndex (required), canvasUuid.

obs-set-source-filter-nameRename Source FilterA
Idempotent

Sets the name of a source filter (rename)

Inputs: filterName (required), sourceName (required), newFilterName (required), canvasUuid.

obs-set-source-filter-settingsSet Source Filter SettingsC
Idempotent

Sets the settings of a source filter

Inputs: filterName (required), sourceName (required), filterSettings (required), overlay, +1 more.

obs-set-stream-service-settingsSet Stream Service SettingsC
Idempotent

Sets the current stream service settings

Inputs: streamServiceType (required), streamServiceSettings (required).

obs-set-studio-modeSet Studio ModeA
Idempotent

Enables or disables studio mode

Inputs: studioModeEnabled (required).

obs-set-tbar-positionSet T-Bar PositionA

Set and optionally release the OBS Studio Mode T-Bar position

Inputs: position (required), release.

obs-set-transition-durationSet Transition DurationA
Idempotent

Set the duration of the current transition in milliseconds

Inputs: duration (required).

obs-set-transition-settingsSet Transition SettingsA
Idempotent

Set the settings of the current transition

Inputs: transitionSettings (required).

obs-set-video-settingsSet Video SettingsC
Idempotent

Sets the current video settings

Inputs: baseWidth, baseHeight, outputWidth, fpsNumerator, +2 more.

obs-sleepOBS SleepA
Read-onlyIdempotent

Sleeps for a time duration or number of frames

Inputs: sleepFrames, sleepMillis.

obs-split-record-fileSplit Record FileB

Splits the current file being recorded into a new file

Inputs: no named parameters.

obs-start-outputStart OutputC

Starts an output

Inputs: outputName (required).

obs-start-recordStart RecordingB

Starts the record output

Inputs: no named parameters.

obs-start-replay-bufferStart Replay BufferB

Starts the replay buffer output

Inputs: no named parameters.

obs-start-streamStart StreamB

Start streaming in OBS

Inputs: no named parameters.

obs-start-virtual-camStart Virtual CameraA

Starts the virtualcam output

Inputs: no named parameters.

obs-stop-outputStop OutputB
Idempotent

Stops an output

Inputs: outputName (required).

obs-stop-recordStop RecordingA
Idempotent

Stops the record output

Inputs: no named parameters.

obs-stop-replay-bufferStop Replay BufferB
Idempotent

Stops the replay buffer output

Inputs: no named parameters.

obs-stop-streamStop StreamA
Idempotent

Stop streaming in OBS

Inputs: no named parameters.

obs-stop-virtual-camStop Virtual CameraA
Idempotent

Stops the virtualcam output

Inputs: no named parameters.

obs-test-connectionTest OBS ConnectionA
Read-onlyIdempotent

Test the connection to OBS WebSocket

Inputs: no named parameters.

obs-toggle-input-muteToggle Input MuteA

Toggles the audio mute state of an input

Inputs: inputName (required).

obs-toggle-outputToggle OutputC

Toggles the status of an output

Inputs: outputName (required).

obs-toggle-recordToggle RecordingB

Toggles the status of the record output

Inputs: no named parameters.

obs-toggle-record-pauseToggle Record PauseA

Toggles pause on the record output

Inputs: no named parameters.

obs-toggle-replay-bufferToggle Replay BufferA

Toggles the state of the replay buffer output

Inputs: no named parameters.

obs-toggle-streamToggle StreamA

Toggle the streaming state in OBS

Inputs: no named parameters.

obs-toggle-virtual-camToggle Virtual CameraA

Toggles the state of the virtualcam output

Inputs: no named parameters.

obs-trigger-hotkey-by-key-sequenceTrigger Hotkey by Key SequenceC
Destructive

Triggers a hotkey using a sequence of keys

Inputs: keyId, keyModifiers.

obs-trigger-hotkey-by-nameTrigger Hotkey by NameB
Destructive

Triggers a hotkey using its name

Inputs: hotkeyName (required), contextName.

obs-trigger-media-input-actionTrigger Media Input ActionC

Triggers an action on a media input

Inputs: inputName (required), mediaAction (required).

obs-trigger-studio-transitionTrigger Studio TransitionA

Trigger a transition from preview to program scene in Studio Mode

Inputs: no named parameters.

obs-trigger-transitionTrigger TransitionB

Trigger a scene transition in OBS (Studio Mode must be enabled)

Inputs: no named parameters.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    B3.2/5.0

    Scored across 155 tools

    Disambiguation4/5

    Most tools map cleanly to distinct OBS resources and actions, and the consistent get/set/toggle/start/stop pattern helps separate them. Only a couple of concepts, such as source active/show state versus scene item enabled state, could cause misselection.

    Naming Consistency5/5

    Every tool is prefixed with obs- and follows a predictable hyphenated verb-noun pattern, e.g., get-, set-, create-, remove-, toggle-, start-, stop-. Despite the large number of tools, the naming convention remains highly consistent throughout the entire set.

    Tool Count1/5

    155 tools is far beyond the 25+ threshold and constitutes an extreme tool-surface mismatch for an MCP server. The set is comprehensive, but the sheer count creates excessive selection overhead and is especially redundant given that obs-call-request already provides generic access to the full OBS WebSocket API.

    Completeness5/5

    The surface covers nearly all major OBS domains: scenes, scene items, inputs, filters, transitions, audio, outputs, recording, streaming, profiles, collections, hotkeys, media, and more. Any niche gap can likely be addressed through obs-call-request, so agents are unlikely to hit dead ends.

    Maintenance

    ActivityMaintained
    ResponsivenessNo recent community issues

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      B
      quality
      C
      maintenance
      A server that provides tools to control OBS Studio remotely via the OBS WebSocket protocol, enabling management of scenes, sources, streaming, and recording through an MCP client interface.
      100
      598 npm
      162
      GPL 2.0
    • A
      license
      B
      quality
      D
      maintenance
      Enables 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.
      89
      MIT