wovain
Provides tools for building a Meta Advantage+ sales campaign as a Meta draft, creating five automated rules in Meta, and launching the campaign (Launch requires a payment method on the ad account).
This server does not currently have a deployable release on Glama. Follow the repository's setup instructions to install and configure it for your MCP client, including any required credentials and local dependencies.
wovain
A Qloo-powered agentic print-on-demand app for independent designers. Qloo finds who would buy and what else they love, Tavily finds why now and checks the evidence, NVIDIA Nemotron on Nebius Token Factory writes and judges the drop, and you approve the Fourthwall products and a paused Meta campaign.
Video: https://youtu.be/s-vzNtS2V_U
Demo for the Nebius x NVIDIA Global AI Hackathon: https://nebius.wovain.com, a build frozen for judging. It runs the same code and Nemotron models as next.wovain.com.
Demo: https://next.wovain.com (the hackathon build; see Demo login)
Production: https://wovain.com runs the 2026-10-27 build, frozen for another hackathon's judging until 2026-11-16. The features this README marks "on next" are not on it.
Docs: https://docs.wovain.com, or
apps/fumadocslocallyLicense: MIT
The seller flow runs on the website and in ChatGPT, both backed by one Next.js 16 app:
Qloo taste graph → Tavily evidence → you pick ideas → Nemotron brief → fal draws the art → the Nemotron judge looks at it → you approve → Fourthwall products → Nemotron ad copy → a paused Meta campaign targeted from Qloo demographics.
Vision
wovain is apparel on demand for brands and big companies, starting with solo sellers. A brand that can measure what each audience segment loves can run many small drops, one per segment, and make each piece only when someone orders it. Today wovain is print-on-demand for solo sellers and small labels.
Related MCP server: autowhisper-mcp
Demo login
Judges share one ready account on next.wovain.com:
Sign in with
judges@wovain.comand the password in the Devpost testing instructions.You land on the overview. Its Start here checklist shows what's left: the brand is set, and the agent drafts only (hidden products, paused campaigns) within a $5 daily spend cap.
On Billing, redeem the judges' code from the Devpost testing instructions if the credits aren't there yet. It works only on this account and covers about 17 full drops.
The password and the code are never in this repository. The owner seeds the account with pnpm --filter @wovain/auth seed:judges --env next (infra/README.md).
A 3-minute path:
New drop. Type a brief that names something Qloo knows, for example "Studio Ghibli", and start the run.
Ideas. Each idea card has a "Why this idea" panel with the Qloo entities, tag, affinities and style cues behind it, plus the Tavily sources, competitor prices and an on-demand research dossier. Tick two ideas and press See designs.
Designs. Each design shows the judge's verdict, the checks the vision model ran on the drawn art, and any trademark findings with links. Approve one.
Products and ads. wovain lists the approved design on Fourthwall, writes the ad variants and stages a paused Meta campaign.
Which model did what. In Runs, open the run's Models link (
/dashboard/models?run=<id>, "Which model did what") to see every agent call with its Nemotron model, time and result.No Qloo match. Start a brief Qloo can't place, like "asdf qwerty". The run stops with "Qloo found no audience for this brief; try naming a band, film, brand or place", shows suggestions with examples, and offers Write a new brief.
Nemotron on Nebius Token Factory
wovain calls NVIDIA Nemotron on Nebius Token Factory through its OpenAI-compatible endpoint (NEBIUS_BASE_URL, https://api.tokenfactory.nebius.com/v1/) with one key, NEBIUS_API_KEY. The app code holds no model ID. Each one is an env var that Pulumi sets per environment: infra/next/Pulumi.next.yaml for next.wovain.com, infra/Pulumi.prod.yaml for production and dev.
Which model does what
With the model-routing flag on (dev and next.wovain.com; off in production), each agent asks for a job, and the job's env var names the model (packages/core/src/model-router.ts, AGENT_ROLES in packages/mastra/src/mastra/agents/kit.ts):
Job | Env var | Model on next.wovain.com | What runs on it |
Default |
| Nemotron 3.5 Super VL ( | Design brief and listing ( |
Reasoning |
| Nemotron 3 Ultra ( | The design judge's verdict ( |
Vision |
| Nemotron 3.5 Super VL | The judge's eyes. It reads the drawn PNG for a garment or mockup as the subject, a background, cropping, printed words that differ from the brief, and art that disappears on a shirt color |
Fast |
| Nemotron 3.5 Lightning ( | Ad judges (copy quality, Meta policy), Mastra scorers, prompt-injection and PII guardrails |
Safety |
| Nemotron 3.5 Lightning | Mastra moderation on what the merchant publishes |
With the flag off, as in production, every agent uses NEMOTRON_MODEL (Nemotron 3.5 Super VL) and the judge's vision check uses NEMOTRON_VISION_MODEL. The docs chat runs on DOCS_CHAT_MODEL (Nemotron 3.5 Lightning, reasoning_effort: none, at most 400 output tokens, rate limited per visitor).
Every model ID
All of them are set in Pulumi config (infra/next/Pulumi.next.yaml, infra/Pulumi.prod.yaml) and read from the env vars in apps/web/.env.schema. All but the last row are called on Nebius Token Factory.
Env var | Model ID (next.wovain.com, nebius.wovain.com) | Called from |
|
| Every agent when |
|
| The judge's vision check when |
|
|
|
|
|
|
|
|
|
|
|
|
|
| Mastra's moderation processor on what the merchant publishes |
|
| The docs chat ( |
|
| Voice commands ( |
The agent-to-job map is AGENT_ROLES in packages/core/src/agents.ts. The Mastra agents are built once in packages/mastra/src/mastra/agents/kit.ts on an OpenAI-compatible provider pointed at NEBIUS_BASE_URL (services.ts), and every call goes through ask in ask.ts. Each call is a PostHog $ai_generation event with its model, latency, tokens and cost.
Runtime calls in one run
Qloo names the audience and its themes.
Tavily Search (news and marketplaces) and Tavily Extract (competitor listings) run live for each theme (
trends.ts,evidence.ts). Lightning pulls the search terms out of the brief first (brief_terms).Super VL names each idea from that evidence (
idea_words) and writes the brief (design_brief).fal draws the art. Super VL looks at the PNG (
design_vision) and Ultra gives the verdict (design_judge). Tavily searches every printed phrase for trademarks.Super VL writes the ad copy. Lightning runs the ad judges, the guardrails and moderation on it.
Research this idea adds a Tavily Research task per idea. See Tavily.
What the agents do
Brief, judge and ad copy. The brief writer turns an approved idea into a design brief and a listing. The judge returns a Zod-validated
readyorreviseverdict, a 0 to 100 score and up to five fixes. Arevisedesign is redrawn once from the fixes at no extra credit; if it fails again, the card lists the failed checks. Code decides the print size and overrides the model.Grounding guard. Ad copy and listing text may only state numbers and claims (prices, percentages, "best-selling", "#1") that appear in what the tools returned. An answer that breaks the rule goes back once with the problem named, and a second miss fails the step with
UNGROUNDED_CLAIM(grounding.ts).Guardrails. Web text from Tavily is untrusted. Before the brief writer reads it, a prompt-injection detector blocks injected instructions and a PII detector blocks personal data. Ad copy is moderated and checked for PII on the way out (
agents.ts).Ad scores. The fast model runs the binary ad judges on every variant. The share of passes is the ad score on the Insights page.
Autopilot. With autopilot on, Nemotron picks the idea and approves or rejects the design, each with a stored reason. Code still gates the run: a design the judge sent back is never approved, the price keeps at least $10 profit and a 30% margin, the daily budget stays between $1 and $500, and every Meta object is created paused.
Trace. Every agent call and guard check of a run goes into its decision trace with the agent, model, duration and result. Only the input's field names are stored, never their values.
/dashboard/models?run=<id>shows the trace, linked from Runs.Evals.
pnpm --filter @wovain/mastra run evalschecks the six judges against a labeled set (judges.v1.json). On 2026-10-28,nemotron-3-super-120b-a12band Nemotron 3.5 Super VL both agreed with all 20 scored labels. With a set this small, that is a smoke test.
Media buying
Built and tested, but not run against a live Meta account in the demo: the judge account has no Meta connection.
Campaign build.
stagePausedCampaigninpackages/core/src/ads.tsbuilds the campaign, ad sets, creatives and ads through Meta's Ads MCP (ads_create_campaign,ads_create_ad_set,ads_create_creative,ads_create_ad), every object paused. The drop's flow iscreateDropCampaigninpackages/mastra/src/mastra/flow/campaigns.ts.Qloo targeting (#161, #347). The idea's Qloo audience sets the ad sets' ages, gender and interests and the copy's persona (
packages/mastra/src/mastra/flow/audiences.ts). It falls back to the brand's, then the brief's; with none, the ads go broad. A failed targeting step still refuses the campaign.Pixel (#212). On the merchant's single Meta grant, wovain finds or creates the pixel (dataset), shares it with the ad account and sends a Conversions API test event (
packages/mastra/src/mastra/flow/pixel-setup.ts,packages/core/src/pixel-setup.ts, flagmeta-pixel-automation).Spend rules (#141). Every 30 minutes (
packages/core/src/ad-rules.ts,packages/mastra/src/mastra/flow/ad-rules.ts, flagads-profit-rules): the stops pause every campaign at the daily cap, the monthly cap or the loss limit ($50 by default: ad spend minus the profit of its sales); the kills pause an ad that spends its target cost per sale with no sale, or breaks the cost-per-click or click-through limits; a raise adds at most 20% to the daily budget after 3 purchases at 1.3 times break-even ROAS, at most every 48 hours.Meta backstop (#215). The kill and stop rules are mirrored into the ad account's Automated Rules (
packages/core/src/meta-backstop.ts,packages/mastra/src/mastra/flow/backstop.ts, flagmeta-backstop-rules), so Meta pauses spend even when wovain is down.Nemotron agents. Super VL writes the ad copy (
writeAdCopy, Default job); Lightning runs the ad judges (ad_judge, Fast job); Ultra reviews the optimizer's proposals (ads_optimizer_review) and makes autopilot's calls (Reasoning job).
Where Token Factory helped
One endpoint and one key serve Super VL, Ultra and Lightning, so routing by job is a config change per environment.
The vision model takes an https image URL, so the judge reads the fal-hosted PNG without a re-upload.
Strict
response_format: json_schemaworks on Super VL, so the judge, the brief and the ad copy come back as validated JSON./v1/modelslists each model'ssupported_features(tools, reasoning). That made it quick to confirm replacements for the two models Nebius removes on 2026-11-09,nemotron-3-super-120b-a12bandNVIDIA-Nemotron-3-Nano-30B-A3B, both of which wovain used.Token Factory serves no Nemotron content-safety model yet (checked 2026-10-28), so moderation runs on Lightning through Mastra's moderation processor.
Details: Nebius and Nemotron.
Qloo-powered
Qloo's taste graph decides what a drop is about and who its ads reach. Every idea is a Qloo taste tag, so without Qloo there are no ideas: no Qloo, no run. On next.wovain.com every run calls Qloo, whatever the plan. The trends-qloo flag is only an ops kill switch: when it is off, runs.start and ideas.research refuse with QLOO_OFF (503), and no run starts. The cross-domain taste map and the "Why this idea" panel are in every run. Today's flow, from Qloo's audience to the ads:
What is rising. For an apparel-relevant Qloo audience, Qloo names the artists and TV shows rising with it.
Tags, then themes. The tags those rising entities share become the drop's theme and its style cues.
Who buys. Qloo's age and gender affinity, the audiences that like the idea most, their cities and the fashion brands they already buy.
Capsule style. The Qloo tag IDs of the idea pick the capsule's style family and product mix.
Ad targeting. Every Meta ad set targets the idea's Qloo audience first, then the brand's, then the brief's: ages, gender and Meta interests, and the ad copy's persona.
Without Qloo there is no run. A brief Qloo can't place stops with QLOO_NO_MATCH. A failed audience step stops the campaign: campaigns.create refuses with QLOO_AUDIENCE_MISSING and stages nothing. Only when there is no audience at all (no idea audience, brand or brief) do the ads go broad, with the targeting marked as a fallback; a missing brand never blocks the ads.
Endpoints
Every call goes to QLOO_API_URL (https://hackathon.api.qloo.com) from packages/core/src/qloo.ts.
Call | Parameters | What wovain does with the result |
| the brief, top 3, all entity types | Resolves the brief to seed entities (artists, films, books, brands, TV, podcasts, games) |
|
| The tags those fans share become the themes Tavily researches. Each idea keeps its tag and affinity, and the affinity is 30% of the idea's score ( |
|
| Cross-domain affinities, with the share each seed entity contributed. Their style and mood tags go into the design brief, and their names never do ( |
|
| Age and gender affinity of the brand's Qloo entities, mapped to the Meta ad set's |
|
| Scores 27 apparel-relevant |
| one taste reference, top 1 | Brand onboarding resolves each reference the designer names to a Qloo entity ( |
|
| Autopilot's scan: brands rising with the brand's audience ( |
A failed theme call (/search or the tag insights) fails the research step with QLOO_FAILED. The step retries, then the run fails and is logged at error level to PostHog Error Tracking. Nothing stands in for Qloo. A failed cross-domain, demographics or audience call is logged at error level, marked failed on the idea or in the run's decision trace, and left out. The "Why this idea" panel (taste-map.tsx) names any domain whose call failed.
Why wovain needs Qloo
Each Qloo call decides one part of a drop, and nothing else in wovain stands in for it:
/search: who the brief is about. Qloo resolves the brief to up to 3 seed entities. When it matches nothing, the run stops withQLOO_NO_MATCH(422): "Qloo found no audience for this brief; try naming a band, film, brand or place". The wizard shows suggestions with examples and a Write a new brief button. wovain never makes up ideas instead.Tag insights: what the drop is about. Each idea is one of Qloo's taste tags for the seed's fans, up to 3 per run (
RUN_THEMES,qlooThemes). Fewer than 3 tags means fewer ideas, never made-up ones. The tag's name is the idea's title.Tag affinity: which idea ranks first. Each tag's affinity is the demand term, 30% of the idea's score (
score.ts). A tag with no affinity is never searched or suggested, and no neutral value stands in for it. The feedback loop re-weights these terms from sales, but it doesn't choose the themes.Seed names: what never goes on a product. The names Qloo matched are saved on each idea as names never to print, and they lower its IP-safety score.
Cross-domain affinities: how the art looks. In every run, Qloo names the brands, films and TV the seed's fans also like, with each seed entity's share. Their style and mood tags go into the design brief as cues, never their names (
design.ts). The "Why this idea" panel shows them, and the Tavily research dossier gets them asqloo-taste.json.Tags: the drop's style family. The Qloo tags of the run's ideas, then the brand's niches, pick a drop's style family and its product mix (
drops.ts).Onboarding
/search: the brand's taste. The references a designer names become the brand's Qloo entities (onboarding.ts). Ads and autopilot start from them.Demographics and audiences: who the ads reach. Qloo's age and gender affinity sets the Meta ad set's ages and gender, and its audiences become Meta interests and the ad writer's persona (
targeting.ts,qloo-audiences.ts).Rising brands: when autopilot suggests a drop. Qloo names the brands rising with the brand's audience. When this week's news talks about one, autopilot suggests a drop (
autopilot-signals.ts).
Tavily only adds evidence to Qloo's themes: news, marketplace listings, prices and research dossiers (trends.ts). It never names a theme. With trends-tavily off, research returns no ideas.
The comparison with an LLM-only run is an offline eval only. The product has no run without Qloo. qloo-ablation.eval.ts runs 8 seeds through the app's Qloo theme step and through an eval-only LLM arm (llm-themes.ts). It reports each arm's grounding, explanation, cue count and distance from the seed, plus the themes the two arms share. Run it with pnpm --filter @wovain/mastra run evals. It needs QLOO_API_KEY, NEBIUS_API_KEY and NEMOTRON_MODEL, and writes packages/mastra/src/mastra/evals/qloo-ablation.report.v1.json.
A live trace
The first calls for the brief "Studio Ghibli", run on 2026-10-28. The key is redacted, entity IDs are shortened, and the timings are as measured:
GET /search?query=Studio Ghibli&take=3&types=urn:entity:artist,…,urn:entity:videogame 200 1536 ms
→ Studio Ghibli (artist), Studio Ghibli: The Films of Hayao Miyazaki and Isao Takahata (book),
Sharing a House with the Never-Ending Man: 15 Years at Studio Ghibli (book)
GET /v2/insights?filter.type=urn:tag&filter.tag.types=urn:tag:genre:media,urn:tag:genre:music,urn:tag:keyword:media
&signal.interests.entities=D1222FA1…,6E9076C7…,832C1302…&take=10&bias.trends=low 200 252 ms
→ J-pop 1.00 · anime 1.00 · J-rock 1.00 · Video-Game Music 0.99 · soundtrack 0.99 · Visual-kei 0.98
GET /v2/insights?filter.type=urn:entity:movie&feature.explainability=true&bias.trends=low&take=3 … 200 1624 ms
→ Wolfwalkers 0.81, because: Studio Ghibli 35% · the Ghibli films book 33% · the Ghibli memoir 32%
cues sent to the brief: Atmospheric, Adventure, Two tone visual dichotomy
GET /v2/insights?filter.type=urn:entity:tv_show&feature.explainability=true&bias.trends=low&take=3 … 200 711 ms
→ The Underground Railroad 0.85, Old Enough! 0.85, 63 Up 0.85
cues: Magical realism, Close up intimacy, Childs eye perspective, Minimalist interview framing
GET /v2/insights?filter.type=urn:entity:brand&feature.explainability=true&bias.trends=low&take=3 … 200 383 ms
→ Vulture 0.83, MacRumors 0.83, Wired 0.83 · cues: Witty, Insightful, Bold, AnalyticalWhat we found working with the hackathon API:
It refuses artist insights from an artist seed, and trend bias for books and games, so the cross-domain affinities are brands, films and TV (no music).
bias.trends=mediumreplaced the Ghibli fans' brands with unrelated trending ones (a medical association, a bank), so wovain useslow./searchtakes the top 3 matches. For "Studio Ghibli", two are books about the studio, which pulls the affinities toward documentaries.Tags carry no explainability, so a theme's "why" is its tag's affinity with the seed entities' fans. The per-entity shares come from the cross-domain affinities.
Audience scores separate brands well (Supreme, Patagonia) but come back flat (0.765) for artists and films, so audiences are scored on brands only.
Qloo's hackathon terms limit it to free and demo plans until 2026-11-05. Only Free is sold (
billing-paid-plansis off everywhere), and paid plans open only with a commercial Qloo licence.
Details: Qloo.
Tavily
Tavily is wovain's live web evidence, called on every run from packages/core/src/trends.ts and packages/core/src/evidence.ts.
Search. Each Qloo theme gets two searches. A news search (
topic: news,time_range: month,search_depth: advanced) finds why the theme matters now. A marketplace search on Etsy, Redbubble, TeePublic and Fourthwall shows how crowded it already is. Code drops results under 0.4 relevance, news older than 31 days and archive or tag pages, then keeps the top 3 sources with their links.Extract. Behind
tavily-evidence(on in development and next), Tavily Extract reads up to 5 competitor listings per theme. Their median price feeds the margin score. When a page fails, the margin falls back to the prices in the search snippets.Research. Research this idea on an idea card starts a Tavily Research task (
TAVILY_RESEARCH_MODEL,mini) with anoutput_schemaof why now, saturation, price band, risks and citations. The idea's Qloo theme and the brand's Qloo entities go in as aqloo-taste.jsonfile. It runs once per idea and costs the merchant no credits.Trademark check. Every phrase printed on a design is searched as an exact phrase on uspto.gov, trademarkia, Justia trademarks and EUIPO, and on the marketplaces. A register page whose title carries the phrase fails the judge's
trademarkrule, and the redraw rewrites the words. A marketplace match shows as a caution with its link.
Guardrails:
Each search settles on its own. A failed search is logged at error level, the idea stands on the other one, and the card says which search failed. The step fails, and refunds the credit, only when every search fails.
The trademark check fails closed. A phrase that couldn't be checked holds the design at
revise, and the merchant decides.Everything Tavily returns is kept as data. The prompt-injection and PII guardrails read it before the brief writer does, and the grounding guard stops ad copy from stating a number Tavily didn't return.
Details: Tavily.
Limitations
Two builds. wovain.com stays on the 2026-10-27 build until 2026-11-16. Everything this README describes past that build runs on next.wovain.com only, behind flags that are on in development and next and off in production.
Spend only through approvals. Meta campaigns are staged paused. With
media-buying-live, a campaign starts only when the merchant approves it inside their daily and monthly caps; the demo account's cap is $5 a day and its autonomy level drafts only. The ads optimizer proposes reallocations through the same queue and never moves money on its own.No mobile app yet. The Expo app (#86) is not merged: its dependencies need a license exception for
react-nativeand an OSV decision on the zod 3 that@expo/clipulls in. Voice input works on the web only.Meta interest search is untested live. wovain calls Graph
search?type=adinterestwith the app token. If Meta refuses it, the step fails visibly and the ad set keeps Qloo's ages and gender.fal. With the onboarding wizard on, designs draw on wovain's own fal key and the design's credits pay for them; without it, each merchant connects their own fal account. Voice commands always transcribe on wovain's key.
Feedback needs history. The feedback loop and the ads optimizer learn from sales and ad results, so a new account starts on the default weights.
Small evals. The judge set has 20 scored cases. The Qloo ablation report and a judge run on the routed models (Ultra, Lightning) are not in the repo yet, because both need the provider keys.
Ultra's latency. Nemotron 3 Ultra must answer within the 90 s agent timeout. If it doesn't,
nemotronModelReasoningon next goes back to Super VL, which is a config change.Tavily images. The news search returns images, and wovain doesn't use them yet.
Durable runs. On next, every run uses the Mastra workflow on Inngest (#218). The earlier engine stays as the fallback and runs the same steps.
What changed since Aug 26 / Sep 30
The repository's first commit is from 2026-10-06. All of wovain was built after the Nebius submission period opened (2026-08-26) and after the Qloo period opened (2026-09-30).
Dates | What shipped |
Oct 19–23 | The first MCP app for ChatGPT: ideas, designs, Fourthwall products and ad concepts. Qloo taste signals and Tavily search in trend research. The design judge and autopilot on Nemotron through Nebius. Fourthwall, fal and Meta connections, with grants sealed by Cloud KMS |
Oct 25–26 | The web app on Cloud Run and Cloud SQL, with Better Auth, Google sign-in and email verification. The seller flow as oRPC procedures and MCP tools. Mastra agents with scorers, guardrails, memory and tracing, and runs as a durable Mastra workflow on Inngest. Credits and the Polar catalog (Free only). The docs site in en, es and fr with a Nemotron docs chat. The Build With AI: Basics submission (tag |
Oct 27 | Development moved to GitHub: Actions CI, Dependabot, and PostHog feature flags managed by Pulumi |
Oct 28 | Model IDs as env vars per environment, ahead of Nebius's 2026-11-09 removals (#28). The judge looks at the drawn art (#23). Designs only for the ideas the merchant approves (#21). next.wovain.com in its own Pulumi stack (#25, #57). Autonomy levels, one approval queue and decision traces (#60). Nemotron routing by job, the grounding guard, real ad scores and the models page (#74). The Qloo taste map with explainability, cross-domain cues and the LLM-only ablation (#79). Qloo demographics and audiences driving Meta targeting and the ad persona (#75). Tavily as the evidence layer: per-search failures, competitor prices, research dossiers and the trademark check (#73). SAST, dependency, license, secret and SBOM scanning (#61). The onboarding wizard (#76), scheduled autopilot triggers (#78), live media buying through approvals (#72), the ads optimizer (#70), the feedback loop (#83), voice input (#85), store management (#87), design drops (#91) and the judges' demo account (#97) |
Oct 29–30 | The Mastra layer in its own package, with the seller flow and workflows (#231, #245). What to sell now, with or without a brand (#140). Who buys this and where, from Qloo (#154). One idea card with an evidence gate and a track-record rank (#203, #214, #256). Tavily's competitive landscape per Qloo theme (#108) and research on every key concept of a brief (#253). Guided brand discovery (#117). Learning from real design outcomes (#202). Meta automated rules and the Meta pixel (#212, #215). Alerts by email, push and Telegram (#204). Dictation in text fields (#208). End-to-end, contract and Storybook tests (#226, #230, #242). A run fails at once when a provider is out of credits (#266) |
Setup from a clean clone
You need Node.js (the version in .nvmrc), pnpm and Docker.
git clone https://github.com/sami-m-g/wovain.git && cd wovain
pnpm run db:start # PostgreSQL in Docker: user postgres, password "password", database wovainVarlock validates every variable in apps/web/.env.schema at start-up, and the per-environment settings have no defaults. Write apps/web/.env.local with local values. CI uses the same ones (.github/workflows/ci.yml):
fixture() { node --input-type=module -e "const m = await import('$1'); console.log(JSON.stringify(m['$2']))"; }
{
echo "BETTER_AUTH_SECRET=$(openssl rand -hex 32)"
echo "BETTER_AUTH_URL=http://localhost:3001"
echo "DATABASE_URL=postgresql://postgres:password@localhost:5432/wovain"
echo "TOKEN_ENCRYPTION_KEY=$(openssl rand -base64 32)"
echo "BILLING_CATALOG=$(fixture ./packages/billing/src/catalog-fixture.ts TEST_CATALOG)"
echo "PRICING_RULES=$(fixture ./packages/core/src/config-fixture.ts TEST_PRICING_RULES)"
echo "DOCS_URL=http://localhost:4000"
echo "MCP_URL=http://localhost:3001/api/mcp"
echo "EMAIL_FROM=wovain <dev@example.com>"
echo "SUPPORT_EMAIL=support@example.com"
echo "PRIVACY_EMAIL=privacy@example.com"
echo "FAL_MCP_URL=https://mcp.fal.ai/mcp-relay"
echo "FOURTHWALL_MCP_URL=https://mcp.fourthwall.com/app"
echo "FOURTHWALL_DEFAULT_PRODUCT_ID=pro_8be1acca2fe7403f89"
echo "META_MCP_URL=https://mcp.facebook.com/ads"
echo "META_MCP_SCOPE=ads_read"
echo "MCP_WIDGET_RESOURCE_DOMAINS=https://fal.media"
echo "GUARDRAIL_INJECTION_THRESHOLD=0.8"
echo "GUARDRAIL_MODERATION_THRESHOLD=0.7"
echo "GUARDRAIL_PII_THRESHOLD=0.7"
echo "NEMOTRON_INPUT_PRICE=0.3"
echo "NEMOTRON_OUTPUT_PRICE=0.9"
echo "INNGEST_DEV=1"
echo "NEBIUS_API_KEY=" # runs need all three provider keys
echo "QLOO_API_KEY="
echo "TAVILY_API_KEY="
} > apps/web/.env.localThen install, migrate and start:
pnpm install # also generates the typed env from the schema
pnpm run db:migrate
pnpm run dev:web # http://localhost:3001
npx inngest-cli@latest dev -u http://localhost:3001/api/inngest # second terminal; runs need itThe model IDs, the fal image model and the Tavily Research model have local defaults in
.env.schema.Without
RESEND_API_KEY, the verification email goes to the dev server's log. Open its link to finish signing up.Fourthwall, fal and Meta connect through OAuth on the Connections page. Meta needs
META_APP_IDandMETA_APP_SECRET, and Google sign-in needsGOOGLE_CLIENT_IDandGOOGLE_CLIENT_SECRET.Feature flags fall back to the registry in
packages/core/src/flag-registry.ts, where every workstream flag is on in development.The docs site (
pnpm run dev, port 4000) needs onlyNEBIUS_API_KEY, for its chat.
Tests and checks: pnpm run test, pnpm run check, pnpm run check-types, pnpm run knip and pnpm run spec:validate.
Local hooks stay light. Pre-commit formats and lints the staged files with Ultracite, commit-msg runs commitlint, and pre-push type-checks only the affected packages (turbo run check-types --affected). The heavy suites run in CI and on demand:
pnpm test: unit and integration tests.pnpm test:e2e: end-to-end tests (the script lands with the E2E suite).pnpm storybook: Storybook (the script lands with the Storybook setup).pnpm run knip: unused code, CI only.
Architecture
Path | Role |
| Next.js 16 app (App Router, oRPC, Better Auth, evlog); the ChatGPT MCP server is |
| Documentation site |
| oRPC routers, seller-flow steps and the MCP server |
| Providers and rules: Qloo, Tavily, Nemotron, fal, pricing, judge, autopilot |
| Better Auth configuration |
| Drizzle schema and client for PostgreSQL (Cloud SQL on GCP) |
| Shared shadcn/ui components |
Hackathons
See the Hackathons page for where each requirement is met.
License
Deployment
Infrastructure is code in infra/ and runs on Google Cloud, with Workload Identity Federation and no stored key:
pulumi upappliesinfra/after a guarded, policy-checked preview (see infra/README.md): Cloud Run serviceswovain-webandwovain-docs, Cloud SQL Postgreswovain, Artifact Registry, Secret Manager, the wovain.com zone's records and domain mappings, Search Console verification, Resend's sending domain.Both images are pushed to Artifact Registry.
drizzle-kit migrateruns against Cloud SQL throughcloud-sql-proxy.gcloud run deployrolls the images out.
Host | Serves |
| apps/web ( |
| the MCP endpoint ChatGPT connects to |
| apps/fumadocs |
| apps/web from main ( |
Secrets live in Secret Manager under kebab-case ids (better-auth-secret is BETTER_AUTH_SECRET). A secret gets a value from the stack config, pulumi config set --secret <id> in infra/, and Cloud Run mounts only the secrets that have one. Pulumi generates database-url, better-auth-secret and token-encryption-key itself. A local pulumi up needs the Site Verification scope: gcloud auth application-default login --scopes=https://www.googleapis.com/auth/cloud-platform,https://www.googleapis.com/auth/userinfo.email,https://www.googleapis.com/auth/siteverification. Logs are JSON lines on stdout (apps/web/src/lib/cloud-logging.ts): Cloud Logging parses them, and Error Reporting groups server errors under wovain-web.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
This server cannot be deployed
Maintenance
Related MCP Connectors
Analyze, edit and launch Meta (Facebook and Instagram) ads from Claude, ChatGPT, Cursor or Codex. Query insights and campaign health, change budgets, bids, status and targeting with undo, bulk-launch many ads across campaigns and ad sets from a live ad's settings, and duplicate by post to keep social proof. Choose per ad account what the agent may do and what waits in the Agent Inbox for approval. Requires a paid Ads Uploader account with MCP access.
Create, write and publish Printify products from chat, after a preview you approve.
Make product photos and ads, and run Meta and Google Ads campaigns, from your AI app.
Generate UGC video ad scripts and render ads with your Promptify credits from any MCP client.
Related MCP Servers
- FlicenseNot gradedqualityDmaintenanceEnables automated generation and publishing of TikTok Shop Affiliate videos using 7 AI agents. Integrates research, script writing, video production, and publishing through the MCP protocol.38-
- AlicenseAqualityBmaintenanceDrives an AI CMO to add products, generate on-brand content (UGC video, posts, images), approve, and publish across 30+ platforms via natural language.277 npmMIT
- AlicenseNot gradedqualityDmaintenanceEnables AI assistants to run a print-on-demand store by creating products on Printify, pricing from production cost, publishing to Shopify and its sales channels, and generating ad creative from mockups.1ISC
- AlicenseNot gradedqualityDmaintenanceEnables users to turn a product brief into a professional ad campaign, generating a validated fal.ai workflow.json with consistent characters, sound, and subtitles while showing costs before any model runs.MIT