@raihan0824/mcp-veo2
Version:
MCP server for generating videos with Google Veo2
166 lines • 7.08 kB
JavaScript
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { z } from 'zod';
import { videoResourceTemplate, readVideoResource, videoPromptsResource } from './resources/videos.js';
import { imageResourceTemplate, readImageResource, imagePromptsResource } from './resources/images.js';
import { generateImage, listGeneratedImages, getImage } from './tools/generateVideo.js';
import { log } from './utils/logger.js';
/**
* Creates and configures the MCP server for Veo2 video generation
*
* @returns The configured MCP server
*/
export function createServer() {
// Create the MCP server
const server = new McpServer({
name: 'veo2-video-generation',
version: '1.0.0'
}, {
capabilities: {
resources: {
listChanged: true,
subscribe: true
},
tools: {
listChanged: true
}
}
});
log.info('Initializing MCP server for Veo2 video generation');
// Register resources
log.info('Registering video and image resources');
// Register the video resource template
server.resource('videos', videoResourceTemplate, {
description: 'Access generated videos'
}, async (uri, variables) => {
// Since we can't access query parameters directly, we'll just pass an empty URLSearchParams
return readVideoResource(uri, variables);
});
// Register the video templates resource
server.resource('video-templates', videoPromptsResource.uri, {
description: videoPromptsResource.description
}, async () => videoPromptsResource.read());
// Register the image resource template
server.resource('images', imageResourceTemplate, {
description: 'Access generated images'
}, async (uri, variables) => {
// Since we can't access query parameters directly, we'll just pass an empty URLSearchParams
return readImageResource(uri, variables);
});
// Register the image templates resource
server.resource('image-templates', imagePromptsResource.uri, {
description: imagePromptsResource.description
}, async () => imagePromptsResource.read());
// Register tools
log.info('Registering video generation tools');
// Define schemas for tool inputs
const TextToVideoConfigSchema = z.object({
aspectRatio: z.enum(['16:9', '9:16']).default('16:9'),
personGeneration: z.enum(['dont_allow', 'allow_adult']).default('dont_allow'),
numberOfVideos: z.union([z.literal(1), z.literal(2)]).default(1),
durationSeconds: z.number().min(5).max(8).default(5),
enhancePrompt: z.boolean().default(false),
negativePrompt: z.string().default(''),
});
// COMMENTED OUT: Register the text-to-video generation tool
/*
server.tool(
'generateVideoFromText',
'Generate a video from a text prompt',
{
prompt: z.string().min(1).max(1000),
aspectRatio: z.enum(['16:9', '9:16']).default('16:9'),
personGeneration: z.enum(['dont_allow', 'allow_adult']).default('dont_allow'),
numberOfVideos: z.union([z.literal(1), z.literal(2)]).default(1),
durationSeconds: z.number().min(5).max(8).default(5),
enhancePrompt: z.union([z.boolean(), z.string()]).default(false),
negativePrompt: z.string().default(''),
includeFullData: z.union([z.boolean(), z.string()]).default(false),
autoDownload: z.union([z.boolean(), z.string()]).default(true),
},
generateVideoFromText
);
*/
// COMMENTED OUT: Register the image-to-video generation tool
/*
server.tool(
'generateVideoFromImage',
'Generate a video from an image',
{
prompt: z.string().min(1).max(1000).optional().default('Generate a video from this image'),
image: z.union([
// ImageContent object
z.object({
type: z.literal('image'),
mimeType: z.string(),
data: z.string().min(1) // base64 encoded image data
}),
// URL string
z.string().url(),
// File path string
z.string().min(1)
]),
aspectRatio: z.enum(['16:9', '9:16']).default('16:9'),
personGeneration: z.enum(['dont_allow', 'allow_adult']).default('dont_allow'),
numberOfVideos: z.union([z.literal(1), z.literal(2)]).default(1),
durationSeconds: z.number().min(5).max(8).default(5),
enhancePrompt: z.union([z.boolean(), z.string()]).default(false),
negativePrompt: z.string().default(''),
includeFullData: z.union([z.boolean(), z.string()]).default(false),
autoDownload: z.union([z.boolean(), z.string()]).default(true),
},
generateVideoFromImage
);
*/
// Schema for image generation configuration
const ImageGenerationConfigSchema = z.object({
numberOfImages: z.number().min(1).max(4).default(1),
// Add other Imagen parameters as needed
});
// Register the image generation tool
server.tool('generateImage', 'Generate an image from a text prompt using Google Imagen', {
prompt: z.string().min(1).max(1000),
numberOfImages: z.number().min(1).max(4).default(1),
includeFullData: z.union([z.boolean(), z.string()]).default(false),
}, generateImage);
// COMMENTED OUT: Register the image-to-video generation with generated image tool
/*
server.tool(
'generateVideoFromGeneratedImage',
'Generate a video from a generated image (one-step process)',
{
prompt: z.string().min(1).max(1000),
videoPrompt: z.string().min(1).max(1000).optional(),
// Image generation parameters
numberOfImages: z.number().min(1).max(4).default(1),
// Video generation parameters
aspectRatio: z.enum(['16:9', '9:16']).default('16:9'),
personGeneration: z.enum(['dont_allow', 'allow_adult']).default('dont_allow'),
numberOfVideos: z.union([z.literal(1), z.literal(2)]).default(1),
durationSeconds: z.number().min(5).max(8).default(5),
enhancePrompt: z.union([z.boolean(), z.string()]).default(false),
negativePrompt: z.string().default(''),
includeFullData: z.union([z.boolean(), z.string()]).default(false),
autoDownload: z.union([z.boolean(), z.string()]).default(true),
},
generateVideoFromGeneratedImage
);
*/
// COMMENTED OUT: Register the list videos tool
/*
server.tool(
'listGeneratedVideos',
'List all generated videos',
listGeneratedVideos
);
*/
// Register the get image tool
server.tool('getImage', 'Get a specific image by ID', {
id: z.string().min(1),
includeFullData: z.union([z.boolean(), z.string()]).default(true),
}, getImage);
// Register the list images tool
server.tool('listGeneratedImages', 'List all generated images', listGeneratedImages);
log.info('MCP server initialized successfully');
return server;
}
//# sourceMappingURL=server.js.map