{
  "markdown": "![cascade-img — direct Midjourney by conversation: a director writes a prompt card, a helper robot carries it to a colossal artist robot forging framed paintings, and hands the cut-out winner back](./.github/assets/readme-banner-alt.png)\n\n[![CI](https://github.com/laffeyp/cascade-img/actions/workflows/ci.yml/badge.svg)](https://github.com/laffeyp/cascade-img/actions/workflows/ci.yml)\n[![PyPI](https://img.shields.io/pypi/v/cascade-img?color=%2334D058&label=pypi)](https://pypi.org/project/cascade-img/)\n[![License: Apache 2.0](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](./LICENSE)\n[![Python 3.12+](https://img.shields.io/badge/Python-3.12%2B-blue.svg)](https://www.python.org/)\n[![MCP Tools: 23](https://img.shields.io/badge/MCP_Tools-23-green.svg)](./AGENTS.md)\n\nGenerate Midjourney images by conversation instead of by hand. You describe what you want; your AI assistant composes the prompt, fires it, inspects the grid with vision, crops the best quadrant, cleans it up, and logs what worked.\n\n```\nYou: \"I need a flat-design mountain icon, centered, simple shapes, transparent background\"\n\nAgent: reads prompt log → composes prompt from parts → fires imagine →\n       waits → inspects 2x2 grid with vision → picks best quadrant →\n       crops it → removes background → saves → logs what worked\n```\n\ncascade-img is an MCP server with 23 tools that plugs into Claude, Cursor, Codex, or anything that speaks [MCP](https://modelcontextprotocol.io). Midjourney is the first backend; Flux, DALL-E, and Imagen are on the [roadmap](#roadmap). There's also a CLI.\n\n> **Not a programmer?** Open an AI assistant that can run commands ([Claude Code](https://claude.com/claude-code), Cursor, or Cline), point it at this repo, and say: *\"Read RUNBOOK.md and set up cascade-img on this machine, then let me make images by describing them to you.\"* It does the technical parts. You just need a Midjourney subscription and to copy a few values from Discord.\n\n---\n\n## Quick Start\n\n**You need:** a [paid Midjourney subscription](https://midjourney.com), a Discord account with the MJ bot in a channel, and Python 3.12 or newer.\n\n```bash\npip install cascade-img\n```\n\nOr from source:\n\n```bash\ngit clone https://github.com/laffeyp/cascade-img\ncd cascade-img/packages/python\npip install -e .\n```\n\nThis puts three commands for operating cascade-img on your PATH: `cascade-mj-bridge` (the daemon), `cascade-mcp` (the MCP server), and `cascade-mj` (the CLI). Installing also adds a fourth command, `cascade-trace-check` — a diagnostics validator (not part of the generation loop) that replays a recorded event log and checks it against the vocabulary's declared event ordering and timing rules.\n\n**Configure** — you need four values from the Discord desktop app (channel ID, server ID, imagine version, and your user token). Takes about five minutes. [RUNBOOK.md](./RUNBOOK.md) walks through each one step by step.\n\n```bash\ncp \"$(python -c 'import cascade_img, pathlib; print(pathlib.Path(cascade_img.__path__[0]) / \".env.example\")')\" .env\n# Fill in the four values per RUNBOOK.md, then validate:\ncascade-mj-bridge --check-env --pretty\n```\n\n**Start the daemon** in one terminal, then connect from another:\n\n```bash\ncascade-mj-bridge          # leave running — holds the Discord connection\n```\n\n**Connect your AI assistant** — add to your MCP config (Claude Desktop, Cursor, Cline):\n\n```json\n{\n  \"mcpServers\": {\n    \"cascade-img\": {\n      \"command\": \"cascade-mcp\"\n    }\n  }\n}\n```\n\nOr point your assistant at this repo and ask it to read [AGENTS.md](./AGENTS.md) — it'll wire everything up.\n\n**Or use the CLI:**\n\n```bash\necho '{\n  \"mountain-icon\": {\n    \"subject\": \"a flat-design icon of a mountain, centered, simple shapes\",\n    \"aspect_ratio\": \"1:1\"\n  }\n}' > assets.json\n\ncascade-mj mountain-icon --registry assets.json --upscale all --pretty\n```\n\n---\n\n## The 23 Tools\n\n| Category | Tools | What they do |\n|----------|-------|-------------|\n| **Onboarding** | `cascade_guide` | Returns the full operating manual in one call — the loop, every tool, the failure→action table. Call it first; the generation and curation tools are gated until it's read. |\n| **Generation** | `imagine`, `generate_video`, `wait`, `status`, `bridge_health`, `mj_action` | Compose and fire prompts, poll for results, check daemon health, trigger Midjourney actions (upscale, vary, pan) |\n| **Catch-up** | `channel_recent`, `adopt_message` | See what the human did by hand in Discord and claim those results into the pipeline — adopted messages become normal jobs that curation and `mj_action` work on |\n| **Composition** | `compose_prompt`, `compose_video` | Build prompts from structured parts — subject, moodboard, style refs, aspect ratio, negatives — not freeform text |\n| **Curation** | `crop_grid`, `alpha_key`, `auto_trim`, `palette_quantize`, `contact_sheet`, `sprite_sheet`, `score_grid`, `video_filmstrip`, `loop_seam_delta`, `promote` | Extract quadrants from grids, remove backgrounds, trim whitespace, build sprite sheets, score results with vision, promote winners to final output |\n| **Working memory** | `log_append`, `read_prompt_log` | Append-only prompt log the agent reads before every run — what was tried, what worked, what didn't. Persists across sessions. |\n\nEvery call returns `{ok, result}` or `{ok: false, error: {code, remediation}}`. Branch on the stable `code`, not the message. Full tool reference in [AGENTS.md](./AGENTS.md).\n\n---\n\n## How This Differs\n\nOther open-source Midjourney tools focus on the generation step — fire the prompt, hand back the image. cascade-img does the work around that:\n\n- **Vision-based self-curation** — the agent inspects its own output and picks the best quadrant\n- **Structured prompt composition** — prompts built from parts (subject, style, identity, constraints), not raw strings\n- **Working memory** — append-only log persists across sessions; each run reads what came before\n- **Curation pipeline** — crop grids, remove backgrounds, build sprite sheets, promote winners\n- **MCP-native** — 23 tools that plug into Claude, Cursor, Codex, or anything that speaks MCP\n- **Pluggable backends** — Midjourney now, Flux/DALL-E/Imagen on the roadmap\n\n---\n\n## How It Works\n\nOne daemon, two stateless clients, all over local HTTP:\n\n- **`cascade-mj-bridge`** — the daemon. Only process that talks to Discord. Holds the live connection and tracks in-flight jobs. Must stay running.\n- **`cascade-mcp`** — the MCP server. Stdio by default (Claude Desktop / Cursor / Cline); `--http <port>` for HTTP. Stateless — start and stop freely.\n- **`cascade-mj`** — the CLI. Takes an asset ID and a registry, composes the prompt, fires, waits, writes to the log.\n\nPrompts are composed from structured parts, not written as raw strings:\n\n```python\nfrom cascade_img.prompt.composer import PromptComposer, Subject, StyleStack, IdentityStack\n\nprompt = PromptComposer().compose(\n    Subject(\n        text=\"a flat-design icon of a mountain\",\n        constraints=[\"centered\", \"simple shapes\", \"transparent background\"],\n    ),\n    # Both optional. moodboard is a Midjourney personalization code;\n    # sref/oref are reference-image URLs you'd set up in MJ first.\n    style=StyleStack(moodboard=\"abc123def\", sref=\"https://cdn.example.com/style.png\"),\n    identity=IdentityStack(oref=\"https://cdn.example.com/ref.png\", ow=1000),\n    aspect_ratio=\"1:1\",\n    version=\"7\",\n)\n```\n\nAll three entry points emit structured JSON and follow the same `{ok, result | error: {code, remediation}}` envelope. Every failure carries a stable error code (e.g. `DISCORD_401`, `MJ_UUID_MISSING`, `UPSCALE_BUTTON_FAILED`) with a machine-readable remediation — so a caller branches on the code, not the message. The full catalog of log events and error codes is in [vocabulary/0.1.json](./vocabulary/0.1.json), and a trace checker (`cascade-trace-check`) enforces event ordering over recorded runs.\n\n<details>\n<summary><strong>Midjourney terminology</strong></summary>\n\n**prompt** — the text + flags you send Midjourney. **grid** — the 2x2 set of four candidates returned per prompt. **quadrant / U1-U4** — the four cells; \"U2\" means upscale the second. **upscale** — render one cell at full resolution. **aspect ratio (`--ar`)** — output shape. **sref** — an image whose *style* to borrow. **oref** — an image whose *subject identity* to keep across poses. **moodboard (`--p`)** — a saved personalization profile. **stylize (`--s`)** — how strongly MJ applies its own aesthetic.\n\n</details>\n\n---\n\n## Documentation\n\n| Doc | What it covers |\n|-----|---------------|\n| [AGENTS.md](./AGENTS.md) | The LLM operator's guide. Read this when handing cascade-img to an agent. |\n| [RUNBOOK.md](./RUNBOOK.md) | Install, env capture, setup, reconnect lifecycle, every failure mode with error codes and fixes. |\n| [CAPABILITIES.md](./CAPABILITIES.md) | Every Midjourney feature cascade-img drives — prompt parameters, mj_actions, the V8.1/V7 split. |\n| [ARCHITECTURE.md](./ARCHITECTURE.md) | Internal architecture and design decisions. |\n| [examples/](./examples/) | Three walkthroughs: single image, batch, video. Read AGENTS.md first. |\n| [CHANGELOG.md](./CHANGELOG.md) | Release history. |\n\n---\n\n## Roadmap\n\n| Version | What's in it |\n|---|---|\n| **v0.1** (current) | MJ backend (V8.1 + V7), prompt composer, curation tools, MCP server, CLI, prompt log |\n| **v0.2** | Channel catch-up + message adoption — **landed on main**: `channel_recent` and `adopt_message` let the agent see what the human did by hand in Discord and act on it ([design](./designs/channel-catchup-and-adoption.md)); still to come: more MJ commands (`/describe`, `/blend`, Vary Region inpaint, `/tune`), retro-U-press on adopted grids, internal refactoring |\n| **v0.3** | TypeScript wrapper; first API backends — [Flux](https://bfl.ai/) via [Fal](https://fal.ai/) + [Flux Kontext](https://bfl.ai/models/flux-kontext), [Ideogram](https://ideogram.ai/) |\n| **v0.4** | [Google Imagen](https://deepmind.google/models/imagen/), [Recraft](https://www.recraft.ai/) (native vector/SVG) |\n| **v0.5** | [OpenAI gpt-image](https://openai.com/api/), [Stable Diffusion](https://stability.ai/stable-image) |\n| **v1.0** | API stable, three+ backends in production |\n\nEvery backend implements one interface, so a later release can chain them — generate on one provider, refine on a second (e.g. Flux Kontext), upscale on a third.\n\n---\n\n## Repository Layout\n\n```\ncascade-img/\n├── packages/python/        # the Python package (cascade_img)\n│   ├── src/cascade_img/    #   prompt/, interfaces/, backends/, curation/, vocabulary/\n│   ├── tests/              #   behavior tests\n│   └── tools/              #   live smoke walk\n├── examples/               # three walkthroughs of the operating loop\n├── vocabulary/0.1.json     # event log-line catalog\n└── *.md                    # README, ARCHITECTURE, RUNBOOK, AGENTS, CAPABILITIES, ...\n```\n\n---\n\n## Disclaimer\n\nThis tool automates Midjourney through a Discord user account. A paid Midjourney subscription is required. Both Discord and Midjourney's Terms of Service prohibit user-account automation. This is the same mechanism used by every open-source MJ tool ([midjourney-proxy](https://github.com/novicezk/midjourney-proxy), [midjourney-api](https://github.com/erictik/midjourney-api), etc.) — there is no public Midjourney API. Use at your own risk.\n\nThe backend interface is pluggable — Flux, DALL-E, and Imagen are on the [roadmap](#roadmap).\n\n## License\n\nApache-2.0. See [LICENSE](./LICENSE).\n\n<!-- mcp-name: io.github.laffeyp/cascade-img -->\n\n",
  "bytes": 11527,
  "sha": "c745fe0a126e533332ffdab4ae794fc2afe8845940fce1ccda85441218bb898d",
  "repo_slug": "laffeyp/cascade-img",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_laffeyp_cascade_img_a4f180c2/readme"
}