@@ -20,6 +20,7 @@ import {
2020 useDeleteMcpServer ,
2121 useMcpServers ,
2222 useMcpToolsQuery ,
23+ useRefreshMcpServer ,
2324} from '@/hooks/queries/mcp'
2425import { useMcpServerTest } from '@/hooks/use-mcp-server-test'
2526import type { InputFieldType , McpServerFormData , McpServerTestResult } from './components'
@@ -89,27 +90,24 @@ export function MCP() {
8990 } = useMcpToolsQuery ( workspaceId )
9091 const createServerMutation = useCreateMcpServer ( )
9192 const deleteServerMutation = useDeleteMcpServer ( )
93+ const refreshServerMutation = useRefreshMcpServer ( )
9294 const { testResult, isTestingConnection, testConnection, clearTestResult } = useMcpServerTest ( )
9395
9496 const urlInputRef = useRef < HTMLInputElement > ( null )
9597
96- // Form state
9798 const [ showAddForm , setShowAddForm ] = useState ( false )
9899 const [ formData , setFormData ] = useState < McpServerFormData > ( DEFAULT_FORM_DATA )
99100 const [ isAddingServer , setIsAddingServer ] = useState ( false )
100101
101- // Search and filtering state
102102 const [ searchTerm , setSearchTerm ] = useState ( '' )
103103 const [ deletingServers , setDeletingServers ] = useState < Set < string > > ( new Set ( ) )
104104
105- // Delete confirmation dialog state
106105 const [ showDeleteDialog , setShowDeleteDialog ] = useState ( false )
107106 const [ serverToDelete , setServerToDelete ] = useState < { id : string ; name : string } | null > ( null )
108107
109- // Server details view state
110108 const [ selectedServerId , setSelectedServerId ] = useState < string | null > ( null )
109+ const [ refreshStatus , setRefreshStatus ] = useState < 'idle' | 'refreshing' | 'refreshed' > ( 'idle' )
111110
112- // Environment variable dropdown state
113111 const [ showEnvVars , setShowEnvVars ] = useState ( false )
114112 const [ envSearchTerm , setEnvSearchTerm ] = useState ( '' )
115113 const [ cursorPosition , setCursorPosition ] = useState ( 0 )
@@ -255,7 +253,6 @@ export function MCP() {
255253 workspaceId,
256254 }
257255
258- // Test connection if not already tested
259256 if ( ! testResult ) {
260257 const result = await testConnection ( serverConfig )
261258 if ( ! result . success ) return
@@ -396,6 +393,25 @@ export function MCP() {
396393 setSelectedServerId ( null )
397394 } , [ ] )
398395
396+ /**
397+ * Refreshes a server's tools by re-discovering them from the MCP server.
398+ */
399+ const handleRefreshServer = useCallback (
400+ async ( serverId : string ) => {
401+ try {
402+ setRefreshStatus ( 'refreshing' )
403+ await refreshServerMutation . mutateAsync ( { workspaceId, serverId } )
404+ logger . info ( `Refreshed MCP server: ${ serverId } ` )
405+ setRefreshStatus ( 'refreshed' )
406+ setTimeout ( ( ) => setRefreshStatus ( 'idle' ) , 2000 )
407+ } catch ( error ) {
408+ logger . error ( 'Failed to refresh MCP server:' , error )
409+ setRefreshStatus ( 'idle' )
410+ }
411+ } ,
412+ [ refreshServerMutation , workspaceId ]
413+ )
414+
399415 /**
400416 * Gets the selected server and its tools for the detail view.
401417 */
@@ -412,12 +428,10 @@ export function MCP() {
412428 const showEmptyState = ! hasServers && ! showAddForm
413429 const showNoResults = searchTerm . trim ( ) && filteredServers . length === 0 && servers . length > 0
414430
415- // Form validation state
416431 const isFormValid = formData . name . trim ( ) && formData . url ?. trim ( )
417432 const isSubmitDisabled = serversLoading || isAddingServer || ! isFormValid
418433 const testButtonLabel = getTestButtonLabel ( testResult , isTestingConnection )
419434
420- // Show detail view if a server is selected
421435 if ( selectedServer ) {
422436 const { server, tools } = selectedServer
423437 const transportLabel = formatTransportLabel ( server . transport || 'http' )
@@ -478,7 +492,18 @@ export function MCP() {
478492 </ div >
479493 </ div >
480494
481- < div className = 'mt-auto flex items-center justify-end' >
495+ < div className = 'mt-auto flex items-center justify-between' >
496+ < Button
497+ onClick = { ( ) => handleRefreshServer ( server . id ) }
498+ variant = 'default'
499+ disabled = { refreshStatus !== 'idle' }
500+ >
501+ { refreshStatus === 'refreshing'
502+ ? 'Refreshing...'
503+ : refreshStatus === 'refreshed'
504+ ? 'Refreshed'
505+ : 'Refresh Tools' }
506+ </ Button >
482507 < Button
483508 onClick = { handleBackToList }
484509 variant = 'primary'
0 commit comments