MCPcopy Create free account
hub / github.com/Noumena-Network/code / MCPRemoteServerMenu

Function MCPRemoteServerMenu

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

Source from the content-addressed store, hash-verified

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

Callers

nothing calls this directly

Calls 15

useThemeFunction · 0.85
useTerminalSizeFunction · 0.85
useAppStateFunction · 0.85
useSetAppStateFunction · 0.85
useMcpReconnectFunction · 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