import { Server, Socket } from 'socket.io'; import { Project, Video, User } from '../models'; // This is the MCP-like Hub for the workspace. // It exposes "tools" to the connected Google Antigravity CLI (the agent) // and broadcasts state changes to connected web browser clients (the humans observing). export function setupMCPServer(io: Server) { // We use namespaces to separate human browsers from the AI CLI agent const agentNamespace = io.of('/mcp'); const browserNamespace = io.of('/browser'); agentNamespace.on('connection', (socket: Socket) => { console.log(`[MCP Server] AI Agent connected: ${socket.id}`); // Tool: Read Workspace State socket.on('mcp:read_state', async (callback) => { try { const projects = await Project.find().lean(); // Return minimal readable state to the agent callback({ status: 'success', data: { projects, count: projects.length } }); } catch (error: any) { callback({ status: 'error', message: error.message }); } }); // Tool: Navigate Browser UI socket.on('mcp:navigate', (data: { path: string }, callback) => { console.log(`[MCP Server] Agent forcing navigation to: ${data.path}`); // Broadcast to humans looking at the browser browserNamespace.emit('agent:navigate', data.path); callback({ status: 'success' }); }); // Tool: Create Project socket.on('mcp:create_project', async (data: { name: string, defaultPlatform: string, defaultFormat: string }, callback) => { try { // Find a default user to associate with agent actions const defaultUser = await User.findOne(); if (!defaultUser) { throw new Error('No users found in database to associate project with.'); } const project = await Project.create({ userId: defaultUser._id, name: data.name, defaultPlatform: data.defaultPlatform, defaultFormat: data.defaultFormat, }); // Notify the frontend that a project was created autonomously browserNamespace.emit('agent:project_created', project); // Force navigation to the newly created project browserNamespace.emit('agent:navigate', `/project/${project._id}`); callback({ status: 'success', data: project }); } catch (error: any) { callback({ status: 'error', message: error.message }); } }); // Tool: Update Video Draft socket.on('mcp:update_video_draft', (data: { projectId: string, script?: string, voiceType?: string }, callback) => { // Broadcast the real-time AI typing/updating to the frontend VideoCreate wizard browserNamespace.emit('agent:video_draft_updated', data); callback({ status: 'success' }); }); // Tool: Send Activity Log socket.on('mcp:activity_log', (data: { message: string, type?: 'info' | 'success' | 'warning' | 'error' }) => { // The CLI agent reports what it is doing. Frontend displays this in AITerminal. browserNamespace.emit('agent:activity_log', { message: data.message, type: data.type || 'info', timestamp: new Date().toISOString() }); }); socket.on('disconnect', () => { console.log(`[MCP Server] AI Agent disconnected: ${socket.id}`); browserNamespace.emit('agent:activity_log', { message: 'Google Antigravity CLI disconnected from workspace.', type: 'error', timestamp: new Date().toISOString() }); }); }); browserNamespace.on('connection', (socket: Socket) => { console.log(`[Browser] Human connected to workspace viewport: ${socket.id}`); // Humans can also send activity logs manually if needed socket.on('browser:activity_log', (data) => { browserNamespace.emit('agent:activity_log', { message: `User typed: ${data.message}`, type: 'info', timestamp: new Date().toISOString() }); }); }); }