Skip to content

Commit 7f6fe29

Browse files
authored
Add OAuth 'Authorization Code + PKCE' flow to MCP UI (#27)
* Add OAuth 'Authorization Code + PKCE' flow to MCP UI * Use well-known metadata * Review fixes * Review fixes * More clear auth flow
1 parent 8e050ce commit 7f6fe29

9 files changed

Lines changed: 1417 additions & 68 deletions

File tree

ui/src/components/ChatView/ChatView.tsx

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { ChatHeader } from "@/components/ChatHeader/ChatHeader";
44
import { ChatInput } from "@/components/ChatInput/ChatInput";
55
import { ChatMessageList } from "@/components/ChatMessageList/ChatMessageList";
66
import { ConversationSettingsModal } from "@/components/ConversationSettingsModal/ConversationSettingsModal";
7-
import { MCPConfigModal } from "@/components/MCPConfigModal";
7+
import { MCPConfigModal, type MCPServerPrefill } from "@/components/MCPConfigModal";
88
import type { ModelInfo } from "@/components/ModelSelector/ModelSelector";
99
import {
1010
useChatUIStore,
@@ -30,7 +30,7 @@ import {
3030
useTotalUsage,
3131
useCurrentConversationForExport,
3232
} from "@/stores/conversationStore";
33-
import { useMemo, useCallback } from "react";
33+
import { useMemo, useCallback, useState, useEffect } from "react";
3434

3535
export interface ChatFile {
3636
id: string;
@@ -115,6 +115,25 @@ export function ChatView({
115115
const widescreenMode = useWidescreenMode();
116116
const subAgentModel = useSubAgentModel();
117117
const mcpConfigModalOpen = useMCPConfigModalOpen();
118+
const [mcpPrefill, setMcpPrefill] = useState<MCPServerPrefill | null>(null);
119+
120+
// Check for ?mcp_server_url= query param to auto-open the MCP config modal
121+
useEffect(() => {
122+
const params = new URLSearchParams(window.location.search);
123+
const serverUrl = params.get("mcp_server_url");
124+
if (serverUrl) {
125+
const serverName = params.get("mcp_server_name") ?? undefined;
126+
setMcpPrefill({ url: serverUrl, name: serverName });
127+
setMCPConfigModalOpen(true);
128+
// Clean the URL to prevent re-triggering
129+
const cleanUrl = new URL(window.location.href);
130+
cleanUrl.searchParams.delete("mcp_server_url");
131+
cleanUrl.searchParams.delete("mcp_server_name");
132+
window.history.replaceState({}, "", cleanUrl.toString());
133+
}
134+
// eslint-disable-next-line react-hooks/exhaustive-deps -- only run on mount
135+
}, []);
136+
118137
const { setSelectedInstances, updateInstance } = useConversationStore();
119138
const {
120139
settingsModalOpen,
@@ -268,7 +287,14 @@ export function ChatView({
268287
/>
269288

270289
{/* MCP Config Modal */}
271-
<MCPConfigModal open={mcpConfigModalOpen} onClose={() => setMCPConfigModalOpen(false)} />
290+
<MCPConfigModal
291+
open={mcpConfigModalOpen}
292+
onClose={() => {
293+
setMCPConfigModalOpen(false);
294+
setMcpPrefill(null);
295+
}}
296+
prefill={mcpPrefill}
297+
/>
272298
</div>
273299
);
274300
}

0 commit comments

Comments
 (0)