import express from "express"; import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js"; import z from "zod"; import { ShortCreator } from "../../short-creator/ShortCreator"; import { logger } from "../../logger"; import { renderConfig, sceneInput } from "../../types/shorts"; export class MCPRouter { router: express.Router; shortCreator: ShortCreator; transports: { [sessionId: string]: SSEServerTransport } = {}; mcpServer: McpServer; constructor(shortCreator: ShortCreator) { this.router = express.Router(); this.shortCreator = shortCreator; this.mcpServer = new McpServer({ name: "Short Creator", version: "0.0.1", capabilities: { resources: {}, tools: {}, }, }); this.setupMCPServer(); this.setupRoutes(); } private setupMCPServer() { this.mcpServer.tool( "get-video-status", "Get the status of a video (ready, processing, failed)", { videoId: z.string().describe("The ID of the video"), }, async ({ videoId }) => { const status = this.shortCreator.status(videoId); return { content: [ { type: "text", text: status, }, ], }; }, ); this.mcpServer.tool( "create-short-video", "Create a short video from a list of scenes", { scenes: z.array(sceneInput).describe("Each scene to be created"), config: renderConfig.describe("Configuration for rendering the video"), }, async ({ scenes, config }) => { const videoId = await this.shortCreator.addToQueue(scenes, config); return { content: [ { type: "text", text: videoId, }, ], }; }, ); } private setupRoutes() { this.router.get("/sse", async (req, res) => { logger.info("SSE GET request received"); const transport = new SSEServerTransport("/mcp/messages", res); this.transports[transport.sessionId] = transport; res.on("close", () => { delete this.transports[transport.sessionId]; }); await this.mcpServer.connect(transport); }); this.router.post("/messages", async (req, res) => { logger.info("SSE POST request received"); const sessionId = req.query.sessionId as string; const transport = this.transports[sessionId]; if (transport) { await transport.handlePostMessage(req, res); } else { res.status(400).send("No transport found for sessionId"); } }); } }