Skip to content

MCP: one server, two transports — the app is the authority when it runs #1174

Closed

Description

@EtienneLescot

Decision

A coding agent connected over MCP must be able to edit the project open in the editor, whichever transport it uses. This supersedes the refusal shipped in #1154 for #1138, which was the right stop-gap against silent data loss but the wrong product behaviour for the stdio server, the transport our agent workflow (openscreen mcp, the openscreen-demo skill) relies on.

Today: two servers that ignore each other

In-app (HTTP) stdio (Openscreen.exe mcp)
Setup app running, AI settings → enable, allow edits, copy token claude mcp add openscreen -- Openscreen.exe mcp
Process the GUI a separate CLI process
Project open in the editor live edit, one Ctrl+Z step per call refused since #1154
Other projects guarded file write, checkpoint required same
Record, export, getFrames, setPointerTrack, listSources absent present
Checkpoints in memory, lost on any server restart (port, token) in memory, lost when the client exits

Neither takes precedence; each client binds to one. Their strengths are inverted, so no single connection gives an agent the full loop (record, edit the open project, export).

What is already shared and stays the base: the tool table and schemas (electron/ai-edition/deep-agent/service.ts, also used by the in-app chat agent), the mutation logic (executeAgentTool), the routing (createToolRunner), the persistence class (DocumentService).

What is not clean (paths at main @ 912b448):

  • Two processes write the same projects; only the .open-in-editor.json marker and a byte compare guard them from each other. Checkpoints are per process and never shared.
  • setPointerTrack (electron/mcp/media-tools.ts) bypasses the runner: it writes the cursor sidecar before the guarded save, adds zooms without a checkpoint, and restoreCheckpoint does not undo the sidecar.
  • stdio replaces MCP_PREAMBLE with MEDIA_PREAMBLE instead of composing them (electron/mcp/stdio-server.ts), so stdio clients lose the checkpoint rule and inherit text that is false there ("Project edits are turned off", "No project is open in the editor", restoreCheckpoint's "one undo step"). The base system prompt says no tool exports, false over stdio. The fix(mcp): refuse stdio edits to a project open in the app's editor #1154 refusal points to the in-app server, which lacks record and export.
  • Docs: technical-documentation/architecture/mcp-server.md only describes HTTP; website/docs/ai-editing.md still says the tools act on the open project only; two settings share the label "Project edits"; a code comment (openscreen-mcp-server.ts ~105) says the MCP edit setting is the agent's, the store says it is separate.

Target: one MCP, two transports

  1. The app is the authority when it runs. The stdio server detects a running app and forwards every call to it over a local, per-user channel (no token; OS-level access limited to the current user). Edits to the open project then land live with Ctrl+Z, and checkpoints live in one place shared by both transports. When no app runs, stdio works alone on files as today; no editor exists, so nothing can conflict. The app starting or quitting mid-session is handled. The fix(mcp): refuse stdio edits to a project open in the app's editor #1154 refusal only remains as a fallback when the app does not answer.
  2. Same tools on both transports. Record, export, getFrames, setPointerTrack, listSources are also offered by the in-app server; the app records anyway.
  3. One source for text and docs. A shared preamble plus capability blocks per transport, tool descriptions true on both, one architecture doc covering both transports, website docs and the skill aligned, one label per setting.
  4. setPointerTrack goes through the runner: guard before any write, covered by checkpoints including the sidecar.

Plan

  • PR 1: text and docs single source, label fix, setPointerTrack through the runner. Low risk.
  • PR 2: stdio forwards to the running app (the core of this issue). Updates the fix(mcp): refuse stdio edits to a project open in the app's editor #1154 refusal path and the e2e checklist line ("MCP server — post-2.0.0").
  • PR 3: tool parity on the in-app server, after PR 2.

Found during the v2.1.0 e2e passes (#1132, #1172). Refs #1138, #1154.

Activity

  1. added
    status: fixed in mainWork is merged into main but may not be in a downloadable release yet.
    status: pending releaseMerged change is waiting for a packaged desktop release.
    on Oct 13, 2026
  2. added this to the Next Release milestone on Oct 13, 2026
  3. github-actions commented on Oct 13, 2026

    @github-actions
    Contributor

    Fixed by #1179 and merged into main.

    This change is assigned to the Next Release release milestone and is not necessarily available in the latest downloadable desktop release yet. It is currently marked as status: pending release until a packaged release containing it is published.

  4. EtienneLescot commented on Oct 15, 2026

    @EtienneLescot
    MemberAuthor

    Moved into v2.1.0 as part of the pre-release cut.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    status: fixed in mainWork is merged into main but may not be in a downloadable release yet.status: pending releaseMerged change is waiting for a packaged desktop release.

    Type

    No type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions