* fix(mcp): close orphaned servers that no app ever claims
- Add ServerOptions.appAttachTimeoutMs: if no app registers within this
window after startup, the server closes itself and removes its
discovery file, instead of squatting the port indefinitely.
- Wire it through the openpencil-mcp-http CLI as
OPENPENCIL_MCP_APP_TIMEOUT_MS (opt-in, unset/0 disables it — a bare
CLI invocation for manual testing should not self-terminate).
- The desktop app opts in with a 30s timeout when it spawns the server.
Without this, a server that outlives its spawning app (renderer crash,
forced reload) keeps holding its port with a stale discovery file. The
app's liveness check only asks whether something answers /health, not
whether an app has ever registered (see /health's no_app status) — so
every later launch finds the orphan already listening and defers to
it, and MCP tool calls fail with "app is not connected" until someone
manually kills the orphaned process. Closing self-caused orphans at
the source means the next launch finds no discovery file and takes
the normal fresh-spawn path.
Fixes#488
* fix(mcp): clean up servers after app disconnects
- Re-arm the orphan watchdog when the registered app disconnects
- Cancel pending shutdown when the app reconnects within the grace period
- Reject timeout values that overflow the runtime timer range
* test(mcp): make watchdog reconnect coverage deterministic
- Wait for the disconnected health state before reconnecting
- Report distinct safe-integer and timer-range validation errors
---------
Co-authored-by: swe-sanad <sanad.arousi@export119.com>
- Rename first-party API, RPC, JSON, CORS, SVG, JSX, and related identifiers to preserve acronym casing
- Keep upstream and serialized boundary names unchanged
- Add a lint guardrail and migration notes for exported APIs
- Resolve MCP workspace subpaths during Vite development
- Remove discovery state before shutdown and close upgraded sockets
- Cover discovery cleanup with a connected WebSocket client
Co-authored-by: Joseph Cumines <joeycumines@gmail.com>
- Prefer private Unix sockets with TCP fallback for local MCP clients
- Unify HTTP and WebSocket lifecycle, authentication, and cleanup
- Discover transport details from an owner-only runtime file
- Add AST-based lint checks for broad unknown object assertions and local JsonObject aliases
- Centralize JsonObject in core and package-local MCP RPC JSON typing
- Replace baseline Record<string, unknown> assertions with named shared/domain types
- Remove stale imports and unused locals from split engine and e2e tests
- Drop the targeted no-unused-vars test allowances
- Keep check and affected test suites warning-free
- Configure oxfmt custom import groups for workspace, app, package, and test aliases
- Keep type imports grouped with their matching source category instead of one global tail group
- Expand the format script to cover formatter config, Vite files, and scripts
- Move top-level engine and e2e prefixed test files under domain folders
- Update fixture path helpers after moving render and pen tests
- Add lint coverage to prevent new top-level prefixed test files
- Refresh testing docs for the new fig and layout paths