Commit fd0d08a
authored
improvement(mcp): push-driven settings freshness + lifecycle-audit fixes (#5842)
* improvement(mcp): subscribe settings page to the live push, lean on it over re-probing
The list_changed → SSE push pipeline was already wired end-to-end but only
mounted in the workflow-editor tool picker. Subscribe the settings MCP page to
the same shared, reference-counted EventSource so tool changes reflect in real
time there too — the reference-client model (discover once, refresh on push).
With push now active on the settings page, raise MCP_SERVER_TOOLS_STALE_TIME
from 30s to 5min (matching the server-side cache TTL) so revisiting the page
leans on push + stored state instead of re-probing every connected server.
There is no background poll (no refetchInterval) — this only affects
refetch-on-visit-if-stale; real changes still arrive instantly via push.
* fix(mcp): re-sync tools on SSE reconnect so a missed list_changed can't strand stale tools
A dropped/reconnected EventSource may miss a tools_changed event during the gap,
which — with a longer stale time — could leave the page showing old tools until
a remount or manual refresh. Invalidate the workspace tools on reconnect (never
on the first open), the standard resync-on-reconnect pattern for push clients.
* fix(mcp): resync on re-subscribe so events missed while the tab was closed reconcile
Leaving the settings tab tears down the shared EventSource; remounting created a
new connection whose first open was skipped, so a tools_changed fired while
unsubscribed wasn't reconciled (the 5min stale time also won't refetch on
remount). Track a per-workspace 'ever subscribed' flag: skip resync only on the
session's first subscription (queries fetch fresh then); resync on the first
open of any re-subscription and on every reconnect.
* fix(mcp): reconcile a recovered server's status on successful discovery + fix stale comment
Lifecycle-audit findings:
- The per-server tools queryFn invalidated the server list only on error. A server
that recovered via the stale re-probe returned fresh tools while the cached status
still showed failed → 'tools present but row red' until the list independently
refetched (a window the 5min stale-time widened). Now a successful probe against a
server the cache still shows non-connected refreshes the list so the row clears.
- Correct the keep/drop comment: tools drop once the stored status leaves 'connected'
(disconnected/error), not at a 3-failure threshold.
* fix(mcp): correct stale SSRF pin docstring and bound the remaining OAuth callback steps
Lifecycle-audit follow-ups (merged-code):
- validateMcpServerSsrf's return docstring described 'pin subsequent connections',
which no longer holds for the public path — the returned IP is a policy signal
selecting the validate-at-connect guarded fetch; redirect/rebind safety comes
from per-connect validation + followRedirectsGuarded, not pinning (only the
self-hosted private carve-out still literally pins). Corrected so a future
reader can't reintroduce a real pin from the misleading text.
- The callback wrapped only the five post-auth steps in timedStep; the earlier
loadOauthRowByState, getSession, and server SELECT (plus the provider_error
clearState) were unbounded, contradicting the 'every awaited step bounded'
invariant. Wrapped them so a wedged DB read surfaces as a labeled timeout.
* fix(mcp): resync on a first SSE open that recovered from an earlier connection error
If the initial EventSource connection errors before opening (and the initial tools
query fails with retry:false), the first successful onopen was skipped, leaving the
query stale. Track erroredBeforeOpen so a first open that followed a connection
error also resyncs — only a clean first subscription still skips.
* fix(mcp): make the SSE push subscription intrinsic to the tools query
The 5min stale time assumed push, but useMcpToolsEvents was only mounted in the
settings page and the tool picker — other consumers of the tools query (dynamic
args, tool selector, canvas block via useMcpToolsQuery/useMcpTools) had no
subscription, so list_changed updates could stay invisible for the full window.
Mount useMcpToolsEvents inside useMcpToolsQuery so every tools consumer gets
real-time push from the shared, reference-counted connection — no consumer is
left re-probing. Removed the now-redundant explicit mounts from the settings
page and tool-input.
* test(mcp): clear the shared SSE collections instead of reassigning globalThis
mcp.ts captures the connections Map and subscribed Set in module consts at import,
so setting the globalThis property to undefined didn't reset what the module uses —
subscription state leaked across tests. Clear the shared instances instead.
* fix(mcp): drop the success-path status reconciliation heuristic
The client-side serversList invalidation on a successful probe assumed the probe
updated the stored status, but a server-side cache hit returns tools without
touching status — so in the failed-cache-delete edge it fired a pointless
refetch. The benefit (instant vs the 60s serversList stale-time for status
recovery) doesn't justify the incorrect assumption; rely on the existing 60s
stale-time + SSE push for status recovery instead. Keeps the corrected keep/drop
comment.1 parent e0e6f24 commit fd0d08a
5 files changed
Lines changed: 87 additions & 24 deletions
File tree
- apps/sim
- app
- api/mcp/oauth/callback
- workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/tool-input
- hooks/queries
- lib/mcp
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
125 | 125 | | |
126 | 126 | | |
127 | 127 | | |
128 | | - | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
129 | 133 | | |
130 | 134 | | |
131 | 135 | | |
132 | 136 | | |
133 | | - | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
134 | 141 | | |
135 | 142 | | |
136 | 143 | | |
| |||
144 | 151 | | |
145 | 152 | | |
146 | 153 | | |
147 | | - | |
| 154 | + | |
148 | 155 | | |
149 | 156 | | |
150 | 157 | | |
| |||
169 | 176 | | |
170 | 177 | | |
171 | 178 | | |
172 | | - | |
173 | | - | |
174 | | - | |
175 | | - | |
176 | | - | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
177 | 186 | | |
178 | 187 | | |
179 | 188 | | |
| |||
Lines changed: 0 additions & 2 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
79 | 79 | | |
80 | 80 | | |
81 | 81 | | |
82 | | - | |
83 | 82 | | |
84 | 83 | | |
85 | 84 | | |
| |||
570 | 569 | | |
571 | 570 | | |
572 | 571 | | |
573 | | - | |
574 | 572 | | |
575 | 573 | | |
576 | 574 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
103 | 103 | | |
104 | 104 | | |
105 | 105 | | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
106 | 115 | | |
107 | 116 | | |
108 | 117 | | |
| 118 | + | |
109 | 119 | | |
110 | 120 | | |
111 | 121 | | |
112 | 122 | | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
113 | 129 | | |
114 | 130 | | |
115 | 131 | | |
| |||
139 | 155 | | |
140 | 156 | | |
141 | 157 | | |
142 | | - | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
143 | 163 | | |
144 | 164 | | |
145 | 165 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
42 | 42 | | |
43 | 43 | | |
44 | 44 | | |
45 | | - | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
46 | 52 | | |
47 | 53 | | |
48 | 54 | | |
| |||
140 | 146 | | |
141 | 147 | | |
142 | 148 | | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
143 | 154 | | |
144 | 155 | | |
145 | 156 | | |
| |||
192 | 203 | | |
193 | 204 | | |
194 | 205 | | |
195 | | - | |
196 | | - | |
197 | | - | |
198 | | - | |
| 206 | + | |
| 207 | + | |
| 208 | + | |
| 209 | + | |
199 | 210 | | |
200 | 211 | | |
201 | 212 | | |
| |||
527 | 538 | | |
528 | 539 | | |
529 | 540 | | |
| 541 | + | |
| 542 | + | |
| 543 | + | |
| 544 | + | |
| 545 | + | |
| 546 | + | |
530 | 547 | | |
531 | 548 | | |
532 | 549 | | |
| |||
563 | 580 | | |
564 | 581 | | |
565 | 582 | | |
| 583 | + | |
| 584 | + | |
| 585 | + | |
| 586 | + | |
| 587 | + | |
| 588 | + | |
| 589 | + | |
| 590 | + | |
| 591 | + | |
| 592 | + | |
| 593 | + | |
| 594 | + | |
| 595 | + | |
| 596 | + | |
| 597 | + | |
566 | 598 | | |
| 599 | + | |
567 | 600 | | |
568 | 601 | | |
569 | 602 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
139 | 139 | | |
140 | 140 | | |
141 | 141 | | |
142 | | - | |
143 | | - | |
144 | | - | |
145 | | - | |
146 | | - | |
147 | | - | |
148 | | - | |
149 | | - | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
150 | 153 | | |
151 | 154 | | |
152 | 155 | | |
| |||
0 commit comments