Improve MCP settings auth flow, remote config support, and diagnostics UX (#953)
* feat: improve MCP settings auth workflow * fix: complete MCP settings auth flow * fix: harden MCP settings auth flow * fix: add MCP settings refresh control * fix: stabilize MCP authorization and status handling * fix: clarify MCP advanced remote options toggle * fix: improve MCP import and diagnostics * feat: improve MCP settings panel visual hierarchy and UX * fix: expose MCP auth actions in connected state * fix: remove MCP import snippet helper text * fix: address MCP review feedback * fix: correct MCP page transport layout after rebase
This commit is contained in:
@@ -17,6 +17,7 @@ import { MobileOverlayPanel } from '@/components/ui/MobileOverlayPanel';
|
||||
import { cn } from '@/lib/utils';
|
||||
import { useDeviceInfo } from '@/lib/device';
|
||||
import { useDirectoryStore } from '@/stores/useDirectoryStore';
|
||||
import { useMcpConfigStore } from '@/stores/useMcpConfigStore';
|
||||
import { computeMcpHealth, useMcpStore } from '@/stores/useMcpStore';
|
||||
import { McpIcon } from '@/components/icons/McpIcon';
|
||||
|
||||
@@ -66,6 +67,8 @@ export const McpDropdownContent: React.FC<McpDropdownContentProps> = ({ active,
|
||||
const refresh = useMcpStore((state) => state.refresh);
|
||||
const connect = useMcpStore((state) => state.connect);
|
||||
const disconnect = useMcpStore((state) => state.disconnect);
|
||||
const mcpServers = useMcpConfigStore((state) => state.mcpServers);
|
||||
const loadMcpConfigs = useMcpConfigStore((state) => state.loadMcpConfigs);
|
||||
const [isSpinning, setIsSpinning] = React.useState(false);
|
||||
const [busyName, setBusyName] = React.useState<string | null>(null);
|
||||
|
||||
@@ -73,14 +76,27 @@ export const McpDropdownContent: React.FC<McpDropdownContentProps> = ({ active,
|
||||
void refresh({ directory, silent: true });
|
||||
}, [refresh, directory]);
|
||||
|
||||
React.useEffect(() => {
|
||||
void loadMcpConfigs({ force: true });
|
||||
}, [loadMcpConfigs]);
|
||||
|
||||
React.useEffect(() => {
|
||||
if (!active) return;
|
||||
void refresh({ directory, silent: true });
|
||||
}, [active, refresh, directory]);
|
||||
void Promise.all([
|
||||
refresh({ directory, silent: true }),
|
||||
loadMcpConfigs({ force: true }),
|
||||
]);
|
||||
}, [active, refresh, directory, loadMcpConfigs]);
|
||||
|
||||
const sortedNames = React.useMemo(() => {
|
||||
return Object.keys(status).sort((a, b) => a.localeCompare(b));
|
||||
}, [status]);
|
||||
const names = new Set<string>(Object.keys(status));
|
||||
for (const server of mcpServers) {
|
||||
if (server?.name) {
|
||||
names.add(server.name);
|
||||
}
|
||||
}
|
||||
return Array.from(names).sort((a, b) => a.localeCompare(b));
|
||||
}, [mcpServers, status]);
|
||||
|
||||
const handleRefresh = React.useCallback((e?: React.MouseEvent) => {
|
||||
e?.preventDefault();
|
||||
@@ -195,6 +211,8 @@ export const McpDropdown: React.FC<McpDropdownProps> = ({ headerIconButtonClass
|
||||
const refresh = useMcpStore((state) => state.refresh);
|
||||
const connect = useMcpStore((state) => state.connect);
|
||||
const disconnect = useMcpStore((state) => state.disconnect);
|
||||
const mcpServers = useMcpConfigStore((state) => state.mcpServers);
|
||||
const loadMcpConfigs = useMcpConfigStore((state) => state.loadMcpConfigs);
|
||||
|
||||
const handleDropdownOpenChange = React.useCallback((isOpen: boolean) => {
|
||||
if (!isOpen) {
|
||||
@@ -219,19 +237,29 @@ export const McpDropdown: React.FC<McpDropdownProps> = ({ headerIconButtonClass
|
||||
// Fetch on mount and when directory changes
|
||||
React.useEffect(() => {
|
||||
void refresh({ directory, silent: true });
|
||||
}, [refresh, directory]);
|
||||
void loadMcpConfigs({ force: true });
|
||||
}, [refresh, directory, loadMcpConfigs]);
|
||||
|
||||
// Refresh when dropdown opens
|
||||
React.useEffect(() => {
|
||||
if (!open) return;
|
||||
void refresh({ directory, silent: true });
|
||||
}, [open, refresh, directory]);
|
||||
void Promise.all([
|
||||
refresh({ directory, silent: true }),
|
||||
loadMcpConfigs({ force: true }),
|
||||
]);
|
||||
}, [open, refresh, directory, loadMcpConfigs]);
|
||||
|
||||
const health = React.useMemo(() => computeMcpHealth(status), [status]);
|
||||
|
||||
const sortedNames = React.useMemo(() => {
|
||||
return Object.keys(status).sort((a, b) => a.localeCompare(b));
|
||||
}, [status]);
|
||||
const names = new Set<string>(Object.keys(status));
|
||||
for (const server of mcpServers) {
|
||||
if (server?.name) {
|
||||
names.add(server.name);
|
||||
}
|
||||
}
|
||||
return Array.from(names).sort((a, b) => a.localeCompare(b));
|
||||
}, [mcpServers, status]);
|
||||
|
||||
const handleRefresh = React.useCallback((e?: React.MouseEvent) => {
|
||||
e?.preventDefault();
|
||||
|
||||
Reference in New Issue
Block a user