Create a Paid MCP App
A SolvaPay-monetized MCP server on Cloudflare Workers. Two input modes share the same destination: OpenAPI auto-generation, or hand-written tools.
Human at a terminal? Fastest path: npm create solvapay@latest <name> -- --type mcp (or pnpm/yarn create solvapay@latest). The @latest suffix forces npm to re-resolve the registry every run so you always get the freshest scaffolder. Ships from-openapi (one-to-one) and from-scratch modes, runs install + solvapay init in one pass.
Agent (Claude / Cursor / etc.)? Use the agent path: scripts/describe.mjs + scripts/scaffold.mjs per from-openapi/guide.md. It owns intent-driven clustering, per-operation curation, and hand-tuned narration — none of which the CLI exposes. The CLI cannot author src/tools/*.ts because that authoring step requires an LLM.
Mandatory read order
Before writing any tool code, load these files in order:
- guide.md — routing decision (existing project vs greenfield, input mode, host).
- tool-design.md — the response-mode contract, gate rules,
registerPayable shape.
- Exactly one input-mode guide: from-openapi/guide.md or from-scratch/guide.md or existing-server/guide.md.
Do not write registerPayable(...), additionalTools, or new files under src/tools/ until those three files are loaded. The detailed guardrails live in guide.md and tool-design.md; this block is the entry gate, not a duplicate of them.
tool-design.md is non-negotiable, including when you think you've seen the patterns before. It is the only file that pins down the registerPayable(name, config) two-argument shape, the c.respond(data, { text }) response-mode contract, and the rule that paid handlers never return raw content arrays. Routing past it and authoring tools "from memory" is the single most common failure mode in this skill — the input-mode guides (from-openapi/, from-scratch/, existing-server/) build on it and do not duplicate its contract. If you find yourself about to call registerPayable and you cannot recall those rules verbatim, you have not read tool-design.md; stop and read it.
First-decision routing
Pick one before scaffolding anything:
| Situation |
Action |
Existing mcp-app project (has wrangler.jsonc, src/worker.ts calling createSolvaPayMcpFetch) |
Do not scaffold. Add tools under src/tools/, then run npm run dev and node scripts/verify.mjs http://localhost:8787. |
| Greenfield, human at a terminal |
Run npm create solvapay@latest <name> -- --type mcp (interactive). |
| Greenfield, agent has an OpenAPI / Swagger doc |
Always use the agent path: from-openapi/guide.md with scripts/describe.mjs + scripts/scaffold.mjs. The published npm create solvapay@latest -- --type mcp CLI is for humans at a terminal — it only emits one-to-one tools and cannot author intent-driven dispatchers (those require the LLM). The agent path also supports one-to-one mode via "mode": "one-to-one" in selections.json, so falling back is one flag away. |
| Inside an unrelated app repo with no paid-MCP server in scope |
Ask where the MCP server should live (sibling directory? apps/mcp/?). Do not scaffold into the app root. |
Dev mode (skill author / internal testing only). If the user explicitly says they're testing against the SolvaPay dev backend, append --dev to every published-CLI invocation: npm create solvapay@latest <name> -- --type mcp --dev and npx -y solvapay@latest init --dev. The flag seeds SOLVAPAY_API_BASE_URL=https://api-dev.solvapay.com into .env and routes browser-auth, wrangler dev, deploy preflight, and the deployed worker to api-dev in one pass. Never enable --dev for end users — production keys are rejected by api-dev.
Quick Start
- Read guide.md — the router that picks input mode, host, and sequences scaffold → init → deploy → verify → test.
- Read tool-design.md before writing any tool (load-bearing).
- Follow the chosen input mode end-to-end:
- from-openapi/guide.md — generate from a spec (agent path)
- from-scratch/guide.md — hand-write paid tools after
npm create solvapay@latest -- --type mcp --no-openapi
- existing-server/guide.md — add SolvaPay to an MCP server that already exists
- Wire credentials via solvapay-init.md.
- Deploy to Cloudflare per hosting/cloudflare.md (or hosting/alternatives.md for other hosts).
Pointers
- Router and guardrails: guide.md
- Shared tool-design contract: tool-design.md
- Credential bootstrap: solvapay-init.md
- OpenAPI mode: from-openapi/
- Hand-written mode: from-scratch/
- Existing-server integration: existing-server/
- Host details: hosting/
1---2name: create-mcp-app3description: Create or scaffold a SolvaPay-monetized MCP server on Cloudflare Workers — from OpenAPI / Swagger or from scratch. Use when the user says "create mcp app", "scaffold mcp", "new mcp server", "openapi to mcp", "wrap rest api as mcp", "npm create solvapay", or wants a greenfield paid MCP worker. For humans at a terminal, point to `npm create solvapay@latest my-mcp -- --type mcp`. For agents, use describe.mjs + scaffold.mjs (intent-driven clustering requires an LLM).4---56# Create a Paid MCP App78A SolvaPay-monetized MCP server on Cloudflare Workers. Two input modes share the same destination: OpenAPI auto-generation, or hand-written tools.910> **Human at a terminal?** Fastest path: `npm create solvapay@latest <name> -- --type mcp` (or `pnpm`/`yarn create solvapay@latest`). The `@latest` suffix forces npm to re-resolve the registry every run so you always get the freshest scaffolder. Ships from-openapi (one-to-one) and from-scratch modes, runs install + `solvapay init` in one pass.11>12> **Agent (Claude / Cursor / etc.)?** Use the agent path: `scripts/describe.mjs` + `scripts/scaffold.mjs` per [from-openapi/guide.md](from-openapi/guide.md). It owns intent-driven clustering, per-operation curation, and hand-tuned narration — none of which the CLI exposes. The CLI cannot author `src/tools/*.ts` because that authoring step requires an LLM.1314## Mandatory read order1516Before writing any tool code, load these files in order:17181. [guide.md](guide.md) — routing decision (existing project vs greenfield, input mode, host).192. [tool-design.md](tool-design.md) — the response-mode contract, gate rules, `registerPayable` shape.203. Exactly one input-mode guide: [from-openapi/guide.md](from-openapi/guide.md) **or** [from-scratch/guide.md](from-scratch/guide.md) **or** [existing-server/guide.md](existing-server/guide.md).2122Do not write `registerPayable(...)`, `additionalTools`, or new files under `src/tools/` until those three files are loaded. The detailed guardrails live in `guide.md` and `tool-design.md`; this block is the entry gate, not a duplicate of them.2324**`tool-design.md` is non-negotiable**, including when you think you've seen the patterns before. It is the only file that pins down the `registerPayable(name, config)` two-argument shape, the `c.respond(data, { text })` response-mode contract, and the rule that paid handlers never return raw `content` arrays. Routing past it and authoring tools "from memory" is the single most common failure mode in this skill — the input-mode guides (`from-openapi/`, `from-scratch/`, `existing-server/`) build on it and do not duplicate its contract. If you find yourself about to call `registerPayable` and you cannot recall those rules verbatim, you have not read `tool-design.md`; stop and read it.2526## First-decision routing2728Pick one before scaffolding anything:2930| Situation | Action |31| --- | --- |32| Existing `mcp-app` project (has `wrangler.jsonc`, `src/worker.ts` calling `createSolvaPayMcpFetch`) | **Do not scaffold.** Add tools under `src/tools/`, then run `npm run dev` and `node scripts/verify.mjs http://localhost:8787`. |33| Greenfield, human at a terminal | Run `npm create solvapay@latest <name> -- --type mcp` (interactive). |34| Greenfield, agent has an OpenAPI / Swagger doc | **Always use the agent path**: [from-openapi/guide.md](from-openapi/guide.md) with `scripts/describe.mjs` + `scripts/scaffold.mjs`. The published `npm create solvapay@latest -- --type mcp` CLI is for humans at a terminal — it only emits one-to-one tools and cannot author intent-driven dispatchers (those require the LLM). The agent path also supports one-to-one mode via `"mode": "one-to-one"` in `selections.json`, so falling back is one flag away. |35| Inside an unrelated app repo with no paid-MCP server in scope | **Ask** where the MCP server should live (sibling directory? `apps/mcp/`?). Do not scaffold into the app root. |3637> **Dev mode (skill author / internal testing only).** If the user explicitly says they're testing against the SolvaPay dev backend, append `--dev` to every published-CLI invocation: `npm create solvapay@latest <name> -- --type mcp --dev` and `npx -y solvapay@latest init --dev`. The flag seeds `SOLVAPAY_API_BASE_URL=https://api-dev.solvapay.com` into `.env` and routes browser-auth, `wrangler dev`, deploy preflight, and the deployed worker to api-dev in one pass. Never enable `--dev` for end users — production keys are rejected by api-dev.3839## Quick Start40411. Read [guide.md](guide.md) — the router that picks input mode, host, and sequences scaffold → init → deploy → verify → test.422. Read [tool-design.md](tool-design.md) before writing any tool (load-bearing).433. Follow the chosen input mode end-to-end:44 - [from-openapi/guide.md](from-openapi/guide.md) — generate from a spec (agent path)45 - [from-scratch/guide.md](from-scratch/guide.md) — hand-write paid tools after `npm create solvapay@latest -- --type mcp --no-openapi`46 - [existing-server/guide.md](existing-server/guide.md) — add SolvaPay to an MCP server that already exists474. Wire credentials via [solvapay-init.md](solvapay-init.md).485. Deploy to Cloudflare per [hosting/cloudflare.md](hosting/cloudflare.md) (or [hosting/alternatives.md](hosting/alternatives.md) for other hosts).4950## Pointers5152- Router and guardrails: [guide.md](guide.md)53- Shared tool-design contract: [tool-design.md](tool-design.md)54- Credential bootstrap: [solvapay-init.md](solvapay-init.md)55- OpenAPI mode: [from-openapi/](from-openapi/)56- Hand-written mode: [from-scratch/](from-scratch/)57- Existing-server integration: [existing-server/](existing-server/)58- Host details: [hosting/](hosting/)