CreatorNode MCP Server

MCP (Model Context Protocol) server providing AI agents with tools for creator workflows.

Table of Contents

Installation

Claude Desktop

Add to claude_desktop_config.json:

{
  "mcpServers": {
    "creatornode": {
      "command": "npx",
      "args": ["-y", "@creatornode/mcp-server"],
      "env": {
        "CREATORNODE_API_KEY": "your-api-key"
      }
    }
  }
}

Cursor

Add to MCP settings:

{
  "mcpServers": {
    "creatornode": {
      "command": "npx",
      "args": ["-y", "@creatornode/mcp-server"],
      "env": {
        "CREATORNODE_API_KEY": "your-api-key"
      }
    }
  }
}

VS Code (Copilot)

Add to .vscode/mcp.json:

{
  "servers": {
    "creatornode": {
      "type": "stdio",
      "command": "npx",
      "args": ["-y", "@creatornode/mcp-server"],
      "env": {
        "CREATORNODE_API_KEY": "your-api-key"
      }
    }
  }
}

Getting an API Key

Free Tier (no signup required)

Use the API immediately with built-in rate limits:

  • 20 API calls per day
  • Up to 3 variants per request
  • 2 requests per minute rate limit

No API key is needed for free tier access to supported public endpoints. Free tier requests use stricter rate limits and lower usage caps.

For higher limits and premium features:

  1. Visit Pricing
  2. Purchase a credit package (Boost $3 / Starter $10 / Professional $100)
  3. Receive your API key via email after purchase
  4. Add the key to your MCP configuration

See the Pricing page for plan comparison.

Environment Variables

VariableDefaultDescription
CREATORNODE_API_KEY-API key for paid tiers and higher limits. Omit it to use anonymous free-tier access on supported public endpoints.
CREATORNODE_API_URLhttps://api.creatornode.ioAPI base URL (override only if self-hosting)
MCP_REQUEST_TIMEOUT_MS10000Request timeout in milliseconds
MCP_LOG_LEVELinfoLog level: silent, error, info, debug

Cost Preview (Price Check)

When calling CreatorNode APIs directly via REST, you can request a pricing preview without executing endpoint logic.

Send this request header:

X-Price-Check: true

Typical response:

{
  "cost": 3,
  "balance": 97,
  "sufficient": true
}

Rules:

  • No credits are consumed for price-check requests.
  • Available only for paid keys (premium, enterprise).
  • Requires a valid key with at least 1 credit.
  • Not available on demo endpoints.
  • Light rate-limiting applies to prevent abuse.

MCP tools in this package always perform the requested operation. Use direct REST calls with X-Price-Check when you need preflight cost estimation.

Tool Namespaces

Tools are organized into namespaces by domain:

NamespaceDescription
youtube.*YouTube creator tools (thumbnails, hook validation)
visual.*Visual tools (Mermaid diagrams, code rendering, code diffs, timelines)
science.*Science tools (chemistry validation, comparison)
audio.*Audio processing tools (merge, concatenation)
postproduction.*Postproduction tools (scene descriptions)
system.*Cross-cutting tools (health checks)

Tools

youtube.rank_thumbnails

Analyze and rank YouTube thumbnail variants to find the best performing option.

What it does:

  • AI-powered visual quality analysis across multiple dimensions
  • Contextual relevance checks when a video title is provided
  • Technical quality verification for mobile and compression scenarios

Inputs:

ParameterTypeRequiredDescription
variantsarray2-10 thumbnail variants with id and imageBase64
titlestringVideo title for context-aware analysis

Example:

{
  "variants": [
    { "id": "option-a", "imageBase64": "iVBORw0KGgoAAAANSUhEUgAA..." },
    { "id": "option-b", "imageBase64": "iVBORw0KGgoAAAANSUhEUgAA..." }
  ],
  "title": "How I Built a $1M Business"
}

Output:

