skills/create-mcp-app/SKILL.md
Use when the user is building a brand-new paid MCP server from zero — no existing server in play. The two entry points: (1) the user has an OpenAPI or Swagger spec they want converted into monetized MCP tools, or (2) they want to write the tools by hand on a fresh SolvaPay-wired scaffold. Also use for the `npm create solvapay` CLI command with `--type mcp`. This skill covers the full greenfield journey: spec parsing, tool authoring, Cloudflare Workers deployment, and SolvaPay paywall setup on a new codebase. Skip when the user already has a running MCP server and wants to add a paywall without rebuilding — use the existing-server skill. Skip for web checkout pages, Lovable flows, and SDK-only integrations.
npx skillsauth add solvapay/skills create-mcp-appInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
SolvaPay-monetized MCP server on Cloudflare Workers. OpenAPI auto-generation or hand-written tools.
Human at a terminal?
npm create solvapay@latest <name> -- --type mcp(use@latest). Ships from-openapi (one-to-one) and from-scratch modes, runs install +solvapay initin one pass.Agent?
scripts/describe.mjs+scripts/scaffold.mjsper references/from-openapi/guide.md. Intent-driven clustering and hand-tuned narration require an LLM — the CLI cannot authorsrc/tools/*.ts. Internal dev runs use the same agent path with--devandcreate-solvapay@preview.
This skill covers any MCP server whose tools return text or structuredContent — data, intelligence and analytics, search and retrieval, integrations with external APIs, actions and workflows, computations, content generation. Domain-agnostic.
The only UI this skill ships is SolvaPay's built-in checkout / account / topup widget, which mounts only when the user deliberately invokes an intent tool (upgrade / topup / manage_account). For custom graphical widgets, keep this skill for server + paywall wiring and add references/mcp-apps-ui.md.
SOLVAPAY_SECRET_KEY to client code, public env vars, or deploy-time plaintext. Upload via npx wrangler secret put and keep it in a gitignored .env only for local dev.upgrade, topup, manage_account, activate_plan, check_purchase) with payable.mcp() — they are the paywall recovery path, not paid business logic._meta.ui.resourceUri on merchant payable tools. Hosts MUST open the iframe on every advertised call (SEP-1865), which flashes an empty widget on silent successes.mode: 'json-stateless' on stateless edge runtimes (Cloudflare Workers, Deno, Supabase Edge).hideToolsByAudience: ['ui'].SOLVAPAY_PRODUCT_REF after solvapay init; under --yes / non-TTY, never treat an auto-picked product as final until the user confirms it belongs to this MCP.selections.plans[] is validated during scaffold but is not created by scaffold.scripts/deploy.mjs, wrangler.jsonc [vars], .env) and never open or edit src/worker.ts — not for imports, CORS, Env, the canonical template, or "stale API shape" patches. Note any API drift in the handoff as a follow-up. Exception: paywall-wiring tasks ("add SolvaPay paywall to my existing MCP server") do edit src/worker.ts — see references/existing-server.md.npx wrangler whoami first (not just wrangler login) to confirm auth and print the *.workers.dev subdomain.@solvapay is not a valid package — use subpaths (@solvapay/mcp, @solvapay/mcp/fetch, etc.).ctx.registerPayable(name, config) takes exactly two arguments — not (toolDef, paymentConfig, handler).c.respond(data, { text: narration }) — never raw content arrays from paid handlers.node scripts/describe.mjs against a local spec file — fetch URLs to /tmp/spec-*.json first; don't pass URLs directly.describe.mjs, grep the original spec for multipart/form-data, application/octet-stream, image/, and application/pdf under requestBody.content and response content. For each matching operation (e.g. uploadFile, uploadImage), set tier: "skip" in selections.json — MCP tools return text, not file streams, so these can't be wrapped usefully.servers must be resolved before scaffold. Confirm the upstream base URL with the user, and watch for path-prefix outliers (e.g. /apifhir/... among /api/fhir/...) before generating tools.selections.json must live outside the scaffold target dir (e.g. /tmp/selections-<uuid>.json) — upstream API keys must not land in the project tree.scripts/describe.mjs and scripts/scaffold.mjs in this skill are wrappers — see scripts/README.md for resolution order.Before writing tool code:
registerPayable shape, response contract.selections.json preview) before executing any gate.Do not write registerPayable(...), additionalTools, or src/tools/* until all required files are loaded.
Before any other gate, ask how chatty you should be. See references/hitl-conventions.md.
"How chatty should I be?
standard(default) confirms each big decision;autoonly confirms irreversible steps (scaffold, deploy, go-live);chattyreviews every intent and file."
1. Existing paid-MCP project? All of: @solvapay/mcp or @solvapay/server in package.json, wrangler.jsonc, and src/worker.ts with createSolvaPayMcpFetch / createSolvaPayMcpServer → references/from-scratch/scaffold-and-extend.md. Do not scaffold.
2. Greenfield — ask once: "OpenAPI/Swagger spec, or hand-written tools?"
| Answer | Guide | Validator |
| --- | --- | --- |
| Has spec (agent) | references/from-openapi/guide.md | validate-selections.mjs → scaffold → verify |
| Hand-written / new | references/from-scratch/guide.md | wrangler dev smoke |
| Existing MCP server (add paywall) | references/existing-server.md | tool invocation smoke |
Inside an unrelated app repo: if cwd is a Next.js app, backend, or monorepo without a paid-MCP server in scope, stop and ask where the MCP server should live before scaffolding (sibling dir or apps/ / packages/ subdirectory).
Dev mode (internal testing only). Use preview tooling and append
--devwhen testing against api-dev:npm create solvapay@preview <name> -- --type mcp --dev,node scripts/describe.mjs --dev ...,node scripts/scaffold.mjs --dev ..., andnpx -y solvapay@preview init --dev. Never for end users.
3. Host: default Cloudflare → references/hosting/cloudflare/README.md. Other hosts → references/hosting/alternatives.md. Optional custom MCP UI → references/mcp-apps-ui.md.
4. Credentials: after scaffold → references/solvapay-init.md (npx -y solvapay@latest init).
Human CLI shortcut (terminal only): see the human block at the top of this file.
describe.mjs → author selections.json → validate-selections.mjs (loop until pass) → scaffold.mjs <selections> <target-dir> → author tools per references/tool-design.md → solvapay init → confirm product/plan → verify → test → deploy. SOLVAPAY_SECRET_KEY is set by solvapay init, never in selections.json. Full G0–G9 HITL gates: references/hitl-conventions.md.
| Script | Action | Purpose |
| --- | --- | --- |
| scripts/describe.mjs | Run | Parse OpenAPI spec |
| scripts/validate-selections.mjs | Run | Validate selections.json before scaffold |
| scripts/scaffold.mjs | Run | Generate worker from selections |
| scripts/README.md | See | Resolution order, upstream --help |
wrangler dev, or guide checklist).## MCP app handoff
- **Input mode:** from-openapi / from-scratch / existing-server
- **Host:** Cloudflare / alternative
- **Worker URL:** [url]
- **Tools authored:** [list]
- **Gates cleared:** G0–G[n]
- **Product ref:** [prd_... + how it was confirmed]
- **Plan / metering status:** [free default / usage-based plan verified / needs user action]
- **Sandbox:** [success path + gate path verified; note skipped checks explicitly]
- **Paid-path verification:** [paywallGate / merchantBootstrap / upstream smoke: passed, skipped, or not run]
- **Known gaps:** [if any]
tools
Use when building a checkout or upgrade flow on an existing website: user clicks subscribe or upgrade → server creates a SolvaPay session → browser redirects to SolvaPay's hosted payment page → returns to your site with access unlocked. Also use for adding a customer portal so subscribers can manage, upgrade, or cancel their plan after checkout. Covers Next.js fully; React without a server framework is partial. Skip for: embedding plan cards or billing dashboards, webhook processing, usage metering, Lovable or Vite+Supabase setups, or MCP tool paywalls.
tools
Load when SolvaPay functionality needs to be coded into an app. Handles: billing UI (buttons, plan status, React components) in React dashboards, web apps, or MCP server UIs; paywalls, access gates, or usage limits on routes or handlers; SolvaPay fetch handler or webhook setup; SDK integration across Next.js, React, Express, Supabase edge functions, and MCP servers. Skip for greenfield MCP scaffolding, Lovable checkout, or redirect-only checkout with no SDK code.
tools
Load when someone is adding SolvaPay to a Lovable app or Vite+Supabase project — especially when they want to install @solvapay/react-supabase @preview packages, paste checkout code into Lovable chat, wire Supabase edge function secrets, or use api-dev.solvapay.com. Also triggers for: keeping SOLVAPAY_SECRET_KEY out of VITE_ env vars, setting up SolvaPayProvider, or getting a paywall running on Lovable fast. This skill handles the full setup: @preview package install, edge function templates, provider wiring, and sandbox testing. Skip for Next.js projects, production solvapay.com deployments, MCP server setup, or general "which SolvaPay product" questions.
tools
Use when work should span one or more detached tasks but still behave like one job with a single owner context. TaskFlow is the durable flow substrate under authoring layers like Lobster, ACPX, plugins, or plain code. Keep conditional logic in the caller; use TaskFlow for flow identity, child-task linkage, waiting state, revision-checked mutations, and user-facing emergence.