Skip to content

fix(mcp): Windows .dxt sign-in browser now opens reliably (product#3839) - #139

Merged
milstan merged 2 commits into
mainfrom
ArtyETH06/fix-windows-authentification-not-showing
Jul 3, 2026
Merged

fix(mcp): Windows .dxt sign-in browser now opens reliably (product#3839)#139
milstan merged 2 commits into
mainfrom
ArtyETH06/fix-windows-authentification-not-showing

Conversation

@ArtyETH06

Copy link
Copy Markdown
Contributor

What & why

Some Windows users installing the .dxt bundle never saw the sign-in browser open for OAuth, so they couldn't authenticate.

Root cause: on Windows openInBrowser resolved on the child's "spawn" event — the moment cmd.exe was created, before its internal start builtin actually handed the URL to the default browser. A silent no-op (no default-browser protocol association, a locked-down shell / AppLocker, a corrupt HKCR\http\shell\open) went undetected: browserOpenFailedAtBootstrap stayed false and the user was told "a browser may have opened" when nothing did.

Change

  • openInBrowser (Windows only) now waits (bounded — 800ms for cmd start, 1200ms otherwise) for each launcher's exit code, treats a non-zero exit as failure, and falls through to shell-free launchers: rundll32 url.dll,FileProtocolHandler (Explorer's ShellExecute path — no command interpreter, honest exit code) then PowerShell Start-Process. Spawns with detached:false on Windows so exit is observable; keeps windowsVerbatimArguments.
  • When every launcher fails, the existing AUTH_REQUIRED envelope honestly reports the browser couldn't be opened and shows the clickable sign-in link.
  • macOS/Linux are unchanged — they keep resolve-on-spawn (the #3805 headless-hang fix; open/xdg-open are the hand-off).
  • The #3801 &-quoting cmd start candidate is unchanged and still tried first; the new shell-free launchers live in a separate windowsFallbackCandidates() so the #3801 "every candidate is quoted" pin stays green.
  • bin.ts shutdown: browserOpenInFlight wait 1.5s → 3s for the multi-launcher walk.
  • Version 0.23.10 → 0.23.11 (+ CHANGELOG). .dxt/.mcpb rebuild via existing release CI.

Tests

New files only (existing oauth-browser-open*.test.ts untouched):

  • oauth-browser-open-win32-candidates.test.tsbrowserOpenCandidates win32 head stays the pinned cmd pair; windowsFallbackCandidates returns rundll32 then powershell with the raw URL.
  • oauth-browser-open-win32-exit-wait.test.ts — cmd exit-0 resolves without spawning fallbacks; cmd no-op (exit 1) falls through to rundll32; all non-zero → rejects; cmd never-exits → resolves via timeout; detached:false on win32 / true on linux; POSIX still resolves on spawn without waiting for exit (protects #3805).

pnpm -r build (dxt bundle builds + staged server starts + version self-check), pnpm -r test (core 494, mcp 512, promptforge 16), and pnpm -r typecheck all green.

No eval coverage for this change — it's a platform browser-launch fix, not a tool/prompt/WORKFLOWS.md behaviour change.

Closes https://github.com/leadbay/product/issues/3839

On Windows, openInBrowser resolved the moment cmd.exe was CREATED — before
its `start` builtin actually handed the URL to the browser. A silent no-op
(no default-browser association / a locked-down shell / AppLocker) went
undetected: nothing opened yet the flow reported success and told the user
"a browser may have opened."

Windows now waits (bounded) for each launcher's exit code, treats a non-zero
exit as failure, and falls through to shell-free launchers — rundll32
url.dll,FileProtocolHandler (Explorer's ShellExecute path, honest exit code)
then PowerShell Start-Process. When all fail, browserOpenFailedAtBootstrap is
set and the AUTH_REQUIRED envelope honestly says the browser couldn't open,
with the clickable sign-in link. macOS/Linux keep resolve-on-spawn (the #3805
headless-hang fix). The #3801 &-quoting cmd candidate is unchanged, tried
first. Shutdown browser-open wait 1.5s -> 3s for the multi-launcher walk.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@ArtyETH06 ArtyETH06 self-assigned this Jul 2, 2026
The PowerShell Start-Process fallback passed the raw URL after `-Command`, which
parses everything as PowerShell SOURCE — so an OAuth authorize URL's `&` (query
separators) would be read as PS's call/separator operator and the URL mangled or
split, breaking the last recovery path on locked-down Windows (both cmd
candidates failed + rundll32 unavailable). Wrap the URL in a single-quoted PS
string literal (verbatim form; escape embedded `'` by doubling). rundll32 keeps
the raw URL (no shell). New test covers the multi-`&` URL and the quote-escape.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@ArtyETH06
ArtyETH06 marked this pull request as ready for review July 2, 2026 20:26
@ArtyETH06
ArtyETH06 requested a review from milstan July 2, 2026 20:26
@milstan
milstan merged commit 2f8ea9c into main Jul 3, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants