CreatorNode MCP Server
MCP (Model Context Protocol) server providing AI agents with tools for creator workflows.
Table of Contents
- Installation
- Getting an API Key
- Environment Variables
- Cost Preview (Price Check)
- Tool Namespaces
- Tools
- Subscores Explained
- Error Handling
- Real-World Examples
- Support
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.
Paid Plans
For higher limits and premium features:
- Visit Pricing
- Purchase a credit package (Boost $3 / Starter $10 / Professional $100)
- Receive your API key via email after purchase
- Add the key to your MCP configuration
See the Pricing page for plan comparison.
Environment Variables
| Variable | Default | Description |
|---|---|---|
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_URL | https://api.creatornode.io | API base URL (override only if self-hosting) |
MCP_REQUEST_TIMEOUT_MS | 10000 | Request timeout in milliseconds |
MCP_LOG_LEVEL | info | Log 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:
| Namespace | Description |
|---|---|
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:
| Parameter | Type | Required | Description |
|---|---|---|---|
variants | array | ✅ | 2-10 thumbnail variants with id and imageBase64 |
title | string | Video 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:
| Parameter | Type | Required | Description |
|---|---|---|---|
thumbnail | object | ✅ | { imageBase64 } |
title | string | ✅ | Video title |
scriptIntro | string | ✅ | First 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 graphsstateDiagram- State machine diagramssequenceDiagram- Sequence diagramsclassDiagram- UML class diagramserDiagram- Entity relationship diagrams
Inputs:
| Parameter | Type | Required | Description |
|---|---|---|---|
definition | string | ✅ | Mermaid diagram definition |
format | string | Output: svg, png, ascii, unicode (default: svg) | |
theme | string | Theme: light, dark, neutral, or full theme name | |
options | object | Additional 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:
| Parameter | Type | Required | Description |
|---|---|---|---|
code | string | ✅ | Source code to render (max 500KB) |
language | string | ✅ | Language identifier (e.g., typescript, python, rust) |
format | string | Output: svg or png (default: svg) | |
theme | string | Color theme (default: github-dark) | |
options | object | Rendering options (see below) |
Options:
| Option | Type | Default | Description |
|---|---|---|---|
filename | string | - | Filename header above the code |
lineNumbers | boolean | true | Show line numbers |
highlightLines | string | - | Lines to highlight: "1,3,5-10" |
startLine | number | 1 | Starting line number |
tabSize | number | 2 | Tab width in spaces |
wordWrap | boolean | false | Wrap long lines |
fontSize | number | 14 | Font size in pixels (8-32) |
padding | number | 16 | Padding in pixels (0-64) |
width | number | auto | Fixed width in pixels (100-4096) |
height | number | auto | Fixed height in pixels (100-4096) |
preset | string | - | 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:
| Parameter | Type | Required | Description |
|---|---|---|---|
before | string | ✅ | Original (before) code. Can be empty for newly added files |
after | string | ✅ | Modified (after) code. Can be empty for deleted files |
language | string | ✅ | Language identifier (e.g., typescript, python, rust) |
format | string | Output: svg or png (default: svg) | |
theme | string | Color theme (default: github-dark) | |
options | object | Rendering options (see below) |
Options:
| Option | Type | Default | Description |
|---|---|---|---|
filename | string | - | Filename header above the diff |
lineNumbers | boolean | true | Show line numbers |
tabSize | number | 2 | Tab width in spaces |
fontSize | number | 14 | Font size in pixels (8-32) |
padding | number | 16 | Padding in pixels (0-64) |
width | number | auto | Fixed width in pixels (100-4096) |
height | number | auto | Fixed height in pixels (100-4096) |
preset | string | - | 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:
| Parameter | Type | Required | Description |
|---|---|---|---|
events | array | ✅ | 1-50 events with date, title, and optional text |
orientation | string | vertical or horizontal (default: vertical) | |
format | string | Output: svg or png (default: svg) | |
layout | string | Card layout: alternate (zigzag) or compact (one side). Default: alternate | |
title | string | Optional title displayed above the timeline | |
theme | string | light or dark (default: light) | |
accentColor | string | Custom accent colour (#RRGGBB) — overrides dot and date colours | |
transparent | boolean | Transparent background, SVG only (default: false) | |
fontFamily | string | inter (default), roboto, or mono (JetBrains Mono) | |
width | number | Image width in pixels (auto if omitted, 200-4096) | |
height | number | Image 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:
| Parameter | Type | Required | Description |
|---|---|---|---|
smiles | string | ✅ | SMILES string (max 5000 chars) |
format | string | svg or png (default: svg) | |
theme | string | light or dark (default: light) | |
preset | string | default, publication, presentation, thumbnail, social-card | |
options | object | Rendering 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.valuesmust 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: truewithdata.valid: false. - Premium-only outputs (
inchiKey,molblock) are omitted on free tier.
Inputs:
| Parameter | Type | Required | Description |
|---|---|---|---|
input | string | ✅ | Chemical notation to validate |
format | string | auto (default), smiles, inchi, mol | |
options | object | Output 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: truewithdata.parseErrorsarray. - Free tier: only
identityandsimilaritymodes.substructureandfullrequire premium.
Inputs:
| Parameter | Type | Required | Description |
|---|---|---|---|
molecules | array | ✅ | Exactly 2 molecules, each with input and optional format |
mode | string | ✅ | identity, similarity, substructure, or full |
options | object | fingerprintRadius (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:
| Score | Interpretation |
|---|---|
| 1.0 | identical |
| ≥ 0.85 | very similar |
| ≥ 0.7 | similar |
| ≥ 0.5 | moderately similar |
| ≥ 0.3 | dissimilar |
| < 0.3 | unrelated |
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:
| Parameter | Type | Required | Description |
|---|---|---|---|
files | string[] | ✅ | Base64-encoded audio files (min 2, max 20). All must share the same codec, sample rate, and channel count. |
format | string | Output format: mp3, aac, or auto (default: auto) | |
spacing | number[] | 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_MIXerror - Files with different sample rates or channel counts return
AUDIO_INCOMPATIBLE_STREAMS
Error Codes:
| Code | Description |
|---|---|
INVALID_INPUT | Missing or empty files |
TOO_MANY_FILES | More than 20 files |
AUDIO_FORMAT_MIX | Mixed codecs (e.g., MP3 + AAC) |
AUDIO_INCOMPATIBLE_STREAMS | Mismatched sample rates or channels |
AUDIO_UNSUPPORTED_FORMAT | Unsupported audio format |
AUDIO_PROBE_FAILED | Could not analyze an input file |
UPLOAD_SIZE_EXCEEDED | Total 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:
| Parameter | Type | Required | Description |
|---|---|---|---|
images | string[] | ✅ | Base64-encoded images in scene order (min 1, max 100). Supported: JPEG, PNG. |
narrationText | string | Full narration/script text for story context. Improves description quality by aligning to narrative. | |
sceneIds | string[] | Optional scene identifiers. Must match images length. Echoed in response. | |
hints | object | Optional 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:
| Code | Description |
|---|---|
VALIDATION_ERROR | Invalid metadata or schema mismatch |
TOO_MANY_FILES | Image count exceeds tier limit |
UPLOAD_SIZE_EXCEEDED | Total upload exceeds size limit |
IMAGE_UNSUPPORTED_FORMAT | Image not JPEG or PNG |
UNSAFE_PROMPT | Narration rejected by safety checks |
UNSAFE_IMAGE | Image rejected by safety checks (includes flaggedIndex) |
AI_DESCRIPTION_FAILED | Scene description generation failed |
SAFETY_CHECK_UNAVAILABLE | Safety service temporarily unavailable |
VISION_RATE_LIMITED | Image analysis service rate limited |
system.health
Check if CreatorNode backend services are responding using dedicated /health endpoints.
Status Levels:
healthy- Service is fully operationaldegraded- Service running but some dependencies may have issuesunhealthy- Service not responding or has critical failures
Inputs:
| Parameter | Type | Required | Description |
|---|---|---|---|
service | string | "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_rankingandyoutube.hook_validatorshare 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 Code | Description | Solution |
|---|---|---|
VALIDATION_ERROR | Invalid input parameters | Check input format - see examples above |
API_ERROR | Backend service error (5xx) | Retry after a few seconds; check system.health |
TIMEOUT | Request exceeded 10s limit | Try with fewer variants or smaller images |
NETWORK_ERROR | Connection to API failed | Check system.health; verify API key is valid |
RATE_LIMITED | Too many requests | Wait 60s and retry; consider upgrading plan |
IMAGE_VALIDATION_FAILED | Image failed to decode or validate | Check format (JPEG/PNG/WebP) and ensure the file is not corrupted |
IMAGE_INVALID | Image invalid or exceeds 2MB limit | Check format (JPEG/PNG/WebP) and compress if needed |
API_KEY_INVALID | API key rejected | Verify your key is correct |
API_KEY_EXPIRED | API key has expired | Get a new key at creatornode.io/pricing |
INSUFFICIENT_CREDITS | No credits remaining | Purchase 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:
- Call
youtube.rank_thumbnailswith thumbnails from your 5 best-performing videos - Call again with 5 worst-performing videos
- 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
- Website: CreatorNode
- Email: support@creatornode.io