33// connected custom servers share the same server-side store.
44
55import { reportError } from "@corbits/error-sink" ;
6- import { Button , ConfirmButton , Input , toast } from "@corbits/react-ui" ;
6+ import { Button , toast } from "@corbits/react-ui" ;
77import {
88 CONNECTOR_REGISTRY ,
99 MCP_PRESETS ,
@@ -12,13 +12,11 @@ import { useEffect, useState } from "react";
1212
1313import {
1414 connectMcpPreset ,
15- disconnectMcpServer ,
1615 listMcpPresets ,
1716 mcpOAuthStartPath ,
1817 type McpPreset ,
1918} from "./mcp-servers-api" ;
2019import { PluginLogo } from "./plugin-logo" ;
21- import { PLUGINS_STRINGS } from "./strings" ;
2220
2321function messageOf ( cause : unknown ) : string {
2422 return cause instanceof Error ? cause . message : String ( cause ) ;
@@ -71,57 +69,42 @@ export function McpPresetCard({
7169 preset,
7270 toolCount,
7371 onChanged,
72+ onOpen,
7473} : {
7574 readonly tenantId : string ;
7675 readonly preset : McpPreset ;
7776 readonly toolCount : number | undefined ;
7877 readonly onChanged : ( toolCount ?: number ) => void ;
78+ readonly onOpen : ( trigger : HTMLButtonElement ) => void ;
7979} ) {
8080 const [ busy , setBusy ] = useState ( false ) ;
8181 const [ error , setError ] = useState < string | null > ( ( ) =>
8282 mcpOauthReturnError ( preset . slug ) ,
8383 ) ;
84- const [ tokenFieldOpen , setTokenFieldOpen ] = useState ( false ) ;
85- const [ token , setToken ] = useState ( "" ) ;
86-
87- function submitConnect ( pastedToken : string | undefined ) {
84+ function submitConnect ( ) {
8885 setBusy ( true ) ;
8986 setError ( null ) ;
90- connectMcpPreset ( tenantId , preset . slug , pastedToken )
87+ connectMcpPreset ( tenantId , preset . slug , undefined )
9188 . then ( ( result ) => {
9289 toast (
9390 `Connected — ${ result . toolCount } tool${ result . toolCount === 1 ? "" : "s" } available.` ,
9491 ) ;
95- setTokenFieldOpen ( false ) ;
96- setToken ( "" ) ;
9792 onChanged ( result . toolCount ) ;
9893 } )
9994 . catch ( ( cause : unknown ) => setError ( messageOf ( cause ) ) )
10095 . finally ( ( ) => setBusy ( false ) ) ;
10196 }
10297
103- function handleConnect ( ) {
98+ function handleConnect ( trigger : HTMLButtonElement ) {
10499 if ( preset . connectionMode === "oauth" ) {
105100 window . location . href = mcpOAuthStartPath ( tenantId , preset . slug ) ;
106101 return ;
107102 }
108103 if ( preset . connectionMode === "token" ) {
109- setTokenFieldOpen ( true ) ;
104+ onOpen ( trigger ) ;
110105 return ;
111106 }
112- submitConnect ( undefined ) ;
113- }
114-
115- function handleDisconnect ( ) {
116- setBusy ( true ) ;
117- setError ( null ) ;
118- disconnectMcpServer ( tenantId , preset . slug )
119- . then ( ( ) => {
120- toast ( `${ preset . displayName } disconnected.` ) ;
121- onChanged ( ) ;
122- } )
123- . catch ( ( ) => setError ( PLUGINS_STRINGS . disconnectError ) )
124- . finally ( ( ) => setBusy ( false ) ) ;
107+ submitConnect ( ) ;
125108 }
126109
127110 const presetDefinition = MCP_PRESETS . find (
@@ -137,8 +120,6 @@ export function McpPresetCard({
137120 : `${ toolCount } tool${ toolCount === 1 ? "" : "s" } `
138121 : "Not connected" ;
139122
140- const tokenFieldId = `mcp-preset-token-${ preset . slug } ` ;
141-
142123 return (
143124 < div
144125 className = "min-w-0 px-2 py-2.5"
@@ -167,91 +148,30 @@ export function McpPresetCard({
167148 < div className = "flex flex-none items-center gap-2" >
168149 < span className = "text-xs text-muted-foreground" > { status } </ span >
169150 { preset . connected ? (
170- < ConfirmButton
171- variant = "ghost "
151+ < Button
152+ type = "button "
172153 size = "sm"
173- confirmLabel = {
174- < >
175- Disconnect
176- < span className = "sr-only" > { preset . displayName } </ span >
177- </ >
178- }
179- disabled = { busy }
180- onConfirm = { handleDisconnect }
154+ variant = "ghost"
155+ aria-label = { `Manage ${ preset . displayName } ` }
156+ onClick = { ( event ) => onOpen ( event . currentTarget ) }
181157 >
182- { busy ? "Disconnecting…" : " Manage" }
158+ Manage
183159 < span className = "sr-only" > { preset . displayName } </ span >
184- </ ConfirmButton >
185- ) : tokenFieldOpen ? null : (
160+ </ Button >
161+ ) : (
186162 < Button
187163 type = "button"
188164 size = "sm"
189165 variant = "ghost"
190166 disabled = { busy }
191167 aria-label = { `Connect ${ preset . displayName } ` }
192- onClick = { handleConnect }
168+ onClick = { ( event ) => handleConnect ( event . currentTarget ) }
193169 >
194170 { busy ? "Connecting…" : "Connect" }
195171 </ Button >
196172 ) }
197173 </ div >
198174 </ div >
199- { tokenFieldOpen && ! preset . connected ? (
200- < div className = "mt-2 flex flex-col gap-2 pl-11" >
201- < ol className = "list-decimal space-y-1 pl-4 text-xs text-muted-foreground" >
202- { ( preset . tokenSteps ?? [ ] ) . map ( ( step ) => (
203- < li key = { step } > { step } </ li >
204- ) ) }
205- </ ol >
206- < a
207- href = { preset . docsUrl }
208- target = "_blank"
209- rel = "noreferrer"
210- className = "text-xs underline underline-offset-2"
211- >
212- Create your token
213- </ a >
214- < label className = "sr-only" htmlFor = { tokenFieldId } >
215- { `${ preset . displayName } access token` }
216- </ label >
217- < Input
218- id = { tokenFieldId }
219- type = "password"
220- value = { token }
221- placeholder = "Paste your access token"
222- disabled = { busy }
223- onChange = { ( event ) => {
224- setToken ( event . target . value ) ;
225- } }
226- />
227- < div className = "flex items-center gap-2" >
228- < Button
229- type = "button"
230- size = "sm"
231- disabled = { busy || token . trim ( ) === "" }
232- aria-label = { `Connect ${ preset . displayName } ` }
233- onClick = { ( ) => {
234- submitConnect ( token . trim ( ) ) ;
235- } }
236- >
237- { busy ? "Connecting…" : "Connect" }
238- </ Button >
239- < Button
240- type = "button"
241- size = "sm"
242- variant = "ghost"
243- disabled = { busy }
244- onClick = { ( ) => {
245- setTokenFieldOpen ( false ) ;
246- setToken ( "" ) ;
247- setError ( null ) ;
248- } }
249- >
250- Cancel
251- </ Button >
252- </ div >
253- </ div >
254- ) : null }
255175 </ div >
256176 ) ;
257177}
0 commit comments