Summary
SessionStore shares a single registry file (~/.screencast-mcp/sessions.json) across all server processes. When a second MCP client launches its own server while a first server is recording, orphan reaping can terminate the first server's live ffmpeg capture.
Where
src/utils/sessions.ts reapOrphans() (~line 149), called from src/index.ts at startup.
Mechanism
- Server A starts a recording -> persists a
status: "recording" record with A's ffmpeg pid to the shared sessions.json.
- Server B starts (second MCP client).
getStore().load() reads the shared registry, then reapOrphans() runs.
- B sees A's
"recording" record, isAlive(pid) is true, so classifyOrphan returns orphaned + reaped.
isFfmpegProcess(pid) confirms it is ffmpeg.exe (but not whose), so killPid(pid) terminates A's still-running capture.
Impact
Opening a second client mid-recording can kill the first client's recording. Also, concurrent persist() calls clobber each other (last-writer-wins; see the registry hardening issue).
Possible fixes
- Tag each record with the owning server's identity (e.g. a per-process instance id / parent pid) and only reap records owned by the current instance, OR
- Only reap records whose pid is dead (never kill a live pid owned by another live server), OR
- Move to per-instance registries, or a lock + read-merge-write on the shared file.
Related: registry concurrency/pruning hardening (see linked issue).
Summary
SessionStoreshares a single registry file (~/.screencast-mcp/sessions.json) across all server processes. When a second MCP client launches its own server while a first server is recording, orphan reaping can terminate the first server's live ffmpeg capture.Where
src/utils/sessions.tsreapOrphans()(~line 149), called fromsrc/index.tsat startup.Mechanism
status: "recording"record with A's ffmpeg pid to the sharedsessions.json.getStore().load()reads the shared registry, thenreapOrphans()runs."recording"record,isAlive(pid)is true, soclassifyOrphanreturnsorphaned+reaped.isFfmpegProcess(pid)confirms it isffmpeg.exe(but not whose), sokillPid(pid)terminates A's still-running capture.Impact
Opening a second client mid-recording can kill the first client's recording. Also, concurrent
persist()calls clobber each other (last-writer-wins; see the registry hardening issue).Possible fixes
Related: registry concurrency/pruning hardening (see linked issue).