fix(code): honest MCP OAuth callback close message (#4410)

Fixed the MCP OAuth callback page so it no longer falsely claims the
browser tab will close automatically.

---

The MCP OAuth loopback callback page told users "This tab will close
automatically", but the flow launches the browser via
`webbrowser.open()` — an OS-opened tab, not a script-opened
`window.open` window — so browser security policy refuses
`window.close()` and the tab stays open with a misleading message. This
keeps the best-effort close (still works for the rare script-opened
case) and updates the wording to tell the user they can close the tab
and return to their terminal.

Made by [Open
SWE](https://openswe.vercel.app/agents/1ae8b968-6cc9-edda-8a81-4c506c40bfc4)

Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
This commit is contained in:
Mason Daugherty
2026-07-01 15:14:12 -04:00
committed by GitHub
parent e355213eb0
commit ef637f4a3f
+17 -8
View File
@@ -766,7 +766,7 @@ class _LoopbackOAuthCallbackServer:
200,
_oauth_success_html(
"MCP authorization complete. "
"This tab will close automatically.",
"You can close this tab and return to your terminal.",
),
)
else:
@@ -810,7 +810,8 @@ class _LoopbackOAuthCallbackServer:
handler,
200,
_oauth_success_html(
"MCP authorization complete. This tab will close automatically.",
"MCP authorization complete. "
"You can close this tab and return to your terminal.",
),
)
@@ -860,12 +861,20 @@ def _oauth_result_html(
escaped_heading = html.escape(heading)
escaped = html.escape(message)
# `window.close()` is only honored for tabs the script itself opened
# (browser policy), but for the common case where the auth flow was
# launched via `window.open` / `target=_blank` from another page, the
# tab closes cleanly. When the browser refuses, the user still sees the
# static success page and the message text remains accurate.
# (browser policy). The loopback flow launches the browser via
# `webbrowser.open`, so the callback tab was opened by the OS rather than
# by a script and the browser refuses to close it. Attempt the close for
# the rare script-opened case, then rewrite the message so it stays
# accurate when the tab stays open instead of promising it will vanish.
auto_close = (
"<script>setTimeout(function(){window.close();},2000);</script>"
"<script>setTimeout(function(){"
"window.close();"
"setTimeout(function(){"
"var m=document.getElementById('oauth-message');"
"if(m){m.textContent="
"'You can close this tab and return to your terminal.';}"
"},500);"
"},1000);</script>"
if status == "success"
else ""
)
@@ -887,7 +896,7 @@ def _oauth_result_html(
"</style></head><body>"
'<main class="panel">'
f'<div class="mark" style="background:{background};color:{accent}">{mark}</div>'
f"<h1>{escaped_heading}</h1><p>{escaped}</p>"
f'<h1>{escaped_heading}</h1><p id="oauth-message">{escaped}</p>'
"</main>"
f"{auto_close}"
"</body></html>"