{
  "success": true,
  "data": {
    "winner": {
      "id": "option-b",
      "score": 80,
      "reasons": ["🏆 Top-ranked thumbnail", "✓ Excellent mobile clarity"]
    },
    "variants": [
      {
        "id": "option-b",
        "rank": 1,
        "score": 80,
        "subscores": {
          "mobileLegibility": 100,
          "contrastRobustness": 98,
          "saliencyProxy": 60,
          "textDensity": 50,
          "facePresence": 85,
          "semanticAlignment": 78
        },
        "diagnostics": {
          "focalPoint": "Person centered with clear eye contact",
          "detectedText": "CLICK HERE",
          "semanticReason": "Strong match - thumbnail shows tutorial action",
          "faceCount": 1
        },
        "reasons": ["🏆 Top-ranked thumbnail", "✓ Excellent mobile clarity"],
        "isWinner": true
      }
    ],
    "confidence": {
      "level": "high",
      "value": 0.82,
      "factors": {
        "signalCoverage": 0.9,
        "scoreStability": 0.85,
        "marginStrength": 0.7
      }
    }
  },
  "meta": {
    "requestId": "req_abc123",
    "processingTimeMs": 1200,
    "variantCount": 2,
    "aiUsed": true
  }
}

youtube.validate_hook

Validate alignment between thumbnail, title, and video intro to predict viewer retention.

What it does:

  • Analyzes alignment between thumbnail, title, and video intro
  • Detects mismatches that cause viewers to leave early
  • Predicts early drop-off risk

Inputs:

ParameterTypeRequiredDescription
thumbnailobject{ imageBase64 }
titlestringVideo title
scriptIntrostringFirst 60-90 seconds of script

Example:

{
  "thumbnail": { "imageBase64": "iVBORw0KGgoAAAANSUhEUgAA..." },
  "title": "I Quit My Job to Build This App",
  "scriptIntro": "Six months ago, I walked into my boss's office..."
}

Output:

{
  "success": true,
  "valid": true,
  "validation": {
    "riskLevel": "low",
    "riskScore": 15,
    "primaryIssue": null,
    "mismatches": [],
    "prediction": {
      "earlyDropoffPercent": 12
    }
  },
  "thumbnail": {
    "emotion": "determination",
    "stakes": "high",
    "keyElements": ["person", "laptop", "office"],
    "energyLevel": "medium"
  },
  "title": {
    "promise": "Career change story",
    "tone": "dramatic",
    "clickbaitScore": 35
  },
  "scriptHook": {
    "wpm": 165,
    "infoDensity": 72,
    "openingEnergy": "high",
    "payoffDelay": 8,
    "actualContent": "Personal story about quitting job",
    "deliversPromise": true
  },
  "recommendations": [
    {
      "type": "tip",
      "title": "Strong alignment",
      "message": "Thumbnail emotion matches intro energy well",
      "priority": "low"
    }
  ],
  "metadata": {
    "requestId": "req_xyz789",
    "processingTimeMs": 2500,
    "aiUsed": true
  }
}

visual.render_diagram

Render Mermaid diagrams to SVG, PNG, ASCII, or Unicode format.

Supported Diagram Types:

  • flowchart / graph - Flow charts and graphs
  • stateDiagram - State machine diagrams
  • sequenceDiagram - Sequence diagrams
  • classDiagram - UML class diagrams
  • erDiagram - Entity relationship diagrams

Inputs:

ParameterTypeRequiredDescription
definitionstringMermaid diagram definition
formatstringOutput: svg, png, ascii, unicode (default: svg)
themestringTheme: light, dark, neutral, or full theme name
optionsobjectAdditional options (colors, font, direction, png settings)

Example:

{
  "definition": "flowchart LR\n  A[Start] --> B{Decision}\n  B -->|Yes| C[Action 1]\n  B -->|No| D[Action 2]\n  C --> E[End]\n  D --> E",
  "format": "svg",
  "theme": "dark"
}

