run402-mcp 1.50.1 → 1.51.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 +345 -153
- package/dist/errors.d.ts +3 -0
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +156 -31
- package/dist/errors.js.map +1 -1
- package/dist/index.js +5 -1
- package/dist/index.js.map +1 -1
- package/dist/tools/bundle-deploy.d.ts +2 -2
- package/dist/tools/bundle-deploy.d.ts.map +1 -1
- package/dist/tools/bundle-deploy.js +8 -4
- package/dist/tools/bundle-deploy.js.map +1 -1
- package/dist/tools/deploy-events.d.ts +25 -0
- package/dist/tools/deploy-events.d.ts.map +1 -0
- package/dist/tools/deploy-events.js +70 -0
- package/dist/tools/deploy-events.js.map +1 -0
- package/dist/tools/deploy-list.d.ts +23 -0
- package/dist/tools/deploy-list.d.ts.map +1 -0
- package/dist/tools/deploy-list.js +65 -0
- package/dist/tools/deploy-list.js.map +1 -0
- package/dist/tools/deploy-resume.d.ts.map +1 -1
- package/dist/tools/deploy-resume.js +2 -3
- package/dist/tools/deploy-resume.js.map +1 -1
- package/dist/tools/deploy.d.ts.map +1 -1
- package/dist/tools/deploy.js +2 -3
- package/dist/tools/deploy.js.map +1 -1
- package/package.json +6 -1
- package/sdk/README.md +132 -30
- package/sdk/dist/errors.d.ts +17 -1
- package/sdk/dist/errors.d.ts.map +1 -1
- package/sdk/dist/errors.js +39 -0
- package/sdk/dist/errors.js.map +1 -1
- package/sdk/dist/kernel.d.ts.map +1 -1
- package/sdk/dist/kernel.js +13 -3
- package/sdk/dist/kernel.js.map +1 -1
- package/sdk/dist/namespaces/allowance.d.ts +3 -0
- package/sdk/dist/namespaces/allowance.d.ts.map +1 -1
- package/sdk/dist/namespaces/allowance.js +10 -1
- package/sdk/dist/namespaces/allowance.js.map +1 -1
- package/sdk/dist/namespaces/apps.d.ts +1 -1
- package/sdk/dist/namespaces/apps.d.ts.map +1 -1
- package/sdk/dist/namespaces/apps.js +1 -11
- package/sdk/dist/namespaces/apps.js.map +1 -1
- package/sdk/dist/namespaces/deploy.d.ts +23 -1
- package/sdk/dist/namespaces/deploy.d.ts.map +1 -1
- package/sdk/dist/namespaces/deploy.js +132 -25
- package/sdk/dist/namespaces/deploy.js.map +1 -1
- package/sdk/dist/namespaces/deploy.types.d.ts +20 -0
- package/sdk/dist/namespaces/deploy.types.d.ts.map +1 -1
- package/sdk/dist/namespaces/projects.types.d.ts +6 -1
- package/sdk/dist/namespaces/projects.types.d.ts.map +1 -1
- package/sdk/dist/namespaces/subdomains.d.ts.map +1 -1
- package/sdk/dist/namespaces/subdomains.js +4 -1
- package/sdk/dist/namespaces/subdomains.js.map +1 -1
package/README.md
CHANGED
|
@@ -2,247 +2,439 @@
|
|
|
2
2
|
<img src=".github/logo.svg" width="120" alt="run402 logo">
|
|
3
3
|
</p>
|
|
4
4
|
|
|
5
|
-
<h1 align="center">run402 —
|
|
5
|
+
<h1 align="center">run402 — Postgres, storage & deploys for AI agents</h1>
|
|
6
6
|
|
|
7
7
|
[](https://github.com/kychee-com/run402/actions/workflows/test.yml)
|
|
8
8
|
[](https://github.com/kychee-com/run402/actions/workflows/codeql.yml)
|
|
9
|
-
[](https://www.npmjs.com/package/@run402/sdk)
|
|
10
10
|
[](https://www.npmjs.com/package/run402)
|
|
11
|
+
[](https://www.npmjs.com/package/run402-mcp)
|
|
12
|
+
[](https://www.npmjs.com/package/@run402/functions)
|
|
11
13
|
[](./LICENSE)
|
|
12
14
|
|
|
13
|
-
|
|
15
|
+
[Run402](https://run402.com) gives an agent a full Postgres database, REST API, user auth, content-addressed file storage, static site hosting, serverless functions, and image generation — provisioned with one call, paid with x402 USDC on Base (or Stripe credits). The prototype tier is free on testnet.
|
|
14
16
|
|
|
15
|
-
|
|
17
|
+
This monorepo ships every surface an agent can pick up:
|
|
16
18
|
|
|
17
|
-
|
|
19
|
+
| Package | Use when… |
|
|
20
|
+
|---------|-----------|
|
|
21
|
+
| [`@run402/sdk`](./sdk/) | Calling Run402 from TypeScript — typed kernel, isomorphic (Node 22 / Deno / Bun / V8 isolates) with a Node entry that auto-loads the local keystore + allowance + x402 fetch |
|
|
22
|
+
| [`run402` CLI](./cli/) | Terminal, scripts, CI, agent-controlled shells — JSON in, JSON out, exit code on failure |
|
|
23
|
+
| [`run402-mcp`](./src/) | Claude Desktop, Cursor, Cline, Claude Code — every CLI capability as an MCP tool |
|
|
24
|
+
| [OpenClaw skill](./openclaw/) | OpenClaw agents (no MCP server required) |
|
|
25
|
+
| [`@run402/functions`](./functions/) | Imported _inside_ deployed functions (`db(req)`, `adminDb()`, `getUser()`, `email`, `ai`) and for TypeScript autocomplete in your editor |
|
|
18
26
|
|
|
19
|
-
|
|
20
|
-
|-----------|-------------|
|
|
21
|
-
| [`sdk/`](./sdk/) (`@run402/sdk`) | Calling run402 from code — inside user-deployed functions, custom agents, or future code-mode sandboxes |
|
|
22
|
-
| [`cli/`](./cli/) | Terminal, scripts, CI/CD |
|
|
23
|
-
| [`openclaw/`](./openclaw/) | OpenClaw agent (no MCP required) |
|
|
24
|
-
| MCP server (this package) | Claude Desktop, Cursor, Cline, Claude Code |
|
|
27
|
+
All four shipped surfaces release in lockstep at the same version and share a single typed kernel: `@run402/sdk`. MCP tools, CLI subcommands, and OpenClaw scripts are thin shims over SDK calls. Pick whichever interface fits your runtime.
|
|
25
28
|
|
|
26
|
-
##
|
|
29
|
+
## 30-second start
|
|
27
30
|
|
|
28
31
|
```bash
|
|
29
|
-
npm install
|
|
32
|
+
npm install -g run402
|
|
33
|
+
run402 init # creates allowance, requests testnet faucet
|
|
34
|
+
run402 tier set prototype # free on testnet (verifies x402 setup)
|
|
35
|
+
run402 projects provision --name my-app # → anon_key, service_key, project_id
|
|
36
|
+
run402 sites deploy-dir ./dist # incremental deploy of a directory → live URL
|
|
37
|
+
run402 subdomains claim my-app # → https://my-app.run402.com
|
|
30
38
|
```
|
|
31
39
|
|
|
32
|
-
|
|
40
|
+
That's a real Postgres database + a deployed static site, paid for autonomously with testnet USDC.
|
|
41
|
+
|
|
42
|
+
## The patterns
|
|
43
|
+
|
|
44
|
+
### Paste-and-go assets — content-addressed URLs with SRI
|
|
45
|
+
|
|
46
|
+
`blobs.put()` returns an `AssetRef` whose `scriptTag()` / `linkTag()` / `imgTag()` emitters produce HTML with the URL, the SRI integrity hash, and modern best-practice attributes (`defer`, `loading="lazy"`, `decoding="async"`, `crossorigin`) already wired. The URL is content-addressed (`pr-<public_id>.run402.com/_blob/<key>-<8hex>.<ext>`), served through the v1.33 CDN, and never needs invalidation:
|
|
47
|
+
|
|
48
|
+
```ts
|
|
49
|
+
import { run402 } from "@run402/sdk/node";
|
|
50
|
+
const r = run402();
|
|
51
|
+
|
|
52
|
+
const logo = await r.blobs.put(projectId, "logo.png", { bytes: pngBytes });
|
|
53
|
+
const app = await r.blobs.put(projectId, "app.js", { content: jsSource });
|
|
54
|
+
const style = await r.blobs.put(projectId, "app.css", { content: css });
|
|
55
|
+
|
|
56
|
+
const html = `
|
|
57
|
+
<!doctype html>
|
|
58
|
+
<html>
|
|
59
|
+
<head>${style.linkTag()}${app.scriptTag({ type: "module" })}</head>
|
|
60
|
+
<body>${logo.imgTag("Company logo")}</body>
|
|
61
|
+
</html>
|
|
62
|
+
`;
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
`immutable: true` is the default — the SDK computes the SHA-256 client-side, the gateway returns a content-hashed URL, and the browser refuses execution on byte mismatch. No cache-invalidation choreography, no waiting, no integrity-attribute construction.
|
|
66
|
+
|
|
67
|
+
### Dark-by-default tables + the expose manifest
|
|
68
|
+
|
|
69
|
+
Tables you create are unreachable via `/rest/v1/*` until you declare them in a manifest. That closes the "agent created a table, forgot to set RLS, data leaked" footgun. The manifest is convergent — applying it twice is a no-op; items removed between applies have their policies, grants, triggers, and views dropped.
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
cat > manifest.json <<'EOF'
|
|
73
|
+
{
|
|
74
|
+
"$schema": "https://run402.com/schemas/manifest.v1.json",
|
|
75
|
+
"version": "1",
|
|
76
|
+
"tables": [
|
|
77
|
+
{ "name": "items", "expose": true, "policy": "user_owns_rows",
|
|
78
|
+
"owner_column": "user_id", "force_owner_on_insert": true },
|
|
79
|
+
{ "name": "audit", "expose": false }
|
|
80
|
+
],
|
|
81
|
+
"views": [
|
|
82
|
+
{ "name": "leaderboard", "base": "items", "select": ["user_id", "score"], "expose": true }
|
|
83
|
+
],
|
|
84
|
+
"rpcs": [
|
|
85
|
+
{ "name": "compute_streak", "signature": "(user_id uuid)", "grant_to": ["authenticated"] }
|
|
86
|
+
]
|
|
87
|
+
}
|
|
88
|
+
EOF
|
|
89
|
+
|
|
90
|
+
run402 projects apply-expose <project_id> --file manifest.json
|
|
91
|
+
run402 projects get-expose <project_id>
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Built-in policies: `user_owns_rows` (rows where `owner_column = auth.uid()`; with `force_owner_on_insert: true` a BEFORE INSERT trigger sets it), `public_read_authenticated_write` (anyone reads, any authenticated user writes), `public_read_write_UNRESTRICTED` (fully open; requires `i_understand_this_is_unrestricted: true`), and `custom` (escape hatch — your own `CREATE POLICY` SQL).
|
|
95
|
+
|
|
96
|
+
**Auth-as-SDLC alternative:** drop the same JSON as `manifest.json` into your bundle's `files[]` and the gateway reads it, validates it against your migration SQL, applies it, and strips it before serving the site — so authorization travels with your code and never gets publicly served. The deploy returns `manifest_applied: true`; if a table referenced by the manifest isn't in the migration, the deploy is rejected with a structured `errors` array listing every violation.
|
|
97
|
+
|
|
98
|
+
### Slick deploys — `deployDir` + plan/commit + progress
|
|
99
|
+
|
|
100
|
+
`deployDir` walks a local directory, hashes every file client-side, asks the gateway _which_ bytes it doesn't already have, and PUTs only those. Re-deploying an unchanged tree returns immediately with `bytes_uploaded: 0`.
|
|
33
101
|
|
|
34
102
|
```ts
|
|
35
103
|
import { run402 } from "@run402/sdk/node";
|
|
36
104
|
|
|
37
105
|
const r = run402();
|
|
38
|
-
const
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
106
|
+
const { url, bytes_uploaded, bytes_total } = await r.sites.deployDir({
|
|
107
|
+
project: projectId,
|
|
108
|
+
dir: "./dist",
|
|
109
|
+
onEvent: (e) => process.stderr.write(JSON.stringify(e) + "\n"),
|
|
42
110
|
});
|
|
43
111
|
```
|
|
44
112
|
|
|
45
|
-
|
|
113
|
+
Progress events stream over `onEvent` (or stderr from the CLI):
|
|
46
114
|
|
|
47
|
-
|
|
115
|
+
| phase | Fires | Extra |
|
|
116
|
+
|-------|-------|-------|
|
|
117
|
+
| `plan` | After `POST /deploy/v1/plan` | `manifest_size` (file count) |
|
|
118
|
+
| `upload` | After each missing file's bytes finish PUTing | `file`, `sha256`, `done`, `total` |
|
|
119
|
+
| `commit` | Just before `POST /deploy/v1/commit` | — |
|
|
120
|
+
| `poll` | Per server-side copy poll tick | `status`, `elapsed_ms` |
|
|
48
121
|
|
|
49
|
-
|
|
122
|
+
CLI:
|
|
50
123
|
|
|
51
124
|
```bash
|
|
52
|
-
|
|
125
|
+
run402 sites deploy-dir ./dist --project prj_… > result.json 2> events.log
|
|
53
126
|
```
|
|
54
127
|
|
|
55
|
-
|
|
128
|
+
### In-function helpers — caller-context vs BYPASSRLS
|
|
56
129
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
| `send_email` | Send email — template or raw HTML mode. Single recipient. |
|
|
94
|
-
| `list_emails` | List sent emails from the project's mailbox. |
|
|
95
|
-
| `get_email` | Get a specific email message with replies. |
|
|
96
|
-
| `get_email_raw` | Get raw RFC-822 bytes of an inbound message (base64). For DKIM/zk-email verification. |
|
|
97
|
-
| `get_mailbox` | Get the project's mailbox info. |
|
|
98
|
-
| `promote_user` | Promote a project user to admin role. |
|
|
99
|
-
| `demote_user` | Demote a project user from admin role. |
|
|
100
|
-
| `ai_translate` | Translate text via AI (OpenRouter). Metered per project. |
|
|
101
|
-
| `ai_moderate` | Moderate text via AI (OpenAI). Free. |
|
|
102
|
-
| `ai_usage` | Check AI translation usage and quota. |
|
|
103
|
-
| `add_custom_domain` | Add a custom domain to a subdomain (Cloudflare SSL). |
|
|
104
|
-
| `list_custom_domains` | List custom domains for a project. |
|
|
105
|
-
| `check_domain_status` | Check custom domain verification status. |
|
|
106
|
-
| `remove_custom_domain` | Remove a custom domain. |
|
|
107
|
-
| `request_magic_link` | Send a passwordless login email (magic link). |
|
|
108
|
-
| `verify_magic_link` | Exchange a magic link token for access + refresh tokens. |
|
|
109
|
-
| `set_user_password` | Change, reset, or set a user's password. |
|
|
110
|
-
| `auth_settings` | Update project auth settings (e.g., allow_password_set). |
|
|
111
|
-
| `register_sender_domain` | Register a custom email sending domain (DKIM verification). |
|
|
112
|
-
| `sender_domain_status` | Check sender domain verification status. |
|
|
113
|
-
| `remove_sender_domain` | Remove a custom sender domain. |
|
|
114
|
-
| `create_email_billing_account` | Create a Stripe-only billing account by email (no wallet required). |
|
|
115
|
-
| `link_wallet_to_account` | Link a wallet to an email account for hybrid Stripe + x402 access. |
|
|
116
|
-
| `tier_checkout` | Subscribe/renew/upgrade to a tier via Stripe (alternative to x402). |
|
|
117
|
-
| `buy_email_pack` | Buy a $5 email pack (10,000 emails, never expire). |
|
|
118
|
-
| `set_auto_recharge` | Enable/disable auto-recharge for email packs when credits run low. |
|
|
119
|
-
| `provision_contract_wallet` | Provision an AWS KMS-backed Ethereum wallet ($0.04/day rental, $1.20 prepay required). |
|
|
120
|
-
| `get_contract_wallet` | Get a KMS contract wallet's metadata + live native balance. |
|
|
121
|
-
| `list_contract_wallets` | List KMS contract wallets owned by the project. |
|
|
122
|
-
| `set_recovery_address` | Set/clear the optional recovery address for auto-drain on day-90 deletion. |
|
|
123
|
-
| `set_low_balance_alert` | Set the low-balance alert threshold (in wei). |
|
|
124
|
-
| `contract_call` | Submit a smart-contract write call (chain gas + $0.000005 KMS sign fee). |
|
|
125
|
-
| `contract_read` | Read-only smart-contract call (free, no signing). |
|
|
126
|
-
| `get_contract_call_status` | Look up a contract call by ID — status, gas, receipt. |
|
|
127
|
-
| `drain_contract_wallet` | Drain native balance to a destination address (works on suspended wallets). |
|
|
128
|
-
| `delete_contract_wallet` | Schedule the KMS key for deletion (refused if balance ≥ dust). |
|
|
129
|
-
|
|
130
|
-
## Client Configuration
|
|
131
|
-
|
|
132
|
-
### CLI
|
|
133
|
-
|
|
134
|
-
A standalone CLI is available in the [`cli/`](./cli/) directory.
|
|
130
|
+
Inside a deployed function, import from `@run402/functions`. Two distinct DB clients keep RLS clean:
|
|
131
|
+
|
|
132
|
+
```ts
|
|
133
|
+
import { db, adminDb, getUser, email, ai } from "@run402/functions";
|
|
134
|
+
|
|
135
|
+
export default async (req: Request) => {
|
|
136
|
+
const user = await getUser(req);
|
|
137
|
+
if (!user) return new Response("unauthorized", { status: 401 });
|
|
138
|
+
|
|
139
|
+
// Caller-context — Authorization header is forwarded; RLS evaluates against the caller's role.
|
|
140
|
+
const mine = await db(req).from("items").select("*").eq("user_id", user.id);
|
|
141
|
+
|
|
142
|
+
// BYPASSRLS — for platform-authored writes (audit logs, cron cleanup, webhook handlers).
|
|
143
|
+
await adminDb().from("audit").insert({ event: "items_read", user_id: user.id });
|
|
144
|
+
|
|
145
|
+
// Send mail from the project's mailbox — discovers it automatically.
|
|
146
|
+
if (mine.length === 0) {
|
|
147
|
+
await email.send({ to: user.email, subject: "Welcome", html: "<h1>hi</h1>" });
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
return Response.json(mine);
|
|
151
|
+
};
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
`adminDb().sql(query, params?)` runs raw parameterized SQL and always bypasses RLS:
|
|
155
|
+
|
|
156
|
+
```ts
|
|
157
|
+
const { rows, rowCount } = await adminDb().sql(
|
|
158
|
+
"SELECT count(*)::int AS n FROM items WHERE user_id = $1",
|
|
159
|
+
[user.id],
|
|
160
|
+
);
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
`@run402/functions` is auto-bundled into deployed code; install it in your editor for full TypeScript autocomplete (also works at build time for static-site generation with `RUN402_SERVICE_KEY` + `RUN402_PROJECT_ID` set).
|
|
164
|
+
|
|
165
|
+
## SDK — `@run402/sdk`
|
|
135
166
|
|
|
136
167
|
```bash
|
|
137
|
-
npm install
|
|
168
|
+
npm install @run402/sdk
|
|
169
|
+
```
|
|
138
170
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
run402
|
|
171
|
+
Two entry points:
|
|
172
|
+
|
|
173
|
+
- **`@run402/sdk`** — isomorphic. Bring your own `CredentialsProvider` (a session-token shim, a remote vault, anything that resolves project keys + auth headers). Works in Node 22, Deno, Bun, V8 isolates.
|
|
174
|
+
- **`@run402/sdk/node`** — Node-only convenience. Reads `~/.config/run402/projects.json`, signs x402 payments from the local allowance, exposes `sites.deployDir(...)`.
|
|
175
|
+
|
|
176
|
+
```ts
|
|
177
|
+
import { run402 } from "@run402/sdk/node";
|
|
178
|
+
|
|
179
|
+
const r = run402();
|
|
180
|
+
const project = await r.projects.provision({ tier: "prototype" });
|
|
181
|
+
await r.blobs.put(project.project_id, "hello.txt", { content: "hi" });
|
|
142
182
|
```
|
|
143
183
|
|
|
144
|
-
See [`
|
|
184
|
+
19 namespaces: `projects`, `deploy`, `sites`, `blobs`, `functions`, `secrets`, `subdomains`, `domains`, `email` (+ `webhooks`), `senderDomain`, `auth`, `apps`, `tier`, `billing`, `contracts`, `ai`, `allowance`, `service`, `admin`. Every operation throws a typed `Run402Error` subclass on failure: `PaymentRequired`, `ProjectNotFound`, `Unauthorized`, `ApiError`, `NetworkError`, `LocalError`, `Run402DeployError`. See [`sdk/README.md`](./sdk/README.md).
|
|
145
185
|
|
|
146
|
-
|
|
186
|
+
## CLI — `run402`
|
|
147
187
|
|
|
148
|
-
|
|
188
|
+
```bash
|
|
189
|
+
npm install -g run402
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
Every subcommand prints JSON to stdout, JSON errors to stderr, exits 0 on success and 1 on failure — designed for an agent shell, not a human. Full reference: [`cli/llms-cli.txt`](./cli/llms-cli.txt) (also at <https://run402.com/llms-cli.txt>).
|
|
149
193
|
|
|
150
194
|
```bash
|
|
151
|
-
|
|
152
|
-
|
|
195
|
+
run402 init # one-shot allowance + faucet + tier check
|
|
196
|
+
run402 status # account snapshot (allowance, balance, tier, projects)
|
|
197
|
+
run402 projects provision --name my-app
|
|
198
|
+
run402 projects sql <id> "CREATE TABLE …"
|
|
199
|
+
run402 projects apply-expose <id> --file manifest.json
|
|
200
|
+
run402 sites deploy-dir ./dist
|
|
201
|
+
run402 functions deploy <id> <name> --file fn.ts
|
|
202
|
+
run402 blob put ./asset.png --immutable
|
|
203
|
+
run402 blob diagnose <url> # inspect live CDN state for a public URL
|
|
204
|
+
run402 cdn wait-fresh <url> --sha <hex> # poll until a mutable URL serves the new SHA
|
|
153
205
|
```
|
|
154
206
|
|
|
155
|
-
|
|
207
|
+
The active project is sticky: `run402 projects use <id>` makes `<id>` the default for every subsequent `<id>`-taking subcommand, so most commands work without it.
|
|
208
|
+
|
|
209
|
+
## MCP server — `run402-mcp`
|
|
156
210
|
|
|
157
|
-
|
|
211
|
+
```bash
|
|
212
|
+
npx -y run402-mcp # standalone test
|
|
213
|
+
```
|
|
158
214
|
|
|
159
|
-
|
|
215
|
+
### Claude Desktop
|
|
160
216
|
|
|
161
217
|
Add to `~/Library/Application Support/Claude/claude_desktop_config.json`:
|
|
162
218
|
|
|
163
219
|
```json
|
|
164
220
|
{
|
|
165
221
|
"mcpServers": {
|
|
166
|
-
"run402": {
|
|
167
|
-
"command": "npx",
|
|
168
|
-
"args": ["-y", "run402-mcp"]
|
|
169
|
-
}
|
|
222
|
+
"run402": { "command": "npx", "args": ["-y", "run402-mcp"] }
|
|
170
223
|
}
|
|
171
224
|
}
|
|
172
225
|
```
|
|
173
226
|
|
|
174
|
-
|
|
227
|
+
### Cursor
|
|
175
228
|
|
|
176
|
-
Add to `.cursor/mcp.json
|
|
229
|
+
Add to `.cursor/mcp.json`:
|
|
177
230
|
|
|
178
231
|
```json
|
|
179
232
|
{
|
|
180
233
|
"mcpServers": {
|
|
181
|
-
"run402": {
|
|
182
|
-
"command": "npx",
|
|
183
|
-
"args": ["-y", "run402-mcp"]
|
|
184
|
-
}
|
|
234
|
+
"run402": { "command": "npx", "args": ["-y", "run402-mcp"] }
|
|
185
235
|
}
|
|
186
236
|
}
|
|
187
237
|
```
|
|
188
238
|
|
|
189
|
-
|
|
239
|
+
### Cline
|
|
190
240
|
|
|
191
|
-
Add to Cline MCP settings:
|
|
241
|
+
Add to your Cline MCP settings:
|
|
192
242
|
|
|
193
243
|
```json
|
|
194
244
|
{
|
|
195
245
|
"mcpServers": {
|
|
196
|
-
"run402": {
|
|
197
|
-
"command": "npx",
|
|
198
|
-
"args": ["-y", "run402-mcp"]
|
|
199
|
-
}
|
|
246
|
+
"run402": { "command": "npx", "args": ["-y", "run402-mcp"] }
|
|
200
247
|
}
|
|
201
248
|
}
|
|
202
249
|
```
|
|
203
250
|
|
|
204
|
-
|
|
251
|
+
### Claude Code
|
|
205
252
|
|
|
206
253
|
```bash
|
|
207
254
|
claude mcp add run402 -- npx -y run402-mcp
|
|
208
255
|
```
|
|
209
256
|
|
|
210
|
-
##
|
|
257
|
+
## OpenClaw skill
|
|
258
|
+
|
|
259
|
+
```bash
|
|
260
|
+
cp -r openclaw ~/.openclaw/skills/run402
|
|
261
|
+
cd ~/.openclaw/skills/run402/scripts && npm install
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
Each script re-exports from `cli/lib/*.mjs` — the OpenClaw command surface is identical to the CLI command surface by construction. See [`openclaw/README.md`](./openclaw/README.md).
|
|
265
|
+
|
|
266
|
+
## MCP tools
|
|
267
|
+
|
|
268
|
+
The full MCP surface — every tool is a thin shim over an SDK call.
|
|
269
|
+
|
|
270
|
+
### Database
|
|
271
|
+
|
|
272
|
+
| Tool | Description |
|
|
273
|
+
|------|-------------|
|
|
274
|
+
| `provision_postgres_project` | Provision a new database. Auto-handles x402 payment. |
|
|
275
|
+
| `run_sql` | Execute SQL (DDL or queries). Returns a markdown table. |
|
|
276
|
+
| `rest_query` | Query/mutate via PostgREST. |
|
|
277
|
+
| `apply_expose` | Apply the declarative authorization manifest (tables, views, RPCs). Convergent — drops items removed between applies. |
|
|
278
|
+
| `get_expose` | Return the current manifest. `source` is either `applied` (from the tracking table) or `introspected` (regenerated from live DB state). |
|
|
279
|
+
| `get_schema` | Introspect tables, columns, types, constraints, RLS policies. |
|
|
280
|
+
| `get_usage` | Per-project usage report (API calls, storage, lease expiry). |
|
|
281
|
+
| `promote_user` / `demote_user` | Manage `project_admin` role on a project user. |
|
|
282
|
+
| `delete_project` | Cascade purge — schema, Lambdas, S3 site files, deployments, secrets, published versions. Irreversible. |
|
|
283
|
+
|
|
284
|
+
### Blob storage (content-addressed CDN)
|
|
285
|
+
|
|
286
|
+
| Tool | Description |
|
|
287
|
+
|------|-------------|
|
|
288
|
+
| `blob_put` | Upload a blob (any size, up to 5 TiB) via direct-to-S3 presigned URLs. Returns an `AssetRef` with `scriptTag()` / `linkTag()` / `imgTag()` emitters. |
|
|
289
|
+
| `blob_get` | Download a blob to a local file. |
|
|
290
|
+
| `blob_ls` | Keyset-paginated list with prefix filter. |
|
|
291
|
+
| `blob_rm` | Delete a blob. |
|
|
292
|
+
| `blob_sign` | Time-boxed presigned GET URL for a private blob. |
|
|
293
|
+
| `diagnose_public_url` | Live CDN state for a public URL — expected vs observed SHA, cache headers, invalidation status. |
|
|
294
|
+
| `wait_for_cdn_freshness` | Poll a mutable URL until it serves the expected SHA-256. |
|
|
295
|
+
|
|
296
|
+
### Sites & subdomains
|
|
297
|
+
|
|
298
|
+
| Tool | Description |
|
|
299
|
+
|------|-------------|
|
|
300
|
+
| `deploy_site` | Deploy a static site from inline file bytes. |
|
|
301
|
+
| `deploy_site_dir` | Deploy a static site from a local directory. v1.32 plan/commit transport — only uploads bytes the gateway doesn't have. |
|
|
302
|
+
| `get_deployment` | Fetch deployment status and URL. |
|
|
303
|
+
| `claim_subdomain` | Claim `<name>.run402.com` (idempotent; reassigns to latest deployment on subsequent deploys). |
|
|
304
|
+
| `list_subdomains` / `delete_subdomain` | Manage subdomains. |
|
|
305
|
+
| `add_custom_domain` / `list_custom_domains` / `check_domain_status` / `remove_custom_domain` | Point your own domain at a Run402 subdomain. |
|
|
306
|
+
| `bundle_deploy` | One-call full-stack deploy: database + migrations + authorization manifest (`manifest.json` in `files[]` — gateway validates it, applies it, then strips it before serving the site) + secrets + functions + site + subdomain. |
|
|
307
|
+
|
|
308
|
+
### Functions & secrets
|
|
309
|
+
|
|
310
|
+
| Tool | Description |
|
|
311
|
+
|------|-------------|
|
|
312
|
+
| `deploy_function` | Deploy a Node 22 serverless function. Cron-schedulable. |
|
|
313
|
+
| `invoke_function` | Invoke a deployed function (test path). |
|
|
314
|
+
| `get_function_logs` | Recent logs (CloudWatch). |
|
|
315
|
+
| `update_function` | Update schedule / timeout / memory without redeploying code. |
|
|
316
|
+
| `list_functions` / `delete_function` | List / remove functions. |
|
|
317
|
+
| `set_secret` / `list_secrets` / `delete_secret` | Manage `process.env` secrets injected into all functions. |
|
|
318
|
+
|
|
319
|
+
### Auth & email
|
|
211
320
|
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
321
|
+
| Tool | Description |
|
|
322
|
+
|------|-------------|
|
|
323
|
+
| `request_magic_link` | Send a passwordless login email. |
|
|
324
|
+
| `verify_magic_link` | Exchange the magic link token for `access_token` + `refresh_token`. |
|
|
325
|
+
| `set_user_password` | Change, reset, or set a user's password. |
|
|
326
|
+
| `auth_settings` | Toggle `allow_password_set` for passwordless users. |
|
|
327
|
+
| `create_mailbox` / `get_mailbox` / `delete_mailbox` | Per-project mailbox at `<slug>@mail.run402.com`. |
|
|
328
|
+
| `send_email` | Template (`project_invite`, `magic_link`, `notification`) or raw HTML. Single recipient. |
|
|
329
|
+
| `list_emails` / `get_email` / `get_email_raw` | Read messages. `get_email_raw` returns RFC-822 bytes for DKIM / zk-email verification. |
|
|
330
|
+
| `register_mailbox_webhook` / `list_mailbox_webhooks` / `get_mailbox_webhook` / `update_mailbox_webhook` / `delete_mailbox_webhook` | Email-event webhooks (delivery, bounced, complained, reply_received). |
|
|
331
|
+
| `register_sender_domain` / `sender_domain_status` / `remove_sender_domain` | Send from your own domain (DKIM verified). |
|
|
332
|
+
| `enable_sender_domain_inbound` / `disable_sender_domain_inbound` | Receive replies on your custom sender domain. |
|
|
333
|
+
|
|
334
|
+
### AI helpers
|
|
335
|
+
|
|
336
|
+
| Tool | Description |
|
|
337
|
+
|------|-------------|
|
|
338
|
+
| `generate_image` | Text-to-PNG via x402 ($0.03 / image). |
|
|
339
|
+
| `ai_translate` | Translate text. Metered per project. |
|
|
340
|
+
| `ai_moderate` | Moderate text (free). |
|
|
341
|
+
| `ai_usage` | Translation quota (used / included / remaining). |
|
|
342
|
+
|
|
343
|
+
### Apps marketplace
|
|
344
|
+
|
|
345
|
+
| Tool | Description |
|
|
346
|
+
|------|-------------|
|
|
347
|
+
| `browse_apps` | Browse public forkable apps. |
|
|
348
|
+
| `get_app` | Inspect an app, including expected `bootstrap_variables`. |
|
|
349
|
+
| `fork_app` | Clone schema + site + functions into a new project. Runs the app's `bootstrap` function with provided variables. |
|
|
350
|
+
| `publish_app` | Publish a project as a forkable app. |
|
|
351
|
+
| `list_versions` / `update_version` / `delete_version` | Manage published versions. |
|
|
352
|
+
|
|
353
|
+
### Tier & billing
|
|
354
|
+
|
|
355
|
+
| Tool | Description |
|
|
356
|
+
|------|-------------|
|
|
357
|
+
| `set_tier` | Subscribe / renew / upgrade a tier (auto-detects action). x402 payment. |
|
|
358
|
+
| `tier_status` | Current tier and lease expiry. |
|
|
359
|
+
| `get_quote` | Tier pricing (free, no auth). |
|
|
360
|
+
| `tier_checkout` | Stripe checkout for a tier (alternative to x402). |
|
|
361
|
+
| `create_email_billing_account` / `link_wallet_to_account` | Email-based billing accounts; hybrid Stripe + x402. |
|
|
362
|
+
| `billing_history` | Ledger history. |
|
|
363
|
+
| `buy_email_pack` | $5 for 10,000 emails (never expire). |
|
|
364
|
+
| `set_auto_recharge` | Auto-buy email packs when credits run low. |
|
|
365
|
+
|
|
366
|
+
### KMS contract wallets (on-chain signing)
|
|
216
367
|
|
|
217
|
-
|
|
368
|
+
| Tool | Description |
|
|
369
|
+
|------|-------------|
|
|
370
|
+
| `provision_contract_wallet` | AWS KMS-backed Ethereum wallet. $0.04/day rental + $0.000005 per call. Private keys never leave KMS. |
|
|
371
|
+
| `get_contract_wallet` / `list_contract_wallets` | Metadata + live native balance. |
|
|
372
|
+
| `set_recovery_address` / `set_low_balance_alert` | Optional safety nets. |
|
|
373
|
+
| `contract_call` | Submit a write call (chain gas at-cost + KMS sign fee). |
|
|
374
|
+
| `contract_read` | Read-only call (free). |
|
|
375
|
+
| `get_contract_call_status` | Lifecycle, gas, receipt. |
|
|
376
|
+
| `drain_contract_wallet` | Drain native balance (works on suspended wallets — the safety valve). |
|
|
377
|
+
| `delete_contract_wallet` | Schedule KMS key deletion (refused if balance ≥ dust). |
|
|
218
378
|
|
|
219
|
-
|
|
379
|
+
### Allowance & account
|
|
220
380
|
|
|
221
|
-
|
|
381
|
+
| Tool | Description |
|
|
382
|
+
|------|-------------|
|
|
383
|
+
| `init` | One-shot setup: allowance + faucet + tier check + project list. |
|
|
384
|
+
| `status` | Full account snapshot (allowance, balance, tier, projects). |
|
|
385
|
+
| `allowance_status` / `allowance_create` / `allowance_export` | Local allowance management. |
|
|
386
|
+
| `request_faucet` | Request testnet USDC. |
|
|
387
|
+
| `check_balance` | USDC balance for an allowance address. |
|
|
388
|
+
| `list_projects` | Active projects for a wallet. |
|
|
389
|
+
| `pin_project` | Pin a project (admin only — bypasses lifecycle state machine). |
|
|
390
|
+
| `project_info` / `project_keys` / `project_use` | Inspect / set the active project. |
|
|
391
|
+
| `create_checkout` | Stripe checkout to add cash credit. |
|
|
392
|
+
| `send_message` / `set_agent_contact` | Send feedback to the Run402 team; register agent contact info. |
|
|
393
|
+
|
|
394
|
+
### Service status (no auth)
|
|
222
395
|
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
- `expires_at` — lease expiration timestamp
|
|
396
|
+
| Tool | Description |
|
|
397
|
+
|------|-------------|
|
|
398
|
+
| `service_status` | Public availability report — 24h/7d/30d uptime per capability, operator, deployment topology. |
|
|
399
|
+
| `service_health` | Liveness probe with per-dependency results. |
|
|
228
400
|
|
|
229
|
-
##
|
|
401
|
+
## Configuration
|
|
230
402
|
|
|
231
|
-
| Variable | Default |
|
|
232
|
-
|
|
233
|
-
| `RUN402_API_BASE`
|
|
234
|
-
| `RUN402_CONFIG_DIR`
|
|
235
|
-
| `RUN402_ALLOWANCE_PATH`
|
|
403
|
+
| Variable | Default | Purpose |
|
|
404
|
+
|----------|---------|---------|
|
|
405
|
+
| `RUN402_API_BASE` | `https://api.run402.com` | API base URL (override for staging) |
|
|
406
|
+
| `RUN402_CONFIG_DIR` | `~/.config/run402` | Local credential storage directory |
|
|
407
|
+
| `RUN402_ALLOWANCE_PATH` | `{config_dir}/allowance.json` | Custom allowance file path |
|
|
408
|
+
|
|
409
|
+
Local state lives at:
|
|
410
|
+
|
|
411
|
+
- `~/.config/run402/projects.json` (`0600`) — `{ projects: { <id>: { anon_key, service_key, tier, lease_expires_at } } }`
|
|
412
|
+
- `~/.config/run402/allowance.json` (`0600`) — wallet for x402 signing
|
|
413
|
+
|
|
414
|
+
`anon_key` and `service_key` have no expiry — lease enforcement happens server-side. Rotate them by deleting the project and re-provisioning.
|
|
236
415
|
|
|
237
416
|
## Development
|
|
238
417
|
|
|
239
418
|
```bash
|
|
240
|
-
npm run build
|
|
241
|
-
npm test
|
|
242
|
-
npm run test:
|
|
243
|
-
npm run test:
|
|
419
|
+
npm run build # builds core/, sdk/, functions/, then the MCP server
|
|
420
|
+
npm test # SKILL + sync + unit tests
|
|
421
|
+
npm run test:e2e # 47 CLI end-to-end tests
|
|
422
|
+
npm run test:sync # checks MCP/CLI/OpenClaw/SDK stay in sync
|
|
423
|
+
npm run test:skill # validates SKILL.md frontmatter + body
|
|
244
424
|
```
|
|
245
425
|
|
|
426
|
+
Architecture: every tool / subcommand / skill script is a thin shim over an `@run402/sdk` call. `core/` holds Node-only filesystem primitives (keystore, allowance, SIWE signing) wrapped by the SDK's Node provider. See [`CLAUDE.md`](./CLAUDE.md) for the full layout.
|
|
427
|
+
|
|
428
|
+
## Links
|
|
429
|
+
|
|
430
|
+
- Web: <https://run402.com>
|
|
431
|
+
- API docs (HTTP): <https://run402.com/llms.txt> · <https://run402.com/openapi.json>
|
|
432
|
+
- CLI docs: <https://run402.com/llms-cli.txt>
|
|
433
|
+
- Status: <https://api.run402.com/status>
|
|
434
|
+
- Health: <https://api.run402.com/health>
|
|
435
|
+
|
|
436
|
+
[简体中文](./README.zh-CN.md)
|
|
437
|
+
|
|
246
438
|
## License
|
|
247
439
|
|
|
248
440
|
MIT
|
package/dist/errors.d.ts
CHANGED
|
@@ -22,6 +22,9 @@ export declare function formatApiError(res: {
|
|
|
22
22
|
status: number;
|
|
23
23
|
body: unknown;
|
|
24
24
|
}, context: string): ToolResult;
|
|
25
|
+
export declare function formatCanonicalErrorContext(source: unknown, opts?: {
|
|
26
|
+
includeDetails?: boolean;
|
|
27
|
+
}): string[];
|
|
25
28
|
/**
|
|
26
29
|
* Consistent "project not found in key store" error.
|
|
27
30
|
*/
|
package/dist/errors.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,qDAAqD;AAQrD,uDAAuD;AACvD,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC/C,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,cAAc,CAC5B,GAAG,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,OAAO,CAAA;CAAE,EACtC,OAAO,EAAE,MAAM,GACd,UAAU,
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,qDAAqD;AAQrD,uDAAuD;AACvD,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC/C,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,cAAc,CAC5B,GAAG,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,OAAO,CAAA;CAAE,EACtC,OAAO,EAAE,MAAM,GACd,UAAU,CAsGZ;AAED,wBAAgB,2BAA2B,CACzC,MAAM,EAAE,OAAO,EACf,IAAI,GAAE;IAAE,cAAc,CAAC,EAAE,OAAO,CAAA;CAAO,GACtC,MAAM,EAAE,CAyBV;AAgGD;;GAEG;AACH,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,UAAU,CAY7D;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,GAAG,UAAU,CA4BrE"}
|