Skip to content

youvandra/bored-comic

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

58 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

BoredComic

An AI comic generator delivered as an A2MCP Agent Service Provider on OKX.AI. A requesting agent sends a prompt, genre, page count, and style — BoredComic writes the story, draws every panel, letters the speech balloons and sound effects, builds a cover, and returns a complete PDF + CBZ plus decision-grade metadata the agent can evaluate without ever looking at the comic.

Beyond one-shot generation, BoredComic is stateful: register characters once and reuse them across comics with a consistent design (create_character), run ongoing series where each episode continues from the previous ending (create_series), and revise a single page of a delivered comic without regenerating the rest (revise_page). Every delivery ships with SHA-256 integrity hashes, a signed receipt, and an explicit commercial-use license.

Type A2MCP — pay-per-call via x402
Agent ID #6006
Endpoint https://boredcomic.web.id/mcp
Transport MCP Streamable HTTP (POST /mcp)
Price Tiered by page count (see Pricing) · no free calls

Example output

Everything below was produced by a single generate_comic call:

prompt: "a young inventor and her clumsy robot race to deliver a package across a bright futuristic city" · genre: action · pages: 2 · style: manga

Cover

Example cover

Page 1

Example page 1

Notice what the renderer adds on top of the AI art: a cream narration caption ("In a city that never stops moving…"), black ink panel frames, shout balloons ("COME ON, BOB! WE CAN'T BE LATE!"), and sound-effect word art ("VROOM", "WHOOPS!") — all lettered in real comic fonts.

Delivery payload

The tool returns structured JSON. This is the delivery payload for the comic above, trimmed — see examples/example-delivery.json for the full shape (the PNG hashes there are real and verifiable against the example images):

{
  "jobId": "cg_example",
  "summary": "2-page action manga 'Package Dash': 8 panels, 3 characters. Generated in 41s. Language: en. Color mode: color.",
  "title": "Package Dash",
  "pages": 2,
  "totalPanels": 8,
  "style": "manga",
  "genre": "action",
  "language": "en",
  "colorMode": "color",
  "characters": [
    { "name": "Mia", "role": "Young inventor",
      "appearance": "16 years old, short messy pink hair, goggles on forehead, blue jumpsuit with patches..." },
    { "name": "Bob (B-0B)", "role": "Clumsy robot",
      "appearance": "Tall, boxy body with mismatched parts, oversized blue eyes, one wheel instead of a left leg..." }
  ],
  "coverUrl": "/comics/cg_example/cover.png",
  "pageUrls": ["/comics/cg_example/cover.png", "/comics/cg_example/page-1.png", "/comics/cg_example/page-2.png"],
  "pdfUrl": "/comics/cg_example/comic.pdf",
  "cbzUrl": "/comics/cg_example/comic.cbz",
  "perPage": [
    { "page": 1, "panels": 4, "storyBeat": "In a city that never stops moving, every second counts...",
      "imageUrl": "/comics/cg_example/page-1.png",
      "panelDetails": [
        { "panel": 2, "imageUrl": "/comics/cg_example/panel-1-1.png",
          "altText": "Mia straps a glowing package onto Bob's back... Dialogue: \"COME ON, BOB! WE CAN'T BE LATE!\"",
          "dialogue": "COME ON, BOB! WE CAN'T BE LATE!" } // one panel shown; every panel is exported
      ],
      "evidence": { "model": "@cf/black-forest-labs/flux-1-schnell", "promptChars": 2773, "layout": "4p" } }
  ],
  "integrity": { "algorithm": "sha256", "files": { "cover.png": "cfb38666...", "page-1.png": "7893e01f...", /* every file */ } },
  "receipt": { "payloadSha256": "...", "algorithm": "HMAC-SHA256", "signature": "..." },
  "license": { "usage": "...full commercial rights...", "provenance": { "imageModel": "...", "seed": 483920175, "promptSha256": "c137036b..." } },
  "evidence": {
    "model": "@cf/black-forest-labs/flux-1-schnell",
    "pagesGenerated": 2, "panelsGenerated": 8,
    "generationTimeSec": 41, "costEstimateUsd": 0.01,
    "caveat": "Comic is AI-generated. Story coherence and visual consistency are heuristic, not guaranteed."
  }
}