Output:

{
  "success": true,
  "data": "<svg>...</svg>",
  "format": "svg",
  "meta": {
    "requestId": "abc123",
    "diagramType": "flowchart",
    "themeName": "tokyo-night",
    "processingTimeMs": 45,
    "sizeBytes": 2048
  }
}

Themes:

  • Aliases: light, dark, neutral
  • Full themes: zinc-light, github-light, slate-light, tokyo-night, github-dark, zinc-dark, slate-dark, dracula, monokai, nord, rose-pine, catppuccin-latte, catppuccin-mocha, solarized-light, solarized-dark

visual.render_code

Render source code to syntax-highlighted SVG or PNG images.

What it does:

  • VS Code-quality syntax highlighting
  • 200+ languages supported
  • Line numbers, line highlighting, filename headers
  • PNG presets for social media cards
  • Auto-sizing with optional fixed dimensions

Inputs:

ParameterTypeRequiredDescription
codestringSource code to render (max 500KB)
languagestringLanguage identifier (e.g., typescript, python, rust)
formatstringOutput: svg or png (default: svg)
themestringColor theme (default: github-dark)
optionsobjectRendering options (see below)

Options:

OptionTypeDefaultDescription
filenamestring-Filename header above the code
lineNumbersbooleantrueShow line numbers
highlightLinesstring-Lines to highlight: "1,3,5-10"
startLinenumber1Starting line number
tabSizenumber2Tab width in spaces
wordWrapbooleanfalseWrap long lines
fontSizenumber14Font size in pixels (8-32)
paddingnumber16Padding in pixels (0-64)
widthnumberautoFixed width in pixels (100-4096)
heightnumberautoFixed height in pixels (100-4096)
presetstring-PNG preset: og (1200×630), twitter (1200×675), square (1080×1080)

Example:

{
  "code": "const greeting = 'Hello, World!';\nconsole.log(greeting);",
  "language": "typescript",
  "format": "svg",
  "theme": "github-dark",
  "options": {
    "filename": "hello.ts",
    "lineNumbers": true,
    "highlightLines": "2"
  }
}

Output:

{
  "success": true,
  "data": "<svg>...</svg>",
  "format": "svg",
  "meta": {
    "requestId": "req_abc123",
    "language": "typescript",
    "theme": "github-dark",
    "filename": "hello.ts",
    "processingTimeMs": 85,
    "lineCount": 2,
    "sizeBytes": 4096,
    "cached": false,
    "width": 620,
    "height": 120
  }
}

Common Themes: github-dark (default), github-light, dracula, one-dark-pro, nord, monokai, tokyo-night, rose-pine, catppuccin-latte, catppuccin-mocha, solarized-light, solarized-dark


visual.render_code_diff

Render a side-by-side code diff as syntax-highlighted SVG or PNG.

What it does:

  • Computes unified diff between before/after code
  • Added lines highlighted green, removed lines highlighted red
  • Full syntax highlighting (not just diff markers)
  • 200+ languages supported
  • PNG presets for social media cards

Inputs:

ParameterTypeRequiredDescription
beforestringOriginal (before) code. Can be empty for newly added files
afterstringModified (after) code. Can be empty for deleted files
languagestringLanguage identifier (e.g., typescript, python, rust)
formatstringOutput: svg or png (default: svg)
themestringColor theme (default: github-dark)
optionsobjectRendering options (see below)

Options:

OptionTypeDefaultDescription
filenamestring-Filename header above the diff
lineNumbersbooleantrueShow line numbers
tabSizenumber2Tab width in spaces
fontSizenumber14Font size in pixels (8-32)
paddingnumber16Padding in pixels (0-64)
widthnumberautoFixed width in pixels (100-4096)
heightnumberautoFixed height in pixels (100-4096)
presetstring-PNG preset: og (1200×630), twitter (1200×675), square (1080×1080)

