revspot-mcp

revspot-mcp

MCP server for Revspot's image generation, exposing DTC-ads tools such as generate_image, show_marketing_studio, and media upload to generate and manage marketing creatives.

Category
访问服务器

README

revspot-mcp

Revspot's image-generation MCP server. It implements the DTC-ads tool surface (generate_image, show_marketing_studio, and friends) so that any client or skill written against that surface works here unchanged.

Run it

npm install
cp .env.example .env.local     # fill in OPENAI_API_KEY at minimum
npm run dev

The server is POST /api/mcp (JSON-RPC, MCP over HTTP). It exposes 13 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            balance

Before you deploy

npm run predeploy

Five checks; non-zero exit on any failure.

widgets:version   widget resource versions consistent
widgets:parse     every widget script parses
widgets:paint     widgets render against a strict host
receipts:diff     request-assembly conformance (see below)
tsc --noEmit      types

widgets:paint needs REVSPOT_BACKEND_URL pointing at a running instance.

receipts:diff — the check that matters

lib/core/dtc-ads/assets/ holds 102 pinned conformance fixtures: for each one, a set of tool parameters and the exact downstream request that surface is expected to produce. The gate rebuilds every fixture through our assembler and requires a byte-for-byte match. Currently 102/102, including the brand-kit path.

This is a golden-file regression suite, and it earns its keep. Code review found nothing; diffing against the fixtures found three real defects in a day:

  • product image URLs emitted as site-relative paths where the spec is absolute, so the model was handed a path fragment instead of an image
  • medias[] accepted and validated, then never read — caller reference images reached neither the payload nor the provider
  • a brand-kit path that sent an opaque UUID while switching on the brand-kit system prompt, telling the model to hold a brand it was never shown

Prefer evidence over inspection. Refresh the fixtures whenever the assembler, catalogue or system prompts change.

Canvas table — read before touching aspect ratios

lib/core/image-generation/openai.ts

The image provider enforces two rules, quoted from its own rejections: both sides divisible by 16, and within a per-resolution pixel budget. The canvas 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 (OBSERVED), or auto. Do not compute one. An earlier invented table produced sizes the provider rejects outright and broke 17 of 45 aspect/resolution combinations.

COMPUTED holds 4:5 only, and is the documented exception. 4:5 is the Meta feed standard, and each of its three sizes is the largest exact-0.8 canvas satisfying the provider's own two rules. They are marked observed: false so a run receipt states plainly that the number rests on arithmetic rather than a measurement. Before this existed, asking for 4:5 silently returned a 1254×1254 square.

Widgets

Three MCP-Apps panels — the generation gallery, the ad-format picker, and 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 this: change the markup without bumping WIDGET_VERSION and the gate fails with the old and new hashes. Bump the constant, commit the regenerated lockfile, and clients refetch.

gate/ — behavioural conformance

Verifies that an agent driving this server chooses the same tools and the same ad templates it would on the reference surface. It deliberately does not compare images: the image model samples, so no surface reproduces its own output.

Latest, Claude driving, 24 briefs:

ours vs reference        24/24  100.0%
reference vs itself      23/24   95.8%   <- the ceiling
ours vs ours             23/24   95.8%

100% is not the target. The reference surface only reproduces itself 95.8% of the time, because template choice over an overlapping catalogue is a judgement call. Start with gate/RUN-IN-FRESH-SESSION.md.

Method note that costs a day if ignored: MCP tool schemas are cached per session, and subagents inherit the cache. After ANY edit to a tool description or parameter doc, re-test from a brand-new session and assert the new wording is actually in the schema the agent received. Testing inside the session that made the change already produced one false negative here.

What is deliberately not here

The earlier Revspot Static Studio tool surface — show_static_studio, create_product_pack, generate_static, list_static_runs — and its prompt-compiler, template and render-spec chain. It collided with the current surface (an agent seeing both generate_image and generate_static picked arbitrarily) and was vertical-locked to real estate, where this surface is vertical-neutral.

NATIVE_TOOL_REPLACEMENT in the route survives it on purpose: clients cache tool lists, so a session opened before the cutover still calls the old names and should be pointed at the current equivalent rather than just failing.

Also dropped: the kie and openrouter image providers. openai is the one measured to produce the correct canvases; kie is a reseller that returns a non-native size.

Naming — what was deliberately left alone

The rename swept the codebase, with four exceptions that are load-bearing rather than cosmetic. Each is commented at its definition:

.prizm-data/                     on-disk data directory
data/prizm-product-packs.json    on-disk store file
prizm_asset_intelligence_v1      persisted schema tag inside records
/prizm-assets/, /prizm-outputs/  legacy URL prefixes, still resolved

The first three exist on any already-deployed volume; renaming them orphans every product pack and run record written before the change. The last two are accepted and rewritten onto assets/ and outputs/ in servedUrlToFilePath, because pack records persist the URL that was current when they were created.

Rename any of them only alongside a migration.

Known open items

  1. Twelve tools on the reference surface that we do not implement. Highest priority are media_import_url and media_upload_widget, which the generate_image documentation names directly — an agent that knows the surface will reach for them and hard-fail. Then show_medias, then the transform tools (upscale_image, reframe, outpaint_image, remove_background), whose absence turns "make it bigger" into a re-generation with different copy.
  2. No brand-kit store. A bare brand_kit_id is refused with an explanatory error rather than silently degraded; an inline brand_kit object works.
  3. No get_cost preflight, so cost cannot be quoted before running.
  4. Generation history has no created_at and no date filter, so "what did I make today" cannot be scoped server-side.
  5. Ambiguous surface: batch_size vs count, url vs scrap_url, image_style aliasing ad_format.
  6. Jobs occasionally accept and sit in queued without starting. Re-submitting clears it; a 15-minute watchdog reaps them. Root cause not diagnosed.
  7. 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 wrong images produced a different building and invalidated a full 18-creative comparison. Verify image by image, not by title or count.
  • style_id has no default and is the dominant creative driver. Its parameter description is load-bearing — wording there changed which templates agents picked. Treat tool descriptions as behaviour, not documentation.
  • Never reconstruct a record from a read that may have missed. A {...(await get(id))!} spread persisted a row with no id and no createdAt; the listing sorted on createdAt.localeCompare and threw. Because activeJobCount() calls that listing at the top of every generate, one bad row took generation down completely, and a restart could not clear it.

推荐服务器

Baidu Map

Baidu Map

百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。

官方
精选
JavaScript
Playwright MCP Server

Playwright MCP Server

一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。

官方
精选
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。

官方
精选
本地
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。

官方
精选
本地
TypeScript
VeyraX

VeyraX

一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。

官方
精选
本地
graphlit-mcp-server

graphlit-mcp-server

模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。

官方
精选
TypeScript
Kagi MCP Server

Kagi MCP Server

一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。

官方
精选
Python
e2b-mcp-server

e2b-mcp-server

使用 MCP 通过 e2b 运行代码。

官方
精选
Neon MCP Server

Neon MCP Server

用于与 Neon 管理 API 和数据库交互的 MCP 服务器

官方
精选
Exa MCP Server

Exa MCP Server

模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。

官方
精选