Repository navigation
MCP stdio edits to a project open in the editor are lost on its next autosave #1138
Description
Summary
An edit sent through the stdio MCP server (Openscreen.exe mcp) to a project that is open in the GUI editor is accepted, written to disk, then silently overwritten by the editor's next autosave. The agent is told the edit succeeded; it is gone. P1, silent data loss.
Repro
Measured on the CI build of release/v2.1.0 @ 9c55596, Windows 11:
- Open project P in the GUI editor.
- From a stdio MCP client (official MCP SDK client):
addTrim {projectId: P, ...}is refused with "not open in the editor ... call createCheckpoint first", so the server believes P is closed.listProjectsreports P withopen: false. createCheckpoint {projectId: P}, thenaddTrim: accepted, project file rewritten at 17:07:25 with the trim.- Change anything in the editor (e.g. background animation): autosave at 17:07:44 rewrites the file without the MCP trim.
The checklist requires the opposite (manual-e2e-checklist.md, MCP server — post-2.0.0): "Open the project in the editor, then send an MCP edit to it as a closed project, and confirm it is refused rather than overwriting the editor's copy."
Root cause
openscreen mcpis a separate process. CLI runs skip the single-instance lock (electron/main.ts,hasSingleInstanceLock) so they can run beside the app.- The MCP server learns which project is open only from
McpDocumentHost.snapshot(), that is from an editor window in its own process (EditorDocumentHost). The stdio process has no editor, so every project looks closed:listProjectssaysopen: falseand edits take the file path (runOnFile). DocumentService.saveProjectIfUnchangedguards against an editor that opened the project mid-call only through an in-process read generation plus a compare of the file content. The GUI read the project before the call, in another process, so neither check sees it.- The editor then saves its own copy with
saveProject, which does not look at the file. The external edit is lost without a word.
The in-app HTTP server is not affected: it lives in the GUI process and asks the editor.
Proposed fix
- The GUI main process records which project its editor holds in a small marker file beside the projects (
<projects>/.open-in-editor.json,{ pid, projectId }), written when the editor loads or switches project and removed when it closes the project or its window goes away. DocumentService.projectOpenInEditor()reads it. A marker whose pid is no longer alive is ignored, so a crashed GUI never blocks edits; the next GUI replaces it.- The MCP server uses it in both processes:
listProjectsreportsopentruthfully across processes, and a write to a project open in another process's editor is refused with a message that says to close it there or use the in-app MCP server. saveProjectIfUnchanged, which every external writer goes through (the document tools andsetPointerTrack), checks the marker again inside the project's write queue just before writing, so the guard does not depend on the tool entry.
Editor-side guard: not in this fix
The editor could also refuse to save over a file someone else changed. Not done here:
- With the marker in place, no OpenScreen writer edits a project the editor holds, so there is no external write left for it to catch, apart from the race below.
- Detecting it is the easy half. The hard half is what to do next (reload, merge, or ask the user), which needs UX of its own and is out of proportion for a release-candidate fix.
Known ceilings:
- An editor that reads the project in the few milliseconds between the marker check and the write can still hold a copy without that edit.
- A pid reused after a GUI crash can make a project look open until the GUI's editor runs again. That fails toward a refusal, never toward a silent overwrite.
Activity
EtienneLescot commentedon Oct 12, 2026
Also reproduced on macOS 26.5 arm64, same candidate (
release/v2.1.0@ 9c55596, build run 38252812147), e2e results in #1131:proj_4a7d8831("E2E speech fixture"), the stdio server'slistProjectsreportedopen: falsefor it. AnaddTrimto it was refused only because no checkpoint existed ("this project is not open in the editor ... Call createCheckpoint"), not because the editor held it.createCheckpoint, the same kind of edit was accepted (success returned to the agent), then lost when the editor saved its own copy.So this is not Windows-specific: the stdio process has no editor of its own on any platform. #1139 was a duplicate of this one and is closed.
fix(mcp): refuse stdio edits to a project open in the app's editor
github-actions commentedon Oct 13, 2026
Fixed by #1154 and merged into
main.This change is assigned to the
Next Releaserelease milestone and is not necessarily available in the latest downloadable desktop release yet. It is currently marked asstatus: pending releaseuntil a packaged release containing it is published.