Example:

{
  "before": "const greeting = 'Hello';\nconsole.log(greeting);",
  "after": "const greeting = 'Hello, World!';\nconsole.log(greeting);\nconsole.log('Done!');",
  "language": "typescript",
  "format": "svg",
  "theme": "github-dark",
  "options": {
    "filename": "hello.ts",
    "lineNumbers": true
  }
}

Output:

{
  "success": true,
  "data": "<svg>...</svg>",
  "format": "svg",
  "meta": {
    "requestId": "req_abc123",
    "language": "typescript",
    "theme": "github-dark",
    "filename": "hello.ts",
    "processingTimeMs": 95,
    "lineCount": 3,
    "sizeBytes": 5120,
    "cached": false,
    "width": 720,
    "height": 160,
    "diff": {
      "added": 2,
      "removed": 1,
      "unchanged": 1
    }
  }
}

visual.render_timeline

Render a timeline visualization from structured events to SVG or PNG.

What it does:

  • Vertical and horizontal orientations
  • Light/dark themes with custom accent colours
  • Alternate (zigzag) and compact card layouts
  • Auto-sizing based on event count
  • Font families: Inter, Roboto, JetBrains Mono
  • Transparent background support (SVG only)

Inputs:

ParameterTypeRequiredDescription
eventsarray1-50 events with date, title, and optional text
orientationstringvertical or horizontal (default: vertical)
formatstringOutput: svg or png (default: svg)
layoutstringCard layout: alternate (zigzag) or compact (one side). Default: alternate
titlestringOptional title displayed above the timeline
themestringlight or dark (default: light)
accentColorstringCustom accent colour (#RRGGBB) — overrides dot and date colours
transparentbooleanTransparent background, SVG only (default: false)
fontFamilystringinter (default), roboto, or mono (JetBrains Mono)
widthnumberImage width in pixels (auto if omitted, 200-4096)
heightnumberImage height in pixels (auto if omitted, 200-4096)

Example:

{
  "events": [
    { "date": "Jan 2026", "title": "Alpha Launch", "text": "Internal testing begins" },
    { "date": "Mar 2026", "title": "Public Beta", "text": "Open to all users" },
    { "date": "Jun 2026", "title": "v1.0 Release", "text": "Production ready" }
  ],
  "title": "Product Roadmap",
  "theme": "dark",
  "orientation": "vertical",
  "layout": "alternate",
  "fontFamily": "inter"
}

Output:

{
  "success": true,
  "data": "<svg>...</svg>",
  "format": "svg",
  "meta": {
    "requestId": "req_xyz789",
    "orientation": "vertical",
    "processingTimeMs": 120,
    "eventCount": 3,
    "sizeBytes": 8192,
    "width": 600,
    "height": 800,
    "cached": false
  }
}

Note: Events are rendered in array order — the API does NOT sort them. Arrange events chronologically in your input.


visual.render_chem

Render a SMILES chemical notation string as a 2D structure diagram (base64 SVG or base64 PNG).

What it does:

  • SMILES → 2D structure rendering
  • Output as base64 SVG (default) or base64 PNG
  • Optional presets and rendering options (dimensions, fit, thickness)
  • Optional atom highlighting and per-atom weights heatmap overlays

Inputs:

ParameterTypeRequiredDescription
smilesstringSMILES string (max 5000 chars)
formatstringsvg or png (default: svg)
themestringlight or dark (default: light)
presetstringdefault, publication, presentation, thumbnail, social-card
optionsobjectRendering options (width/height/transparent/colors, etc.)

Example:

{
  "smiles": "[CH3:1][CH2:2][OH:3]",
  "format": "svg",
  "theme": "light",
  "preset": "publication",
  "options": {
    "width": 600,
    "height": 400,
    "highlightAtoms": [{ "atomClass": 2, "color": "#ff0000" }],
    "weights": { "values": [0.0, 0.5, 1.0], "normalized": true }
  }
}

Note: weights.values must have the same length as the number of heavy atoms in the molecule.


science.validate_chemistry

Validate chemical notation (SMILES, InChI, or MDL Molfile/Molblock) and return normalized outputs.

Important:

  • Invalid molecules are NOT errors: the API returns success: true with data.valid: false.
  • Premium-only outputs (inchiKey, molblock) are omitted on free tier.

Inputs:

ParameterTypeRequiredDescription
inputstringChemical notation to validate
formatstringauto (default), smiles, inchi, mol
optionsobjectOutput toggles: canonicalSmiles, inchi, inchiKey, molblock, descriptors, sanitize

Example:

{
  "input": "CC(=O)OC1=CC=CC=C1C(=O)O",
  "format": "auto",
  "options": {
    "inchiKey": false,
    "molblock": false
  }
}

Output (valid):

{
  "success": true,
  "data": {
    "valid": true,
    "format": "smiles",
    "input": "CC(=O)OC1=CC=CC=C1C(=O)O",
    "canonicalSmiles": "CC(=O)Oc1ccccc1C(=O)O",
    "inchi": "InChI=1S/..."
  },
  "meta": {
    "requestId": "req_123",
    "processingTimeMs": 12,
    "tier": "free",
    "rdkitVersion": "2025.3.4",
    "cached": false
  }
}

Output (invalid):

{
  "success": true,
  "data": {
    "valid": false,
    "format": "smiles",
    "input": "C1CC",
    "error": { "message": "Failed to parse molecule" }
  },
  "meta": {
    "requestId": "req_123",
    "processingTimeMs": 4,
    "tier": "free",
    "rdkitVersion": "2025.3.4",
    "cached": false
  },
  "recommendations": [
    { "type": "fix", "title": "Input fix", "message": "Ring opened with digit '1' was never closed. Add a matching ring closure digit.", "priority": "high" }
  ]
}

Output:

{
  "success": true,
  "data": "PHN2Zy4uLiA=",
  "format": "svg",
  "meta": {
    "requestId": "req_abc123",
    "processingTimeMs": 45,
    "sizeBytes": 2048,
    "cached": false,
    "molecularFormula": "C9H8O4",
    "width": 600,
    "height": 400,
    "tier": "free"
  }
}

science.compare_chemistry

Compare two molecules (SMILES, InChI, or MDL Molfile/Molblock) for identity, similarity, or substructure relationship.

Modes:

  • identity — Are the two molecules the same compound? (canonical SMILES comparison)
  • similarity — Tanimoto coefficient on Morgan fingerprints (0.0–1.0)
  • substructure — Is molecule A a substructure of B, or vice versa?
  • full — All three comparisons at once

Important:

  • Parse failures are NOT errors: the API returns success: true with data.parseErrors array.
  • Free tier: only identity and similarity modes. substructure and full require premium.

Inputs:

ParameterTypeRequiredDescription
moleculesarrayExactly 2 molecules, each with input and optional format
modestringidentity, similarity, substructure, or full
optionsobjectfingerprintRadius (1-4, default 2), fingerprintBits (1024 or 2048, default 2048)

Example:

{
  "molecules": [
    { "input": "CC(=O)Oc1ccccc1C(=O)O" },
    { "input": "OC(=O)c1ccccc1O" }
  ],
  "mode": "full"
}

Output (success):

{
  "success": true,
  "data": {
    "identity": { "identical": false },
    "similarity": {
      "tanimoto": 0.5556,
      "fingerprintRadius": 2,
      "fingerprintBits": 2048,
      "interpretation": "moderately similar"
    },
    "substructure": {
      "aInB": false,
      "bInA": true,
      "relationship": "b_in_a"
    }
  },
  "meta": {
    "requestId": "req_123",
    "processingTimeMs": 8,
    "tier": "premium",
    "rdkitVersion": "2025.3.4",
    "cached": false
  }
}

Output (parse error):

{
  "success": true,
  "data": {
    "parseErrors": [
      { "index": 1, "format": "smiles", "message": "Failed to parse molecule" }
    ]
  },
  "meta": {
    "requestId": "req_456",
    "processingTimeMs": 3,
    "tier": "free",
    "rdkitVersion": "2025.3.4",
    "cached": false
  }
}

Tanimoto Interpretation:

ScoreInterpretation
1.0identical
≥ 0.85very similar
≥ 0.7similar
≥ 0.5moderately similar
≥ 0.3dissimilar
< 0.3unrelated

audio.merge_audio_fast

Losslessly merge multiple MP3 or AAC audio files into a single file without re-encoding.

What it does:

  • Concatenates audio files in the order provided
  • No re-encoding — near-instant, quality-preserving
  • Optional silence gaps between tracks
  • Automatic format detection from input files

Inputs:

ParameterTypeRequiredDescription
filesstring[]Base64-encoded audio files (min 2, max 20). All must share the same codec, sample rate, and channel count.
formatstringOutput format: mp3, aac, or auto (default: auto)
spacingnumber[]Silence durations (ms) between tracks. spacing[0] = gap between file 0 and 1. Max 10 000 ms each.

Example:

{
  "files": [
    "<base64-encoded-intro.mp3>",
    "<base64-encoded-episode.mp3>",
    "<base64-encoded-outro.mp3>"
  ],
  "format": "auto",
  "spacing": [500, 1000]
}

Output:

{
  "success": true,
  "data": "<base64-encoded-merged-audio>",
  "contentType": "audio/mpeg",
  "meta": {
    "requestId": "abc-123",
    "processingTimeMs": 85,
    "tier": "premium",
    "format": "mp3",
    "codec": "mp3",
    "sampleRate": 44100,
    "channels": 2,
    "durationMs": 183520,
    "fileCount": 3,
    "spacingCount": 2,
    "outputSizeBytes": 2941952
  }
}

Requirements:

  • All input files must have the same codec, sample rate, and channel count
  • Mixing MP3 and AAC files in one request returns AUDIO_FORMAT_MIX error
  • Files with different sample rates or channel counts return AUDIO_INCOMPATIBLE_STREAMS

Error Codes:

CodeDescription
INVALID_INPUTMissing or empty files
TOO_MANY_FILESMore than 20 files
AUDIO_FORMAT_MIXMixed codecs (e.g., MP3 + AAC)
AUDIO_INCOMPATIBLE_STREAMSMismatched sample rates or channels
AUDIO_UNSUPPORTED_FORMATUnsupported audio format
AUDIO_PROBE_FAILEDCould not analyze an input file
UPLOAD_SIZE_EXCEEDEDTotal upload exceeds size limit

postproduction.describe_scenes

Generate per-scene descriptions from images and optional narration text.

What it does:

  • AI-powered scene description generation from uploaded images
  • Optional narration context for story-aligned descriptions
  • Safety checks on both text and images before processing
  • Scene IDs for downstream mapping

Inputs:

ParameterTypeRequiredDescription
imagesstring[]Base64-encoded images in scene order (min 1, max 100). Supported: JPEG, PNG.
narrationTextstringFull narration/script text for story context. Improves description quality by aligning to narrative.
sceneIdsstring[]Optional scene identifiers. Must match images length. Echoed in response.
hintsobjectOptional hints: languageCode (ISO, e.g. "en"), style ("normal", "concise", "detailed").

Example:

{
  "images": [
    "<base64-encoded-bridge-shot.jpg>",
    "<base64-encoded-market-shot.jpg>",
    "<base64-encoded-sunset-shot.jpg>"
  ],
  "narrationText": "A quiet morning in the city, then a crowded market, and finally a sunset skyline.",
  "sceneIds": ["scene-1", "scene-2", "scene-3"],
  "hints": { "languageCode": "en", "style": "normal" }
}

Output:

{
  "success": true,
  "data": {
    "narrationHash": "7dc8f3ebf53f8dd8af3fd4f2ab5e4f0f7bfa5ecf0f6fae17c3f1152e9f8c8d6b",
    "scenes": [
      { "index": 0, "id": "scene-1", "imageName": "bridge-shot.jpg", "description": "Cyclist crossing a bridge in soft morning light." },
      { "index": 1, "id": "scene-2", "imageName": "market-shot.jpg", "description": "Busy market street with people moving between stalls." },
      { "index": 2, "id": "scene-3", "imageName": "sunset-shot.jpg", "description": "City skyline glowing in warm sunset colors." }
    ]
  },
  "meta": {
    "requestId": "req_abc123",
    "processingTimeMs": 412,
    "tier": "premium",
    "imageCount": 3
  }
}

Error Codes:

CodeDescription
VALIDATION_ERRORInvalid metadata or schema mismatch
TOO_MANY_FILESImage count exceeds tier limit
UPLOAD_SIZE_EXCEEDEDTotal upload exceeds size limit
IMAGE_UNSUPPORTED_FORMATImage not JPEG or PNG
UNSAFE_PROMPTNarration rejected by safety checks
UNSAFE_IMAGEImage rejected by safety checks (includes flaggedIndex)
AI_DESCRIPTION_FAILEDScene description generation failed
SAFETY_CHECK_UNAVAILABLESafety service temporarily unavailable
VISION_RATE_LIMITEDImage analysis service rate limited

system.health

Check if CreatorNode backend services are responding using dedicated /health endpoints.

Status Levels:

  • healthy - Service is fully operational
  • degraded - Service running but some dependencies may have issues
  • unhealthy - Service not responding or has critical failures

Inputs:

ParameterTypeRequiredDescription
servicestring"youtube.thumbnail_ranking", "youtube.hook_validator", "visual.render_diagram", "visual.render_code", "visual.render_code_diff", "visual.render_timeline", "visual.render_chem", "science.chemistry_validate", "science.chemistry_compare", "audio.merge_audio_fast", "postproduction.describe_scenes", or "all"

Output:

{
  "overall": "healthy",
  "services": [
    { 
      "service": "youtube.thumbnail_ranking", 
      "status": "healthy", 
      "url": "https://api.creatornode.io/youtube/health",
      "responseTimeMs": 45,
      "version": "1.0.0",
      "uptime": 86400
    },
    { 
      "service": "visual.render_diagram", 
      "status": "healthy", 
      "url": "https://api.creatornode.io/visual/health",
      "responseTimeMs": 38,
      "version": "1.0.0",
      "uptime": 86400
    }
  ],
  "timestamp": "2026-01-25T12:00:00.000Z"
}

Note: When checking "all" services, youtube.thumbnail_ranking and youtube.hook_validator share the same backend — only one health check is performed for both.

Subscores Explained

Each thumbnail variant receives multiple quality subscores (0-100 each) covering different visual and contextual dimensions. The exact set of subscores may vary depending on analysis mode and tier. All subscores are returned in the subscores object as key-value pairs.

Higher scores indicate better performance in that dimension. The overall score is a weighted aggregate of all subscores.

Error Handling

All tools return consistent error format:

{
  "success": false,
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "At least 2 variants required"
  }
}