The summary, characters, perPage, and evidence fields let a calling agent judge the result programmatically — panel counts, story beats, generation time, and cost — without rendering the images.


Why an agent needs this

An autonomous agent working with creative requests constantly hits things it cannot do itself: a user wants a comic, but the agent cannot draw, cannot lay out panels, cannot keep characters consistent across pages. BoredComic is the primitive that answers:

"I have a story idea — make it into a comic I can share."

It returns structured data the agent can compose — not a web app it has to navigate. Pay-per-call via x402. And because the service is stateful, an agent can build on past calls instead of starting over: a registered cast, a running series, a paid revision of one page instead of a full regeneration.


MCP tools

generate_comic (paid — tiered by pages)

Generates a complete comic from a natural-language prompt.

Input Type Description
prompt string What the comic is about (min 3 chars) — required
pages integer Number of pages, 1–10 — required
genre enum horror · romance · action · comedy · manga · fantasy · sci-fi · slice-of-life
style enum manga · western · semi-realistic · chibi (default: manga)
aspectRatio enum 3:4 · 9:16 · 1:1 (default: 3:4; ignored in webtoon mode)
language string BCP-47 dialogue language, e.g. en, id, ja, zh (default: en)
colorMode enum color · bw (default: color)
layoutMode enum page · webtoon (default: page) — webtoon renders full-width panels stacked vertically plus a single tall strip.png
characterIds string[] Registered characters (from create_character) that must star in the comic
seriesId string Series (from create_series) — the story continues from the previous episode's ending

Returns the delivery payload shown above, extended with per-panel images + alt text (perPage[].panelDetails), cbzUrl, stripUrl (webtoon), integrity (SHA-256 of every file), receipt (signed proof of delivery), and license (commercial-use grant + provenance).

create_character (paid — base rate)

Register a character once, reuse it forever. Stores a canonical appearance description and a stable generation seed, and renders a reference character sheet. Comics generated with this character reuse both, so its design stays consistent across every comic and series episode. Inputs: name, appearance (detailed visual description, min 20 chars), optional role, style.

create_series (free) / get_series (free)

create_series starts a series container with optional defaults (genre, style, language, colorMode) and a fixed cast of registered characterIds. Every generate_comic call carrying the seriesId becomes the next episode: the writer receives each previous episode's title and ending summary as context and continues the story. get_series returns the episode history.

revise_page (paid — base rate)

Revise one page of a delivered comic without regenerating the rest: { jobId, page, instruction } — e.g. "make panel 2 a dramatic close-up" or "rewrite the dialogue to be funnier". The page spec is rewritten by the LLM, re-rendered with the job's original seed and cast, and the PDF/CBZ are rebuilt when the other pages are still on disk. Jobs stay revisable for 7 days (JOB_TTL_MS).

get_job (free)

Re-fetch the full delivery payload of a previously generated comic by jobId — the recovery path when a paid generate_comic response was lost to a connection drop or timeout. You paid once; the result stays fetchable for 7 days. The payload reports filesAvailable since comic files expire from disk on a shorter TTL (24h) than the metadata.

get_character (free)

Look up a registered character: canonical appearance, style, seed, reference sheet URL.

clarify_comic (free)

Given a partial or vague request, returns structured clarification questions (missing fields, genre/style options, defaults). Use it before generate_comic when the user's request is incomplete. Always free.

get_quota (free)

Returns current per-tool x402 pricing, payment address, and whether the gate is enabled. Always free.


Verifiable delivery

Every delivery carries three trust artifacts:

  • integrity — SHA-256 of every delivered file (cover, pages, panels, PDF, CBZ, strip). The payer can verify the bytes they downloaded are the bytes they paid for.
  • receiptpayloadSha256 over the job's file hashes plus an HMAC-SHA256 signature (when RECEIPT_SECRET is configured): portable proof of what was delivered for which job.
  • license — explicit commercial-use grant, attribution status, AI disclosure, and provenance (image model, seed, prompt hash) so a commercial agent knows exactly what it may do with the output before publishing.

