director-ai / server /src /services /mcpServer.ts
algorembrant's picture
Upload 79 files
11f4e50 verified
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()
});
});
});
}