refactor: fall back to the bare MCP URL instead of alerting on a failed read

When the setting read fails, show the bare URL rather than an error with a retry.
It works whichever way the setting is, so no alert is needed, and it still never
mints a token for a URL the server may refuse. The connect drawer's wording falls
back the same way so the blurb matches the panel.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
hugocasa
2026-09-16 16:00:14 +02:00
co-authored by Claude Opus 5
parent ede9ab96a1
commit 0d1fdb5da8
3 changed files with 9 additions and 19 deletions
@@ -26,10 +26,10 @@ wmill sync pull`)
export function openDrawer(tab: ConnectTab = 'cli') {
selectedTab = tab
openVersion += 1
// Only drives this blurb's wording; CreateToken below surfaces a failed check itself.
// Falls back like CreateToken below, which shows the bare URL when the read fails.
void mcpTokenUrlDisabled()
.then((v) => (tokenUrlDisabled = v))
.catch(() => (tokenUrlDisabled = false))
.catch(() => (tokenUrlDisabled = true))
drawer?.openDrawer()
}
@@ -57,9 +57,9 @@
let readOnly = $state(false)
// How this instance lets an MCP client in. `oauth` means it refuses `?token=`, so a
// generated token would not get a client in and the URL is handed over bare instead.
// Never assumed while unknown: guessing `token` mints a non-expiring credential for a
// URL the server would refuse.
type McpUrlPolicy = 'loading' | 'token' | 'oauth' | 'unavailable'
// A failed read lands on `oauth`: the bare URL works whichever way the setting is,
// whereas guessing `token` mints a non-expiring credential the server may refuse.
type McpUrlPolicy = 'loading' | 'token' | 'oauth'
let mcpUrlPolicy = $state<McpUrlPolicy>('loading')
async function loadMcpUrlPolicy() {
@@ -68,7 +68,7 @@
mcpUrlPolicy = (await mcpTokenUrlDisabled()) ? 'oauth' : 'token'
} catch (err) {
console.error('Failed to load the MCP token setting:', err)
mcpUrlPolicy = 'unavailable'
mcpUrlPolicy = 'oauth'
}
}
@@ -234,17 +234,7 @@
</div>
{/if}
{#if mcpCreationMode && mcpUrlPolicy === 'unavailable'}
<Alert type="error" title="Could not check how this instance accepts MCP clients" size="xs">
<div class="flex flex-col items-start gap-2">
<span>
Without that answer a generated token could be one this instance refuses, so nothing is
created here until the check succeeds.
</span>
<Button onClick={loadMcpUrlPolicy} variant="default" unifiedSize="xs">Try again</Button>
</div>
</Alert>
{:else if mcpCreationMode && mcpUrlPolicy === 'loading'}
{#if mcpCreationMode && mcpUrlPolicy === 'loading'}
<Skeleton layout={[[2], 0.5, [1]]} />
{:else if mcpCreationMode && mcpUrlPolicy === 'oauth'}
{#if !lockWorkspace}
+2 -2
View File
@@ -8,8 +8,8 @@ import { SettingService } from '$lib/gen'
* Deliberately uncached: callers read it at the moment an MCP URL is asked for, so a superadmin
* flipping the setting does not leave open tabs handing out URLs the server now refuses.
*
* Throws rather than falling back. A caller that guessed `false` here would mint a
* non-expiring token and hand over a URL the server refuses for as long as it exists.
* Throws rather than falling back, so the caller picks the safe default. Guessing `false`
* here would mint a non-expiring token for a URL the server may refuse.
*/
export async function mcpTokenUrlDisabled(): Promise<boolean> {
return (