From 7411fc886e86108ad013e7f2231a7c8898d6884a Mon Sep 17 00:00:00 2001 From: cliffhall Date: Sat, 11 Jul 2026 23:41:10 -0400 Subject: [PATCH] =?UTF-8?q?web:=20address=20rollup=20review=20#1=20?= =?UTF-8?q?=E2=80=94=20deep-link=20reconnect=20on=20restored=20activeServe?= =?UTF-8?q?rId?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Gate the deep-link connect phase on 'not already connected' rather than on activeServerId identity: if a prior session restored activeServerId to the 'deep-link' id while disconnected, the old guard marked the ref consumed and never connected, so reloading the same deep-link URL silently didn't auto- connect. onToggleConnection only disconnects when the id is active AND status is connected, so the new condition also avoids toggling a live connection off. Also documents (rollup review #3) that pre-selecting a deep-linked app deliberately bypasses AppsScreen.handleSelect's no-input auto-launch — a URL must not fire a tool call without the token-gated autoOpen. Co-Authored-By: Claude Opus 4.8 (1M context) Claude-Session: https://claude.ai/code/session_01BrihGWcrM9JGRyu41nzZYw --- clients/web/src/App.tsx | 12 +++++++++++- .../components/views/InspectorView/InspectorView.tsx | 7 +++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/clients/web/src/App.tsx b/clients/web/src/App.tsx index 1511ce27..350213f4 100644 --- a/clients/web/src/App.tsx +++ b/clients/web/src/App.tsx @@ -2569,7 +2569,16 @@ function App() { if (deepLinkConnectRef.current) return; deepLinkConnectRef.current = true; - if (activeServerId !== deepLink.serverId) { + // Connect unless we're already *connected* to the deep-link server. Gating + // on `activeServerId` identity alone would skip the connect when a prior + // session restored `activeServerId` to the `deep-link` id while the socket + // is disconnected — a reload of the same deep-link URL would then silently + // never connect. `onToggleConnection` only disconnects when the id is the + // active one AND the status is connected, so this condition also avoids + // toggling a live connection off. + const alreadyConnected = + activeServerId === deepLink.serverId && connectionStatus === "connected"; + if (!alreadyConnected) { void onToggleConnection(deepLink.serverId).catch((err) => { // The toast fires from inside `onToggleConnection` for the common // cases; this catch covers the rest (surfaced on `data-error-message`). @@ -2581,6 +2590,7 @@ function App() { deepLink, servers, activeServerId, + connectionStatus, addServer, updateServer, onToggleConnection, diff --git a/clients/web/src/components/views/InspectorView/InspectorView.tsx b/clients/web/src/components/views/InspectorView/InspectorView.tsx index cd18bded..d8d335cd 100644 --- a/clients/web/src/components/views/InspectorView/InspectorView.tsx +++ b/clients/web/src/components/views/InspectorView/InspectorView.tsx @@ -892,6 +892,13 @@ export function InspectorView({ ...collectSchemaDefaults(target.inputSchema), ...deepLink.appArgs, }; + // Seed the selection directly rather than routing through + // AppsScreen.handleSelect. This deliberately bypasses handleSelect's + // no-input-app auto-launch: a deep link must never invoke a tool against + // the target server unless the token-gated `autoOpen` is set — even a + // no-input app waits for that explicit signal (or a manual "Open App" + // click), matching the security stance that a crafted URL alone can't fire + // a tool call. onActiveTabChange("Apps"); onAppsUiChange({ ...appsUi,