Skip to content

feat: expose OpenWork UI control MCP bridge - #1644

Merged
benjaminshafii merged 4 commits into
devfrom
feat/openwork-ui-control-mcp
May 4, 2026
Merged

benjaminshafii merged 4 commits into
devfrom
feat/openwork-ui-control-mcp

Conversation

@benjaminshafii

@benjaminshafii benjaminshafii commented May 4, 2026 •

Copy link
Copy Markdown
Member

Summary

  • Adds a provider-neutral window.__openworkControl action registry for semantic OpenWork UI state/action discovery.
  • Registers domain-owned session/composer/status actions so external controllers can list sessions, open/rename/delete sessions, type/send/stop composer drafts, read transcript/latest messages, and navigate app surfaces.
  • Adds the private localhost OpenWork UI bridge plus packages/openwork-ui-mcp so MCP clients can call ui_status, ui_snapshot, ui_list_actions, and ui_execute_action.

Scope

This PR intentionally excludes built-in Realtime, microphone permissions, Realtime server endpoints, and Feature Preview UI. Those are split into the follow-up draft PR.

Verification

  • pnpm install --lockfile-only ✅
  • pnpm install ✅
  • node --check packages/openwork-ui-mcp/index.mjs ✅
  • node --check apps/desktop/electron/main.mjs ✅
  • pnpm --filter @openwork/app typecheck ✅

How to test

Package checks

git checkout feat/openwork-ui-control-mcp
cd packages/openwork-ui-mcp
npm install --ignore-scripts
node --check index.mjs
npm publish --dry-run --access public

Local Electron bridge

Launch OpenWork desktop locally, then confirm one discovery file exists:

ls "$HOME/Library/Application Support/com.differentai.openwork/openwork-ui-control.json"
ls "$HOME/Library/Application Support/com.differentai.openwork.dev/openwork-ui-control.json"

Test the bridge directly:

DISCOVERY="$HOME/Library/Application Support/com.differentai.openwork.dev/openwork-ui-control.json"
BASE_URL=$(jq -r .baseUrl "$DISCOVERY")
TOKEN=$(jq -r .token "$DISCOVERY")

curl "$BASE_URL/health"
curl -H "Authorization: Bearer $TOKEN" "$BASE_URL/snapshot"
curl -H "Authorization: Bearer $TOKEN" "$BASE_URL/actions"
curl -X POST "$BASE_URL/execute" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"actionId":"composer.set_text","args":{"text":"Testing OpenWork UI MCP"}}'

Expected: /health returns ok: true, /actions includes actions like composer.set_text, composer.send, and session.list_sessions, and composer.set_text visibly updates the desktop composer. Unauthorized raw HTTP requests should return 401.

MCP client flow

From the repo root:

npx @modelcontextprotocol/inspector node packages/openwork-ui-mcp/index.mjs

In the inspector, call:

  1. ui_status
  2. ui_snapshot
  3. ui_list_actions
  4. ui_execute_action with:
{
  "actionId": "composer.set_text",
  "args": {
    "text": "Hello from MCP"
  }
}

Optionally send it with:

{
  "actionId": "composer.send"
}

A successful end-to-end pass means OpenWork desktop is running, MCP status is connected, snapshot shows route/actions, composer.set_text visibly updates the composer, and session.list_sessions returns sessions. Use the underscore MCP tool names (ui_snapshot, ui_list_actions, ui_execute_action).

@vercel

vercel Bot commented May 4, 2026 •

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
openwork-app Ready Ready Preview, Comment May 4, 2026 8:07pm
openwork-den Ready Ready Preview, Comment May 4, 2026 8:07pm
openwork-den-worker-proxy Ready Ready Preview, Comment May 4, 2026 8:07pm
openwork-landing Ready Ready Preview, Comment, Open in v0 May 4, 2026 8:07pm
openwork-share Ready Ready Preview, Comment May 4, 2026 8:07pm

@github-actions

github-actions Bot commented May 4, 2026

Copy link
Copy Markdown
Contributor

The following comment was made by an LLM, it may be inaccurate:

@benjaminshafii
benjaminshafii merged commit a41c464 into dev May 4, 2026
16 checks passed
benjaminshafii added a commit that referenced this pull request May 15, 2026
* feat: expose UI control MCP bridge

* docs: rewrite MCP UI control as a tutorial

* ci: add isolated openwork-ui-mcp check and publish workflow

* fix: harden UI control bridge
benjaminshafii added a commit that referenced this pull request May 15, 2026
* feat: expose UI control MCP bridge

* docs: rewrite MCP UI control as a tutorial

* ci: add isolated openwork-ui-mcp check and publish workflow

* fix: harden UI control bridge
@benjaminshafii
benjaminshafii deleted the feat/openwork-ui-control-mcp branch May 15, 2026 17:37
yomgui added a commit that referenced this pull request Sep 10, 2026
* fix(app): return every loaded session from session.list_sessions

session.list_sessions hard-coded `out.slice(0, 30)` since the original UI
control bridge (#1644) even though the app already holds up to 200 sessions
per workspace in memory. The action exposed no `limit` or `workspaceId` args
and no truncation signal, so an agent asked to inventory ~100 sessions could
not see them and fell back to scraping OpenCode storage on disk.

- Return every loaded session (pinned first, then newest) by default.
- Accept optional `limit` (opt-in cap) and `workspaceId` (exact id or
  display-name match, never falls back to another workspace).
- Extract the pure listing into list-control-sessions.ts so the behavior is
  provable without booting Electron; keep the array result shape that the
  existing e2e specs consume.
- Document the args in the UI control profile and cross-chat memory docs.

Proof: evals/specs/session-list-sessions-inventory.test.ts (4 tests) fails
3/4 with the old cap and passes 4/4 with the fix.

* fix(app): parse list_sessions args in the pure helper; drop personal name from docs

- listControlSessions now takes the raw control-action payload, so the hook's
  execute is a one-line pass-through and the spec covers arg forwarding
  (null / {} / positive-integer limit / trimmed workspaceId) exactly as the
  control bridge delivers it (Warden 2C6-KRW).
- Replace a real-looking personal name in the public cross-chat-memory example
  with a fictional topic (Warden 2T3-GM4).

This branch was successfully deployed

5 active deployments
Preview – openwork-den-worker-proxy — 84d3df41 Deployed May 4, 2026 by vercel[bot]
Preview – openwork-den — 84d3df41 Deployed May 4, 2026 by vercel[bot]
Preview – openwork-landing — 84d3df41 Deployed May 4, 2026 by vercel[bot]
Preview – openwork-app — 84d3df41 Deployed May 4, 2026 by vercel[bot]
Preview – openwork-share — 84d3df41 Deployed May 4, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant