#!/usr/bin/env nu # AuroraFrame MCP Server - Native Nushell Implementation # # Model Context Protocol server providing AI-powered tools for AuroraFrame: # - Content generation from KCL schemas # - Schema intelligence and validation # - Multi-format content optimization # - Error resolution and debugging # - Asset generation and optimization # Global configuration let MCP_CONFIG = { name: "auroraframe-mcp-server" version: "1.0.0" openai_model: "gpt-4" openai_api_key: ($env.OPENAI_API_KEY? | default "") project_path: ($env.AURORAFRAME_PROJECT_PATH? | default (pwd)) default_language: ($env.AURORAFRAME_DEFAULT_LANGUAGE? | default "en") max_tokens: 4000 temperature: 0.7 } # Import tool modules use content-generator.nu * use schema-intelligence.nu * use error-resolver.nu * use asset-generator.nu * # MCP Protocol Implementation export def main [ --debug(-d) # Enable debug logging --config(-c): string # Custom config file path ] { if $debug { print "🔥 Starting AuroraFrame MCP Server in debug mode" print $" Configuration: ($MCP_CONFIG)" } # Load custom config if provided let config = if ($config | is-not-empty) { load_custom_config $config } else { $MCP_CONFIG } # Start MCP server loop mcp_server_loop $config $debug } # Main MCP server event loop def mcp_server_loop [config: record, debug: bool] { if $debug { print "📡 Starting MCP server event loop" } loop { # Read MCP message from stdin let input_line = try { input } catch { break } if ($input_line | is-empty) { continue } # Parse JSON message let message = try { $input_line | from json } catch { if $debug { print $"❌ Failed to parse JSON: ($input_line)" } continue } # Process MCP message and send response let response = (handle_mcp_message $message $config $debug) $response | to json --raw | print } } # Handle incoming MCP messages def handle_mcp_message [message: record, config: record, debug: bool] { if $debug { print $"📨 Received MCP message: ($message.method)" } match $message.method { "initialize" => (handle_initialize $message $config) "tools/list" => (handle_tools_list $message) "tools/call" => (handle_tool_call $message $config $debug) _ => (create_error_response $message.id "Method not found" -32601) } } # Handle MCP initialize request def handle_initialize [message: record, config: record] { { jsonrpc: "2.0" id: $message.id result: { protocolVersion: "2024-11-05" capabilities: { tools: {} } serverInfo: { name: $config.name version: $config.version } } } } # Handle tools list request def handle_tools_list [message: record] { { jsonrpc: "2.0" id: $message.id result: { tools: [ # Content Generation Tools { name: "generate_content" description: "Generate content from KCL schema and prompt" inputSchema: { type: "object" properties: { schema: { type: "object" description: "KCL schema definition for content structure" } prompt: { type: "string" description: "Content generation prompt" } format: { type: "string" enum: ["markdown", "html", "json"] default: "markdown" description: "Output format" } } required: ["schema", "prompt"] } } { name: "enhance_content" description: "Enhance existing content with AI improvements" inputSchema: { type: "object" properties: { content: { type: "string" description: "Existing content to enhance" } enhancements: { type: "array" items: { type: "string" enum: ["seo", "readability", "structure", "metadata", "images"] } description: "Types of enhancements to apply" } } required: ["content", "enhancements"] } } { name: "generate_variations" description: "Generate content variations for A/B testing" inputSchema: { type: "object" properties: { content: { type: "string" description: "Base content to create variations from" } count: { type: "number" default: 3 description: "Number of variations to generate" } focus: { type: "string" enum: ["tone", "length", "structure", "conversion"] description: "Aspect to vary" } } required: ["content"] } } # Schema Intelligence Tools { name: "generate_schema" description: "Generate KCL schema from natural language description" inputSchema: { type: "object" properties: { description: { type: "string" description: "Natural language description of desired schema" } examples: { type: "array" items: { type: "object" } description: "Example data objects to inform schema" } } required: ["description"] } } { name: "validate_schema" description: "Validate and suggest improvements for KCL schema" inputSchema: { type: "object" properties: { schema: { type: "string" description: "KCL schema to validate" } data: { type: "array" items: { type: "object" } description: "Sample data to validate against schema" } } required: ["schema"] } } { name: "migrate_schema" description: "Help migrate data between schema versions" inputSchema: { type: "object" properties: { old_schema: { type: "string" description: "Previous schema version" } new_schema: { type: "string" description: "New schema version" } data: { type: "array" items: { type: "object" } description: "Data to migrate" } } required: ["old_schema", "new_schema"] } } # Error Resolution Tools { name: "resolve_error" description: "Analyze and suggest fixes for AuroraFrame errors" inputSchema: { type: "object" properties: { error: { type: "object" properties: { message: { type: "string" } code: { type: "string" } file: { type: "string" } line: { type: "number" } context: { type: "string" } } description: "Error details from AuroraFrame" } project_context: { type: "object" description: "Project context for better error resolution" } } required: ["error"] } } { name: "analyze_build" description: "Analyze build performance and suggest optimizations" inputSchema: { type: "object" properties: { build_log: { type: "string" description: "Build log output from AuroraFrame" } metrics: { type: "object" description: "Build performance metrics" } } required: ["build_log"] } } # Asset Generation Tools { name: "generate_images" description: "Generate images from text descriptions" inputSchema: { type: "object" properties: { prompt: { type: "string" description: "Image generation prompt" } count: { type: "number" default: 1 description: "Number of images to generate" } size: { type: "string" enum: ["1024x1024", "1024x1792", "1792x1024"] default: "1024x1024" description: "Image dimensions" } style: { type: "string" enum: ["natural", "vivid"] default: "natural" description: "Image style" } } required: ["prompt"] } } { name: "optimize_assets" description: "Optimize images and assets for web delivery" inputSchema: { type: "object" properties: { assets: { type: "array" items: { type: "object" properties: { path: { type: "string" } type: { type: "string" } } } description: "List of assets to optimize" } targets: { type: "array" items: { type: "string" enum: ["web", "email", "mobile"] } description: "Target formats for optimization" } } required: ["assets"] } } ] } } } # Handle tool call request def handle_tool_call [message: record, config: record, debug: bool] { let tool_name = $message.params.name let args = $message.params.arguments if $debug { print $"🔧 Calling tool: ($tool_name)" } let result = match $tool_name { # Content Generation Tools "generate_content" => (generate_content_tool $args $config $debug) "enhance_content" => (enhance_content_tool $args $config $debug) "generate_variations" => (generate_variations_tool $args $config $debug) # Schema Intelligence Tools "generate_schema" => (generate_schema_tool $args $config $debug) "validate_schema" => (validate_schema_tool $args $config $debug) "migrate_schema" => (migrate_schema_tool $args $config $debug) # Error Resolution Tools "resolve_error" => (resolve_error_tool $args $config $debug) "analyze_build" => (analyze_build_tool $args $config $debug) # Asset Generation Tools "generate_images" => (generate_images_tool $args $config $debug) "optimize_assets" => (optimize_assets_tool $args $config $debug) _ => { error: $"Unknown tool: ($tool_name)" } } if "error" in $result { create_error_response $message.id $result.error -32603 } else { { jsonrpc: "2.0" id: $message.id result: { content: $result.content } } } } # Create MCP error response def create_error_response [id: any, message: string, code: int] { { jsonrpc: "2.0" id: $id error: { code: $code message: $message } } } # Load custom configuration def load_custom_config [config_path: string] { if ($config_path | path exists) { let custom_config = (open $config_path) $MCP_CONFIG | merge $custom_config } else { print $"⚠️ Config file not found: ($config_path)" $MCP_CONFIG } } # OpenAI API call helper export def call_openai_api [ messages: list config: record temperature: float = 0.7 max_tokens: int = 4000 ] { if ($config.openai_api_key | is-empty) { return { error: "OpenAI API key not configured" } } let payload = { model: $config.openai_model messages: $messages temperature: $temperature max_tokens: $max_tokens } let response = try { http post "https://api.openai.com/v1/chat/completions" --headers [ "Content-Type" "application/json" "Authorization" $"Bearer ($config.openai_api_key)" ] $payload } catch { |e| return { error: $"OpenAI API call failed: ($e.msg)" } } if "error" in $response { { error: $response.error.message } } else { { content: $response.choices.0.message.content } } } # Utility: Extract frontmatter from content export def extract_frontmatter [content: string] { let lines = ($content | lines) if ($lines | first) == "---" { let end_idx = ($lines | skip 1 | enumerate | where { |it| $it.item == "---" } | first?.index) if ($end_idx | is-not-empty) { let frontmatter_lines = ($lines | skip 1 | first ($end_idx)) let content_lines = ($lines | skip ($end_idx + 2)) { frontmatter: ($frontmatter_lines | str join "\n" | from yaml) content: ($content_lines | str join "\n") } } else { { frontmatter: {}, content: $content } } } else { { frontmatter: {}, content: $content } } } # Utility: Generate frontmatter export def generate_frontmatter [title: string, additional: record = {}] { let base_frontmatter = { title: $title date: (date now | format date "%Y-%m-%d") generated: true generator: "auroraframe-mcp-server" } $base_frontmatter | merge $additional | to yaml } # Utility: Validate KCL syntax (basic check) export def validate_kcl_syntax [kcl_content: string] { # Basic KCL syntax validation let issues = [] # Check for schema definitions if not ($kcl_content | str contains "schema ") { $issues = ($issues | append "No schema definitions found") } # Check for proper schema syntax let schema_matches = ($kcl_content | str find-replace -ar 'schema\s+(\w+):' 'SCHEMA_FOUND') if not ($schema_matches | str contains "SCHEMA_FOUND") { $issues = ($issues | append "Invalid schema syntax") } # Check for type annotations if not (($kcl_content | str contains ": str") or ($kcl_content | str contains ": int") or ($kcl_content | str contains ": bool")) { $issues = ($issues | append "No type annotations found") } if ($issues | length) > 0 { { valid: false, issues: $issues } } else { { valid: true, issues: [] } } } # Debug helper def debug_log [message: string, debug: bool] { if $debug { print $"🐛 DEBUG: ($message)" } }