bug: desktop app 0.15.0 (Windows) MCP self-spawn still never fires; manual-server workaround needs undocumented CORS origin

Author: BennyjitsuCreated Sep 17, 2026Updated Sep 20, 2026

What happened?

On a clean v0.15.0 install (both desktop app and @open-pencil/mcp/@open-pencil/cli npm packages), the desktop app's own MCP self-spawn path never fires — no mcp.json discovery file is ever written and nothing ever binds port 7600 — even from a fully clean state (no stale process, no stale discovery file, confirmed by deleting %LOCALAPPDATA%\OpenPencil\mcp.json and fully quitting/relaunching the app first). This looks like the same failure #589 described for v0.14.0 ("neither self-spawn nor reuse-existing-server path completes"), still present after the v0.15.0 fix (5689ecc, closes #589).

Devtools console confirms the app is only polling health rather than spawning anything:

GET http://127.0.0.1:7600/health net::ERR_CONNECTION_REFUSED   spawn-B0Yf5ykk.js:2
[MCP] Error: MCP server did not become healthy   router-BHA7cVfY.js:154

Clicking Settings → MCP & automation → "Restart MCP server" reproduces the same two lines every time; no discovery file is ever created as a result of clicking it.

A second, separate bug in the manual-server workaround

Starting the server manually as a workaround (openpencil-mcp-http from the same npm package, matching version) does bind port 7600 and reports itself healthy over plain curl — but the desktop app's own webview still can't use it, because the server sends no CORS header for the app's origin:

Access to fetch at 'http://127.0.0.1:7600/health' from origin 'http://tauri.localhost' has been
blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

openpencil-mcp-http --help documents OPENPENCIL_MCP_CORS_ORIGIN (Allowed CORS origin), but nothing sets it automatically to match the app's own origin (http://tauri.localhost), and the desktop app doesn't set it when it (attempts to) spawn its own server either. Manually exporting OPENPENCIL_MCP_CORS_ORIGIN=http://tauri.localhost before starting openpencil-mcp-http fixes this half, and after that fix the app does find and use the manually-started server on the next "Restart MCP server" click / list_documents call. So the manual-server path is a full workaround for the self-spawn bug, but only once this second CORS gap is also worked around — undocumented anywhere in the CLI's own --help beyond the bare one-line flag description.

Steps to reproduce (self-spawn failure)

  1. Windows 11 (build 10.0.26200.9457), OpenPencil desktop v0.15.0, @open-pencil/mcp/@open-pencil/cli v0.15.0 (npm global install).
  2. Confirm clean state: no %LOCALAPPDATA%\OpenPencil\mcp.json, nothing listening on 127.0.0.1:7600, no orphaned node.exe from a prior run.
  3. Launch the desktop app, open a .fig document.
  4. GET http://127.0.0.1:7600/health → connection refused. No discovery file appears at any point.
  5. Settings → MCP & automation shows Status: Error, "MCP server did not become healthy." Click "Restart MCP server" — same result, every time, no discovery file, nothing on port 7600.
  6. From an MCP client (Claude Code via openpencil-mcp stdio bridge), any tool call (list_documents) fails with "OpenPencil app is not connected."

Steps to reproduce (CORS gap in manual workaround)

  1. With the app in the broken state above, run openpencil-mcp-http manually in a terminal (no env vars) — binds :7600, writes a correct mcp.json (matching pid/port/token), GET /health returns 200 via curl.
  2. Click "Restart MCP server" in the app (or wait for its own poll) → devtools console shows the CORS error above (net::ERR_FAILED 200 (OK), blocked by missing Access-Control-Allow-Origin), and the same "MCP server did not become healthy" toast as before, despite the server being genuinely up and healthy.
  3. Kill that server, restart it with OPENPENCIL_MCP_CORS_ORIGIN=http://tauri.localhost set, confirm the header is now present:
    bash
    curl -s -H "Origin: http://tauri.localhost" -D - http://127.0.0.1:7600/health -o /dev/null
    → access-control-allow-origin: http://tauri.localhost
  4. Click "Restart MCP server" again → connects successfully, list_documents from the MCP client now succeeds.

Environment

  • OS: Windows 11, build 10.0.26200.9457
  • OpenPencil desktop: 0.15.0 (OpenPencil.exe ProductVersion)
  • @open-pencil/mcp / @open-pencil/cli: 0.15.0 (npm global)
  • node: v24.19.0
  • Transport: TCP, port 7600, authRequired: true

Suggested direction

  • Whatever regressed between the #589 fix landing and this v0.15.0 build for the self-spawn path — the app-side "spawn my own server" logic still appears not to run/complete on this environment, going by the complete absence of any discovery file or bound port, ever, across multiple clean-state relaunches.
  • Separately: the desktop app should pass its own origin as OPENPENCIL_MCP_CORS_ORIGIN whenever it spawns (or expects a user to spawn) the MCP server, or the server should default to allowing http://tauri.localhost out of the box, since that's the only origin that will ever legitimately call it from the app's own webview. Right now a user who manually works around the self-spawn bug hits a second, silent, undocumented wall.

Happy to gather more diagnostics (HAR export, more console output, etc.) if useful — this was fully reproduced live tonight, not a one-off.