prompt-to-asset
MCP server + CLI for production-grade software assets (logos, app icons, favicons, OG, illustrations) — routes across 30+ image models, zero
Open source Open in the app JSON README (API)
About
MCP server + CLI for production-grade software assets (logos, app icons, favicons, OG, illustrations) — routes across 30+ image models, zero-key first, validates before shipping.
Details
- Kind
- Plugins
- Topic
- Developer tools
- Publisher
- mohamedabdallah-14
- Origin
- gemini
- Category
- ferramentas
- Version
- 0.1.0
- Stars
- 18
- Forks
- 2
- Open pull requests
- 16
- Last push
- 2026-09-07T05:11:39Z
- Repository state
- ativo
- Language
- TypeScript
- License
- MIT
- Added
- 2026-08-30 14:13:39
- Updated
- 2026-08-30 14:13:39
- Origin id
mohamedabdallah-14/prompt-to-asset
README
<div align="center">
<a id="top"></a>
<img src="./.github/assets/hero.gif" alt="prompt-to-asset demo — one prompt becomes a full favicon bundle in 20 seconds. Works with Claude Code, Cursor, Windsurf, VS Code. Zero API key required." width="100%" />
<h1>prompt‑to‑asset</h1>
<p><b>Free image generation for developers, from the CLI or your AI assistant.</b><br/>
Turn one brief into app icons, favicons, OG images, logos, splash screens, SVG, and platform bundles using the best zero-cost routes first.<br/>
<b>Built for Cloudflare Workers AI, NVIDIA NIM, HF Inference, Stable Horde, Pollinations, free trials, and offline SVG.</b></p>
<p>
<a href="https://www.npmjs.com/package/prompt-to-asset"><img alt="npm" src="https://img.shields.io/npm/v/prompt-to-asset?style=flat&color=cb3837&logo=npm&logoColor=white&label=npm"/></a>
<a href="https://www.npmjs.com/package/prompt-to-asset"><img alt="downloads" src="https://img.shields.io/npm/dm/prompt-to-asset.svg?style=flat&color=8b5cf6&label=downloads"/></a>
<a href="https://github.com/MohamedAbdallah-14/prompt-to-asset/actions/workflows/ci.yml"><img alt="CI" src="https://github.com/MohamedAbdallah-14/prompt-to-asset/actions/workflows/ci.yml/badge.svg"/></a>
<a href="./LICENSE"><img alt="license" src="https://img.shields.io/badge/license-MIT-22d3ee.svg?style=flat"/></a>
<a href="https://nodejs.org"><img alt="node" src="https://img.shields.io/badge/node-%E2%89%A520.11-10b981.svg?style=flat"/></a>
<a href="https://modelcontextprotocol.io"><img alt="MCP" src="https://img.shields.io/badge/MCP-1.0-a78bfa.svg?style=flat"/></a>
<a href="https://glama.ai/mcp/servers/MohamedAbdallah-14/prompt-to-asset"><img alt="Glama score" src="https://glama.ai/mcp/servers/MohamedAbdallah-14/prompt-to-asset/badges/score.svg"/></a>
<a href="#30-second-start"><img alt="zero-key" src="https://img.shields.io/badge/zero--key-ready-16a34a.svg?style=flat"/></a>
<a href="https://github.com/MohamedAbdallah-14/prompt-to-asset/stargazers"><img alt="stars" src="https://img.shields.io/github/stars/MohamedAbdallah-14/prompt-to-asset?style=flat&color=f59e0b&logo=github"/></a>
</p>
<p>
<a href="cursor://anysphere.cursor-deeplink/mcp/install?name=prompt-to-asset&config=eyJjb21tYW5kIjogIm5weCIsICJhcmdzIjogWyIteSIsICJwcm9tcHQtdG8tYXNzZXQiXX0="><img alt="Install in Cursor" src="https://img.shields.io/badge/Install_in_Cursor-000000?style=for-the-badge&logo=cursor&logoColor=white"/></a>
<a href="vscode:mcp/install?%7B%22name%22%3A%20%22prompt-to-asset%22%2C%20%22type%22%3A%20%22stdio%22%2C%20%22command%22%3A%20%22npx%22%2C%20%22args%22%3A%20%5B%22-y%22%2C%20%22prompt-to-asset%22%5D%7D"><img alt="Install in VS Code" src="https://img.shields.io/badge/Install_in_VS_Code-007ACC?style=for-the-badge&logo=visualstudiocode&logoColor=white"/></a>
<a href="https://github.com/MohamedAbdallah-14/prompt-to-asset/releases/latest"><img alt="Claude Desktop" src="https://img.shields.io/badge/Claude_Desktop_(.mcpb)-D97706?style=for-the-badge&logo=anthropic&logoColor=white"/></a>
<a href="https://smithery.ai/server/prompt-to-asset"><img alt="Smithery" src="https://img.shields.io/badge/Smithery-6366F1?style=for-the-badge&logo=bookstack&logoColor=white"/></a>
</p>
<sub>
<a href="#30-second-start">Quickstart</a> ·
<a href="#free-paths-at-a-glance">Free paths</a> ·
<a href="#usage">Usage</a> ·
<a href="#the-three-modes">Modes</a> ·
<a href="#free-paths-beyond-pollinations">Free APIs</a> ·
<a href="#mcp-tools">MCP tools</a> ·
<a href="./GETTING_STARTED.md">Full guide</a> ·
<a href="./CHANGELOG.md">Changelog</a>
</sub>
</div>
---
## 30-second start
**Pick one. Run it. You're done.** The recommended path is first.
Runtime: **Node ≥ 20.11** (24 recommended). macOS, Linux, Windows (WSL2 for `--fix` native deps).
<table>
<tr>
<td width="34%" valign="top">
### 🔵 AI assistant · recommended
Click an install button above. Then paste one of these into chat:
```text
• Make a transparent logo for Forge, a dev-tools brand. Flat vector, warm orange.
• Make a favicon for my app, dark-mode aware.
• Fan this master.png out to iOS + Android + PWA.
• Ingest this screenshot as a mark, vectorize, export everything.
```
Works in Cursor, Claude Code, VS Code, Windsurf, Codex, Gemini CLI. Zero terminal typing.
</td>
<td width="33%" valign="top">
### 🟢 Zero key, zero install
One `curl`, one `npx`. Offline fan-out to every platform.
```bash
curl -o logo.png \
"https://image.pollinations.ai/prompt/\
minimal+flat+vector+logo\
?model=flux&width=1024&nologo=true"
npx prompt-to-asset export logo.png \
--platforms ios,android,pwa,favicon
```
Outputs: iOS AppIconSet, Android adaptive, PWA, favicon bundle, visionOS scaffold.
</td>
<td width="33%" valign="top">
### 🟣 CLI · free API keys
Best CLI experience: free tokens first, paid keys optional.
```bash
npm i -g prompt-to-asset
p2a doctor # check env
p2a doctor --fix # auto-install deps
p2a pick # interactive
```
Start with Cloudflare Workers AI, NVIDIA NIM, HF Inference, Stable Horde, and free trials. Paid providers remain optional fallbacks.
</td>
</tr>
</table>
<a id="free-paths-at-a-glance"></a>
### Free paths at a glance
You don't need a paid API key. Ranked best-first:
| Route | Gets you | Signup |
| ------------------------------------ | -------------------------------------- | ----------------------- |
| **`inline_svg`** via AI assistant | Logos, favicons, icon packs — instant | None |
| **Cloudflare Workers AI** | Flux-1-Schnell + SDXL, 10k neurons/day | Free token + account ID |
| **NVIDIA NIM** | Flux.1-dev, Flux.2-klein, SDXL, SANA | Free token, no card |
| **HF Inference** | SDXL, SD3, Flux dev/schnell | Free read token |
| **Stable Horde** | SDXL, Flux on community GPUs | Anonymous queue |
| **Pollinations** (HTTP GET) | Last-resort raster, RGB | None |
| **Google AI Studio** (paste-only UI) | Nano Banana / Nano Banana Pro | Google account |
Details + quotas: [Free paths beyond Pollinations](#free-paths-beyond-pollinations). Run `p2a doctor` or ask your assistant for `asset_doctor()` to see what's live right now.
> [!TIP]
> Stuck? Click **Install in Cursor** or **Install in VS Code** above, restart the editor, and say: _"make a favicon for my app, dark-mode aware."_
---
## Highlights
- **Free CLI-first generation** — `p2a doctor`, `p2a pick`, and the MCP tools rank free API routes before paid models, so developers can generate inside the CLI without enabling billing.
- **[Three execution modes](#the-three-modes)** — `inline_svg` (host LLM authors SVG), `external_prompt_only` (paste into any web UI), `api` (server calls a free or paid provider). Pick what fits. All three can finish on $0.
- **[60+ models, free-first routing](#the-router)** — Cloudflare Workers AI, NVIDIA NIM, HF, Horde, Pollinations, free trials, plus optional paid OpenAI / Ideogram / Recraft / BFL / Gemini. Each rule cites a research source.
- **[Refuses to do the wrong thing](#the-router)** — the `Never` column. No wordmarks past 3 words through a diffusion sampler. No transparent PNG through Imagen. No `negative_prompt` on Flux.
- **[Offline platform fan-out](#platform-support)** — one 1024² master → iOS AppIconSet, Android adaptive + monochrome, PWA 192/512/512-maskable, favicon bundle, visionOS parallax, Flutter launcher. Zero network.
- **[Validates before shipping](#security)** — tier-0 checks on every output: dims, alpha presence, checkerboard FFT, safe-zone bbox, ΔE2000 palette drift, WCAG contrast, OCR Levenshtein on wordmarks.
- **[Sprite sheets + 9-slice](#mcp-tools)** — pack PNG frames into TexturePacker-compatible atlases (Phaser, PixiJS, Godot, Unity); emit 9-slice numbers + CSS `border-image` + Android `.9.png`.
---
## Table of contents
<details>
<summary>Click to expand</summary>
- [30-second start](#30-second-start)
- [Usage](#usage) — what to say to your assistant
- [The three modes](#the-three-modes) — inline_svg · external_prompt_only · api
- [The router](#the-router) — which model for which job, and what never
- [Free paths beyond Pollinations](#free-paths-beyond-pollinations)
- [Install](#install)
- [Models covered](#models-covered) — 60+
- [MCP tools](#mcp-tools) — 25 tools
- [CLI surface](#cli-surface)
- [Brand bundle (`brand.json`)](#brand-bundle)
- [Platform support](#platform-support)
- [Architecture](#architecture)
- [Comparison](#comparison)
- [Security](#security)
- [Research-backed decisions](#research-backed-decisions)
- [Development](#development)
- [Community](#community) · [License](#license)
</details>
---
## Usage
You just talk to your assistant. Example from a new chat:
> **Make me a transparent logo for a developer-tools company called Forge. Flat vector, two-tone warm orange on neutral.**
Behind the scenes:
1. **`asset_doctor()`** — check what modes and providers are live.
2. **`asset_init_brand({ app_name: "Forge", palette: ["#EA580C", "#F5F5F4"] })`** if no `brand.json` exists.
3. **`asset_enhance_prompt({ brief })`** returns an `AssetSpec`: classification, rewritten prompt, `modes_available[]`, optional `svg_brief`, optional `paste_targets`, and a `routing_trace` pointing at the research file that backed the decision (plus `never_models` — why Imagen or DALL·E got rejected).
4. Assistant offers you **`inline_svg`** / **`external_prompt_only`** / **`api`**.
5. If **`inline_svg`**: it writes `<svg>` inline and calls `asset_save_inline_svg` → writes `master.svg`, `favicon.ico`, apple-touch, AppIconSet, PWA bundle to disk.
6. If **`external_prompt_only`**: assistant shows the refined prompt and the best paste target (free first). You generate, save, then say _"ingest this file"_ → `asset_ingest_external`.
7. If **`api`**: assistant calls the routed provider. Server mattes, vectorizes, exports, validates.
8. Follow-up: _"also fan this out for iOS and Android"_ → `asset_export_bundle` with the saved master.
Zero CLI typing. The CLI is still first-class for CI, shell scripts, and non-MCP environments — both surfaces hit the same core.
---
## Why this exists
Two facts shape everything here.
> **Producing production-grade software assets is a routing and post-processing problem, not a prompt-engineering problem.**
Imagen 3/4 and Gemini Flash Image can't produce real RGBA PNGs — their VAE is RGB-only, so asking for a transparent background renders the grey-and-white checkerboard _as pixels_. SDXL can't spell past ~8 characters. Only Recraft emits native SVG. Flux errors on `negative_prompt`. None of that is visible in the model UI. All of it silently breaks one-shot "prompt → asset" tools.
> **You may not have an image-model API key. The plugin works anyway.**
Every one of the three modes can finish on $0.
---
## The three modes
```mermaid
flowchart LR
A["one-line brief"] --> B["asset_enhance_prompt"]
B --> C{"mode"}
C -->|inline_svg| D["Host LLM emits SVG inline<br/>→ asset_save_inline_svg"]
C -->|external_prompt_only| E["Paste into web UI<br/>→ asset_ingest_external"]
C -->|api| F["Server calls routed provider"]
D --> G["matte · vectorize · validate"]
E --> G
F --> G
G --> H["AssetBundle<br/>ios · android · pwa · favicon · visionos · flutter"]
```
| Mode | Key? | What happens | Best for |
| -------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------- |
| **`inline_svg`** | No | Server returns an SVG-authoring brief (viewBox, palette, path budget ≤ 40). Host LLM emits `<svg>…</svg>` inline, then `asset_save_inline_svg` writes master + favicon.ico + apple-touch + AppIconSet + PWA bundle. Instant. Deterministic. | Logos, favicons, icon packs, stickers, simple app-icon masters |
| **`external_prompt_only`** | No | Server returns the dialect-correct prompt plus a ranked list of paste targets, free paths first: Pollinations, HF Inference, Stable Horde, Google AI Studio, Ideogram, Recraft, Midjourney, fal.ai, BFL, ChatGPT, Firefly, Krea. Generate elsewhere, save locally, call `asset_ingest_external`. | Anything — best for illustrations, heroes, text-heavy logos |
| **`api`** | Optional | Server calls the provider directly. Works **zero-key via Pollinations / Horde / HF**, or with paid keys. Route → generate → matte → vectorize → export → validate → content-addressed bundle. | Automation, CI, no rate-limit tolerance |
The host LLM picks the mode, or you do. The server surfaces `modes_available` so the assistant offers them to you. **Free paths first — always.**
---
## The router
Router decisions live in [`data/routing-table.json`](./data/routing-table.json). Capability matrix in [`data/model-registry.json`](./data/model-registry.json). **Every rule cites its research source.**
| Need | Primary | Fallback | Never |
| ------------------------ | --------------------------------------------------------------- | ------------------------------------------------------- | ---------------------------------- |
| Transparent PNG mark | `gpt-image-1.5` with `background:"transparent"` | Ideogram 3 Turbo (`/generate-transparent`) → Recraft V4 | Imagen, Gemini Flash Image, SD 1.5 |
| Logo with 1–3 word text | Ideogram 3 Turbo → `gpt-image-1.5` → Recraft V4 | Composite SVG type over mark | Imagen, SD 1.5, `flux-schnell` |
| Logo with >3 word text | **Never a diffusion sampler.** Mark + SVG typography composite. | — | — |
| Native SVG | Recraft V4 (V3 for brand-style pipelines) | `inline_svg` (host LLM authors SVG) | Everyone else |
| Photoreal hero | Free CLI route first: Cloudflare / NVIDIA NIM / HF | Flux Pro / `gpt-image-1.5` / Gemini with paid keys | DALL·E 3, Imagen 4 for new work |
| Iterate an existing mark | `flux-kontext-pro` (edit-only) | Pollinations Kontext (free) | — |
| Zero-cost everything | `inline_svg` → Cloudflare / NVIDIA NIM / HF / Horde | Pollinations → paste-only | — |
The **Never** column matters. It's why `prompt-to-asset` refuses to render wordmarks past 3 words in any diffusion sampler, and why asking for a transparent PNG never goes to Imagen.
---
## Free paths beyond Pollinations
| Option | How | Best at | Catch |
| -------------------------- | ---------------------------------------------- | ------------------------------------ | -------------------------------------------------------------------- |
| **Cloudflare Workers AI** | Free API token + account ID | Flux-1-Schnell, SDXL, DreamShaper | 10k neurons/day cap (~900 Flux-Schnell or 5k SDXL-Lightning) |
| **NVIDIA NIM** | Free API token, no card | Flux.1-dev, Flux.2-klein, SDXL, SANA | 1k requests/month; strong free CLI route |
| **HF Inference** | Free read token | SDXL, SD3, Flux dev + schnell | Rate-limited, cold-start latency |
| **Stable Horde** | Anonymous kudos queue | SDXL, Flux community GPUs | Minutes of queue on the free lane |
| **Pollinations.ai** | `curl` → HTTP GET. No signup. | Throwaway raster | Last resort: silent model swaps, downsizing, RGB only |
| **Google AI Studio (UI)** | Free interactive web UI at aistudio.google.com | Nano Banana / Nano Banana Pro | No free API — paste-only; download PNG, call `asset_ingest_external` |
| **Local ComfyUI** | Community `comfyui-mcp` adapter | Full fidelity, no caps | You bring the GPU |
| **`inline_svg`** | Host LLM emits `<svg>` in chat | Logos, favicons, simple icons | ≤40 paths; simple geometry |
| **`external_prompt_only`** | Paste into any web UI | Whatever that UI gives you | Manual save, then `asset_ingest_external` |
<details>
<summary><b>Google Gemini / Imagen — verified pricing (Apr 2026)</b></summary>
Verified 2026-04-26 against public Gemini API pricing:
- **Imagen 4 image output is paid API.** The pricing table lists Free Tier as "Not available" and prices Fast / Standard / Ultra at $0.02 / $0.04 / $0.06 per image.
- **Nano Banana family is paid API.** `gemini-3.1-flash-image-preview` (Nano Banana 2), `gemini-3-pro-image-preview` (Nano Banana Pro), and `gemini-2.5-flash-image` (original Nano Banana) list image output only in the paid tier. Billing must be enabled on the GCP project to use these via API.
- **Free for text, multimodal understanding, and embeddings.** The Gemini text-out models still have `Free of charge` input + output on the free tier.
- **Free interactive image generation is also via the AI Studio web UI** at [aistudio.google.com](https://aistudio.google.com). Community-observed limit 500–1,000 images/day, dynamic. Use `external_prompt_only` + `asset_ingest_external` if you want Nano Banana quality without billing.
- **Free image generation via the Gemini consumer app** at [gemini.google.com](https://gemini.google.com): Basic 20/day, AI Plus 50/day, AI Pro 100/day, Ultra 1,000/day.
- **Paid API pricing (per image, standard):** Nano Banana (`gemini-2.5-flash-image`) $0.039; Nano Banana 2 Flash (`gemini-3.1-flash-image-preview`) $0.045/0.5K, $0.067/1K, $0.101/2K, $0.151/4K; Nano Banana Pro (`gemini-3-pro-image-preview`) $0.134/1K-2K, $0.24/4K (+ $0.0011 per input image); Imagen 4 Fast $0.02, Standard $0.04, Ultra $0.06. Batch API is 50% off.
</details>
> Run `p2a doctor` (or ask your assistant for `asset_doctor()`) to see what's live in your environment right now.
---
## Install
Every command works via `npx` — no install required.
```bash
# Zero install
npx prompt-to-asset doctor # what's live in this shell right now
npx prompt-to-asset doctor --fix # auto-install native deps (brew / cargo / scoop; never sudo)
npx prompt-to-asset pick # interactive route picker
npx prompt-to-asset init --register # scaffold brand.json + register in .cursor / .vscode / .windsurf
# Or global for daily use
npm i -g prompt-to-asset
p2a doctor
# Or per-project for CI
npm i -D prompt-to-asset
```
### Register with your AI assistant
<table>
<tr>
<td width="50%">
**Claude Code**
```bash
claude mcp add prompt-to-asset -- p2a
```
**Smithery (universal)**
```bash
npx -y @smithery/cli install prompt-to-asset --client claude
```
</td>
<td width="50%">
**Cursor · VS Code · Windsurf · Codex · Gemini CLI**
Use the **install buttons at the top** of this README, or see [`docs/install.md`](./docs/install.md) for the exact stanza per IDE.
**Claude Desktop**
Download the [`.mcpb` bundle](https://github.com/MohamedAbdallah-14/prompt-to-asset/releases/latest) → double-click → restart.
</td>
</tr>
</table>
Once registered, your assistant has the full **24 `asset_*` tool** surface.
---
## Models covered
**Paid direct APIs:** `gpt-image-1`, `gpt-image-1.5`, `dall-e-3` (deprecated 2026-05-12), `imagen-3`, `imagen-4`, `gemini-3-flash-image` (Nano Banana), `gemini-3-pro-image`, `sd-1.5`, `sdxl`, `sd3-large`, `playground-v3`, `flux-schnell`, `flux-dev`, `flux-pro`, `flux-2`, `flux-kontext-pro`, `ideogram-3`, `ideogram-3-turbo`, `recraft-v3`, `leonardo-phoenix`, `leonardo-diffusion-xl`, `fal-flux-pro`, `fal-flux-2`, `fal-sdxl`.
**Free-tier / zero-key:** `pollinations-flux`, `pollinations-turbo`, `pollinations-kontext`, `pollinations-sd`, `horde-sdxl`, `horde-flux`, `hf-sdxl`, `hf-sd3`, `hf-flux-schnell`, `hf-flux-dev`.
**Paste-only surfaces:** `midjourney-v6`, `midjourney-v7`, `firefly-3`, `krea-image-1`. Calling `asset_generate_*` with `mode: "api"` against a paste-only primary soft-falls-back to the first API-reachable model in the chain and surfaces a warning. If the whole chain is paste-only, you get an `ExternalPromptPlan` rather than an error.
---
<a id="mcp-tools"></a>
<details>
<summary><b>🛠 MCP tool surface (25 tools)</b></summary>
| Tool | Purpose |
| ------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `asset_capabilities` | Inventory of modes + providers. Buckets paid / free-tier / paste-only; surfaces zero-key routes first. Read-only. |
| `asset_enhance_prompt` | Classify, route, rewrite. Returns modes + `svg_brief` + `paste_targets` + `routing_trace { research_sources, never_models, fallback_chain }` + `clarifying_questions[]` when the brief is ambiguous. Read-only. |
| `asset_generate_logo` | `inline_svg` / `external_prompt_only` / `api`. Returns `InlineSvgPlan` / `ExternalPromptPlan` / `AssetBundle`. |
| `asset_generate_app_icon` | Same three modes. `api` produces full iOS / Android / PWA / visionOS / Flutter fan-out. Set `ios_18_appearances: true` for dark + tinted variants. |
| `asset_generate_favicon` | `favicon-{16,32,48}.png`, `icon.svg`, `icon-dark.svg`, `apple-touch`, PWA 192/512/512-maskable, `<link>` snippet, `manifest.webmanifest`. |
| `asset_generate_og_image` | 1200×630 via Satori + `@resvg/resvg-js`. Deterministic typography, no diffusion-rendered text garbage. |
| `asset_generate_illustration` | `external_prompt_only` / `api`. Brand-locked via bundle refs, LoRA, or `style_id`. Routed primary: Flux.2 (up to 8 refs). |
| `asset_generate_splash_screen` | iOS `LaunchScreen-2732.png`, Android `mipmap-*/splash.png` + theme XML, PWA splash + README. Pass `existing_mark_svg` to reuse an approved mark. |
| `asset_generate_hero` | Marketing hero art (16:9 / 21:9 / 3:2 / 2:1). `external_prompt_only` / `api`. |
| `asset_save_inline_svg` | Round-trip for `inline_svg`. Validates the SVG against the brief, writes the bundle. |
| `asset_ingest_external` | Round-trip for `external_prompt_only`. Matte → vectorize → validate → bundle. |
| `asset_remove_background` | BiRefNet / BRIA RMBG-2.0 / LayerDiffuse / difference matte / U²-Net. |
| `asset_vectorize` | `vtracer` / `potrace` / Recraft / posterize fallback, then SVGO. |
| `asset_upscale_refine` | DAT2 / Real-ESRGAN / SUPIR / img2img / Lanczos; asset-type-aware. |
| `asset_validate` | Tier-0 (dims, alpha, checkerboard FFT, safe-zone bbox, ΔE2000 palette, WCAG contrast, OCR Levenshtein). Tier-2 VLM-as-judge via `PROMPT_TO_BUNDLE_VLM_URL`. |
| `asset_brand_bundle_parse` | Parse `brand.json` / DTCG tokens / AdCP / Markdown into a canonical `BrandBundle`. |
| `asset_doctor` | Structured env inventory: native deps, free-tier routes ranked best-first, paid keys, paste-only surfaces, pipeline URLs, mode flags, "what to try next." Read-only. |
| `asset_models_list` | Browse the 60+ model registry with filters: `free` / `paid` / `paste_only` / `rgba` / `svg`. Read-only. |
| `asset_models_inspect` | Full capability dump for one model id (or aka alias). Strengths, weaknesses, paste targets, routing rules, env status. Read-only. |
| `asset_export_bundle` | Fan a 1024² master PNG into iOS AppIconSet + Android adaptive + PWA maskable + visionOS parallax + Flutter launcher + favicon. Offline. |
| `asset_sprite_sheet` | Pack PNG/WEBP/JPG frames into a sprite sheet + TexturePacker-compatible JSON atlas (Phaser / PixiJS / Godot / Unity). Offline. |
| `asset_nine_slice` | Emit a 9-slice config + CSS `border-image` + engine-ready numbers (Unity / Godot / Phaser / PixiJS) from an image plus four pixel guides. Optional Android `.9.png`. |
| `asset_init_brand` | Scaffold `brand.json` and ensure the assets dir exists. Auto-detects Next.js, Expo, Flutter, Xcode, Astro, Vite, Remix, Nuxt, React Native, Electron, Node. |
| `asset_train_brand_lora` | Wrap a user-owned LoRA training endpoint (`PROMPT_TO_BUNDLE_MODAL_LORA_TRAIN_URL`). Path-guarded; validates inputs. |
Tools are annotated `readOnlyHint` / `idempotentHint` so Cursor auto-approves without prompting.
</details>
<a id="cli-surface"></a>
<details>
<summary><b>⌨️ CLI surface</b></summary>
Used by the LLM over `Bash` when MCP isn't registered yet, and by CI. Every read-only command accepts `--json`.
```
p2a # default — MCP stdio server
p2a mcp # same, explicit
p2a export <master.png> # offline platform fan-out
p2a export <master.png> --json
p2a init # interactive brand.json + IDE registration hints
p2a init --register # + auto-write .cursor/mcp.json / .vscode/mcp.json / .windsurf/mcp.json
p2a pick # interactive model picker
p2a doctor # environment inventory
p2a doctor --json # structured output
p2a doctor --data # check data/model-registry.json ↔ data/routing-table.json consistency
p2a doctor --fix # auto-install missing native deps (brew / cargo / scoop; never sudo)
p2a models list # --free | --paid | --paste-only | --rgba | --svg
p2a models inspect <id> # full capability dump
p2a sprite-sheet <dir> # pack frames → PNG + atlas
p2a nine-slice <image> # 9-slice JSON + CSS + engine numbers + .9.png
p2a --help
```
</details>
<a id="brand-bundle"></a>
<details>
<summary><b>🎨 Brand bundle — <code>brand.json</code></b></summary>
```json
{
"name": "Halcyon",
"palette": ["#2563eb", "#ffffff"],
"fonts": { "display": { "family": "Inter", "weights": [700, 800] } },
"style_refs": ["https://…/sample1.png", "./refs/style2.png"],
"do_not": ["drop shadows", "heavy gradients"],
"lora": "halcyon-flux-v2",
"sref_code": "--sref 1234567890",
"style_id": "rc_halcyon_01"
}
```
`p2a init` writes this for you, detecting the framework and suggesting an assets directory. Once present, every generator reads from it automatically.
</details>
<a id="platform-support"></a>
<details>
<summary><b>📱 Platform support</b></summary>
| Platform | What you get |
| -------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **iOS (Xcode)** | `AppIcon.appiconset` with 1024 opaque, squircle-ready. iOS 18 dark + tinted variants via `ios_18_appearances: true`. |
| **Android** | Adaptive foreground + background, Android 13 monochrome, all mipmap densities, optional `.9.png`. |
| **PWA / web** | `favicon.ico` (16/32/48 multi-res), `icon.svg` with `prefers-color-scheme` dark support, `apple-touch-icon.png` 180×180 opaque, 192/512/512-maskable, `manifest.webmanifest`, `<link>` snippet for your `<head>`. |
| **Flutter** | Pre-populated `flutter_launcher_icons.yaml` wiring iOS, Android adaptive, web, macOS, Windows. |
| **visionOS** | Three-layer parallax scaffold with a README. Layer split stays a human decision. |
| **Next.js / Astro / Vite / Remix / Nuxt / Expo / React Native / Electron** | Framework detection via `p2a init` / `asset_init_brand` and a sensible output dir. |
| **Games** | `sprite-sheet` produces TexturePacker-compatible atlases (Phaser, PixiJS, Godot, Unity). `nine-slice` emits engine-ready numbers. |
</details>
<a id="architecture"></a>
<details>
<summary><b>🏗 Architecture</b></summary>
```
brief (text)
↓ asset_capabilities → modes available + free/paid/paste-only bucketing
↓ asset_enhance_prompt → AssetSpec {
↓ routing_trace: { rule_id, reason, research_sources, never_models, fallback_chain },
↓ modes_available,
↓ svg_brief?, (inline_svg)
↓ paste_targets?, (external_prompt_only)
↓ rewritten_prompt, …
↓ }
↓
├─ mode: inline_svg → host LLM emits <svg>; asset_save_inline_svg writes bundle
├─ mode: external_prompt_only → user pastes into web UI; asset_ingest_external runs matte → vectorize → validate
└─ mode: api → provider(model, prompt, params) → matte → vectorize → upscale → export → validate
```
Content-addressed storage: `assets/<hash[0:2]>/<hash>/<variant>.<ext>`. The MCP server is synchronous and stateless. `prompt_hash` and `params_hash` in every `AssetBundle` are designed to drop straight into a BullMQ / SQS / Cloudflare Queues `jobId` for a hosted pipeline. Reference design: [`docs/research/18-asset-pipeline-tools/18e-production-pipeline-architecture.md`](./docs/research/18-asset-pipeline-tools/18e-production-pipeline-architecture.md).
### Design thesis
You own the API keys. The LLM owns everything else.
The only thing that happens in a terminal is installing the package and putting keys in `.env`. Secrets shouldn't pass through chat. Every other verb — doctor checks, model inspection, platform fan-out, brand scaffolding, sprite sheets, 9-slice configs — is an MCP tool the assistant calls when you ask in natural language.
</details>
---
## Comparison
| Tool | Prompt enhancement | Multi-model routing | Zero-key | Dev-asset bundle | Offline platform fan-out |
| ---------------------------------------- | :----------------: | :-----------------: | :---------------------------------: | :--------------: | :----------------------------------------------------: |
| Promptati / PromptHero | cinematic only | ✗ | ✗ | ✗ | ✗ |
| Looka / Brandmark / Designs.ai | ✗ | ✗ | ✗ | partial | ✗ |
| ChatGPT / Midjourney / Ideogram (direct) | ✗ | ✗ | ✗ | ✗ | ✗ |
| appicon.co | ✗ | ✗ | ✓ | partial | iOS only |
| flutter_launcher_icons | ✗ | ✗ | ✓ | partial | iOS + Android |
| **`prompt-to-asset`** | ✓ | ✓ (60+ models) | ✓ (Pollinations / HF / Horde / SVG) | ✓ | ✓ (iOS + Android + PWA + visionOS + favicon + Flutter) |
---
## Security
This tool handles API keys for up to 15 providers. Non-negotiables:
- **Keys live in env vars only.** Never written to disk, never logged, never echoed in MCP responses. Provider error bodies go through `redact()` (`packages/mcp-server/src/security/redact.ts`) before reaching the host LLM.
- **Path access is allow-listed.** `image_path` / `output_dir` / `existing_mark_svg` resolve through symlinks and reject anything escaping project cwd + configured output dir + cache dir + OS tempdir. Widen with `P2A_ALLOWED_PATHS=/path1:/path2`.
- **SVG is XSS-sanitized before any write.** `<script>`, `<foreignObject>`, `on*=` handlers, `javascript:` URIs, external `<image href>` / `<use href>`, CSS `@import` over the network — all rejected. The check runs unconditionally; SVGO is not required.
- **Cost guardrail.** Set `P2A_MAX_SPEND_USD_PER_RUN=5.00` to cap any single tool call. Pre-flight estimate refuses to call if over. Free-tier routes are always $0.
- **Data integrity at boot.** `assertDataIntegrityAtBoot()` runs on start. If a routing rule points at a model id not in the registry, the server refuses to boot with a clear error. Check in CI with `p2a doctor --data`.
- **No telemetry. No remote calls unless the routed provider explicitly requires one.**
Full policy: [SECURITY.md](./SECURITY.md).
---
## Research-backed decisions
Every routing rule, dialect switch, safe-zone size, and text ceiling that's implemented is backed by a file under [`docs/research/`](./docs/research/). `asset_enhance_prompt` returns a `routing_trace.research_sources` array on every call. The angle → code pointer map, plus an honest ledger of what's wired and what's deferred, lives in [`docs/RESEARCH_MAP.md`](./docs/RESEARCH_MAP.md).
---
## Development
```bash
git clone https://github.com/MohamedAbdallah-14/prompt-to-asset.git
cd prompt-to-asset
npm install
npm run build
npm run typecheck
npm run lint
npm test # vitest watch
npm run test:run # vitest run (CI)
npm run smoke # list tools via MCP stdio + correctness assertions
npm run sync # regenerate IDE mirrors from SSOTs
npm run verify # byte-verify mirrors match SSOTs
```
SSOTs live in `skills/*/SKILL.md`, `rules/*.md`, `.claude-plugin/`, and `data/*.json`. Don't edit `.cursor/`, `.claude/`, `.windsurf/` directly — they're regenerated by `scripts/sync-mirrors.sh` and CI byte-verifies them.
- **Contribution flow:** [CONTRIBUTING.md](./CONTRIBUTING.md)
- **User on-ramp:** [GETTING_STARTED.md](./GETTING_STARTED.md)
- **Common snags:** [TROUBLESHOOTING.md](./TROUBLESHOOTING.md)
- **Release notes:** [CHANGELOG.md](./CHANGELOG.md)
---
## Community
- **Issues + feature requests:** [GitHub Issues](https://github.com/MohamedAbdallah-14/prompt-to-asset/issues)
- **Security disclosures:** [SECURITY.md](./SECURITY.md)
- **Code of Conduct:** [CODE_OF_CONDUCT.md](./CODE_OF_CONDUCT.md)
- **Star history:**
<a href="https://star-history.com/#MohamedAbdallah-14/prompt-to-asset&Date">
<img src="https://api.star-history.com/svg?repos=MohamedAbdallah-14/prompt-to-asset&type=Date" alt="Star History" width="600"/>
</a>
If this repo saved you from hand-crafting another AppIconSet, a star helps it reach other developers fighting the same fight.
---
## Read more
The thinking behind the design, in long-form:
- **[Why I stopped picking image models and built a router instead](https://blog.mohamedabdallah.com/image-model-router)** — the case for routing across 30+ image models.
- **[MCP server architecture: what's inside prompt-to-asset](https://blog.mohamedabdallah.com/mcp-server-architecture)** — architecture deep-dive.
Cross-posted on [Medium](https://medium.com/@mohamedmabdallah14) and [dev.to](https://dev.to/mohamedabdallah14).
---
## License
[MIT](./LICENSE) © prompt-to-asset contributors.
<div align="center">
<sub>Built on a 34-category research compendium. See <a href="./docs/research/SYNTHESIS.md">SYNTHESIS.md</a> and <a href="./docs/RESEARCH_MAP.md">RESEARCH_MAP.md</a>.</sub>
<br/><br/>
<sub><a href="#top">⬆ back to top</a></sub>
</div>