Control OBSBOT Tiny 2 webcam over USB with pan/tilt/zoom, AI tracking, image settings, snapshots, and recording via MCP.
Copy the AI prompt to install this server into Claude Code, Cursor, or another agent β or use 1-click editor setup below.
We haven't yet run this listing's install command through our automated sandbox check. This isn't a red flag β we're steadily working through the catalog.
π‘ Paste the JSON block into your client's configuration file under mcpServers, then restart the application.
Inspect callable tools, capabilities, and parameters exposed to AI agents by Obsbot MCP.
obsbot_devicesList attached OBSBOT cameras with each one's serial (where obtainable), name, and status (`available`/`bound`/`busy`). A `busy` camera is held by another process.
obsbot_wakeWake the camera/gimbal (sends `"run"`). **Moves the camera:** un-stows the gimbal back to level (pitch ~0). Most control commands also wake it implicitly.
obsbot_sleepSleep the camera/gimbal (sends `"sleep"`). **Moves the camera:** stows the gimbal face-down at roughly pitch `84`, so `obsbot_gimbal_position` reads ~84 rather than the pose you left.
obsbot_statusRead the live status block: `{ awake, hdr, faceAe, aiMode, trackSpeed, fovMode, zoomPercent, focusMode, focusPosition }` (`faceAe` = auto-exposure metering for a detected face; `fovMode` = `wide`\
obsbot_gimbal_moveMove the gimbal to an absolute angle. Positive yaw pans to the camera's left, positive pitch tilts down. Yaw clamped to `[-150, 150]`, pitch to `[-90, 90]`. Absolute 1:1 degrees, hardware-verified.
obsbot_gimbal_move_speedDrive the gimbal at a speed, then auto-stop after `autoStopMs` so it can't run away. Same yaw/pitch sign convention as `gimbal_move`. Returns the speeds actually used. Past its limit the firmware ignores the command outright rather than saturating β 180 deg/s and above move the gimbal exactly 0Β° ββ¦
A cross-platform Model Context Protocol server that controls an OBSBOT Tiny 2 camera over its standard UVC/USB interface β pan/tilt/roll the gimbal, zoom, AI subject tracking, focus/exposure/white-balance/image controls, HDR and field-of-view, plus snapshot, preview, and recording β without any vendor SDK.
Add a stdio server entry pointing at the installed binary (or directly at dist/index.js):
If you're running from a local checkout instead of an npm install, point command/args at
node and the built entry point instead:
By default the server advertises only the normal control surface. Pass --debug to additionally
expose the diagnostics surface β the obsbot_debug_probe tool (raw XU byte get/set/query) and the
raw 60-byte status block on obsbot_status:
With the installed binary, use "command": "obsbot-mcp" and "args": ["--debug"].
35 tools on Windows and macOS, 34 on Linux (obsbot_gimbal_move_speed is unavailable there β see
limitations). --debug adds obsbot_debug_probe for
one more. All names below are current as of v0.4.0 β every tool was renamed in this
release and there is no backward-compatible alias; see CHANGELOG.md for the
full oldβnew mapping if you're updating a caller.
camera selectorEvery camera-addressing tool accepts an optional camera parameter: the target camera's serial
number. Omit it with a single camera attached and nothing changes β this matches the server's
pre-v0.4.0, single-camera behaviour exactly. With more than one camera attached, a call that omits
camera fails with an error naming every attached serial, so you always know what to pass next.
Exempt (no camera parameter, ever): obsbot_devices (enumerates the whole fleet),
obsbot_capture_stop / obsbot_capture_list (address a sessionId, not a device), and
obsbot_debug_probe (operates on the current diagnostics transport). Two more tools honor it only
partially β see Capture below.
Multi-camera support is new in v0.4.0. It's exercised by the unit test suite against fakes; running two physical Tiny 2s at once has not yet been hardware-verified (see Known limitations).
obsbot_devices is the way to discover the serials you pass as camera: it reports each attached
camera's serial (where obtainable β reading it requires briefly opening the camera), name, and
status (available | bound | busy). A camera another process already holds comes back busy
with no serial, since it can't be opened to read one.
| Tool | Parameters | Description |
|---|---|---|
obsbot_devices | β | List attached OBSBOT cameras with each one's serial (where obtainable), name, and status (available/bound/busy). A busy camera is held by another process. |
obsbot_wake | camera? | Wake the camera/gimbal (sends "run"). Moves the camera: un-stows the gimbal back to level (pitch ~0). Most control commands also wake it implicitly. |
obsbot_sleep | camera? | Sleep the camera/gimbal (sends "sleep"). Moves the camera: stows the gimbal face-down at roughly pitch 84, so obsbot_gimbal_position reads ~84 rather than the pose you left. |
obsbot_status | camera? | Read the live status block: { awake, hdr, faceAe, aiMode, trackSpeed, fovMode, zoomPercent, focusMode, focusPosition } (faceAe = auto-exposure metering for a detected face; fovMode = wide|medium|narrow|custom|unknown, where custom means a continuous zoom overrode the discrete modes; zoomPercent = zoom position, 0-100; focusMode = auto|manual|unknown). focusPosition appears only in manual mode, on the same 0-100 scale obsbot_focus_manual takes β under autofocus the camera echoes the last written value rather than exposing the motor, so a number there would read as a live focus distance while being stale. Focus is a standard UVC control, not part of the status block, so it costs one extra read; a device that can't answer reports focusMode: "unknown" rather than failing the whole call. Under --debug, also returns the raw 60-byte block as hex. |
| Tool | Parameters | Description |
|---|---|---|
obsbot_gimbal_move | yaw, pitch, roll (degrees, roll defaults 0), camera? | Move the gimbal to an absolute angle. Positive yaw pans to the camera's left, positive pitch tilts down. Yaw clamped to [-150, 150], pitch to [-90, 90]. Absolute 1:1 degrees, hardware-verified. |
obsbot_gimbal_move_speed | yaw, pitch, roll (deg/s, clamped to Β±150, roll defaults 0), autoStopMs (default 800), camera? | Drive the gimbal at a speed, then auto-stop after autoStopMs so it can't run away. Same yaw/pitch sign convention as gimbal_move. Returns the speeds actually used. Past its limit the firmware ignores the command outright rather than saturating β 180 deg/s and above move the gimbal exactly 0Β° β so requests are clamped into the hardware-verified band. Not available on Linux β see limitations. |
obsbot_gimbal_recenter | camera? | Recenter the gimbal β drives it to yaw 0 / pitch 0. Returns as soon as the command is sent, so poll obsbot_gimbal_position if you need to know it arrived. |
obsbot_gimbal_position | camera? | Read the gimbal's current absolute { yaw, pitch } in degrees via standard UVC Pan/Tilt. Valid during a move as well as after one. On Linux this is the last-commanded value, not a live in-flight reading β see limitations. |
obsbot_aim_at_pixel | x, y, frameWidth, frameHeight, source (default "device"), camera? | Point the camera at a pixel from a frame you just captured. Reads the camera's magnification from its own reported state β a discrete FOV mode or a continuous zoom alike β so it needs no FOV or zoom argument and works at any zoom. Refuses while AI tracking is active, when the FOV mode can't be decoded, or when a corrupt zoom reading would resolve to an implausible magnification, and refuses if the camera had to be woken (waking moves the gimbal, invalidating the frame you measured) or if the zoom is still ramping (the frame was captured at a magnification the camera has already left, so wait for the zoom and take a fresh snapshot). source declares which feed the frame came from (default device) β it cannot be inferred from the pixels. A virtual/ndi frame is accepted, not refused, but only aims correctly if that feed is an unmodified pass-through of the camera; a compositor's rescale or letterbox is invisible in the picture and silently wrong here, so a non-device declaration returns a note stating that assumption. It reads the live pose to compute the aim, so on Linux it is affected the same way obsbot_gimbal_position is β see limitations. Returns clamped:true if the target was outside the gimbal's range, in which case the camera still moves β to the nearest reachable pose. Refuses (ok:false) instead of moving when the pixel lies past vertical from the current pose, since the only rotation that reaches it would swing the camera toward the opposite side of the room; tilt toward the pixel first, then re-aim. |
obsbot_zoom_to_fit | x, y, width, height, frameWidth, frameHeight, margin (default 0.1), source (default "device"), camera? | Frame a region of a frame you just captured: centre the gimbal on it and zoom so the region fills the frame. Same refusal conditions as obsbot_aim_at_pixel (AI tracking, undecodable FOV/zoom, a woken camera, a zoom still ramping, an over-the-top target, a non-16:9 frame), and the same source declaration, plus a refusal if the region isn't within the frame (edges included) or has non-positive size. margin backs the zoom off by that fraction so the region isn't framed edge-to-edge; the tighter of the region's two axes sets the zoom, so the whole region stays visible rather than being cropped on one side. Moves the gimbal before zooming β zoom is centre-preserving but not target-preserving, so zooming first can push the region out of frame. Zoom ramps rather than jumping, so the tool polls for up to 3s and returns settled:false (not an error) if the zoom hadn't arrived in time β check it before trusting a follow-up snapshot. |
obsbot_capture_snapshot returns the frame as an image plus its width/height, so a model can
locate something in the picture and then point the camera at it:
obsbot_capture_snapshot β look at the frameobsbot_aim_at_pixel β pass the target's pixel and that frame's dimensionsobsbot_capture_snapshot again β confirm it landed, and repeat if neededPass the frameWidth/frameHeight from the same snapshot the pixel came from. Mixing a pixel from
one frame with dimensions from another aims at the wrong place, and nothing can detect it.
Factual signals from GitHub, npm, and our automated checks β not a rating.
No reviews yet β be the first to share how this listing worked for you.
Showcase your server listing on GitHub or your project documentation. Embed this dynamic SVG badge to highlight official listing status and live engagement.
[](https://allmcps.com/mcp/lxman-obsbot-mcp)<a href="https://allmcps.com/mcp/lxman-obsbot-mcp"><img src="https://allmcps.com/api/badge/lxman-obsbot-mcp?style=directory" alt="Obsbot MCP on AllMCPs" /></a>