create-solvapay 0.7.0 → 0.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -2
- package/dist/{chunk-BH3INHDI.js → chunk-W4KM7GUB.js} +8 -7
- package/dist/cli.js +2 -2
- package/dist/{mcp-YJ55XDBZ.js → mcp-EZUBUZLF.js} +1 -1
- package/dist/{next-auth0-YAG227HM.js → next-auth0-WNIMA6EQ.js} +1 -1
- package/package.json +1 -1
- package/templates/mcp/_base/README.md +21 -3
- package/templates/mcp/_base/package.json +4 -3
- package/templates/mcp/_base/scripts/deploy.mjs +4 -4
- package/templates/mcp/_base/scripts/dev.mjs +2 -2
- package/templates/mcp/_base/scripts/verify.mjs +1 -1
- package/templates/mcp/_base/src/worker.ts +6 -6
- package/templates/mcp/from-scratch/README.append.md +2 -1
- package/templates/mcp/from-scratch/src/tools/_placeholder.ts +15 -1
package/README.md
CHANGED
|
@@ -24,6 +24,13 @@ From scratch (single placeholder tool):
|
|
|
24
24
|
npm create solvapay@latest my-mcp-app -- --type mcp --no-openapi
|
|
25
25
|
```
|
|
26
26
|
|
|
27
|
+
Next.js + Auth0 starter:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
npm create solvapay@latest my-app -- --type next-auth0
|
|
31
|
+
# equivalent: npm create solvapay@latest my-app -- --auth auth0
|
|
32
|
+
```
|
|
33
|
+
|
|
27
34
|
### Skills for coding agents
|
|
28
35
|
|
|
29
36
|
> **Already in an agent session?** Run `npx skills add solvapay/skills` and ask to create a paid MCP app — the agent routes to `create-mcp-app` and runs the scaffold for you.
|
|
@@ -61,7 +68,8 @@ npm run deploy # Cloudflare Workers deploy
|
|
|
61
68
|
|
|
62
69
|
| Flag | Description |
|
|
63
70
|
| --- | --- |
|
|
64
|
-
| `--type <kind>` | Project type (`mcp`
|
|
71
|
+
| `--type <kind>` | Project type (`mcp` or `next-auth0`). Required in non-interactive mode. |
|
|
72
|
+
| `--auth <provider>` | Shortcut for auth-focused starters. `--auth auth0` selects `--type next-auth0`. |
|
|
65
73
|
| `-y`, `--yes` | Non-interactive: accept all defaults |
|
|
66
74
|
| `--product <ref>` | Pre-fill `SOLVAPAY_PRODUCT_REF` (skip the picker) |
|
|
67
75
|
| `--non-interactive` | Alias for `--yes`; fail fast on missing prompt input |
|
|
@@ -78,7 +86,7 @@ npm run deploy # Cloudflare Workers deploy
|
|
|
78
86
|
| `--no-openapi` | From-scratch mode with a placeholder paid tool |
|
|
79
87
|
| `--tool-name <camel>` | Placeholder tool name in from-scratch mode (default: `helloTool`) |
|
|
80
88
|
|
|
81
|
-
Run `npm create solvapay my-app -- --type mcp --help` for MCP-specific help.
|
|
89
|
+
Run `npm create solvapay@latest my-app -- --type mcp --help` for MCP-specific help.
|
|
82
90
|
|
|
83
91
|
## Integration paths
|
|
84
92
|
|
|
@@ -88,6 +96,7 @@ Run `npm create solvapay my-app -- --type mcp --help` for MCP-specific help.
|
|
|
88
96
|
| Next.js checkout | `npx solvapay init` | `@solvapay/next` + `@solvapay/react` | [checkout-demo](https://github.com/solvapay/solvapay-sdk/tree/main/examples/checkout-demo) | [Next.js](https://docs.solvapay.com/sdks/typescript/guides/nextjs), [React](https://docs.solvapay.com/sdks/typescript/guides/react) |
|
|
89
97
|
| Hosted checkout | `npx solvapay init` | `@solvapay/next` | [hosted-checkout-demo](https://github.com/solvapay/solvapay-sdk/tree/main/examples/hosted-checkout-demo) | [Purchase management](https://docs.solvapay.com/sdks/typescript/guides/purchase-management) |
|
|
90
98
|
| Supabase Edge | `npx solvapay init` | `@solvapay/server/fetch` + `@solvapay/react` | [supabase-edge](https://github.com/solvapay/solvapay-sdk/tree/main/examples/supabase-edge) | [Supabase Edge](https://docs.solvapay.com/sdks/typescript/guides/supabase-edge) |
|
|
99
|
+
| Next.js + Auth0 | **`npm create solvapay@latest <name> -- --type next-auth0`** | `@solvapay/next` + `@auth0/nextjs-auth0` | scaffold template | [Customer linkage](https://docs.solvapay.com/sdks/typescript/guides/customer-linkage) |
|
|
91
100
|
| **MCP app (server + UI)** | **`npm create solvapay@latest <name> -- --type mcp`** | `@solvapay/mcp` + `@solvapay/react/mcp` + `@solvapay/server` | scaffold template | [MCP](https://docs.solvapay.com/sdks/typescript/guides/mcp), [MCP app](https://docs.solvapay.com/sdks/typescript/guides/mcp-app) |
|
|
92
101
|
| MCP App UI (advanced) | manual on existing server | `@solvapay/mcp` + `@solvapay/react/mcp` | [mcp-checkout-app](https://github.com/solvapay/solvapay-sdk/tree/main/examples/mcp-checkout-app) | [MCP app](https://docs.solvapay.com/sdks/typescript/guides/mcp-app) |
|
|
93
102
|
| Existing MCP server | `npx solvapay init` | `@solvapay/server` + `@solvapay/mcp-core` | [mcp-oauth-bridge](https://github.com/solvapay/solvapay-sdk/tree/main/examples/mcp-oauth-bridge) | [MCP](https://docs.solvapay.com/sdks/typescript/guides/mcp) |
|
|
@@ -240,7 +240,7 @@ function printConnectionSnippets(options) {
|
|
|
240
240
|
out(` Cursor \u2014 add to \`~/.cursor/mcp.json\` (or the workspace's \`.cursor/mcp.json\`):`);
|
|
241
241
|
out(" {");
|
|
242
242
|
out(' "mcpServers": {');
|
|
243
|
-
out(` "${projectName}": { "url": "${workerUrl}/" }`);
|
|
243
|
+
out(` "${projectName}": { "url": "${workerUrl}/mcp" }`);
|
|
244
244
|
out(" }");
|
|
245
245
|
out(" }");
|
|
246
246
|
out("");
|
|
@@ -249,26 +249,27 @@ function printConnectionSnippets(options) {
|
|
|
249
249
|
out(' "mcpServers": {');
|
|
250
250
|
out(` "${projectName}": {`);
|
|
251
251
|
out(' "command": "npx",');
|
|
252
|
-
out(` "args": ["mcp-remote", "${workerUrl}/"]`);
|
|
252
|
+
out(` "args": ["mcp-remote", "${workerUrl}/mcp"]`);
|
|
253
253
|
out(" }");
|
|
254
254
|
out(" }");
|
|
255
255
|
out(" }");
|
|
256
256
|
out("");
|
|
257
257
|
out(" ChatGPT (Custom Connectors) \u2014 add a Custom MCP Connector with:");
|
|
258
|
-
out(` URL: ${workerUrl}
|
|
258
|
+
out(` URL: ${workerUrl}/mcp`);
|
|
259
259
|
out(" Note: ChatGPT needs a reachable (deployed or tunneled) URL \u2014");
|
|
260
260
|
out(" localhost only works for native-scheme hosts. Use `npm run deploy`");
|
|
261
261
|
out(" and point ChatGPT at the *.workers.dev URL once available.");
|
|
262
262
|
out("");
|
|
263
263
|
out(" MCP Inspector \u2014 explore tools locally:");
|
|
264
264
|
out(" npx @modelcontextprotocol/inspector");
|
|
265
|
-
out(` (set the server URL to ${workerUrl}/)`);
|
|
265
|
+
out(` (set the server URL to ${workerUrl}/mcp)`);
|
|
266
266
|
out("");
|
|
267
267
|
}
|
|
268
268
|
var SOLVAPAY_RUNTIME_DEPS = Object.freeze([
|
|
269
|
-
{ name: "@solvapay/mcp", fallback: "0.3
|
|
270
|
-
{ name: "@solvapay/
|
|
271
|
-
{ name: "@solvapay/
|
|
269
|
+
{ name: "@solvapay/mcp", fallback: "0.4.3" },
|
|
270
|
+
{ name: "@solvapay/mcp-core", fallback: "0.4.4" },
|
|
271
|
+
{ name: "@solvapay/server", fallback: "2.8.0" },
|
|
272
|
+
{ name: "@solvapay/react", fallback: "2.3.1" }
|
|
272
273
|
]);
|
|
273
274
|
async function resolveLatestSolvapayVersions(deps = SOLVAPAY_RUNTIME_DEPS, options = {}) {
|
|
274
275
|
const timeoutMs = options.timeoutMs ?? 3e3;
|
package/dist/cli.js
CHANGED
|
@@ -15,8 +15,8 @@ import { stdin, stdout } from "process";
|
|
|
15
15
|
|
|
16
16
|
// src/types/registry.ts
|
|
17
17
|
var PROJECT_TYPES = {
|
|
18
|
-
mcp: () => import("./mcp-
|
|
19
|
-
"next-auth0": () => import("./next-auth0-
|
|
18
|
+
mcp: () => import("./mcp-EZUBUZLF.js").then((m) => m.mcpProjectType),
|
|
19
|
+
"next-auth0": () => import("./next-auth0-WNIMA6EQ.js").then((m) => m.nextAuth0ProjectType)
|
|
20
20
|
// cli: () => import('./cli/index.js').then(m => m.cliProjectType), // future
|
|
21
21
|
};
|
|
22
22
|
var PROJECT_TYPE_IDS = Object.keys(PROJECT_TYPES);
|
package/package.json
CHANGED
|
@@ -71,11 +71,11 @@ Useful URLs printed at startup:
|
|
|
71
71
|
|
|
72
72
|
| What | URL |
|
|
73
73
|
| --- | --- |
|
|
74
|
-
| Worker MCP endpoint | `http://localhost:8787
|
|
74
|
+
| Worker MCP endpoint | `http://localhost:8787/mcp` |
|
|
75
75
|
| OAuth discovery | `http://localhost:8787/.well-known/oauth-protected-resource` |
|
|
76
76
|
| OAuth metadata | `http://localhost:8787/.well-known/oauth-authorization-server` |
|
|
77
77
|
|
|
78
|
-
Inspect tools with: `npx @modelcontextprotocol/inspector` and point it at `http://localhost:8787
|
|
78
|
+
Inspect tools with: `npx @modelcontextprotocol/inspector` and point it at `http://localhost:8787/mcp`.
|
|
79
79
|
|
|
80
80
|
Other scripts:
|
|
81
81
|
|
|
@@ -110,7 +110,7 @@ actual header names from the OpenAPI security schemes, for example:
|
|
|
110
110
|
UPSTREAM_API_HEADERS={"x-api-client-id":"client-id","x-api-client-secret":"client-secret"}
|
|
111
111
|
```
|
|
112
112
|
|
|
113
|
-
Point an MCP client (MCP Inspector, MCPJam, Claude Desktop, ChatGPT Custom Connectors) at `http://localhost:8787
|
|
113
|
+
Point an MCP client (MCP Inspector, MCPJam, Claude Desktop, ChatGPT Custom Connectors) at `http://localhost:8787/mcp`.
|
|
114
114
|
|
|
115
115
|
## Deploy
|
|
116
116
|
|
|
@@ -174,6 +174,24 @@ export function registerMyTool(ctx: AdditionalToolsContext, env: Env) {
|
|
|
174
174
|
|
|
175
175
|
Then add an import + `registerMyTool(ctx, env)` line to `src/tools/index.ts`. Re-deploy.
|
|
176
176
|
|
|
177
|
+
For a per-customer free allowance instead of a per-call charge, use `registerFree` with a `limit` (same handler shape):
|
|
178
|
+
|
|
179
|
+
```ts
|
|
180
|
+
export function registerPreview(ctx: AdditionalToolsContext) {
|
|
181
|
+
ctx.registerFree('preview', {
|
|
182
|
+
title: 'Preview',
|
|
183
|
+
description: 'Free preview — 5 calls / 30 days, then a plan is required.',
|
|
184
|
+
schema: { input: z.string() },
|
|
185
|
+
annotations: { readOnlyHint: true, idempotentHint: true, openWorldHint: true },
|
|
186
|
+
limit: { meter: 'free-previews', cap: 5, scope: 'rolling_window', windowDays: 30 },
|
|
187
|
+
handler: async ({ input }, c) => {
|
|
188
|
+
const data = await doSomething(input)
|
|
189
|
+
return c.respond(data, { text: `Preview for ${input}: …` })
|
|
190
|
+
},
|
|
191
|
+
})
|
|
192
|
+
}
|
|
193
|
+
```
|
|
194
|
+
|
|
177
195
|
## Reference
|
|
178
196
|
|
|
179
197
|
- [`@solvapay/mcp/fetch`](https://www.npmjs.com/package/@solvapay/mcp) — `createSolvaPayMcpFetch` is the entire integration surface.
|
|
@@ -17,9 +17,10 @@
|
|
|
17
17
|
"@modelcontextprotocol/ext-apps": "^1.7.1",
|
|
18
18
|
"@modelcontextprotocol/core": "^2.0.0",
|
|
19
19
|
"@modelcontextprotocol/server": "^2.0.0",
|
|
20
|
-
"@solvapay/mcp": "^0.3
|
|
21
|
-
"@solvapay/
|
|
22
|
-
"@solvapay/
|
|
20
|
+
"@solvapay/mcp": "^0.4.3",
|
|
21
|
+
"@solvapay/mcp-core": "^0.4.4",
|
|
22
|
+
"@solvapay/react": "^2.3.1",
|
|
23
|
+
"@solvapay/server": "^2.8.0",
|
|
23
24
|
"react": "^19.2.5",
|
|
24
25
|
"react-dom": "^19.2.5",
|
|
25
26
|
"zod": "^4.3.6"
|
|
@@ -633,16 +633,16 @@ function printDeployedConnectionSnippets(publicUrl, workerName) {
|
|
|
633
633
|
out('Connect an MCP client to the deployed worker:')
|
|
634
634
|
out('')
|
|
635
635
|
out(' Cursor (~/.cursor/mcp.json):')
|
|
636
|
-
out(` { "mcpServers": { "${name}": { "url": "${url}/" } } }`)
|
|
636
|
+
out(` { "mcpServers": { "${name}": { "url": "${url}/mcp" } } }`)
|
|
637
637
|
out('')
|
|
638
638
|
out(' Claude Desktop (claude_desktop_config.json):')
|
|
639
639
|
out(
|
|
640
|
-
` { "mcpServers": { "${name}": { "command": "npx", "args": ["mcp-remote", "${url}/"] } } }`,
|
|
640
|
+
` { "mcpServers": { "${name}": { "command": "npx", "args": ["mcp-remote", "${url}/mcp"] } } }`,
|
|
641
641
|
)
|
|
642
642
|
out('')
|
|
643
|
-
out(` ChatGPT Custom MCP Connector URL: ${url}
|
|
643
|
+
out(` ChatGPT Custom MCP Connector URL: ${url}/mcp`)
|
|
644
644
|
out('')
|
|
645
|
-
out(` MCP Inspector: npx @modelcontextprotocol/inspector (set URL to ${url}/)`)
|
|
645
|
+
out(` MCP Inspector: npx @modelcontextprotocol/inspector (set URL to ${url}/mcp)`)
|
|
646
646
|
out('')
|
|
647
647
|
}
|
|
648
648
|
|
|
@@ -34,12 +34,12 @@ function printBanner() {
|
|
|
34
34
|
const lines = [
|
|
35
35
|
'',
|
|
36
36
|
'┌─ SolvaPay MCP — local dev ─────────────────────────────────',
|
|
37
|
-
`│ Worker MCP endpoint ${WORKER_URL}
|
|
37
|
+
`│ Worker MCP endpoint ${WORKER_URL}/mcp`,
|
|
38
38
|
`│ OAuth discovery ${WORKER_URL}/.well-known/oauth-protected-resource`,
|
|
39
39
|
`│ OAuth metadata ${WORKER_URL}/.well-known/oauth-authorization-server`,
|
|
40
40
|
'│',
|
|
41
41
|
'│ Inspect tools npx @modelcontextprotocol/inspector',
|
|
42
|
-
`│ (set the server URL to ${WORKER_URL}/)`,
|
|
42
|
+
`│ (set the server URL to ${WORKER_URL}/mcp)`,
|
|
43
43
|
'│',
|
|
44
44
|
'│ Verify contract node scripts/verify.mjs ' + WORKER_URL,
|
|
45
45
|
'└────────────────────────────────────────────────────────────',
|
|
@@ -113,7 +113,7 @@ async function main() {
|
|
|
113
113
|
: await runIntentToolsTextCheck(base, rpcOptions)
|
|
114
114
|
|
|
115
115
|
// `merchantBootstrap` exercises the SolvaPay bootstrap path by
|
|
116
|
-
// calling `
|
|
116
|
+
// calling `account` (an intent tool, always registered) and
|
|
117
117
|
// asserting the response is not an error envelope. Without a bearer
|
|
118
118
|
// token, the call would gate at the HTTP layer — so it skips. With
|
|
119
119
|
// a bearer token, a 500 or text containing `"bootstrap"` is a real
|
|
@@ -122,12 +122,12 @@ function getHandler(env: Env): (req: Request) => Promise<Response> {
|
|
|
122
122
|
responseMode: 'json',
|
|
123
123
|
// Hide UI-only transport tools from the LLM-facing `tools/list`
|
|
124
124
|
// (text hosts: Claude Desktop, MCPJam, Cursor) — keeps the model's
|
|
125
|
-
// tool catalogue narrow to the
|
|
126
|
-
// `
|
|
127
|
-
//
|
|
128
|
-
//
|
|
129
|
-
//
|
|
130
|
-
//
|
|
125
|
+
// tool catalogue narrow to the intent tools (`account`,
|
|
126
|
+
// `activate_plan`) plus this worker's generated tools. ChatGPT-
|
|
127
|
+
// originated tools/list requests are auto-detected and receive the
|
|
128
|
+
// full catalog so the iframe's `create_payment_intent` calls
|
|
129
|
+
// (plan + topup via `purpose`) pass ChatGPT's gateway catalogue
|
|
130
|
+
// check.
|
|
131
131
|
hideToolsByAudience: ['ui'],
|
|
132
132
|
additionalTools: ctx => registerTools(ctx, env),
|
|
133
133
|
})
|
|
@@ -10,4 +10,5 @@ To add more paid tools later, create a new file under `src/tools/` that
|
|
|
10
10
|
exports a `register<ToolName>` function and call it from
|
|
11
11
|
`src/tools/index.ts`. Each `ctx.registerPayable(...)` call earns the
|
|
12
12
|
configured paywall amount per invocation against
|
|
13
|
-
`SOLVAPAY_PRODUCT_REF`.
|
|
13
|
+
`SOLVAPAY_PRODUCT_REF`. Use `ctx.registerFree(...)` with a `limit` for
|
|
14
|
+
a per-customer free allowance instead of a per-call charge.
|
|
@@ -26,7 +26,7 @@ export function register__TOOL_NAME_PASCAL__(ctx: AdditionalToolsContext): void
|
|
|
26
26
|
ctx.registerPayable('__TOOL_NAME__', {
|
|
27
27
|
title: '__TOOL_NAME__',
|
|
28
28
|
description:
|
|
29
|
-
'Placeholder paid tool — echoes the input message back so you can verify the paywall is wired before writing real logic. 1 credit per call; returns a text-only purchase-required narration naming the `
|
|
29
|
+
'Placeholder paid tool — echoes the input message back so you can verify the paywall is wired before writing real logic. 1 credit per call; returns a text-only purchase-required narration naming the `account` recovery tool when the customer is out of balance. Replace this description (and the handler) with your tool semantics before going live.',
|
|
30
30
|
schema: {
|
|
31
31
|
message: z.string().describe('What the caller wants').optional(),
|
|
32
32
|
},
|
|
@@ -42,6 +42,20 @@ export function register__TOOL_NAME_PASCAL__(ctx: AdditionalToolsContext): void
|
|
|
42
42
|
},
|
|
43
43
|
})
|
|
44
44
|
|
|
45
|
+
// Free-allowance sibling — swap `registerPayable` for this when the
|
|
46
|
+
// tool should be free up to a per-customer cap:
|
|
47
|
+
//
|
|
48
|
+
// ctx.registerFree('__TOOL_NAME__', {
|
|
49
|
+
// title: '__TOOL_NAME__',
|
|
50
|
+
// description: 'Free up to 5 calls / 30 days, then a plan is required.',
|
|
51
|
+
// schema: { message: z.string().optional() },
|
|
52
|
+
// annotations: { readOnlyHint: true, openWorldHint: true },
|
|
53
|
+
// limit: { meter: 'free-previews', cap: 5, scope: 'rolling_window', windowDays: 30 },
|
|
54
|
+
// handler: async (input, c) => {
|
|
55
|
+
// return c.respond({ ok: true, echoed: input.message ?? 'hello' })
|
|
56
|
+
// },
|
|
57
|
+
// })
|
|
58
|
+
|
|
45
59
|
ctx.server.registerPrompt(
|
|
46
60
|
'__TOOL_NAME__',
|
|
47
61
|
{
|