feat: Add WebMCP token polling for automatic browser connection
- Add token API endpoint to server for storing/retrieving pending tokens - Add token polling in frontend to auto-detect and connect with tokens - Add xterm dependencies for terminal functionality - Add terminal page support in toolRegistry
This commit is contained in:
@@ -35,7 +35,7 @@ import {
|
||||
SOURCE_CODE_TOOLS
|
||||
} from './tools/sourceCodeTools'
|
||||
|
||||
type PageName = 'home' | 'canvas' | 'components' | 'themes' | 'projects' | 'project-canvas' | 'database' | 'source'
|
||||
type PageName = 'home' | 'canvas' | 'components' | 'themes' | 'projects' | 'project-canvas' | 'database' | 'source' | 'terminal'
|
||||
|
||||
interface PageToolSet {
|
||||
register: () => void
|
||||
@@ -105,6 +105,11 @@ const pageTools: Record<PageName, PageToolSet> = {
|
||||
register: registerSourceCodeTools,
|
||||
unregister: unregisterSourceCodeTools,
|
||||
toolNames: SOURCE_CODE_TOOLS
|
||||
},
|
||||
terminal: {
|
||||
register: () => {},
|
||||
unregister: () => {},
|
||||
toolNames: []
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,9 @@ import { useCanvasStore } from '../stores/canvas'
|
||||
let webmcpInstance: any = null
|
||||
const registeredTools = new Set<string>()
|
||||
|
||||
const API_BASE = 'http://localhost:4101'
|
||||
let tokenPollingInterval: number | null = null
|
||||
|
||||
export async function initWebMCP() {
|
||||
if (webmcpInstance) return webmcpInstance
|
||||
|
||||
@@ -95,3 +98,80 @@ export function getRegisteredTools(): string[] {
|
||||
export function isToolRegistered(name: string): boolean {
|
||||
return registeredTools.has(name)
|
||||
}
|
||||
|
||||
// Token polling functions
|
||||
export async function checkForToken(): Promise<string | null> {
|
||||
try {
|
||||
const res = await fetch(`${API_BASE}/api/webmcp-token`)
|
||||
const data = await res.json()
|
||||
return data.token || null
|
||||
} catch (e) {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
export async function clearToken(): Promise<void> {
|
||||
try {
|
||||
await fetch(`${API_BASE}/api/webmcp-token`, { method: 'DELETE' })
|
||||
} catch (e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
export function startTokenPolling(onToken: (token: string) => void, intervalMs: number = 2000) {
|
||||
if (tokenPollingInterval) return
|
||||
|
||||
console.log('[WebMCP] Starting token polling...')
|
||||
tokenPollingInterval = window.setInterval(async () => {
|
||||
const token = await checkForToken()
|
||||
if (token) {
|
||||
console.log('[WebMCP] Token detected!')
|
||||
stopTokenPolling()
|
||||
onToken(token)
|
||||
}
|
||||
}, intervalMs)
|
||||
}
|
||||
|
||||
export function stopTokenPolling() {
|
||||
if (tokenPollingInterval) {
|
||||
window.clearInterval(tokenPollingInterval)
|
||||
tokenPollingInterval = null
|
||||
console.log('[WebMCP] Token polling stopped')
|
||||
}
|
||||
}
|
||||
|
||||
export function parseToken(token: string): { server: string; token: string } | null {
|
||||
try {
|
||||
const decoded = atob(token)
|
||||
return JSON.parse(decoded)
|
||||
} catch (e) {
|
||||
console.error('[WebMCP] Failed to parse token:', e)
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
export async function connectWithToken(token: string): Promise<boolean> {
|
||||
const parsed = parseToken(token)
|
||||
if (!parsed) return false
|
||||
|
||||
console.log('[WebMCP] Connecting with token to:', parsed.server)
|
||||
|
||||
// Store token for webmcp to use
|
||||
localStorage.setItem('webmcp_token', token)
|
||||
|
||||
// Clear the pending token from server
|
||||
await clearToken()
|
||||
|
||||
// If webmcp is already initialized, try to reconnect
|
||||
if (webmcpInstance && typeof webmcpInstance.connect === 'function') {
|
||||
try {
|
||||
await webmcpInstance.connect()
|
||||
return true
|
||||
} catch (e) {
|
||||
console.error('[WebMCP] Failed to connect:', e)
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user