Architecture

Agent → POST /mcp (MCP Streamable HTTP)
             │
        ┌────▼────┐   x402 gate: discovery, clarify_comic, get_quota, get_character,
        │ x402.ts │   create_series, get_series are free. generate_comic is priced by
        └────┬────┘   page count; revise_page + create_character cost the base rate.
             │        Deterministic failures are rejected before payment.
        ┌────▼─────────┐
        │ pipeline.ts  │  one-shot orchestrator
        └────┬─────────┘
   ┌─────────┼───────────────────────┐
   ▼         ▼                        ▼
writer.ts  illustrator.ts        assembler.ts
(LLM →     (Cloudflare Workers    (pdf-lib →
 storyboard) AI → panel images)    combined PDF)
             │
             ▼
        pipeline.ts assembly (sharp): panel frames · smart crop ·
        speech/shout/thought balloons · SFX word art · narration
        caption · cover · B&W grayscale

Pipeline stages

  1. Writer (writer.ts) — Sumopod LLM turns the prompt into a storyboard: title, synopsis, characters (with detailed visual appearance), and per-page panel descriptions including dialogue, dialogueType, sfx, and camera angle. Dialogue is generated in the requested language.
  2. Illustrator (illustrator.ts) — each panel is rendered by Cloudflare Workers AI (@cf/black-forest-labs/flux-1-schnell, free tier). A shared per-job seed keeps panels visually coherent. Requests time out after 60s and fall back across multiple Cloudflare accounts on quota exhaustion.
  3. Assembly (pipeline.ts) — sharp composites each page: a layout template chosen per page (the final page favours a hero/splash panel), attention-based smart cropping, panel frames, balloons whose shape varies by type, SFX word art, and a narration caption box. B&W mode applies a grayscale pass.
  4. Cover — a hero key-art image with the title, genre badge, and synopsis, prepended to the pages and the PDF.
  5. PDF (assembler.ts) — every page PNG is embedded into a single PDF via pdf-lib.

Comic rendering features

  • Panel frames — black ink borders around every panel.
  • Smart crop — sharp attention strategy keeps faces and action in frame.
  • Balloon variety — rounded speech, jagged shout balloons (auto-applied to exclamations), and puffy thought clouds.
  • Sound effects — the writer emits onomatopoeia on action panels, rendered as angled, outlined word art.
  • Real comic lettering — bundled OFL fonts (Bangers for display/SFX, Comic Neue for balloons) are converted to vector outlines with opentype.js, because sharp's bundled librsvg ignores system fonts.
  • Dynamic layouts — layout templates for 1–4 panels, varied per page, with a climax splash on the last page.

Pricing

Charged per tool call via x402 v2 on X Layer (USDT0). No free quota. generate_comic scales with page count; single-generation tools cost the base rate:

Tool Multiplier Price (at 0.5 base)
generate_comic 1–3 pages 0.50 USDT
generate_comic 4–6 pages 1.00 USDT
generate_comic 7–10 pages 1.50 USDT
revise_page 0.50 USDT
create_character 0.50 USDT

The base price is set by X402_PRICE_USD; multipliers are applied automatically. Discovery calls (initialize, tools/list), clarify_comic, get_quota, get_job, get_character, create_series, and get_series are always free. Deterministic failures (bad input, unknown characterIds/jobId, missing image provider) are rejected before payment.

Abuse guards: /mcp is rate-limited to 120 requests/minute per IP, create_series (free but disk-writing) to 20/hour per IP, and the persistent store caps each collection at 5000 records.

Our own cost per generation is roughly $0.01 (LLM storyboard ~$0.005 + free-tier image generation + assembly), so the fee reflects real cost with margin.


Quick start

cd backend
npm install
cp .env.example .env    # fill in the keys below
npm run dev             # starts on PORT (default 3001)

Point an MCP client at http://localhost:3001/mcp. With X402_MODE=off (the default) the payment gate is disabled, so generate_comic runs without payment — useful for local testing.

