Repository navigation
Resources, prompts, and opt-in confirmation for live actions - #7
Conversation
Resources: obs://status, obs://scenes, obs://scene/{sceneName}/items, and
obs://scene/{sceneName}/screenshot. OBS events become resources/updated
notifications: 2025-era clients get them for URIs they subscribe to, and
2026-07-28 clients filter them on their listen stream. Each session removes
its OBS listeners when it closes.
Prompts: record-demo and pre-stream-check.
OBS_MCP_CONFIRM_LIVE makes stop/toggle stream and record ask first: through
elicitation when the client supports it (2025 elicitation/create and the
2026 input_required round trip), otherwise by requiring confirm: true.
initialize() now takes an options object. Long-running tasks are left out:
SDK 2.0.0 has no tasks runtime and no client surveyed supports the extension.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Vjn8uBEa4mJshaQU3pFuqX
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 9a20e4ae1c
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| const [record, stream, scene] = await Promise.all([ | ||
| client.sendRequest("GetRecordStatus"), | ||
| client.sendRequest("GetStreamStatus"), | ||
| client.sendRequest("GetCurrentProgramScene"), | ||
| ]); |
There was a problem hiding this comment.
Return connection status while OBS is offline
When OBS is unavailable, each sendRequest attempts to connect and rejects, so this Promise.all fails before the resource can serialize client.getConnectionStatus(). As a result, obs://status cannot report the disconnected state—the main reason to include connection information—and instead blocks for the connection timeout and returns a resource error. Return the connection state with unavailable OBS fields omitted or nullable when the client is disconnected.
Useful? React with 👍 / 👎.
| const listeners: [string, (eventData: unknown) => void][] = [ | ||
| ...STATUS_EVENTS.map((event): [string, () => void] => [event, () => notify(STATUS_URI)]), | ||
| ...SCENE_LIST_EVENTS.map((event): [string, () => void] => [event, () => notify(SCENES_URI)]), |
There was a problem hiding this comment.
Notify status subscribers on connection changes
When the OBS socket disconnects or reconnects, OBSWebSocketClient emits disconnected and identified (src/client.ts), not any of the OBS protocol events in STATUS_EVENTS. Therefore a client subscribed to obs://status receives no update for the connection changes that this resource explicitly advertises, leaving its cached status stale until an unrelated output or scene event occurs.
Useful? React with 👍 / 👎.
| const SCENE_ITEM_EVENTS = [ | ||
| "SceneItemCreated", | ||
| "SceneItemRemoved", | ||
| "SceneItemListReindexed", | ||
| "SceneItemEnableStateChanged", | ||
| "SceneItemLockStateChanged", | ||
| ]; |
There was a problem hiding this comment.
Notify scene-item subscribers after transform changes
When an item's position, crop, scale, or other transform changes, GetSceneItemList returns different data and OBS emits SceneItemTransformChanged, but that event is omitted here. Subscribers to the per-scene items resource therefore keep stale transform data after common layout operations until another listed item event happens.
Useful? React with 👍 / 👎.
Stacked on #6.
Resources. Each one duplicates a read-only tool, since many clients read resources rarely or not at all.
obs://statusobs://scenesobs://scene/{sceneName}/itemsobs://scene/{sceneName}/screenshotresources/updatedonly for URIs they subscribed to. The subscribe and unsubscribe handlers are registered here, becauseMcpServerdoesn't register them.subscriptions/listenstream.Prompts.
record-demowalks through capture-window → preflight → record-clip.pre-stream-checkis a read-only go/no-go review.OBS_MCP_CONFIRM_LIVE(off by default)elicitation/createand the 2026input_requiredround trip are tested.confirm: true..mcpbuser setting.Left out on purpose
tools/list_changed: tool filtering is fixed at startup.Tests
Results:
npm run check: 106 unit, 10 e2enpm run test:packagepasses🤖 Generated with Claude Code
https://claude.ai/code/session_01Vjn8uBEa4mJshaQU3pFuqX