UNPKG

@dondonudonjp/vertexai-imagen-mcp-server

Version:

[DEPRECATED] MCP Server for Vertex AI Imagen image generation. Imagen endpoints shut down 2026-06-30; migrate to the nanoBanana MCP Server (Gemini image models).

294 lines 12.2 kB
/** * Zod validation schemas for tool arguments * Provides runtime validation to complement TypeScript's compile-time type checking */ import { z } from 'zod'; // Common enums and shared schemas const AspectRatioSchema = z.enum(['1:1', '3:4', '4:3', '9:16', '16:9']); const SafetyLevelSchema = z.enum([ 'BLOCK_NONE', 'BLOCK_ONLY_HIGH', 'BLOCK_MEDIUM_AND_ABOVE', 'BLOCK_LOW_AND_ABOVE' ]); const PersonGenerationSchema = z.enum(['DONT_ALLOW', 'ALLOW_ADULT', 'ALLOW_ALL']); const LanguageSchema = z.enum(['auto', 'en', 'zh', 'zh-TW', 'hi', 'ja', 'ko', 'pt', 'es']); const SampleImageSizeSchema = z.enum(['1K', '2K']); const ImagenGenerateModelSchema = z.enum([ 'imagen-4.0-ultra-generate-001', 'imagen-4.0-fast-generate-001', 'imagen-4.0-generate-001', 'imagen-3.0-generate-002', 'imagen-3.0-fast-generate-001' ]); const ImagenCapabilityModelSchema = z.enum(['imagen-3.0-capability-001']); /** * Generate Image Arguments Schema */ export const GenerateImageArgsSchema = z.object({ prompt: z.string().min(1, 'Prompt is required and must not be empty'), output_path: z.string().optional(), aspect_ratio: AspectRatioSchema.default('1:1'), return_base64: z.boolean().optional(), include_thumbnail: z.boolean().optional(), safety_level: SafetyLevelSchema.default('BLOCK_MEDIUM_AND_ABOVE'), person_generation: PersonGenerationSchema.default('DONT_ALLOW'), language: LanguageSchema.default('auto'), model: ImagenGenerateModelSchema.default('imagen-3.0-generate-002'), region: z.string().optional(), sample_count: z.number().int().min(1).max(4).default(1), sample_image_size: SampleImageSizeSchema.optional(), }).refine((data) => { // Business rule: 2K only supported by specific models if (data.sample_image_size === '2K') { return data.model === 'imagen-4.0-generate-001' || data.model === 'imagen-4.0-ultra-generate-001'; } return true; }, { message: '2K resolution is only supported by imagen-4.0-generate-001 and imagen-4.0-ultra-generate-001', path: ['sample_image_size'], }); /** * Upscale Image Arguments Schema */ export const UpscaleImageArgsSchema = z.object({ input_path: z.string().min(1, 'Input path is required'), output_path: z.string().optional(), scale_factor: z.enum(['2', '4']).default('2'), return_base64: z.boolean().optional(), include_thumbnail: z.boolean().optional(), region: z.string().optional(), }); /** * Edit Image Arguments Schema */ export const EditImageArgsSchema = z.object({ prompt: z.string().min(1, 'Prompt is required'), reference_image_base64: z.string().optional(), reference_image_path: z.string().optional(), mask_image_base64: z.string().optional(), mask_image_path: z.string().optional(), mask_mode: z.enum(['background', 'foreground', 'semantic', 'user_provided', 'mask_free']).optional(), mask_classes: z.array(z.number().int()).optional(), mask_dilation: z.number().min(0).max(1).optional(), edit_mode: z.enum(['inpaint_removal', 'inpaint_insertion', 'bgswap', 'outpainting']).optional(), base_steps: z.number().int().min(1).max(75).optional(), output_path: z.string().optional(), return_base64: z.boolean().optional(), include_thumbnail: z.boolean().optional(), guidance_scale: z.number().optional(), sample_count: z.number().int().min(1).max(4).default(1), negative_prompt: z.string().optional(), model: ImagenCapabilityModelSchema.default('imagen-3.0-capability-001'), region: z.string().optional(), sample_image_size: SampleImageSizeSchema.optional(), }).refine((data) => { // Must have either reference_image_base64 or reference_image_path return data.reference_image_base64 || data.reference_image_path; }, { message: 'Either reference_image_base64 or reference_image_path is required', path: ['reference_image_base64'], }).refine((data) => { // If mask_mode is semantic, mask_classes is required if (data.mask_mode === 'semantic') { return data.mask_classes && data.mask_classes.length > 0; } return true; }, { message: 'mask_classes is required when mask_mode is "semantic"', path: ['mask_classes'], }); /** * Customize Image Arguments Schema */ const SubjectImageSchema = z.object({ image_base64: z.string().optional(), image_path: z.string().optional(), }).refine((data) => data.image_base64 || data.image_path, { message: 'Either image_base64 or image_path is required', path: ['image_base64'], }); export const CustomizeImageArgsSchema = z.object({ prompt: z.string().min(1, 'Prompt is required'), control_image_base64: z.string().optional(), control_image_path: z.string().optional(), control_type: z.enum(['face_mesh', 'canny', 'scribble']).optional(), enable_control_computation: z.boolean().optional(), subject_images: z.array(SubjectImageSchema).optional(), subject_description: z.string().optional(), subject_type: z.enum(['person', 'animal', 'product', 'default']).optional(), style_image_base64: z.string().optional(), style_image_path: z.string().optional(), style_description: z.string().optional(), output_path: z.string().optional(), aspect_ratio: AspectRatioSchema.default('1:1'), return_base64: z.boolean().optional(), include_thumbnail: z.boolean().optional(), safety_level: SafetyLevelSchema.default('BLOCK_MEDIUM_AND_ABOVE'), person_generation: PersonGenerationSchema.default('DONT_ALLOW'), language: LanguageSchema.default('auto'), negative_prompt: z.string().optional(), sample_count: z.number().int().min(1).max(4).default(1), model: ImagenCapabilityModelSchema.default('imagen-3.0-capability-001'), region: z.string().optional(), sample_image_size: SampleImageSizeSchema.optional(), }).refine((data) => { // Must have at least one of: control_image, subject_images, or style_image const hasControl = data.control_image_base64 || data.control_image_path; const hasSubject = data.subject_images && data.subject_images.length > 0; const hasStyle = data.style_image_base64 || data.style_image_path; return hasControl || hasSubject || hasStyle; }, { message: 'At least one of control_image, subject_images, or style_image is required', path: ['prompt'], }).refine((data) => { // If control image is provided, control_type is required if (data.control_image_base64 || data.control_image_path) { return !!data.control_type; } return true; }, { message: 'control_type is required when control image is provided', path: ['control_type'], }).refine((data) => { // If subject_images is provided, subject_description and subject_type are required if (data.subject_images && data.subject_images.length > 0) { return !!data.subject_description && !!data.subject_type; } return true; }, { message: 'subject_description and subject_type are required when subject_images are provided', path: ['subject_description'], }); /** * Generate and Upscale Image Arguments Schema */ export const GenerateAndUpscaleImageArgsSchema = z.object({ prompt: z.string().min(1, 'Prompt is required'), output_path: z.string().optional(), aspect_ratio: AspectRatioSchema.default('1:1'), scale_factor: z.enum(['2', '4']).default('2'), return_base64: z.boolean().optional(), include_thumbnail: z.boolean().optional(), safety_level: SafetyLevelSchema.default('BLOCK_MEDIUM_AND_ABOVE'), person_generation: PersonGenerationSchema.default('DONT_ALLOW'), language: LanguageSchema.default('auto'), model: ImagenGenerateModelSchema.default('imagen-3.0-generate-002'), region: z.string().optional(), sample_image_size: SampleImageSizeSchema.optional(), }).refine((data) => { if (data.sample_image_size === '2K') { return data.model === 'imagen-4.0-generate-001' || data.model === 'imagen-4.0-ultra-generate-001'; } return true; }, { message: '2K resolution is only supported by imagen-4.0-generate-001 and imagen-4.0-ultra-generate-001', path: ['sample_image_size'], }); /** * Job-related schemas */ export const StartJobArgsSchema = z.object({ tool_type: z.enum(['generate', 'edit', 'customize', 'upscale', 'generate_and_upscale']), params: z.record(z.string(), z.any()), }); export const CheckJobStatusArgsSchema = z.object({ job_id: z.string().uuid('Job ID must be a valid UUID'), }); export const GetJobResultArgsSchema = z.object({ job_id: z.string().uuid('Job ID must be a valid UUID'), }); export const CancelJobArgsSchema = z.object({ job_id: z.string().uuid('Job ID must be a valid UUID'), }); export const ListJobsArgsSchema = z.object({ status: z.enum(['pending', 'running', 'completed', 'failed']).optional(), limit: z.number().int().positive().default(50), }); /** * History-related schemas */ export const ListHistoryArgsSchema = z.object({ filters: z.object({ tool_name: z.string().optional(), model: z.string().optional(), aspect_ratio: z.string().optional(), date_from: z.string().optional(), date_to: z.string().optional(), }).optional(), sort_by: z.enum(['created_at', 'file_size']).default('created_at'), sort_order: z.enum(['asc', 'desc']).default('desc'), limit: z.number().int().positive().default(50), offset: z.number().int().nonnegative().default(0), }); export const SearchHistoryArgsSchema = z.object({ query: z.string().min(1, 'Search query is required'), limit: z.number().int().positive().default(50), filters: z.object({ tool_name: z.string().optional(), model: z.string().optional(), aspect_ratio: z.string().optional(), date_from: z.string().optional(), date_to: z.string().optional(), }).optional(), }); export const GetHistoryByUuidArgsSchema = z.object({ uuid: z.string().uuid('UUID must be a valid UUID'), }); export const GetMetadataFromImageArgsSchema = z.object({ image_path: z.string().min(1, 'Image path is required'), }); /** * Template-related schemas */ export const SavePromptTemplateArgsSchema = z.object({ name: z.string().regex(/^[a-zA-Z0-9_-]+$/, 'Template name must contain only alphanumeric characters, hyphens, and underscores'), description: z.string().min(1, 'Description is required'), template: z.string().min(1, 'Template is required'), variables: z.array(z.string()).optional(), default_params: z.record(z.string(), z.any()).optional(), tags: z.array(z.string()).optional(), }); export const ListPromptTemplatesArgsSchema = z.object({ tags: z.array(z.string()).optional(), search: z.string().optional(), }); export const GetTemplateDetailArgsSchema = z.object({ template_name: z.string().min(1, 'Template name is required'), }); export const GenerateFromTemplateArgsSchema = z.object({ template_name: z.string().min(1, 'Template name is required'), variable_values: z.record(z.string(), z.any()), override_params: z.record(z.string(), z.any()).optional(), }); export const DeleteTemplateArgsSchema = z.object({ template_name: z.string().min(1, 'Template name is required'), }); export const UpdateTemplateArgsSchema = z.object({ template_name: z.string().min(1, 'Template name is required'), description: z.string().optional(), template: z.string().optional(), variables: z.array(z.string()).optional(), default_params: z.record(z.string(), z.any()).optional(), tags: z.array(z.string()).optional(), }); /** * Other tool schemas */ export const ListGeneratedImagesArgsSchema = z.object({ directory: z.string().optional(), }); export const ListSemanticClassesArgsSchema = z.object({ category: z.string().optional(), search: z.string().optional(), ids: z.array(z.number().int()).optional(), }); export const CustomizeImageFromYamlArgsSchema = z.object({ yaml_path: z.string().min(1, 'YAML path is required'), }); export const CustomizeImageFromYamlInlineArgsSchema = z.object({ yaml_content: z.string().min(1, 'YAML content is required'), }); //# sourceMappingURL=schemas.js.map