Configuration

Variable Purpose
SUMOPOD_API_KEY LLM API key (Sumopod) — required
SUMOPOD_BASE_URL / SUMOPOD_MODEL LLM endpoint and model (default deepseek-v4-flash)
CLOUDFLARE_ACCOUNT_ID / CLOUDFLARE_API_TOKEN Cloudflare Workers AI for image generation — required
CLOUDFLARE_ACCOUNT_ID_2 / _3 … up to _8 Optional extra accounts for quota fallback
FLUX_STEPS Diffusion steps per panel (default 8)
XLAYER_API_KEY / XLAYER_SECRET_KEY / XLAYER_PASSPHRASE OKX facilitator credentials for x402 settlement
X402_MODE off · demo · on (default off)
X402_PAY_TO Payment recipient address (required when the gate is enabled)
X402_PRICE_USD Base price; multiplied by the page tier
COMIC_DIR / COMIC_TTL_MS Output directory and cleanup TTL (default 24h)
DATA_DIR Persistent store for characters, series, and revisable jobs (default ./data)
JOB_TTL_MS How long a job stays revisable via revise_page (default 7 days)
RECEIPT_SECRET HMAC key for signed delivery receipts (unset → receipts unsigned)
PORT / NODE_ENV Server port and environment

Scripts

npm run dev        # dev server with reload (tsx watch)
npm run build      # compile TypeScript to dist/
npm start          # run compiled server
npm test           # run the test suite (node:test)
npm run typecheck  # tsc --noEmit

Project structure

bored-comic/
├── README.md
├── examples/                 # sample cover, pages, and delivery JSON (this README)
└── backend/
    ├── assets/fonts/         # bundled OFL comic fonts (Bangers, Comic Neue)
    └── src/
        ├── index.ts          # Express + MCP + x402 + static files
        ├── config.ts         # env configuration
        ├── types.ts          # types, layout templates, pickLayout()
        ├── mcp.ts            # MCP server: all 9 tools
        ├── x402.ts           # x402 payment gate + per-tool pricing + preflight
        ├── pipeline.ts       # orchestrator, page/webtoon assembly, revise_page
        ├── writer.ts         # LLM → storyboard, series context, page revision
        ├── illustrator.ts    # Cloudflare Workers AI → panel images
        ├── assembler.ts      # pdf-lib → combined PDF
        ├── cbz.ts            # dependency-free CBZ (zip) writer
        ├── character.ts      # character registration + reference sheets
        ├── store.ts          # persistent store: characters, series, jobs
        ├── receipt.ts        # integrity hashes, signed receipts, license
        ├── fonts.ts          # opentype.js glyph-path lettering
        ├── storage.ts        # temp file serving + TTL cleanup
        └── *.test.ts         # tests

Honesty rules

  • Evidence travels with every comic — model, panel count, generation time, cost, and a caveat.
  • Counts are real — reported pages and panels reflect what was actually generated, not what the LLM claimed.
  • No fabricated characters — every character in the output is explicitly defined in the storyboard.
  • The fee matches reality — pricing reflects actual LLM + image-generation cost.

Known limitations

  • Character consistency is heuristic. Faces can drift between panels. The image model (flux-1-schnell) has no reference-image conditioning, so consistency relies on prompt detail and seeds. Registered characters (create_character) narrow the drift — canonical appearance text plus a stable per-character seed reused across jobs — but do not eliminate it. Fully solving this requires a model with reference-image conditioning.
  • Image quality is capped by flux-1-schnell (a fast, free-tier turbo model). A higher-fidelity model would improve raw art at the cost of leaving the free tier.
  • Safety filter — Cloudflare blocks NSFW prompts; some innocuous words ("haunted", "magical") can occasionally trip it. There is no 18+ support.

Licenses

Bundled fonts are used under the SIL Open Font License; see backend/assets/fonts/OFL-Bangers.txt and OFL-ComicNeue.txt.

About

AI comic generator as an A2MCP Agent Service Provider on OKX.AI.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors