File size: 4,068 Bytes
11f4e50 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 | 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()
});
});
});
}
|