MCPcopy
hub / github.com/codeaashu/claude-code / MCPRemoteServerMenu

Function MCPRemoteServerMenu

src/components/mcp/MCPRemoteServerMenu.tsx:41–648  ·  view source on GitHub ↗
({
  server,
  serverToolsCount,
  onViewTools,
  onCancel,
  onComplete,
  borderless = false
}: Props)

Source from the content-addressed store, hash-verified

39 borderless?: boolean;
40};
41export function MCPRemoteServerMenu({
42 server,
43 serverToolsCount,
44 onViewTools,
45 onCancel,
46 onComplete,
47 borderless = false
48}: Props): React.ReactNode {
49 const [theme] = useTheme();
50 const exitState = useExitOnCtrlCDWithKeybindings();
51 const {
52 columns: terminalColumns
53 } = useTerminalSize();
54 const [isAuthenticating, setIsAuthenticating] = React.useState(false);
55 const [error, setError] = React.useState<string | null>(null);
56 const mcp = useAppState(s => s.mcp);
57 const setAppState = useSetAppState();
58 const [authorizationUrl, setAuthorizationUrl] = React.useState<string | null>(null);
59 const [isReconnecting, setIsReconnecting] = useState(false);
60 const authAbortControllerRef = useRef<AbortController | null>(null);
61 const [isClaudeAIAuthenticating, setIsClaudeAIAuthenticating] = useState(false);
62 const [claudeAIAuthUrl, setClaudeAIAuthUrl] = useState<string | null>(null);
63 const [isClaudeAIClearingAuth, setIsClaudeAIClearingAuth] = useState(false);
64 const [claudeAIClearAuthUrl, setClaudeAIClearAuthUrl] = useState<string | null>(null);
65 const [claudeAIClearAuthBrowserOpened, setClaudeAIClearAuthBrowserOpened] = useState(false);
66 const [urlCopied, setUrlCopied] = useState(false);
67 const copyTimeoutRef = useRef<ReturnType<typeof setTimeout> | undefined>(undefined);
68 const unmountedRef = useRef(false);
69 const [callbackUrlInput, setCallbackUrlInput] = useState('');
70 const [callbackUrlCursorOffset, setCallbackUrlCursorOffset] = useState(0);
71 const [manualCallbackSubmit, setManualCallbackSubmit] = useState<((url: string) => void) | null>(null);
72
73 // If the component unmounts mid-auth (e.g. a parent component's Esc handler
74 // navigates away before ours fires), abort the OAuth flow so the callback
75 // server is closed. Without this, the server stays bound and the process
76 // can outlive the terminal. Also clear the copy-feedback timer and mark
77 // unmounted so the async setClipboard callback doesn't setUrlCopied /
78 // schedule a new timer after unmount.
79 useEffect(() => () => {
80 unmountedRef.current = true;
81 authAbortControllerRef.current?.abort();
82 if (copyTimeoutRef.current !== undefined) {
83 clearTimeout(copyTimeoutRef.current);
84 }
85 }, []);
86
87 // A server is effectively authenticated if:
88 // 1. It has OAuth tokens (server.isAuthenticated), OR
89 // 2. It's connected and has tools (meaning it's working via some auth mechanism)
90 const isEffectivelyAuthenticated = server.isAuthenticated || server.client.type === 'connected' && serverToolsCount > 0;
91 const reconnectMcpServer = useMcpReconnect();
92 const handleClaudeAIAuthComplete = React.useCallback(async () => {
93 setIsClaudeAIAuthenticating(false);
94 setClaudeAIAuthUrl(null);
95 setIsReconnecting(true);
96 try {
97 const result = await reconnectMcpServer(server.name);
98 const success = result.client.type === 'connected';

Callers

nothing calls this directly

Calls 15

useTerminalSizeFunction · 0.85
useAppStateFunction · 0.85
useSetAppStateFunction · 0.85
useMcpReconnectFunction · 0.85
logEventFunction · 0.85
handleReconnectErrorFunction · 0.85
clearServerCacheFunction · 0.85
excludeToolsByServerFunction · 0.85
excludeCommandsByServerFunction · 0.85
excludeResourcesByServerFunction · 0.85
useKeybindingFunction · 0.85

Tested by

no test coverage detected