Files
BrowserOS/apps/agent/lib/mcp/useSyncRemoteIntegrations.ts
Dani Akash f35ac0ddd3 feat: new onboarding tools (#385)
* feat: new tools for breadcrumbs

* feat: setup scheduled task card

* feat: added dismiss cooldown

* chore: update prompt

* fix: support api key tool

* fix: prompt text to limit nudges

* fix: scheduled tasks card

* fix: update nudges prompt

* feat: skip nudges when user dismisses nudge

* fix: ensure nudges only show if they are not dismissed

* Revert "fix: ensure nudges only show if they are not dismissed"

This reverts commit d825254698829b8e9941aae7873bd440027d0c74.

* Revert "feat: skip nudges when user dismisses nudge"

This reverts commit 12b552b454d10ec4209b88668fc48681423ff6fc.

* Revert "fix: update nudges prompt"

This reverts commit 80b7520b953b4d3cbed2ed477b9e508e39938dca.

* feat: update agent with mcp when new mcp connection is added

* feat: created connect apps option as a blocking card system

* feat: schedule tasks passive without dismiss

* fix: nudges and prompt texts

* fix: biome lint errors

* fix: review comments

* fix: resolve comments

* fix: review comments

* fix: review comments

* fix: auto resolve state

* fix: eliminate the race where the async delete could resolve after the
new session

* feat: track ignored apps list

* fix: empty response text object on message reply

* feat: sync previously connected mcps

* feat: sync integrations with klavis

* feat: account for unauthenticated connections

* fix: analytics events

* fix: typescript issues

* fix: klavis client issue

* fix: invalid mcps causing entire responses from failing

* fix: prompt with card for integrations when the integration fails

* fix: prompt structure to support declined apps

* fix: refresh session on mcp changes
2026-03-10 17:44:10 +05:30

66 lines
2.4 KiB
TypeScript

import { useEffect, useRef } from 'react'
import { useGetMCPServersList } from '@/entrypoints/app/connect-mcp/useGetMCPServersList'
import { useGetUserMCPIntegrations } from '@/entrypoints/app/connect-mcp/useGetUserMCPIntegrations'
import { type McpServer, mcpServerStorage } from './mcpServerStorage'
/**
* Syncs remote Klavis integrations into local Chrome storage.
*
* Klavis ties integrations to an email address, so connecting Gmail on device A
* and Slack on device A means device B (same email) also has Slack authenticated.
* But local Chrome storage on device B won't know about Slack.
*
* This hook detects authenticated remote integrations missing from local storage
* and adds them so they appear in the UI (and can be disconnected).
*/
export function useSyncRemoteIntegrations() {
const { data: userMCPIntegrations, isLoading: isIntegrationsLoading } =
useGetUserMCPIntegrations()
const { data: serversList } = useGetMCPServersList()
const integrationsRef = useRef(userMCPIntegrations)
const serversListRef = useRef(serversList)
integrationsRef.current = userMCPIntegrations
serversListRef.current = serversList
const hasSynced = useRef(false)
const integrationCount = userMCPIntegrations?.integrations?.length ?? 0
useEffect(() => {
if (isIntegrationsLoading || !integrationCount) return
if (hasSynced.current) return
const integrations = integrationsRef.current?.integrations
if (!integrations) return
const syncMissing = async () => {
const localServers = await mcpServerStorage.getValue()
const missing = integrations.filter(
(remote) =>
remote.is_authenticated &&
!localServers.some((s) => s.managedServerName === remote.name),
)
if (missing.length === 0) return
const catalog = serversListRef.current
const newServers: McpServer[] = missing.map((integration) => {
const catalogEntry = catalog?.servers.find(
(s) => s.name === integration.name,
)
return {
id: `${Date.now()}-${integration.name}`,
displayName: integration.name,
type: 'managed',
managedServerName: integration.name,
managedServerDescription: catalogEntry?.description ?? '',
}
})
await mcpServerStorage.setValue([...localServers, ...newServers])
}
hasSynced.current = true
syncMissing()
}, [isIntegrationsLoading, integrationCount])
}