Error Codes & Solutions

Error CodeDescriptionSolution
VALIDATION_ERRORInvalid input parametersCheck input format - see examples above
API_ERRORBackend service error (5xx)Retry after a few seconds; check system.health
TIMEOUTRequest exceeded 10s limitTry with fewer variants or smaller images
NETWORK_ERRORConnection to API failedCheck system.health; verify API key is valid
RATE_LIMITEDToo many requestsWait 60s and retry; consider upgrading plan
IMAGE_VALIDATION_FAILEDImage failed to decode or validateCheck format (JPEG/PNG/WebP) and ensure the file is not corrupted
IMAGE_INVALIDImage invalid or exceeds 2MB limitCheck format (JPEG/PNG/WebP) and compress if needed
API_KEY_INVALIDAPI key rejectedVerify your key is correct
API_KEY_EXPIREDAPI key has expiredGet a new key at creatornode.io/pricing
INSUFFICIENT_CREDITSNo credits remainingPurchase more credits at creatornode.io/pricing

Troubleshooting Flow

Tool fails → Check error.code
  ├─ NETWORK_ERROR → Run system.health → Is backend up?
  │   ├─ No  → Wait & retry
  │   └─ Yes → Check API key validity
  ├─ TIMEOUT → Reduce variants/image size
  ├─ RATE_LIMITED → Wait 60s or upgrade plan
  ├─ INSUFFICIENT_CREDITS → Purchase more credits
  └─ VALIDATION_ERROR → Fix input per error.message

