Files
tolaria/src/hooks/useMcpStatus.ts
lucaronin f2ec2ab55c feat: make MCP restore command always available in Cmd+K
The "Install MCP Server" command was only enabled when status was
"not_installed", preventing users from re-registering when MCP got
removed or broken. Now the command is always available:
- Shows "Install MCP Server" when not installed
- Shows "Restore MCP Server" when already installed
- Added restore/fix/repair keywords for discoverability
- Context-aware toast: "installed" vs "restored"
- Menu bar label updated to "Restore MCP Server"

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 11:33:18 +01:00

76 lines
2.6 KiB
TypeScript

import { useCallback, useEffect, useRef, useState } from 'react'
import { invoke } from '@tauri-apps/api/core'
import { isTauri, mockInvoke } from '../mock-tauri'
export type McpStatus = 'checking' | 'installed' | 'not_installed' | 'no_claude_cli'
function tauriCall<T>(command: string, args?: Record<string, unknown>): Promise<T> {
return isTauri() ? invoke<T>(command, args) : mockInvoke<T>(command, args)
}
/**
* Detects MCP server status on vault open and provides an install action.
*
* Combines the old `useMcpRegistration` functionality (auto-register on vault
* switch) with new status detection for the status bar indicator.
*/
export function useMcpStatus(
vaultPath: string,
onToast: (msg: string) => void,
) {
const [status, setStatus] = useState<McpStatus>('checking')
const statusRef = useRef<McpStatus>(status)
const registeredRef = useRef<string | null>(null)
const onToastRef = useRef(onToast)
useEffect(() => { onToastRef.current = onToast })
useEffect(() => { statusRef.current = status }, [status])
// Check MCP status on vault open / vault switch
useEffect(() => {
let cancelled = false
setStatus('checking') // eslint-disable-line react-hooks/set-state-in-effect -- reset to checking on vault switch
tauriCall<string>('check_mcp_status')
.then((result) => {
if (!cancelled) setStatus(result as McpStatus)
})
.catch(() => {
if (!cancelled) setStatus('not_installed')
})
return () => { cancelled = true }
}, [vaultPath])
// Auto-register on vault switch (preserves old useMcpRegistration behavior)
useEffect(() => {
if (registeredRef.current === vaultPath) return
registeredRef.current = vaultPath
tauriCall<string>('register_mcp_tools', { vaultPath })
.then((result) => {
if (result === 'registered') {
onToastRef.current('Laputa registered as MCP tool for Claude Code')
}
setStatus('installed')
})
.catch(() => {
// Non-critical — status check will show the right state
})
}, [vaultPath])
const install = useCallback(async () => {
const wasInstalled = statusRef.current === 'installed'
setStatus('checking')
try {
await tauriCall<string>('register_mcp_tools', { vaultPath })
setStatus('installed')
onToastRef.current(wasInstalled ? 'MCP server restored successfully' : 'MCP server installed successfully')
} catch (e) {
setStatus('not_installed')
onToastRef.current(`MCP install failed: ${e}`)
}
}, [vaultPath])
return { mcpStatus: status, installMcp: install }
}