revspot-mcp
Provides image generation and editing through OpenAI's image API, supporting tools for generating, batch generating, editing images, and managing generation jobs and media.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@revspot-mcpCreate an ad creative for our holiday collection"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
revspot-mcp
Revspot's image-generation MCP server. Exposes a DTC-ads tool surface
(generate_image, show_marketing_studio, …) over MCP, so any MCP client —
Claude included — can generate ad creatives against your product library.
Run it
npm install
cp .env.example .env.local # OPENAI_API_KEY at minimum
npm run devPOST /api/mcp — JSON-RPC, MCP over HTTP. Thirteen tools:
generate_image generate_image_batch jobs_wait
job_status show_marketing_studio show_generations
show_generation_by_ids show_marketing_studio_generations
edit_image media_upload media_confirm
models_explore balanceRelated MCP server: ImageMcp
Layout
app/api/mcp/route.ts the MCP endpoint — JSON-RPC, tool dispatch,
widget resources
app/api/media/[id] PUT target for media_upload; the id is the
capability, write-once
app/assets, app/outputs serve product-pack images and generated files
lib/core/dtc-ads/ the surface: prompt assembly, ad-format
catalogue, tool schemas, handlers, widgets
lib/core/image-generation/ provider + the canvas table
lib/core/ product-pack store, run store, storageThe prompt layer — lib/core/dtc-ads/
This is the part that decides what a creative looks like. Four files carry it:
assets/system-base.txt system prompt, no brand kit
assets/system-brandkit.txt system prompt when a brand kit is supplied
assets/formats-base.json ad-format definitions (layout per template)
assets/formats-brandkit.json the same, brand-kit variant
assets/catalogue.json the 42 ad formats: id, name, orderingassembly.ts composes these into the enhanced_prompt payload the image model
receives. Key ordering, whitespace and which blocks appear are all significant —
the payload is consumed as a whole, so a change anywhere shifts output.
Two things worth knowing before editing:
style_idhas no default and is the dominant creative driver. Its parameter description intools.tsis load-bearing: wording there changes which template agents pick. Treat tool descriptions as behaviour, not docs.The brand-kit path switches system prompt. Supplying a kit selects
system-brandkit.txtand folds the kit into the payload. Passing a barebrand_kit_idwith nothing to resolve is refused rather than silently degraded — otherwise the model is told to hold a brand it was never shown.
Canvas table — read before touching aspect ratios
lib/core/image-generation/openai.ts
The provider enforces two rules, quoted from its own rejections: both sides
divisible by 16, and within a per-resolution pixel budget. The sizes in
OBSERVED satisfy both, and no formula reproduces them — 3:4 at 2k is
1744×2336, not 2× the 1k 880×1168. The relationship is bespoke per ratio.
So there are two outcomes: a canvas backed by a measurement, or auto. Do not
compute one — an earlier computed table produced sizes the provider rejects and
broke 17 of 45 aspect/resolution combinations.
COMPUTED holds 4:5 only, the documented exception: it is the Meta feed
standard, and each size is the largest exact-0.8 canvas satisfying both rules.
Marked observed: false so a run record says the number rests on arithmetic.
Before it existed, asking for 4:5 silently returned a 1254×1254 square.
Widgets
Three MCP-Apps panels — generation gallery, ad-format picker, media upload —
served as ui://revspot/<name>.<version>.html from lib/core/dtc-ads/widgets.ts.
Hosts cache widget HTML against its URI, so markup changes are invisible to any
client that already opened a panel. widgets:version enforces that: change the
markup without bumping WIDGET_VERSION and it fails with both hashes. Bump the
constant, commit the regenerated lockfile, and clients refetch.
Before you deploy
npm run predeploy
widgets:version resource versions consistent
widgets:parse every widget script parses
widgets:paint widgets render against a strict host
tsc --noEmit typeswidgets:paint needs REVSPOT_BACKEND_URL pointing at a running instance.
Storage
REVSPOT_DATA_DIR is the root — a mounted volume in production, any writable
path locally.
.prizm-data/store.json generation runs
data/prizm-product-packs.json product packs
assets/product-packs/<id>/ pack images
outputs/ generated imagesThose two prizm-prefixed names, and the legacy /prizm-assets and
/prizm-outputs URL prefixes accepted in servedUrlToFilePath, are held over
from an earlier name. They are not dead: records already on disk reference them,
so renaming orphans every pack and run written before the change. Rename only
alongside a migration. New writes already use assets/ and outputs/.
Known gaps
Tools not implemented that MCP clients may reach for:
media_import_url,media_upload_widget,show_medias, and the transform set —upscale_image,reframe,outpaint_image,remove_background. Without the last group, "make it bigger" or "make it vertical" becomes a fresh generation with different copy rather than a transform of the existing image.No brand-kit store. An inline
brand_kitobject works; a bare id is refused.No cost preflight, so spend cannot be quoted before running.
Run history has no
created_atand no date filter, so "what did I make today" cannot be scoped server-side.Jobs occasionally accept and sit in
queuedwithout starting. Re-submitting clears it and a 15-minute watchdog reaps them; root cause not diagnosed.Concurrency cap is 8 — larger batches need a queue that waits for slots.
Things that will bite you
Product packs do not transfer between instances. Rebuild them with the same images. A pack with the right name and the wrong images renders a different product and looks like a model failure. Verify image by image, not by title or count.
Never reconstruct a record from a read that may have missed. A
{...(await get(id))!}spread once persisted a row with no id and no createdAt; the listing sorted oncreatedAt.localeCompareand threw. Because the concurrency check calls that listing at the top of every generate, one bad row took generation down completely, and restarting could not clear it.
This server cannot be deployed
Maintenance
Related MCP Connectors
MCP server for Pixapi: check live credit pricing and balance, then generate images and video.
Google Ads MCP server — manage campaigns, keywords, and metrics.
MCP server for QPost — lets AI agents publish video and image posts to YouTube, TikTok, Instagram.
Focused MCP server for OpenAI image/audio generation (v2.0.0). Wraps endpoints via HAPI CLI.
Related MCP Servers
- AlicenseAqualityDmaintenanceMCP server for MarkItUp's AI image-annotation pipeline. Generate polished marketing-visual variations of any screenshot, regenerate, AI outpaint, and remove backgrounds — powered by Claude analysis + Gemini rendering.543 npm2MIT
- FlicenseNot gradedqualityDmaintenanceA full-featured image processing MCP server for AI assistants, exposing ~55 tools across 11 categories for editing, layers, conversion, AI segmentation/cleanup/generation, design analysis, and screenshot-to-code.-
- FlicenseAqualityDmaintenanceMCP server that wraps the Meta Marketing API (Graph API v25.0) as semantic tools for LLM agents.181-
- AlicenseNot gradedqualityDmaintenanceMCP server for Meta/Facebook Marketing API allowing you to view and manage ad accounts, campaigns, ad sets, ads, and creatives, as well as fetch insights and upload ad images.MIT