obs-action-history
Server Configuration
Describes the environment variables required to run the server.
| Name | Required | Description | Default |
|---|---|---|---|
No arguments | |||
Instructions
Guidance the server publishes about itself, which clients place ahead of the tool catalog so the model reads it before choosing anything.
This server publishes no instructions, or was last inspected before Glama recorded them.
Capabilities
Features and capabilities supported by this server
Protocol revision2025-11-25
| Capability | Details |
|---|---|
| tools | {} |
Tools
Functions exposed to the LLM to take actions
| Name | Description |
|---|---|
| obs_who_is_talkingA | Listen to the microphones for a moment and report who is actually speaking, loudest first. This is the reactive primitive: it answers 'which person should I cut to right now'. Returns a peak level in dB per audio source over the sampling window, so compare the sources against EACH OTHER rather than against a fixed threshold - the two mics have different gains and each usually picks up everyone in the room, so the loudest is the speaker, not whoever crosses a fixed number. A source that reports no level at all is muted, on no audio track, or its scene is not live. |
| obs_watchA | What OBS has been doing: recent events from the live event stream (scene changes, mute and visibility changes, media starting and ending, stream and record state, filter changes). Use it to see what happened rather than polling for what is true now. Optionally waits first, so you can watch for something you are about to trigger. Audio meters are NOT here - they are summarised by obs_who_is_talking instead, because they arrive ~50 times a second. |
| obs_healthA | Full health snapshot: OBS version, active scene, stream/record state, and live stats (CPU %, memory, FPS, render lag, encoding lag, skipped and dropped frames). Use this first to diagnose anything, and to check whether the machine is keeping up. |
| obs_list_scenesA | List every scene, and which one is currently live (program) and previewed. |
| obs_switch_sceneA | Switch the LIVE scene. This is the POV cut. It never interrupts the stream; the encoder keeps running and viewers just see the camera change. |
| obs_create_sceneA | Create a new empty scene. It is created but NOT switched to, so this is safe while live. A new scene is empty in the literal sense: no background, no audio, nothing inherited from any other scene, so cutting to it before adding sources shows black. Build it first with obs_scene_item_add, then switch. Scene names are unique across the collection and are what every other tool addresses, so pick one you can live with; renaming later is safe inside OBS and breaks anything outside it that refers to the old name. |
| obs_list_sources_in_sceneA | List the sources (scene items) inside a scene, with their item IDs, visibility and transform. Needed before moving, resizing or hiding anything. |
| obs_set_source_visibleA | Show or hide one source inside a scene (e.g. drop the overlay, hide a camera). |
| obs_set_source_transformB | Position and size a source inside a scene, to build picture-in-picture and side-by-side layouts. Coordinates are in canvas pixels. |
| obs_list_inputsA | List every input/source in OBS with its kind (video capture device, media source, browser, audio input, etc). Use this to see which cameras and mics OBS can actually see. |
| obs_get_input_settingsA | Read the full settings object of one input (resolution, device id, URL, file path...). |
| obs_set_input_settingsA | Change settings on an input: swap a webcam's device, change an SRT/RTMP media source URL, change resolution or FPS. Pass only the keys you want to change. |
| obs_create_inputA | Create a new source in a scene. Common kinds: 'dshow_input' (USB webcam/capture card), 'ffmpeg_source' (SRT/RTMP/RTSP network feed or video file), 'browser_source', 'wasapi_input_capture' (microphone), 'wasapi_output_capture' (desktop audio), 'text_gdiplus_v3', 'color_source_v3', 'image_source', 'ndi_source' (needs the NDI plugin). |
| obs_list_input_kindsA | List every source type this OBS install supports (tells you which plugins loaded). |
| obs_audio_controlA | Get or set mute state and volume for an audio input. Volume is in dB (0 = unity, -100 = silence). |
| obs_stream_controlA | Start, stop or query the live stream. Use 'status' freely. Be deliberate with start and stop, because stopping ends the broadcast for every viewer on every platform. |
| obs_record_controlA | Start, stop, pause, resume or query local recording (your local backup / VOD master). |
| obs_screenshotA | Capture what a scene or source looks like RIGHT NOW and return it as an image. This is how Claude visually verifies framing, layout and that a camera is actually alive instead of showing a black frame. |
| obs_video_settingsA | Get or set canvas resolution, output resolution and FPS. Changing these requires the stream to be stopped. |
| obs_profile_and_collectionB | List / switch OBS profiles (encoder + streaming settings) and scene collections (scene layouts). |
| obs_transitionB | List transitions, or set the active one and its duration (how POV cuts look). |
| obs_filtersA | List filters on a source, or add one. Useful filters: 'noise_suppress_filter_v2' (RNNoise mic cleanup), 'noise_gate_filter', 'compressor_filter', 'chroma_key_filter_v2', 'color_filter_v2', 'async_delay_filter' (sync a lagging network camera to the others). |
| obs_rawA | ESCAPE HATCH. Call any obs-websocket v5 request directly by name with a raw payload. Covers everything the wrapped tools do not, including plugin-provided vendor requests. See the obs-websocket protocol reference for request names. |
| obs_scene_item_addA | Add an EXISTING source to a scene, as a new scene item. This is the missing half of obs_create_input: that one makes a brand new source, this one places a source you already have into another scene. Reusing a source is almost always what you want - one camera placed in six scenes is one device opened once, while six separate inputs on the same webcam will fight over the device and most will fail to start. A scene can be added to another scene this way, which is how layer scenes work: on the reference machine the HUD scene holds every overlay and is added as a SINGLE item into each scene, so editing HUD once changes all of them. Do not rebuild overlays per scene. The new item lands at the TOP of the z-order and covers whatever it overlaps. If you are adding a background it has to be moved down to index 0 afterwards with obs_scene_item_order. The response reports the index it actually received, so check it rather than assuming. sceneItemEnabled defaults to true. Note that a source can be enabled but sitting off-canvas: see obs_scene_item_transform for why that is not the same as hidden. |
| obs_scene_item_removeA | Remove one scene item from its scene. This removes the PLACEMENT, not the source. The same input placed in other scenes keeps working there, keeps its settings and keeps its filters - so deleting a camera from the BRB scene does not disturb it anywhere else. Only when you remove the last placement does the input itself lose its last reference, and its settings go with it, so the final copy is the one to think twice about. There is no undo over the websocket. If the goal is just to get something off screen, obs_set_source_visible is reversible and this is not. |
| obs_scene_item_duplicateA | Copy a scene item, with its transform, crop and blend mode intact, either within the same scene or into another one. Omit toScene to duplicate in place. The copy points at the SAME underlying source - this clones the placement, not the camera. That is what makes it the fast way to build a matching layout: place one screen capture exactly, duplicate it into the next scene, then move only what differs. It is also why duplicating an audio-carrying source needs care, because you now have two items playing the same audio in one scene and the result is doubled, not louder. Duplicating into a scene that already has that source is allowed; OBS does not deduplicate. |
| obs_scene_item_orderA | Read or change z-order - which source is drawn on top of which. INDEX 0 IS THE BOTTOM. Higher index draws later, so it covers everything below it. This is upside down from the OBS window, which lists the topmost source first, and getting it backwards is the single easiest way to make a layer vanish. On the reference machine the BG layer is deliberately parked at index 0 of every scene so no scene is ever pure black. Anything full-canvas and opaque placed above it hides it completely and the symptom is simply a black background with no error anywhere - two opaque black rectangles had to be hidden before BG showed at all. If a background stopped showing, check what is above it before you touch the background itself. Call with sceneName only to read the whole stack bottom-first. Add sceneItemId and index to move one item; the full resulting order comes back either way. Indexes are renumbered contiguously after a move, so read the stack again before a second move rather than reusing the numbers you just saw. |
| obs_scene_item_lockA | Lock or unlock a scene item. A locked item cannot be dragged or resized in the OBS window by a human, and cannot be transformed over the websocket either - SetSceneItemTransform on a locked item fails rather than silently doing nothing. Worth using on the pieces that must not drift: a HUD layer or a background that someone might grab by accident while adjusting a camera on top of it. Locking changes nothing about what viewers see - it affects editing only, not visibility and not audio. If a transform keeps being rejected, read the lock state before assuming the coordinates were wrong. Omit |
| obs_scene_item_blend_modeA | Read or set how a scene item composites with the layers under it. OBS_BLEND_NORMAL is plain alpha and is the default. OBS_BLEND_ADDITIVE and OBS_BLEND_SCREEN both drop black toward transparent, which is the usual trick for glows, light leaks and particle or scanline overlays shot on a black field - they let an overlay sit on top without boxing off what is underneath. OBS_BLEND_MULTIPLY and OBS_BLEND_DARKEN do the opposite and drop white, useful for shadowing or tinting a region. SUBTRACT and LIGHTEN are situational. Blend mode only matters against what is BELOW the item, so it interacts directly with z-order: the same overlay set to additive looks completely different depending on its index. An item at index 0 has nothing under it to blend with and will look unchanged no matter what mode you pick - if a blend mode appears to do nothing, check the index first. Omit |
| obs_scene_item_transformA | The complete transform: position, scale, rotation, alignment, crop and bounds. obs_set_source_transform covers position, scale and crop only; this one reaches the rest. Call with just sceneName and sceneItemId to READ the current transform, including the read-only width/height/sourceWidth/sourceHeight that tell you how big the thing actually is on canvas right now. Only the fields you pass change; everything else keeps its current value. BOUNDS ARE INERT WITHOUT boundsType. boundsWidth, boundsHeight and boundsAlignment are ignored while boundsType is OBS_BOUNDS_NONE, which is the default, so setting a bounding box and nothing else accomplishes nothing at all and reports success. Set boundsType in the same call. Bounds are the right tool for a slot of fixed size - OBS_BOUNDS_SCALE_INNER fits the source inside the box keeping its aspect ratio, which is how you drop a camera of unknown resolution into a layout without doing the arithmetic. Once bounds are active they drive the size and scaleX/scaleY stop being the thing to adjust. ALIGNMENT IS A BITMASK, NOT AN ENUM: 0 centre, 1 left, 2 right, 4 top, 8 bottom, added together. 5 is top-left and is what every item on the reference machine uses. It sets which point of the source positionX/positionY actually refers to, so changing alignment alone appears to teleport the source even though position never changed. Crop is measured in SOURCE pixels, before scaling, and cuts in from each edge. width/height/sourceWidth/sourceHeight cannot be written - to resize, set scale, or use bounds. A source moved off the canvas is still ENABLED and still renders and, more to the point, its audio still plays. Parking something at x=2600 on a 1920 canvas does not silence it. That is what doubled both voices on day one, from a phone parked out of frame but unmuted; it is also used deliberately here, because the mic and music sources are off-canvas precisely so they stay audible without taking up pixels. Hiding a source with obs_set_source_visible DOES cut its audio, which is why those are parked rather than hidden. Choose the one you mean. |
| obs_filter_kindsA | List every filter kind this OBS install can create - 43 on the reference machine - and optionally the default settings for one of them. This is the honest way to find out whether a PLUGIN actually loaded, because plugin filters only appear here once their DLL is in place: move_source_filter and its siblings come from the Move plugin, ndi_filter from the NDI runtime. If a filter kind you expect is missing, the plugin did not load and no amount of retrying CreateSourceFilter will help - it fails with an invalid-kind error that reads like a typo. Kind strings are exact and several ship as v2 alongside a legacy original (chroma_key_filter_v2, color_filter_v2, noise_suppress_filter_v2). Prefer the v2. Pass filterKind to also fetch that kind's defaults - though be aware OBS returns an empty object for kinds that register no explicit defaults, which means 'nothing declared', not 'no settings'. |
| obs_filter_getA | Read the filter chain on a source, or one filter in full detail. Do this before changing anything: every other filter tool addresses filters by exact name, and the settings you get back are the keys that actually exist for that kind. THE SETTINGS OBJECT IS PARTIAL. OBS only reports values that DIFFER from the kind's defaults, so a filter showing {} is running entirely on defaults, not broken and not empty. This is the reason a compressor here reports five keys while a delay reports one. It also means you cannot learn a kind's full parameter list from an existing filter - use obs_filter_kinds with filterKind for the declared defaults. Order is returned lowest index first, which is the order audio and video actually flow through. Omit filterName for the whole chain. |
| obs_filter_settingsA | Tune a filter that already exists - the threshold on a gate, delay_ms on a sync delay, opacity on a colour correction, similarity on a chroma key. By default your keys are MERGED into the existing settings, so you can send one value and leave the rest alone. Setting replace:true instead resets the filter to its kind defaults and then applies only what you sent, silently discarding every other tuned value on that filter. On a mic chain that has been dialled in over days, replace:true on a compressor is how you lose the ratio, the attack and the release while only meaning to change the threshold. Use the default merge unless you specifically want a clean slate. Setting keys are per kind and are not validated: an unknown or misspelled key is accepted, stored and ignored, and nothing reports an error. The response returns the filter's real settings afterwards - compare them against what you sent, because a key that silently vanished was the wrong name. Read obs_filter_get first to see the keys a kind really uses. Changes apply live to a running broadcast the instant they land; there is no staging. |
| obs_filter_toggleA | Switch a filter on or off without removing it. Settings are kept, so this is the reversible way to find out what a filter is actually doing - toggle the noise suppression off, listen, toggle it back. Reach for this instead of obs_filter_remove whenever the question is 'is this helping', because removing loses the tuning and there is no undo. A disabled filter stays in the chain and keeps its index, so the numbering does not shift under you while you experiment. The effect is immediate on the live output. Disabling a sync delay on a camera will jump that camera out of lip-sync on stream at once, not at the next scene change. |
| obs_filter_removeA | Delete a filter from a source, permanently. Its settings go with it and the websocket has no undo - if you might want it back, obs_filter_toggle bypasses it instead and keeps the tuning. Removing renumbers everything below it in the chain, so any filterIndex you noted before this call is stale afterwards. Re-read with obs_filter_get before reordering. Filters are per source, so this affects every scene that uses the source, not just the scene you happen to be looking at. The response returns the chain that is left. |
| obs_filter_orderA | Move a filter within the chain. Index 0 runs FIRST, and each filter processes what the one before it produced, so the order is a signal path and not a preference. This is why the mic chain here reads noise suppression, then compressor, then limiter: the compressor is levelling speech rather than chasing room hiss up and down, and the limiter has the last word on the peaks. Put the limiter first and it clamps a signal the compressor has not levelled yet, then the compressor raises everything back up past the ceiling the limiter was there to hold. Video is the same idea - crop before scale, and a colour key before a colour correction that would move the colour you are keying on. Indexes are contiguous and renumber after every move, so read the chain again rather than reusing numbers from before. Valid range is 0 to 8192; the resulting chain comes back. |
| obs_filter_renameA | Rename a filter. The name is the only handle every other filter request has - there is no filter id - so renaming is the one edit here that can break something outside OBS: scripts, panel code and Move-plugin filters all address filters by exact name and will simply fail to find the old one afterwards. On the reference machine the sync delays are named consistently and the music ducking compressors DUCK, DUCK-IRL and so on, and tooling looks for exactly those strings. Names must be unique per source. Renaming does not change the filter's index, its settings or whether it is enabled. |
| obs_audio_routingA | Read - and optionally change - WHERE one audio input goes: which recording/stream tracks carry it, whether OBS monitors it out of the speakers, its A/V sync offset, and its stereo balance. Call it with only inputName to read; every other field is a change. This is separate from mute and volume on purpose: those are 'how loud', these are 'does it reach anyone at all', and a source can be at 0 dB, unmuted, and still inaudible to viewers. TRAPS, all of which return success while doing nothing you wanted: (1) syncOffsetMs is capped near 960 ms - OBS accepts far larger values, stores them, and applies nothing, so 2000 ms is silently 0. The protocol declares a floor of -950 on the negative side but a ceiling of 20000 on the positive one, so only the positive side gets to fail quietly. If a feed is more than a second late, cut the real latency; you cannot compensate past the cap. (2) A source on no track at all does not even meter, so it looks like dead hardware. (3) Only the tracks named by RecTracks reach the recording, and only one reaches the stream; a source on any other track meters perfectly and reaches nobody. That is how a detection microphone exists without being heard, so do not 'fix' such a source onto track 1. (4) monitorType anything but NONE sends this to the room speakers, where the microphone picks it up and it goes out a second time, out of phase. MONITOR_AND_OUTPUT is the one that does both. The reply always contains what OBS holds AFTER the write, plus a |
| obs_audio_routing_mapA | The whole audio routing picture in one call: every input that carries audio, with its tracks, monitoring, sync offset and balance, and an explicit list of what is misrouted. Read-only. Start here when audio is wrong and you do not yet know which source is at fault - the alternative is four requests per input, and the answer is usually a comparison between sources rather than a fact about one of them. It names the failures that a level meter cannot show you: sources on no track (inaudible AND unmeterable), sources off track 1 (they meter but never reach the stream or the recording on the reference machine), monitoring left enabled (doubled, out-of-phase audio via the room microphone), sync offsets stored past the ~960 ms cap where OBS applies nothing, and balances pushed off centre. Inputs with no audio at all are skipped rather than listed as errors. |
| obs_special_inputsA | Names of OBS's six built-in audio slots: Desktop Audio, Desktop Audio 2, and Mic/Aux 1-4. Read-only. The trap is what an empty answer means. Any slot a user never configured comes back null, and on a rig that creates its audio sources explicitly - which is every rig built by a script - all six are null. On this machine they are: every audio source here, microphones included, is a named input, not a special slot. Six nulls therefore means 'this OBS has no special inputs assigned, go read the input list', NOT 'this OBS has no audio' and NOT 'the request failed'. Use this to resolve the two names OBS itself uses in its settings UI; use obs_audio_routing_map to actually find the microphones. |
| obs_replay_bufferA | The replay buffer: OBS holding the last N seconds of the show in memory so you can decide AFTER something happens that you wanted to keep it. This is the only capture primitive that works backwards in time, which makes it the one an automated producer actually needs - by the time a moment is recognisable as good, recording it is already too late. action 'save' is the interesting one: it writes the buffer to a file and returns the path. TRAPS: (1) The save is asynchronous. SaveReplayBuffer returns before the file is written, so asking for the filename immediately gives you the PREVIOUS clip. This tool polls until the path changes and reports |
| obs_virtual_camA | OBS's virtual webcam output - the program feed presented to the operating system as a camera, so Zoom, Discord, a browser or a second OBS can consume it. Safe to touch during a live broadcast: it is a separate output and starting or stopping it changes nothing that viewers see, unlike the stream and record controls. TRAP: prefer 'start' and 'stop' over 'toggle'. Toggle is the single most common way an automated caller turns the virtual camera OFF while meaning to turn it on - it acts on a state it did not check, and it returns the state it produced rather than the one you wanted. 'status' is read-only; it reports only whether the output is active, not who is consuming it, so a running virtual camera with nobody watching looks identical to a working one. |
| obs_save_screenshotA | Write a frame of a scene or source straight to a file on disk, and return the path. Use this instead of the image-returning screenshot tool whenever the picture is for a FILE - a thumbnail, a clip poster, a before/after pair, anything sampled on a loop. That tool base64s the whole image back through the conversation, which for a 1080p frame is megabytes of context spent on something nobody is going to look at. This one costs a path. Keep using the other one when you personally need to SEE the frame to judge framing or spot a black camera. TRAPS: (1) OBS writes the file itself, so imageFilePath is resolved on the machine running OBS, not wherever this MCP server lives, and it must be absolute. Point it at a directory that already exists. (2) imageWidth and imageHeight are 'scale to inner' - the aspect ratio is kept and the smaller ratio wins, so passing both does not crop, it fits. Pass one, or neither for native resolution. (3) imageFormat must be one this OBS build compiled in; png, jpg and webp are the safe ones, and GetVersion's supportedImageFormats is the real list. (4) A source that is not currently rendering gives you a black or stale frame, not an error. |
| obs_record_chapterA | Drop a named chapter marker into the local recording at this instant, so the VOD can be navigated later without anyone scrubbing through six hours of it. This is the cheap version of clipping: it costs nothing, it cannot fail loudly mid-show, and it turns one long recording into something with an index. TRAPS: (1) Recording must be ACTIVE. Streaming is not recording, and a rig can be live for hours with no recording file open at all; in that state this fails with code 501. Check obs_record_control status first. (2) Chapters only exist in Hybrid MP4. Any other container and the marker goes nowhere; OBS 30.2 onward supports no other format for this. The reference machine records hybrid_mp4, so it works here. (3) The marker lands where the recording is NOW, which is the live edge - you cannot chapter something that already happened. Name it for what is starting, not for what just ended. |
| obs_record_splitA | Close the recording file being written right now and immediately start the next one, without stopping the recording. Use it to cut a long show into pieces you can upload or hand off while the show is still going, rather than waiting six hours for one enormous file. The stream is untouched - this is the local recording only, and viewers see nothing. TRAPS: (1) Recording must be active; otherwise code 501. Streaming being live is not enough - the local recording is a separate output. (2) There is no 'undo' and no way to rejoin the halves afterwards without re-encoding. (3) The new file is named by OBS's filename formatting, so you do not choose the name here - read it back from obs_record_control status if you need it. (4) A split is a real container boundary: anything that was mid-chapter or mid-scene at that instant is split across two files. |
| obs_studio_modeA | Read or set whether OBS is in studio mode - the two-stage layout where a scene can be staged in PREVIEW and inspected before it is cut to PROGRAM. This is the safety rail for anything automated. Switching scenes on a live broadcast is otherwise unreviewable: the request lands and every viewer sees the result before you do. With studio mode on, the sequence becomes stage -> screenshot the preview -> cut, and a camera that has not reconnected or a screen share showing the wrong window gets caught by you rather than by chat. If you are going to move scenes automatically, turn this on first. Turning it on or off changes NOTHING that viewers see - program keeps playing throughout, so this is safe to enable mid-broadcast. What it does change is the operator's OBS window, which matters if a human is also driving. TRAPS: (1) It is not a lock. With studio mode on, obs_switch_scene / SetCurrentProgramScene still cuts straight to air with no review. Studio mode ADDS the reviewed path; it does not close the unreviewed one. (2) Disabling it throws away whatever was staged in preview, silently. (3) Every preview request fails with code 506 while this is off, which is the single most common reason those tools appear broken. |
| obs_preview_sceneA | Read or set the scene sitting in PREVIEW - staged, rendering, and not on air. Setting this is the safe half of a scene change: nothing viewers see moves, so it is the one scene operation that is genuinely harmless during a live broadcast. Stage here, screenshot the scene by name to confirm the cameras are alive and the layout is right, then cut with obs_studio_transition. TRAPS: (1) Requires studio mode. With it off, both reading and setting fail with a bare code 506 that says nothing useful - this tool translates it, but the fix is always obs_studio_mode first. (2) Staging does not guarantee a feed is connected. Network sources - SRT, RTMP, NDI - accept a new connection only while they are being rendered, and how long that handshake takes is not something the preview tells you. Stage early, then confirm with a screenshot of the preview scene rather than assuming a staged source is a live one. (3) A staged scene is not frozen. It keeps updating, so a preview screenshot taken thirty seconds ago is not evidence about now. (4) Preview and program swap places after a transition, so whatever you just cut away from is now sitting in preview. |
| obs_studio_transitionA | CUT TO AIR. Runs the current transition, taking whatever is in preview to program. This is the irreversible half of a studio-mode scene change and the moment every viewer on every platform sees the new scene - treat it exactly as seriously as switching the program scene directly, because that is what it does. Read obs_preview_scene and look at a screenshot of it before calling this. TRAPS: (1) Requires studio mode; code 506 otherwise. (2) It returns immediately, BEFORE the transition finishes. With a fade or a stinger configured, program is mid-transition when this resolves, so a screenshot taken right after shows a blend of two scenes rather than the new one. Wait out the transition duration before verifying. (3) It uses whatever transition and duration OBS currently has selected - this request takes no parameters and cannot override them. Check the current transition first if the timing matters. (4) Preview and program swap, so calling it twice in a row returns you to the scene you started from, which looks like it did nothing. |
| obs_input_property_itemsA | Enumerate the real choices behind a dropdown in a source's Properties dialog - every webcam, capture card, microphone, speaker and monitor this machine has, with the exact device ID string OBS wants written back. This is the difference between configuring OBS on a machine somebody already set up by hand and configuring one from nothing: without it, pointing a capture source at a camera means GUESSING a Windows device path, and pointing an audio source at a mic means guessing a GUID like '{0.0.1.00000000}.{xxxxxxxx-...}' that appears in no documentation and is different on every PC. Read the list here, then write the chosen itemValue with obs_set_input_settings under the SAME property name. Write back itemValue, never itemName. itemName is the label a human reads ('Logitech StreamCam'); itemValue is the device path, and it is what OBS matches on. itemEnabled false means the device is known to OBS but not selectable right now - typically another application holds it open. propertyName is the plugin's INTERNAL id, not the label in the dialog. Verified on the reference machine: dshow_input (webcam / capture card): video_device_id, audio_device_id, res_type, resolution, video_format, color_space wasapi_input_capture and wasapi_output_capture (mic / desktop audio): device_id monitor_capture (screen): monitor_id, method Other kinds and other plugins have their own ids; the two failure messages tell them apart. 'Unable to find a property by that name' means the id is wrong. 'The property found is not a list' means the id is RIGHT but that property is a button, a checkbox, a path or a text box - which is itself useful, because it is how you confirm a button exists before pressing it with obs_press_input_button. These values are not portable and not permanent: a USB camera moved to a different port gets a different video_device_id, which is the usual reason a scene that worked yesterday shows a black rectangle today. Re-read this list rather than reusing a stored string. |
| obs_press_input_buttonA | Press a button inside a source's Properties dialog. OBS exposes a handful of actions only as buttons - there is no setting to write instead - so without this an agent simply cannot perform them, and two of them are the standard recoveries for the reference machine:
Two cautions. A press on a live source is visible on stream: toggling 'activate' on a camera that is currently on air drops it to black for as long as the device takes to re-open, and if the device is genuinely gone it stays black and you have just deactivated a working scene - check which scene is live first. And OBS returns nothing at all on success, so a clean result means 'the button was pressed', not 'the thing you wanted happened'; confirm with obs_screenshot. Buttons are not discoverable through obs_input_property_items, which only enumerates dropdowns. What that tool does give you is existence: 'The property found is not a list' confirms the id is real before you press it, while 'Unable to find a property by that name' means it is not. |
| obs_remove_inputA | Delete a source outright, removing it from every scene it appears in at once. The trap: a clean result does NOT prove the source is gone. OBS drops its own reference and answers success, but the source itself survives as long as anything else still holds a reference to it - and those references are not all visible from the scene list. A plugin that maintains a second canvas (the vertical-canvas plugin on the reference machine does exactly that) keeps its own reference, so the input can vanish from obs_list_inputs while the decoder is still running and still costing GPU. If you removed something to reclaim resources and the machine did not get faster, this is why. This tool re-reads the input list afterwards and tells you which of the two happened. So if the goal is to stop something DECODING rather than to delete it, do not use this at all: take it out of every scene, or hide it. A source that is in no active scene does not decode and does not burn GPU, and it is reversible - which matters here, because removal is not undoable over the websocket. Re-creating the input afterwards will not bring back its filters, its audio routing, its sync offset, or its position and crop in any scene. Read obs_get_input_settings first if there is any chance you will need to rebuild it. |
| obs_rename_inputA | Rename a source. Inside OBS this is safe and complete: scene items reference the source itself, not its name, so every scene follows the rename and nothing breaks visually. Outside OBS it is the opposite, and that is the real risk. Everything that automates OBS addresses sources BY NAME over the websocket - health checks asking whether a mic is producing sound, audio tooling, scene builders, and every tool call in this server. None of them are updated by a rename, none of them fail loudly, and the symptom arrives later as 'that check stopped reporting' rather than as an error. A source name that has drifted from what it now shows is often still worth keeping for exactly this reason. Prefer renaming the SCENE, which nothing addresses by name, or leaving it alone. Names are unique across the whole collection, so a rename onto a name already in use fails. |
| obs_input_kind_referenceA | What source types this OBS build supports, and which settings keys each type legally accepts. Call it with no arguments to list the kinds - that list is also the honest answer to 'which plugins are loaded', since a kind like 'ndi_source' only appears if its plugin initialised. Call it with inputKind to get that kind's default settings object, which is the closest thing to a schema OBS offers: an input's kind decides which settings keys mean anything, and a key that belongs to a different kind is accepted and silently ignored rather than rejected. That silent acceptance is why guessing keys wastes so much time - obs_set_input_settings returns success either way. Two limits worth knowing. The defaults object lists only keys the plugin registered a default for, so it is a floor and not the full set: dshow_input returns nine keys and video_device_id is not among them, because it has no sensible default. To see the rest, read a WORKING input of the same kind with obs_get_input_settings, and get legal values for the dropdown keys from obs_input_property_items. Second, kind ids carry version suffixes - this build reports color_source_v3, text_gdiplus_v3, slideshow_v2 - and the versioned id is what existing inputs report and what obs_create_input expects. unversioned:true strips the suffixes, which is useful for recognising a kind named in an older config or article, but do not create sources with the stripped names. |
| obs_list_outputsA | List every output OBS currently has - the stream, the recording, the replay buffer, the virtual camera, and any output contributed by a plugin - with which ones are running right now. Start here before touching anything in this module, because the names are not predictable. OBS's own are internal ids (adv_stream, adv_file_output); plugin outputs use whatever label the plugin chose, and on the reference machine the vertical-canvas plugin contributes one called 'Vertical Backtrack' that also reports its width and height as 0 in this list, which is the plugin not filling those in rather than a broken output. Do not infer what an output does from its name. The field that actually matters is outputFlags.OBS_OUTPUT_SERVICE. True means the output feeds a streaming service - that is the live broadcast, and on the reference machine exactly one output has it: adv_stream, which is the single RTMP connection to the local relay that fans out to Twitch, YouTube and Kick. Everything downstream of it dies together, so 'which platform does this stop' has no useful answer: it stops all three. This tool annotates each output with that reading so the distinction is not left to name-guessing. |
| obs_output_statusA | Live health of an output: whether it is running, how long it has been running, how many bytes it has pushed, how many frames it dropped, and how congested it is. Omit outputName to get all of them at once, which is the fastest read of 'what is this machine actually doing right now'. Read outputActive first and let it gate everything else, because the counters are NOT cleared when an output stops. On the live rig, adv_file_output reported outputActive false alongside 1.68 GB of outputBytes and 131,933 outputTotalFrames - leftovers from the previous recording session. Reading bytes alone would say the recording is running when it has not been for hours. outputTimecode and outputDuration are the ones that do reset to zero, so they agree with outputActive. For a stream that is up, the two numbers to watch over time are outputSkippedFrames and outputCongestion. Congestion is a percentage of how close the encoder is to not keeping up; rising congestion with climbing skipped frames means the upload or the encoder is the bottleneck and viewers are seeing it. outputReconnecting true means the connection dropped and OBS is trying to re-establish it - the broadcast is interrupted even though outputActive has not gone false. One caution specific to this setup: healthy numbers here only prove OBS is successfully pushing bytes into the local relay. They say nothing about whether the relay is still forwarding to each platform. A YouTube broadcast can be receiving nothing while this reports a perfect stream. |
| obs_get_output_settingsA | Read one output's settings object. Use it before obs_set_output_settings, because the keys an output accepts depend entirely on its kind and there is no schema request for them - the object you get back IS the list of keys that mean anything. Expect less than you think. adv_stream on the reference machine returns only bind_ip, ip_family, dyn_bitrate, low_latency_mode_enabled and new_socket_loop_enabled: network tuning, and nothing else. There is no server URL and no stream key in there. The destination lives on the stream SERVICE, which is part of the profile, not the output - so reading this to find out where the rig is streaming will not tell you, and neither will writing to it change where the rig streams. Bitrate and encoder settings are likewise profile-level, not here. |
| obs_set_output_settingsA | Write an output's settings. This REPLACES the settings object rather than merging into it, so read obs_get_output_settings first and send the full object with your change applied - sending one key on its own is how you lose the others. Do not reach for this to change where the stream goes or how good it looks. The destination and stream key belong to the profile's stream service, and bitrate and encoder belong to the profile; none of them appear in an output's settings. What is here is network-level behaviour - which interface to bind, IPv4 vs IPv6, dynamic bitrate, low-latency mode. For anything about quality or destination, use obs_profile_and_collection. Change settings while the output is stopped. A running output has already read its configuration, and a write that appears to succeed may do nothing until the next start - which reads as a broken tool when it is really a timing mistake. On a live broadcast, changing adv_stream's networking settings is not a safe experiment: verify with obs_output_status afterwards and be ready for the possibility that it takes the connection down. |
| obs_output_controlA | Start, stop or toggle any output by name - covers StartOutput, StopOutput and ToggleOutput. This is the general lever for outputs that have no dedicated tool: the replay buffer, the virtual camera, and above all the outputs a plugin brought with it, such as the vertical canvas's own recording on the reference machine. Without it, a whole second canvas is unreachable. Know which output you are aiming at before you fire. Stopping the SERVICE output ends the broadcast for every viewer on every platform simultaneously - here that is adv_stream, the one RTMP connection into the local relay that feeds Twitch, YouTube and Kick, so there is no such thing as stopping just one platform from OBS. Stopping the local recording (adv_file_output) is merely annoying by comparison. Stopping a replay buffer discards what is in memory. Because these are so far apart in consequence and the names give no hint, this tool refuses to stop a service output unless you pass confirm:true, and names the output in the refusal. For the main stream and the main recording, prefer obs_stream_control and obs_record_control. Those are the paths the rest of the reference machine's tooling and OBS's own state follow; this tool operates on the raw output and is the right choice only for what they do not cover. 'toggle' is convenient and dangerous in the same way: it decides based on state you have not looked at, so a toggle aimed at something you believed was stopped will stop it instead. Check obs_output_status first, or use explicit start/stop. Starting an already-running output, or stopping an already-stopped one, is an error rather than a no-op - this tool reports the state it found instead of failing obscurely. |
| obs_media_statusA | Survey what media sources are actually playing. With no inputName it checks EVERY media input (ffmpeg_source and vlc_source) in one go, which is the form you almost always want: the failure worth catching is 'one of them quietly ended', and you cannot spot that by asking about a source you already suspect. THE TRAP: mediaState PLAYING does not mean video or audio is arriving. A disconnected SRT feed sits at PLAYING with its cursor frozen at 0 forever - measured on the reference machine, every media input claimed PLAYING and only the cursor separated the working ones from a dead feed. Pass probeMs (e.g. 2000) to take a second sample and get advancing:true/false per source, computed from whether cursorMs actually moved. That is the only honest liveness test. Why it matters here: background music is an ffmpeg_source named a looping media source whose next track is queued by a Node process listening for MediaInputPlaybackEnded. When that listener dies the source parks in state 'ended' and every other indicator - process table, supervisor, dashboard - stays green. That gap once hid seventeen hours of silence. state:'ended' on a looping media source is the whole diagnosis. Note durationMs is null for live feeds: OBS returns INT64_MIN, not null, for a stream with no end, so unboundedDuration:true flags a live source rather than a broken one. |
| obs_media_seekA | Move the playhead of a media source, either to an absolute position (positionMs) or by a relative amount (offsetMs, negative to rewind). Exactly one of the two. There is NO bounds checking, by design of the protocol - seeking past the end does not clamp, and seeking a live feed that has no meaningful duration is not a defined operation. Read obs_media_status first: if durationMs is null and unboundedDuration is true, this source is a live stream and seeking it is meaningless. On the reference machine, do not seek a looping media source to reach the next track. The queue lives in music/player.js, not in OBS; running |
| obs_media_controlA | Transport control for a media source: play, pause, stop, restart, next, previous. next and previous are PLAYLIST actions. They only do something on a vlc_source, which holds a list of files. On an ffmpeg_source - which is every media input on the reference machine, a looping media source included - there is no playlist, so they succeed and change nothing. A tool call that returns success while nothing happened is worse than an error, so check the returned state. Careful with a looping media source specifically: its watchdog in music/player.js advances the queue on states ended, none and error, but NOT on paused or stopped. So pausing or stopping a looping media source here is not self-healing - the music stays silent until a person notices, which is the exact failure mode the reference machine already paid seventeen hours for. Use |
| obs_hotkey_listA | List the hotkey action names OBS knows about, which is how you discover what PLUGINS can do - a plugin's actions usually have no obs-websocket request at all, so this list is their only index. Results are grouped into core OBS actions and plugin-provided ones, and deduplicated with a count, because the raw response on the reference machine is 411 strings of which 37 are repeats. Pass filter to narrow by substring (case-insensitive), or pluginsOnly:true to skip the ~390 core entries and see just what the installed plugins registered. THE TRAP THIS LIST REVEALS: a repeated name means the action exists once per source or per scene - libobs.mute is registered separately for every audio input - and the trigger request takes only a name, so you cannot address a specific one. When you see count > 1 here, do not trigger it; find the real request instead (SetInputMute, SetSceneItemEnabled, and so on). Names with count 1 that are plugin-provided are the ones worth triggering. |
| obs_hotkey_triggerA | Fire an OBS hotkey action by name - the way to invoke plugin features that have no obs-websocket request of their own. On the reference machine that means the vertical-canvas plugin's separate recording and streaming pipeline (VerticalCanvasDock*) and Advanced Scene Switcher's start/stop and macro segments (*SwitcherHotkey). Get names from obs_hotkey_list. DANGEROUS NAMES ARE IN THE SAME NAMESPACE. OBSBasic.StopStreaming, OBSBasic.ForceStopStreaming and VerticalCanvasDockStopStreaming all sit in that list and all end a live broadcast instantly; OBSBasic.StartStreaming starts one. There is no undo and no confirmation. This tool refuses nothing, so read the name you are about to send. DO NOT USE IT AS A SHORTCUT FOR A REAL REQUEST. Duplicated names - libobs.mute, MediaSource.Play, libobs.show_scene_item.N - are registered once per source or scene, and this request takes a bare name, so which one fires is not something you control. Mute with SetInputMute, hide with SetSceneItemEnabled, switch scenes with SetCurrentProgramScene. Hotkeys are for what those cannot reach. OBS returns success for a name it accepted, not for an effect it produced; verify the thing you wanted actually changed. |
| obs_hotkey_keyA | Press a key combination at OBS, as if typed while OBS had focus. Use this only when an action has no name in obs_hotkey_list and no request - for instance a plugin binding a user configured by hand in Settings > Hotkeys. It is a blunt instrument and fails silently in both directions. If nothing is bound to the combination, OBS accepts the request and does nothing at all. If something you did not expect is bound to it, that fires instead - and OBS's default bindings include stopping the stream and the recording. There is no request that reports what is bound to what, so you cannot check first. keyId values are the OBS_KEY_* identifiers from libobs/obs-hotkeys.h - OBS_KEY_F1, OBS_KEY_A, OBS_KEY_SPACE, OBS_KEY_NUM1 and so on - not browser key names and not raw characters. Modifiers go in keyModifiers, not in keyId. |
| obs_monitor_listA | List the physical displays OBS can put a fullscreen projector on, with the index each one answers to. Always call this before opening a fullscreen projector: the index is positional, it is not stable across replugging a display, and there is no request that tells you which one OBS's own window is on. If this returns a single monitor - which is what the reference machine reports, one 1920x1080 at index 0 - then there is no spare screen, and every fullscreen projector will land on top of the operator's OBS window. Since obs-websocket has no way to close a projector, that has to be undone by hand at the machine. Use windowed mode instead when the count is 1. |
| obs_projector_open_mixA | Open a projector showing a whole video mix - program (what is going out), preview (what studio mode has queued up), or multiview (the grid of all scenes). program on a second monitor is the standard clean-feed trick: a capture card or a second PC pointed at that display gets the finished broadcast picture without a second encode and without OBS chrome. preview is the confidence monitor for whoever is operating. multiview is for a director watching everything at once. Defaults to a WINDOW. Pass monitorIndex only when obs_monitor_list shows a display you can afford to lose, because fullscreen covers that entire screen and obs-websocket cannot close or enumerate projectors - this window stays until someone closes it in the OBS UI. |
| obs_projector_open_sourceA | Open a projector showing ONE source on its own, rather than the whole mix. sourceName takes a scene name as readily as an input name - in OBS a scene is a source - so this projects either a single camera, screen capture or media input, or an entire scene composed as it would look on air. What it is for: feeding one specific picture to hardware or to a person. A guest's camera on a monitor they can see, one screen share to a capture card, a scene routed to a second machine - all without re-encoding anything, because the projector is just the same frames drawn to a window. A source projector shows that source ALONE. Overlays that live in a different scene are not in it: on the reference machine the HUD is its own scene added into the others, so projecting a camera source gives you the bare camera, and projecting a scene gives you that scene's own composite. If you want what the audience sees, that is the program mix, not a source - use obs_projector_open_mix. Defaults to a WINDOW. obs-websocket cannot close or enumerate projectors - this window stays until someone closes it in the OBS UI. |
Prompts
Interactive templates invoked by user choice
| Name | Description |
|---|---|
No prompts | |
Resources
Contextual data attached and managed by the client
| Name | Description |
|---|---|
No resources | |
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/Giancarlo26/obs-action-history'
If you have feedback or need assistance with the MCP directory API, please join our Discord server