Real-World Examples

Example 1: Pre-Upload Thumbnail Test

You're about to upload a video and have 3 thumbnail options. Test which one will perform best:

Prompt to AI agent:

"I have 3 thumbnails for my video 'How I Made $10K in 30 Days'. Compare them and tell me which one to use."

Tool call:

{
  "variants": [
    { "id": "shocked-face", "imageBase64": "<base64-thumb-1>" },
    { "id": "money-stack", "imageBase64": "<base64-thumb-2>" },
    { "id": "before-after", "imageBase64": "<base64-thumb-3>" }
  ],
  "title": "How I Made $10K in 30 Days"
}

What you learn:

  • Which thumbnail has the clearest focal point
  • If your face is prominent enough (faces drive CTR)
  • Whether the thumbnail matches your title's promise

Example 2: Debugging Low Retention

Your video has high CTR but viewers leave within 30 seconds. Check if there's a mismatch:

Prompt to AI agent:

"My latest video has 8% CTR but only 35% retention at 60 seconds. Check if my thumbnail/title promise matches my intro."

Tool call (youtube.validate_hook):

{
  "thumbnail": { "imageBase64": "<base64-youtube-thumbnail>" },
  "title": "I Quit My $200K Job (Here's Why)",
  "scriptIntro": "Hey everyone, so today I want to talk about some career advice I learned recently. First, let me tell you about my background in software engineering..."
}

