Skip to main content
Glama
character-tools.js17.8 kB
// MCP Tools for Character Production Pipeline // These tools will be exposed through the MCP server for LM Studio access // Removed deprecated character-pipeline.js import - using corrected AffogatoClient from guidance notes import { getProductionToolDefinitions, getProductionToolHandlers } from './production-tools.js'; import { getVideoProductionToolDefinitions, getVideoProductionToolHandlers } from './video-production-tools.js'; import { getStorylineToolDefinitions, getStorylineToolHandlers } from './storyline-tools.js'; import { getAgentManagementToolDefinitions, getAgentManagementToolHandlers } from './agent-management-tools.js'; import { DatabaseSchemaEnhancer } from '../integrations/database-schema-enhancer.js'; import path from 'path'; import fs from 'fs'; // Legacy pipeline removed - these tools now use the corrected Affogato integration // const pipeline = new CharacterProductionPipeline(process.env.AFFOGATO_API_KEY); export const characterTools = { // Tool 1: Create character from text description create_character_from_description: { name: "create_character_from_description", description: "Create a complete puppet character from a text description using Claude AI analysis and Affogato image generation. Generates 11 images (7 emotions + 4 directional views) with authentic puppet mechanics.", inputSchema: { type: "object", properties: { character_name: { type: "string", description: "Name of the character to create" }, description: { type: "string", description: "Detailed description of the character (appearance, personality, background)" }, cultural_background: { type: "string", description: "Optional cultural background for authentic representation (e.g., 'Brazilian', 'Irish', 'Japanese')" } }, required: ["character_name", "description"] }, handler: async (args) => { try { // Construct proper characterData object for pipeline const characterData = { name: args.character_name, description: args.description, characterType: 'Main Character', personalityTraits: [], voiceDescription: '', characterTraits: { cultural_background: args.cultural_background || 'Not specified', physical: {}, clothing: {}, personality: {}, puppet_specs: {} } }; const result = await pipeline.createCharacterFromDescription(characterData); if (result.success) { return { success: true, message: `Character "${args.character_name}" created successfully with ${result.character.images.length} images`, character: { name: result.character.name, description: result.character.description, affogato_id: result.character.affogatoId, output_path: result.character.outputPath, image_count: result.character.images.length, emotions_generated: result.character.images.filter(img => img.type === 'emotion').length, directions_generated: result.character.images.filter(img => img.type === 'direction').length } }; } else { return { success: false, error: result.error }; } } catch (error) { return { success: false, error: error.message }; } } }, // Tool 2: Analyze existing character images analyze_character_images: { name: "analyze_character_images", description: "Analyze existing character images with Claude AI to extract detailed traits and save to database. Perfect for adding existing characters to the production pipeline.", inputSchema: { type: "object", properties: { character_name: { type: "string", description: "Name of the character being analyzed" }, image_paths: { type: "array", items: { type: "string" }, description: "Array of file paths to character images" } }, required: ["character_name", "image_paths"] }, handler: async (args) => { try { const result = await pipeline.analyzeExistingCharacterImages( args.character_name, args.image_paths ); if (result.success) { return { success: true, message: `Character "${args.character_name}" analyzed successfully from ${result.imageCount} images`, analysis: { character_name: args.character_name, images_analyzed: result.imageCount, traits_extracted: Object.keys(result.analysis.traits).length, database_saved: true } }; } else { return { success: false, error: result.error }; } } catch (error) { return { success: false, error: error.message }; } } }, // Tool 3: Generate scene with character consistency generate_character_scene: { name: "generate_character_scene", description: "Generate a scene featuring an existing character while maintaining perfect consistency. Character traits are automatically pulled from the database.", inputSchema: { type: "object", properties: { character_name: { type: "string", description: "Name of existing character in database" }, scene_description: { type: "string", description: "Description of the scene to generate" }, scene_title: { type: "string", description: "Title for the scene" }, directional_overrides: { type: "object", description: "Optional overrides for character direction/pose", properties: { direction: { type: "string", enum: ["front", "left", "right", "back"], description: "Character facing direction" }, emotion: { type: "string", description: "Character emotion override" } } } }, required: ["character_name", "scene_description", "scene_title"] }, handler: async (args) => { try { const sceneData = { sceneDescription: args.scene_description, sceneTitle: args.scene_title }; const result = await pipeline.generateScene( args.character_name, sceneData, args.directional_overrides || {} ); if (result.success) { return { success: true, message: `Scene "${args.scene_title}" generated successfully with character consistency`, scene: { title: args.scene_title, character: args.character_name, file_path: result.scene.filepath, consistency_score: result.scene.consistency?.score || 'N/A' } }; } else { return { success: false, error: result.error }; } } catch (error) { return { success: false, error: error.message }; } } }, // Tool 4: Generate multi-character scene generate_multi_character_scene: { name: "generate_multi_character_scene", description: "Generate a scene with multiple characters maintaining individual consistency. All characters must exist in the database.", inputSchema: { type: "object", properties: { character_names: { type: "array", items: { type: "string" }, description: "Array of character names to include in scene" }, scene_description: { type: "string", description: "Description of the multi-character scene" }, scene_title: { type: "string", description: "Title for the scene" }, character_interactions: { type: "string", description: "Optional description of how characters interact", default: "standing together" }, lighting_setup: { type: "string", description: "Optional lighting setup", default: "studio_standard" } }, required: ["character_names", "scene_description", "scene_title"] }, handler: async (args) => { try { const sceneData = { sceneDescription: args.scene_description, sceneTitle: args.scene_title, characterInteractions: args.character_interactions, lightingSetup: args.lighting_setup }; const result = await pipeline.generateMultiCharacterScene( args.character_names, sceneData ); if (result.success) { return { success: true, message: `Multi-character scene "${args.scene_title}" generated with ${args.character_names.length} characters`, scene: { title: args.scene_title, characters: result.scene.characters, file_path: result.scene.filepath, consistency_validation: result.scene.consistency?.promptValidation || 'N/A' } }; } else { return { success: false, error: result.error }; } } catch (error) { return { success: false, error: error.message }; } } }, // Tool 5: List available characters list_characters: { name: "list_characters", description: "List all characters available in the production database with their key details.", inputSchema: { type: "object", properties: { include_traits: { type: "boolean", description: "Include detailed character traits in response", default: false } } }, handler: async (args) => { try { const notion = await pipeline.getNotionClient(); if (!notion || !notion.databases || !notion.databases.query) { throw new Error('Notion client not properly initialized'); } const response = await notion.databases.query({ database_id: process.env.CHARACTERS_MASTER_DB || '5b96c172-96b2-4b53-a52c-60d4874779f4' }); const characters = response.results.map(page => { const basic = { name: page.properties['Character Name']?.title[0]?.text?.content || 'Unnamed', description: page.properties['Description']?.rich_text[0]?.text?.content || 'No description', cultural_background: page.properties['Cultural Background']?.rich_text[0]?.text?.content || 'Not specified', affogato_id: page.properties['Voice ID']?.rich_text[0]?.text?.content || 'None', created: page.created_time, page_id: page.id }; if (args.include_traits) { // Extract detailed traits if requested if (!pipeline.dbEnhancer) { pipeline.dbEnhancer = new DatabaseSchemaEnhancer(notion); } basic.traits = pipeline.dbEnhancer.extractCharacterTraits(page); } return basic; }); return { success: true, message: `Found ${characters.length} characters in database`, characters: characters, total_count: characters.length }; } catch (error) { return { success: false, error: error.message }; } } }, // Tool 6: Get character details get_character_details: { name: "get_character_details", description: "Get detailed information about a specific character including all traits and production history.", inputSchema: { type: "object", properties: { character_name: { type: "string", description: "Name of the character to retrieve details for" } }, required: ["character_name"] }, handler: async (args) => { try { const characterData = await pipeline.getCharacterTraitsFromNotion(args.character_name); return { success: true, message: `Retrieved details for character "${args.character_name}"`, character: { name: args.character_name, affogato_id: characterData.affogatoId, traits: characterData.traits, notion_page_id: characterData.page.id, last_updated: characterData.page.last_edited_time } }; } catch (error) { return { success: false, error: error.message }; } } } }; // Export tool definitions for MCP server registration export const getCharacterToolDefinitions = () => { const characterToolDefs = Object.values(characterTools).map(tool => ({ name: tool.name, description: tool.description, inputSchema: tool.inputSchema })); // Combine with production, storyline, and agent management tools const productionToolDefs = getProductionToolDefinitions(); const videoToolDefs = getVideoProductionToolDefinitions(); const storylineToolDefs = getStorylineToolDefinitions(); const agentToolDefs = getAgentManagementToolDefinitions(); return [...characterToolDefs, ...productionToolDefs, ...videoToolDefs, ...storylineToolDefs, ...agentToolDefs]; }; // Export tool handlers for MCP server execution export const getCharacterToolHandlers = () => { const handlers = {}; // Add character tool handlers Object.values(characterTools).forEach(tool => { handlers[tool.name] = tool.handler; }); // Add production tool handlers const productionHandlers = getProductionToolHandlers(); Object.assign(handlers, productionHandlers); // Add video tool handlers const videoTools = getVideoProductionToolHandlers(); Object.values(videoTools).forEach((tool, index) => { const toolName = Object.keys(videoTools)[index]; handlers[toolName] = tool.handler; }); // Add storyline tool handlers const storylineHandlers = getStorylineToolHandlers(); Object.assign(handlers, storylineHandlers); // Add agent management tool handlers const agentHandlers = getAgentManagementToolHandlers(); Object.assign(handlers, agentHandlers); return handlers; };

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/bermingham85/mcp-puppet-pipeline'

If you have feedback or need assistance with the MCP directory API, please join our Discord server