mirror of
https://github.com/davidkaya/aryx.git
synced 2026-08-29 22:17:13 +02:00
feat: add MCP OAuth authentication frontend wiring and banner
- Add McpOauthRequiredEvent and McpOauthStaticClientConfigEvent to sidecar contracts - Add PendingMcpAuthRecord domain type with status tracking (pending/authenticating/failed/done) - Add pendingMcpAuth field to SessionRecord for session-level auth state - Wire onMcpOAuthRequired callback through sidecarProcess, runTurnPending, and AryxAppService - Handle mcp-oauth-required events: set session pendingMcpAuth, clear on turn finalize/cancel - Add dismissSessionMcpAuth IPC channel with preload binding and handler registration - Create McpAuthBanner component (amber-themed, shows server name/URL, dismiss button) - Integrate McpAuthBanner into ChatPane with placeholder text and App.tsx callback - Update test fixtures for new RunTurnPendingCommand.onMcpOAuthRequired field Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -0,0 +1,63 @@
|
||||
import { useCallback } from 'react';
|
||||
import { KeyRound, X } from 'lucide-react';
|
||||
|
||||
import type { PendingMcpAuthRecord } from '@shared/domain/mcpAuth';
|
||||
|
||||
export function McpAuthBanner({
|
||||
mcpAuth,
|
||||
onDismiss,
|
||||
}: {
|
||||
mcpAuth: PendingMcpAuthRecord;
|
||||
onDismiss: () => void;
|
||||
}) {
|
||||
const handleDismiss = useCallback(() => {
|
||||
onDismiss();
|
||||
}, [onDismiss]);
|
||||
|
||||
const isAuthenticating = mcpAuth.status === 'authenticating';
|
||||
const hasFailed = mcpAuth.status === 'failed';
|
||||
|
||||
return (
|
||||
<div className="rounded-xl border border-amber-500/30 bg-amber-500/5 px-4 py-3" role="alert">
|
||||
<div className="flex items-start gap-2.5">
|
||||
<KeyRound className="mt-0.5 size-4 shrink-0 text-amber-400" />
|
||||
<div className="min-w-0 flex-1">
|
||||
<div className="flex items-center justify-between gap-2">
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="text-[13px] font-semibold text-amber-200">Authentication required</span>
|
||||
<span className="rounded-full bg-amber-500/15 px-2 py-0.5 text-[9px] font-semibold uppercase tracking-wider text-amber-400">
|
||||
MCP
|
||||
</span>
|
||||
</div>
|
||||
<button
|
||||
aria-label="Dismiss authentication prompt"
|
||||
className="rounded p-0.5 text-zinc-500 transition hover:bg-zinc-700/50 hover:text-zinc-300"
|
||||
onClick={handleDismiss}
|
||||
type="button"
|
||||
>
|
||||
<X className="size-3.5" />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<p className="mt-2 text-[13px] leading-relaxed text-zinc-200">
|
||||
The MCP server{' '}
|
||||
<span className="font-medium text-amber-200">{mcpAuth.serverName}</span>{' '}
|
||||
requires OAuth authentication to connect.
|
||||
</p>
|
||||
|
||||
<p className="mt-1 text-[11px] text-zinc-500">{mcpAuth.serverUrl}</p>
|
||||
|
||||
{hasFailed && mcpAuth.errorMessage && (
|
||||
<p className="mt-2 text-[12px] text-red-400">{mcpAuth.errorMessage}</p>
|
||||
)}
|
||||
|
||||
<p className="mt-3 text-[12px] leading-relaxed text-zinc-400">
|
||||
{isAuthenticating
|
||||
? 'Waiting for authentication to complete in the browser…'
|
||||
: 'Authentication support for HTTP MCP servers is not yet available. Configure a static access token in the MCP server headers instead.'}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user