What you learn:

  • Risk level: high (dramatic title + slow intro = mismatch)
  • Primary issue: "Title promises dramatic story, intro is generic advice"
  • Recommendation: "Start with the quit moment, then backstory"

Example 3: A/B Test Before Recording

Test thumbnail concepts before even filming:

Prompt to AI agent:

"I'm planning a video about Python vs JavaScript. Which thumbnail concept works better - comparison chart or developer reaction face?"

Tool call:

{
  "variants": [
    { "id": "comparison-chart", "imageBase64": "<base64-chart-mockup>" },
    { "id": "reaction-face", "imageBase64": "<base64-reaction-mockup>" }
  ],
  "title": "Python vs JavaScript - Which Should You Learn?"
}

What you learn:

  • Face presence scores (reaction face likely wins)
  • Semantic alignment (chart may score higher for "vs" comparison context)
  • Decision: Use face but add small comparison element

Example 4: Batch Analysis for Channel Audit

Analyze your last 5 video thumbnails to find patterns:

Workflow:

  1. Call youtube.rank_thumbnails with thumbnails from your 5 best-performing videos
  2. Call again with 5 worst-performing videos
  3. Compare subscores to find patterns

Common findings:

  • Low performers often have lower overall scores and weaker subscores across multiple dimensions
  • Winners usually maintain consistently high subscores (>80) across quality dimensions
  • Low relevance scores correlate with poor retention

Support