- Documented Fluent-based i18n system with locale detection - Bumped version from 1.0.10 to 1.0.11
527 lines
18 KiB
Plaintext
527 lines
18 KiB
Plaintext
#!/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)"
|
|
}
|
|
}
|