feat(mcp): add OSC 52 copy hotkey for OAuth authorization URL#3393
Conversation
When MCP OAuth authentication falls back to the "copy this URL into your browser" path (e.g. remote/web terminal where the browser can't auto-open), long URLs wrap across lines inside the bordered dialog and the trailing │ border characters get selected alongside the URL, forcing the user to manually strip them out before pasting. Surface the URL on a dedicated event and let the user press 'c' to push it to the local clipboard via an OSC 52 escape sequence. Works through SSH and modern web terminals (iTerm2, Windows Terminal, xterm.js-based emulators, tmux with set-clipboard, etc.) without a subprocess, and falls back to a visible "copy the URL above manually" hint when the terminal is not a TTY or OSC 52 is blocked. Key points: - OAuth provider emits OAUTH_AUTH_URL_EVENT carrying the full URL. - AuthenticateStep listens, tracks it in state, and binds 'c' while authenticating (modifier/paste keys are filtered out). - copyToClipboardViaOsc52 writes to stderr when it's a TTY, falls back to stdout, and wraps the sequence for tmux/GNU screen via DCS passthrough so multiplexed sessions still work. - Honest feedback: distinct "copy request sent" / "cannot write to terminal" states with a short auto-revert so repeated presses reset the timer. Fixes #3337
Code Coverage Summary
CLI Package - Full Text ReportCore Package - Full Text ReportFor detailed HTML reports, please see the 'coverage-reports-22.x-ubuntu-latest' artifact from the main CI run. |
wenshao
left a comment
There was a problem hiding this comment.
No issues found. LGTM! ✅ — gpt-5.4 via Qwen Code /review
EnglishProblem#3337 — when MCP OAuth falls back to the "copy this URL into your browser" path, long URLs wrap inside the bordered dialog and get tangled with Approach
Strengths
Concerns
SuggestionsThe fundamentals are right. Before merging:
The value is real (#3337 is a concrete pain point) and the approach is more elegant than the 中文要解决的问题#3337 — MCP OAuth 回退到"复制 URL 到浏览器"路径时,长 URL 在带边框对话框内换行,选中复制会混入 实现思路
优点
需要指出的问题
建议基本盘是对的,合并前建议:
问题的价值是真的(#3337 是具体痛点),方案也比 issue 里建议的"用 pbcopy/xclip"优雅,值得合。 |
Merged 6 upstream commits while preserving HopCode architecture: Features synced from upstream: - feat(mcp): OSC 52 copy hotkey for OAuth authorization URL (QwenLM#3393) Press 'c' during OAuth to copy URL via terminal clipboard, works over SSH - feat(cli): early input capture to prevent keystroke loss during startup (QwenLM#3319) Buffers keystrokes during REPL init, replays once UI is mounted - perf(vscode): fix input lag in long conversations via React.memo (QwenLM#2550) MessageList/UserMessage/AssistantMessage wrapped with React.memo - feat(vscode-ide-companion): agent execution tool display (QwenLM#2590) Render dedicated agent execution cards in webview - fix(build): invoke tsx via node --import instead of npx (QwenLM#3237) Fixes bun compatibility for generate:settings-schema script - ci(stale): enable 35+35 stale/close PR policy (QwenLM#3375) Conflict resolution: - packages/vscode-ide-companion/.../toolcalls/index.tsx: kept @hoptrendy/webui, added ToolCallData to imports (upstream added it) - All @qwen-code/* import paths preserved as @hoptrendy/* (HopCode arch) - HopCode branding, version, and CI workflows preserved Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…#3337) (QwenLM#3393) When MCP OAuth authentication falls back to the "copy this URL into your browser" path (e.g. remote/web terminal where the browser can't auto-open), long URLs wrap across lines inside the bordered dialog and the trailing │ border characters get selected alongside the URL, forcing the user to manually strip them out before pasting. Surface the URL on a dedicated event and let the user press 'c' to push it to the local clipboard via an OSC 52 escape sequence. Works through SSH and modern web terminals (iTerm2, Windows Terminal, xterm.js-based emulators, tmux with set-clipboard, etc.) without a subprocess, and falls back to a visible "copy the URL above manually" hint when the terminal is not a TTY or OSC 52 is blocked. Key points: - OAuth provider emits OAUTH_AUTH_URL_EVENT carrying the full URL. - AuthenticateStep listens, tracks it in state, and binds 'c' while authenticating (modifier/paste keys are filtered out). - copyToClipboardViaOsc52 writes to stderr when it's a TTY, falls back to stdout, and wraps the sequence for tmux/GNU screen via DCS passthrough so multiplexed sessions still work. - Honest feedback: distinct "copy request sent" / "cannot write to terminal" states with a short auto-revert so repeated presses reset the timer. Fixes QwenLM#3337
Summary
Fixes #3337.
When MCP OAuth falls back to the "copy this URL into your browser" path (browser can't auto-open, e.g. remote/SSH/web terminal), long URLs wrap across lines inside the bordered dialog and get tangled with
│border characters on selection. The user has to paste into another buffer and manually strip borders and newlines before it's usable.This PR adds a
chotkey on the authentication step that pushes the full URL to the user's local clipboard via an OSC 52 terminal escape sequence — no subprocess, no platform shims.How it works
MCPOAuthProvideremits a newOAUTH_AUTH_URL_EVENTcarrying the full URL alongside the existing display messages.AuthenticateStepsubscribes, stores the URL in state, and bindscwhile authentication is in progress. Modifier / paste keys (ctrl,meta,paste) are filtered soCtrl+C, bracketed paste, etc. don't misfire.copyToClipboardViaOsc52base64-encodes the URL and writes\x1b]52;c;<base64>\x07tostderrwhen it's a TTY, falls back tostdout, and wraps the sequence in DCS passthrough when$TMUX/$STYis set so multiplexed sessions still deliver to the host terminal.Copy request sent to your terminal. If paste is empty, copy the URL above manually.Cannot write to terminal — copy the URL above manually.Press c to copy the authorization URL to your clipboard.The original "copy/paste the URL manually" hint is preserved verbatim, so users on terminals that don't support OSC 52 (or where the sequence is silently ignored) aren't regressed — they still see the URL and the manual-copy guidance.
Terminal support
OSC 52 is implemented by iTerm2, Windows Terminal, kitty, Alacritty, WezTerm, GNOME Terminal (recent), modern xterm, tmux (with
set-clipboard on), GNU screen, and xterm.js-based web terminals with@xterm/addon-clipboard. Where unsupported, the sequence is harmlessly ignored.Test plan
npm run typecheck— workspace-wide cleannpx vitest run packages/core/src/mcp/oauth-provider.test.ts— 22/22 passnpx eslint --max-warnings 0on touched files — cleanc; paste in browser — URL is intact.set -g set-clipboard on) — clipboard is updated on the host terminal.qwen 2>/tmp/err) — hint flips toCannot write to terminal — copy the URL above manually.