@shaferllc/keel 0.83.4 → 0.83.5
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/dist/accounts/provider.js +12 -2
- package/dist/billing/provider.js +12 -2
- package/dist/mcp/cloud.d.ts +2 -1
- package/dist/mcp/cloud.js +117 -8
- package/dist/mcp/server.js +4 -2
- package/dist/teams/provider.js +12 -2
- package/docs/ai-manifest.json +1 -1
- package/docs/ai.md +19 -9
- package/docs/changelog.md +11 -0
- package/llms-full.txt +19 -9
- package/package.json +1 -1
|
@@ -15,7 +15,17 @@ import { defaultConfig, resolveConfig } from "./config.js";
|
|
|
15
15
|
import { accountsMigration } from "./migration.js";
|
|
16
16
|
import { registerAccountsRoutes } from "./routes.js";
|
|
17
17
|
import { setAccountStore, tableStore } from "./store.js";
|
|
18
|
-
|
|
18
|
+
function packageDir() {
|
|
19
|
+
try {
|
|
20
|
+
const url = import.meta.url;
|
|
21
|
+
if (!url)
|
|
22
|
+
return ".";
|
|
23
|
+
return dirname(fileURLToPath(url));
|
|
24
|
+
}
|
|
25
|
+
catch {
|
|
26
|
+
return ".";
|
|
27
|
+
}
|
|
28
|
+
}
|
|
19
29
|
export class AccountsServiceProvider extends PackageProvider {
|
|
20
30
|
name = "accounts";
|
|
21
31
|
config;
|
|
@@ -24,7 +34,7 @@ export class AccountsServiceProvider extends PackageProvider {
|
|
|
24
34
|
this.config = resolveConfig();
|
|
25
35
|
setAccountStore(tableStore(this.config.userTable));
|
|
26
36
|
this.migrations([accountsMigration(this.config.userTable)]);
|
|
27
|
-
this.publishes({ [join(
|
|
37
|
+
this.publishes({ [join(packageDir(), "accounts.config.stub")]: "config/accounts.ts" }, "accounts-config");
|
|
28
38
|
}
|
|
29
39
|
boot() {
|
|
30
40
|
if (!this.config.routes.enabled)
|
package/dist/billing/provider.js
CHANGED
|
@@ -17,7 +17,17 @@ import { BillingManager, setBilling } from "./manager.js";
|
|
|
17
17
|
import { registerDefaultGateways } from "./drivers/index.js";
|
|
18
18
|
import { billingMigration } from "./migration.js";
|
|
19
19
|
import { registerBillingRoutes } from "./routes.js";
|
|
20
|
-
|
|
20
|
+
function packageDir() {
|
|
21
|
+
try {
|
|
22
|
+
const url = import.meta.url;
|
|
23
|
+
if (!url)
|
|
24
|
+
return ".";
|
|
25
|
+
return dirname(fileURLToPath(url));
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
return ".";
|
|
29
|
+
}
|
|
30
|
+
}
|
|
21
31
|
export class BillingServiceProvider extends PackageProvider {
|
|
22
32
|
name = "billing";
|
|
23
33
|
config;
|
|
@@ -31,7 +41,7 @@ export class BillingServiceProvider extends PackageProvider {
|
|
|
31
41
|
this.app.instance(BillingManager, this.manager);
|
|
32
42
|
// Default billable table is `users`.
|
|
33
43
|
this.migrations([billingMigration("users")]);
|
|
34
|
-
this.publishes({ [join(
|
|
44
|
+
this.publishes({ [join(packageDir(), "billing.config.stub")]: "config/billing.ts" }, "billing-config");
|
|
35
45
|
}
|
|
36
46
|
boot() {
|
|
37
47
|
this.routes((r) => registerBillingRoutes(r, this.config.webhook.path));
|
package/dist/mcp/cloud.d.ts
CHANGED
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
* Keel Cloud MCP tools — registered only when KEEL_CLOUD_TOKEN is set.
|
|
3
3
|
*
|
|
4
4
|
* Talks to a Keel Cloud control plane over HTTP (Bearer token). Agents use these
|
|
5
|
-
* to create sites, preview/publish,
|
|
5
|
+
* to create sites, preview/publish, manage secrets/domains/billing, and export
|
|
6
|
+
* without leaving the IDE.
|
|
6
7
|
*/
|
|
7
8
|
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
8
9
|
/** Register Cloud tools on an existing MCP server when a Cloud token is present. */
|
package/dist/mcp/cloud.js
CHANGED
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
* Keel Cloud MCP tools — registered only when KEEL_CLOUD_TOKEN is set.
|
|
3
3
|
*
|
|
4
4
|
* Talks to a Keel Cloud control plane over HTTP (Bearer token). Agents use these
|
|
5
|
-
* to create sites, preview/publish,
|
|
5
|
+
* to create sites, preview/publish, manage secrets/domains/billing, and export
|
|
6
|
+
* without leaving the IDE.
|
|
6
7
|
*/
|
|
7
8
|
import { z } from "zod";
|
|
8
9
|
const PRESETS = ["minimal", "api", "app", "saas"];
|
|
@@ -42,18 +43,49 @@ function jsonText(data, isError = false) {
|
|
|
42
43
|
...(isError ? { isError: true } : {}),
|
|
43
44
|
};
|
|
44
45
|
}
|
|
46
|
+
function requireConfirm(confirm, action) {
|
|
47
|
+
if (confirm)
|
|
48
|
+
return null;
|
|
49
|
+
return jsonText({
|
|
50
|
+
error: `${action} requires confirm=true. Ask the user to confirm before calling again.`,
|
|
51
|
+
}, true);
|
|
52
|
+
}
|
|
45
53
|
/** Register Cloud tools on an existing MCP server when a Cloud token is present. */
|
|
46
54
|
export function registerCloudTools(server) {
|
|
47
55
|
if (!cloudConfig())
|
|
48
56
|
return false;
|
|
49
57
|
server.registerTool("keel_cloud_me", {
|
|
50
58
|
title: "Keel Cloud — who am I",
|
|
51
|
-
description: "Return the Keel Cloud user authenticated by KEEL_CLOUD_TOKEN.",
|
|
59
|
+
description: "Return the Keel Cloud user authenticated by KEEL_CLOUD_TOKEN (plan, site_limit, team_id). Token binds to the user's first team.",
|
|
52
60
|
inputSchema: {},
|
|
53
61
|
}, async () => {
|
|
54
62
|
const res = await cloudFetch("/api/v1/me");
|
|
55
63
|
return jsonText(res.body, !res.ok);
|
|
56
64
|
});
|
|
65
|
+
server.registerTool("keel_cloud_billing", {
|
|
66
|
+
title: "Keel Cloud — billing status",
|
|
67
|
+
description: "Current team plan (free|pro), site limits, custom-domain eligibility, and whether the caller is the owner.",
|
|
68
|
+
inputSchema: {},
|
|
69
|
+
}, async () => {
|
|
70
|
+
const res = await cloudFetch("/api/v1/billing");
|
|
71
|
+
return jsonText(res.body, !res.ok);
|
|
72
|
+
});
|
|
73
|
+
server.registerTool("keel_cloud_billing_checkout", {
|
|
74
|
+
title: "Keel Cloud — Stripe checkout URL",
|
|
75
|
+
description: "Create a Stripe Checkout session for Keel Cloud Pro (owner only). Return the url for the user to open — do not scrape cards.",
|
|
76
|
+
inputSchema: {},
|
|
77
|
+
}, async () => {
|
|
78
|
+
const res = await cloudFetch("/api/v1/billing/checkout", { method: "POST", body: "{}" });
|
|
79
|
+
return jsonText(res.body, !res.ok);
|
|
80
|
+
});
|
|
81
|
+
server.registerTool("keel_cloud_billing_portal", {
|
|
82
|
+
title: "Keel Cloud — Stripe customer portal URL",
|
|
83
|
+
description: "Open the Stripe customer portal URL for the team (owner only) to update card / cancel. Return the url for the user.",
|
|
84
|
+
inputSchema: {},
|
|
85
|
+
}, async () => {
|
|
86
|
+
const res = await cloudFetch("/api/v1/billing/portal", { method: "POST", body: "{}" });
|
|
87
|
+
return jsonText(res.body, !res.ok);
|
|
88
|
+
});
|
|
57
89
|
server.registerTool("keel_cloud_list_sites", {
|
|
58
90
|
title: "Keel Cloud — list sites",
|
|
59
91
|
description: "List sites on the current Keel Cloud team. Includes storage_path for local editing and hostnames.",
|
|
@@ -64,7 +96,7 @@ export function registerCloudTools(server) {
|
|
|
64
96
|
});
|
|
65
97
|
server.registerTool("keel_cloud_get_site", {
|
|
66
98
|
title: "Keel Cloud — get site",
|
|
67
|
-
description: "Fetch one Keel Cloud site by id (paths, hostnames, status).",
|
|
99
|
+
description: "Fetch one Keel Cloud site by id (paths, hostnames, status, git).",
|
|
68
100
|
inputSchema: {
|
|
69
101
|
site_id: z.number().int().describe("Site id from keel_cloud_list_sites"),
|
|
70
102
|
},
|
|
@@ -86,6 +118,36 @@ export function registerCloudTools(server) {
|
|
|
86
118
|
});
|
|
87
119
|
return jsonText(res.body, !res.ok);
|
|
88
120
|
});
|
|
121
|
+
server.registerTool("keel_cloud_delete_site", {
|
|
122
|
+
title: "Keel Cloud — soft-delete site",
|
|
123
|
+
description: "Soft-delete a site (detaches hostnames; recoverable within retention). Requires confirm=true.",
|
|
124
|
+
inputSchema: {
|
|
125
|
+
site_id: z.number().int().describe("Site id"),
|
|
126
|
+
confirm: z.boolean().describe("Must be true — ask the user before setting this"),
|
|
127
|
+
},
|
|
128
|
+
}, async ({ site_id, confirm }) => {
|
|
129
|
+
const blocked = requireConfirm(confirm, "Delete");
|
|
130
|
+
if (blocked)
|
|
131
|
+
return blocked;
|
|
132
|
+
const res = await cloudFetch(`/api/v1/sites/${site_id}/delete`, {
|
|
133
|
+
method: "POST",
|
|
134
|
+
body: JSON.stringify({ confirm: true }),
|
|
135
|
+
});
|
|
136
|
+
return jsonText(res.body, !res.ok);
|
|
137
|
+
});
|
|
138
|
+
server.registerTool("keel_cloud_restore_site", {
|
|
139
|
+
title: "Keel Cloud — restore soft-deleted site",
|
|
140
|
+
description: "Restore a soft-deleted site within the retention window. Redeploy to reattach hostnames.",
|
|
141
|
+
inputSchema: {
|
|
142
|
+
site_id: z.number().int().describe("Site id"),
|
|
143
|
+
},
|
|
144
|
+
}, async ({ site_id }) => {
|
|
145
|
+
const res = await cloudFetch(`/api/v1/sites/${site_id}/restore`, {
|
|
146
|
+
method: "POST",
|
|
147
|
+
body: "{}",
|
|
148
|
+
});
|
|
149
|
+
return jsonText(res.body, !res.ok);
|
|
150
|
+
});
|
|
89
151
|
server.registerTool("keel_cloud_preview", {
|
|
90
152
|
title: "Keel Cloud — deploy preview",
|
|
91
153
|
description: "Deploy the site's preview Worker (and attach preview hostname when Cloudflare is configured). Safe to call freely while iterating.",
|
|
@@ -106,11 +168,9 @@ export function registerCloudTools(server) {
|
|
|
106
168
|
.describe("Must be true to publish — ask the user before setting this"),
|
|
107
169
|
},
|
|
108
170
|
}, async ({ site_id, confirm }) => {
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
}, true);
|
|
113
|
-
}
|
|
171
|
+
const blocked = requireConfirm(confirm, "Publish");
|
|
172
|
+
if (blocked)
|
|
173
|
+
return blocked;
|
|
114
174
|
const res = await cloudFetch(`/api/v1/sites/${site_id}/publish`, {
|
|
115
175
|
method: "POST",
|
|
116
176
|
body: JSON.stringify({ confirm: true }),
|
|
@@ -127,6 +187,16 @@ export function registerCloudTools(server) {
|
|
|
127
187
|
const res = await cloudFetch(`/api/v1/sites/${site_id}/deploys`);
|
|
128
188
|
return jsonText(res.body, !res.ok);
|
|
129
189
|
});
|
|
190
|
+
server.registerTool("keel_cloud_list_secrets", {
|
|
191
|
+
title: "Keel Cloud — list secret keys",
|
|
192
|
+
description: "List vault key names for a site (values are never returned).",
|
|
193
|
+
inputSchema: {
|
|
194
|
+
site_id: z.number().int().describe("Site id"),
|
|
195
|
+
},
|
|
196
|
+
}, async ({ site_id }) => {
|
|
197
|
+
const res = await cloudFetch(`/api/v1/sites/${site_id}/secrets`);
|
|
198
|
+
return jsonText(res.body, !res.ok);
|
|
199
|
+
});
|
|
130
200
|
server.registerTool("keel_cloud_set_secret", {
|
|
131
201
|
title: "Keel Cloud — set secret",
|
|
132
202
|
description: "Store a secret in the site vault (never in git). Injected into the Worker on the next preview/publish.",
|
|
@@ -142,6 +212,45 @@ export function registerCloudTools(server) {
|
|
|
142
212
|
});
|
|
143
213
|
return jsonText(res.body, !res.ok);
|
|
144
214
|
});
|
|
215
|
+
server.registerTool("keel_cloud_delete_secret", {
|
|
216
|
+
title: "Keel Cloud — delete secret",
|
|
217
|
+
description: "Remove a secret key from the site vault.",
|
|
218
|
+
inputSchema: {
|
|
219
|
+
site_id: z.number().int().describe("Site id"),
|
|
220
|
+
key: z.string().min(1).describe("Secret key to remove"),
|
|
221
|
+
},
|
|
222
|
+
}, async ({ site_id, key }) => {
|
|
223
|
+
const res = await cloudFetch(`/api/v1/sites/${site_id}/secrets?key=${encodeURIComponent(key)}`, { method: "DELETE" });
|
|
224
|
+
return jsonText(res.body, !res.ok);
|
|
225
|
+
});
|
|
226
|
+
server.registerTool("keel_cloud_set_custom_domain", {
|
|
227
|
+
title: "Keel Cloud — set custom domain",
|
|
228
|
+
description: "Set a Pro custom hostname (CNAME instructions returned). Optionally attach=true to verify DNS and attach to the production Worker.",
|
|
229
|
+
inputSchema: {
|
|
230
|
+
site_id: z.number().int().describe("Site id"),
|
|
231
|
+
hostname: z.string().min(1).describe("Customer hostname, e.g. app.example.com"),
|
|
232
|
+
attach: z
|
|
233
|
+
.boolean()
|
|
234
|
+
.optional()
|
|
235
|
+
.describe("If true, verify DNS and attach Workers Custom Domain now"),
|
|
236
|
+
},
|
|
237
|
+
}, async ({ site_id, hostname, attach }) => {
|
|
238
|
+
const res = await cloudFetch(`/api/v1/sites/${site_id}/custom-domain`, {
|
|
239
|
+
method: "PUT",
|
|
240
|
+
body: JSON.stringify({ hostname, attach: Boolean(attach) }),
|
|
241
|
+
});
|
|
242
|
+
return jsonText(res.body, !res.ok);
|
|
243
|
+
});
|
|
244
|
+
server.registerTool("keel_cloud_clear_custom_domain", {
|
|
245
|
+
title: "Keel Cloud — clear custom domain",
|
|
246
|
+
description: "Detach and clear the site's custom hostname (Pro).",
|
|
247
|
+
inputSchema: {
|
|
248
|
+
site_id: z.number().int().describe("Site id"),
|
|
249
|
+
},
|
|
250
|
+
}, async ({ site_id }) => {
|
|
251
|
+
const res = await cloudFetch(`/api/v1/sites/${site_id}/custom-domain`, { method: "DELETE" });
|
|
252
|
+
return jsonText(res.body, !res.ok);
|
|
253
|
+
});
|
|
145
254
|
server.registerTool("keel_cloud_export", {
|
|
146
255
|
title: "Keel Cloud — export manifest",
|
|
147
256
|
description: "Return the site's export manifest (paths, hostnames, Keel version, SQL dump URLs). Use storage_path / git_url for code; use keel_cloud_export_sql for data.",
|
package/dist/mcp/server.js
CHANGED
|
@@ -190,12 +190,14 @@ export async function createServer() {
|
|
|
190
190
|
? [
|
|
191
191
|
"",
|
|
192
192
|
"## Keel Cloud (token detected)",
|
|
193
|
-
"Cloud tools are enabled.
|
|
193
|
+
"Cloud tools are enabled. Token binds to the user's first team.",
|
|
194
|
+
"Typical loop:",
|
|
194
195
|
"1. keel_cloud_create_site { name, preset }",
|
|
195
196
|
"2. Edit files at the returned storage_path (real Keel app)",
|
|
196
197
|
"3. keel_cloud_preview { site_id }",
|
|
197
198
|
"4. keel_cloud_publish { site_id, confirm: true } after user approval",
|
|
198
|
-
"Also:
|
|
199
|
+
"Also: me, billing(+checkout/portal), list/get/delete/restore sites,",
|
|
200
|
+
"secrets (list/set/delete), custom domain (set/clear), deploys, export(+sql).",
|
|
199
201
|
]
|
|
200
202
|
: []),
|
|
201
203
|
].join("\n");
|
package/dist/teams/provider.js
CHANGED
|
@@ -14,7 +14,17 @@ import { dirname, join } from "node:path";
|
|
|
14
14
|
import { PackageProvider } from "../core/package.js";
|
|
15
15
|
import { defaultConfig, resolveConfig } from "./config.js";
|
|
16
16
|
import { teamsMigration } from "./migration.js";
|
|
17
|
-
|
|
17
|
+
function packageDir() {
|
|
18
|
+
try {
|
|
19
|
+
const url = import.meta.url;
|
|
20
|
+
if (!url)
|
|
21
|
+
return ".";
|
|
22
|
+
return dirname(fileURLToPath(url));
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
return ".";
|
|
26
|
+
}
|
|
27
|
+
}
|
|
18
28
|
export class TeamsServiceProvider extends PackageProvider {
|
|
19
29
|
name = "teams";
|
|
20
30
|
config;
|
|
@@ -22,6 +32,6 @@ export class TeamsServiceProvider extends PackageProvider {
|
|
|
22
32
|
this.mergeConfig("teams", defaultConfig);
|
|
23
33
|
this.config = resolveConfig();
|
|
24
34
|
this.migrations([teamsMigration(this.config.userTable)]);
|
|
25
|
-
this.publishes({ [join(
|
|
35
|
+
this.publishes({ [join(packageDir(), "teams.config.stub")]: "config/teams.ts" }, "teams-config");
|
|
26
36
|
}
|
|
27
37
|
}
|
package/docs/ai-manifest.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@shaferllc/keel",
|
|
3
|
-
"version": "0.83.
|
|
3
|
+
"version": "0.83.5",
|
|
4
4
|
"description": "The house framework for Node.js — a service container, providers, routing, JSX views, and a code-generating console.",
|
|
5
5
|
"repo": "https://github.com/shaferllc/keel",
|
|
6
6
|
"generated": "run `npm run build:ai` to regenerate",
|
package/docs/ai.md
CHANGED
|
@@ -62,18 +62,23 @@ package, so it always matches your installed version.
|
|
|
62
62
|
| `keel_scaffold` | Generate a controller/provider/middleware/factory/seeder/job/notification/transformer stub. Returns code + target path — it does **not** write to disk. |
|
|
63
63
|
|
|
64
64
|
When `KEEL_CLOUD_TOKEN` (and optional `KEEL_CLOUD_URL`) is set, Cloud tools are
|
|
65
|
-
also registered
|
|
65
|
+
also registered. Create a token at `/tokens` on the control plane — the plaintext
|
|
66
|
+
looks like `keel_<selector>.<verifier>`.
|
|
66
67
|
|
|
67
68
|
| Tool | What it does |
|
|
68
69
|
|------|--------------|
|
|
69
|
-
| `keel_cloud_me` | Authenticated Cloud user |
|
|
70
|
-
| `
|
|
70
|
+
| `keel_cloud_me` | Authenticated Cloud user (plan, site limit, team) |
|
|
71
|
+
| `keel_cloud_billing` | Team plan / limits / owner flag |
|
|
72
|
+
| `keel_cloud_billing_checkout` / `_portal` | Stripe Checkout or Customer Portal URL (owner) |
|
|
73
|
+
| `keel_cloud_list_sites` / `keel_cloud_get_site` | List or fetch a site (`storage_path`, hostnames, git) |
|
|
71
74
|
| `keel_cloud_create_site` | Create from preset (`minimal` \| `api` \| `app` \| `saas`) |
|
|
75
|
+
| `keel_cloud_delete_site` / `keel_cloud_restore_site` | Soft-delete (confirm) / restore |
|
|
72
76
|
| `keel_cloud_preview` | Deploy preview Worker |
|
|
73
77
|
| `keel_cloud_publish` | Publish production — requires `confirm: true` |
|
|
74
|
-
| `
|
|
75
|
-
| `
|
|
76
|
-
| `
|
|
78
|
+
| `keel_cloud_deploys` | Deploy history + logs |
|
|
79
|
+
| `keel_cloud_list_secrets` / `keel_cloud_set_secret` / `keel_cloud_delete_secret` | Vault keys (values never returned) |
|
|
80
|
+
| `keel_cloud_set_custom_domain` / `keel_cloud_clear_custom_domain` | Pro custom hostname (+ optional attach) |
|
|
81
|
+
| `keel_cloud_export` / `keel_cloud_export_sql` | Export manifest / portable `.sql` dump |
|
|
77
82
|
|
|
78
83
|
```json
|
|
79
84
|
{
|
|
@@ -82,7 +87,7 @@ also registered:
|
|
|
82
87
|
"command": "npx",
|
|
83
88
|
"args": ["-y", "keel-mcp"],
|
|
84
89
|
"env": {
|
|
85
|
-
"KEEL_CLOUD_TOKEN": "
|
|
90
|
+
"KEEL_CLOUD_TOKEN": "keel_….…",
|
|
86
91
|
"KEEL_CLOUD_URL": "https://app.keeljs.cloud"
|
|
87
92
|
}
|
|
88
93
|
}
|
|
@@ -90,6 +95,8 @@ also registered:
|
|
|
90
95
|
}
|
|
91
96
|
```
|
|
92
97
|
|
|
98
|
+
The token binds to the user's **first team**. Switch teams in the dashboard before
|
|
99
|
+
minting a token if you need a different team context.
|
|
93
100
|
### Resources
|
|
94
101
|
|
|
95
102
|
- `keel://overview` — the same orientation text as `keel_overview`
|
|
@@ -108,8 +115,11 @@ also registered:
|
|
|
108
115
|
|
|
109
116
|
1. `keel_cloud_create_site { name: "Acme", preset: "app" }`
|
|
110
117
|
2. Edit the returned `storage_path` (real Keel app + git)
|
|
111
|
-
3. `
|
|
112
|
-
4. `
|
|
118
|
+
3. `keel_cloud_set_secret` for env the Worker needs
|
|
119
|
+
4. `keel_cloud_preview { site_id }`
|
|
120
|
+
5. `keel_cloud_publish { site_id, confirm: true }` after the user approves
|
|
121
|
+
6. Optional Pro: `keel_cloud_set_custom_domain { hostname, attach: true }`
|
|
122
|
+
7. Escape hatch anytime: `keel_cloud_export` + `keel_cloud_export_sql`
|
|
113
123
|
|
|
114
124
|
## `llms.txt` and `llms-full.txt`
|
|
115
125
|
|
package/docs/changelog.md
CHANGED
|
@@ -4,6 +4,17 @@ All notable changes to Keel are documented here. The format follows
|
|
|
4
4
|
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and the project aims to
|
|
5
5
|
adhere to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
6
6
|
|
|
7
|
+
## [0.83.5] — 2026-07-13
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- **Full Keel Cloud MCP surface** — billing status/checkout/portal, soft-delete
|
|
12
|
+
and restore sites, list/delete secrets, set/clear custom domains. Documented in
|
|
13
|
+
[Building with AI](./docs/ai.md). Pairs with expanded `/api/v1` routes on Keel
|
|
14
|
+
Cloud.
|
|
15
|
+
|
|
16
|
+
[0.83.5]: https://github.com/shaferllc/keel/releases/tag/v0.83.5
|
|
17
|
+
|
|
7
18
|
## [0.83.4] — 2026-07-13
|
|
8
19
|
|
|
9
20
|
### Added
|
package/llms-full.txt
CHANGED
|
@@ -4726,18 +4726,23 @@ package, so it always matches your installed version.
|
|
|
4726
4726
|
| `keel_scaffold` | Generate a controller/provider/middleware/factory/seeder/job/notification/transformer stub. Returns code + target path — it does **not** write to disk. |
|
|
4727
4727
|
|
|
4728
4728
|
When `KEEL_CLOUD_TOKEN` (and optional `KEEL_CLOUD_URL`) is set, Cloud tools are
|
|
4729
|
-
also registered
|
|
4729
|
+
also registered. Create a token at `/tokens` on the control plane — the plaintext
|
|
4730
|
+
looks like `keel_<selector>.<verifier>`.
|
|
4730
4731
|
|
|
4731
4732
|
| Tool | What it does |
|
|
4732
4733
|
|------|--------------|
|
|
4733
|
-
| `keel_cloud_me` | Authenticated Cloud user |
|
|
4734
|
-
| `
|
|
4734
|
+
| `keel_cloud_me` | Authenticated Cloud user (plan, site limit, team) |
|
|
4735
|
+
| `keel_cloud_billing` | Team plan / limits / owner flag |
|
|
4736
|
+
| `keel_cloud_billing_checkout` / `_portal` | Stripe Checkout or Customer Portal URL (owner) |
|
|
4737
|
+
| `keel_cloud_list_sites` / `keel_cloud_get_site` | List or fetch a site (`storage_path`, hostnames, git) |
|
|
4735
4738
|
| `keel_cloud_create_site` | Create from preset (`minimal` \| `api` \| `app` \| `saas`) |
|
|
4739
|
+
| `keel_cloud_delete_site` / `keel_cloud_restore_site` | Soft-delete (confirm) / restore |
|
|
4736
4740
|
| `keel_cloud_preview` | Deploy preview Worker |
|
|
4737
4741
|
| `keel_cloud_publish` | Publish production — requires `confirm: true` |
|
|
4738
|
-
| `
|
|
4739
|
-
| `
|
|
4740
|
-
| `
|
|
4742
|
+
| `keel_cloud_deploys` | Deploy history + logs |
|
|
4743
|
+
| `keel_cloud_list_secrets` / `keel_cloud_set_secret` / `keel_cloud_delete_secret` | Vault keys (values never returned) |
|
|
4744
|
+
| `keel_cloud_set_custom_domain` / `keel_cloud_clear_custom_domain` | Pro custom hostname (+ optional attach) |
|
|
4745
|
+
| `keel_cloud_export` / `keel_cloud_export_sql` | Export manifest / portable `.sql` dump |
|
|
4741
4746
|
|
|
4742
4747
|
```json
|
|
4743
4748
|
{
|
|
@@ -4746,7 +4751,7 @@ also registered:
|
|
|
4746
4751
|
"command": "npx",
|
|
4747
4752
|
"args": ["-y", "keel-mcp"],
|
|
4748
4753
|
"env": {
|
|
4749
|
-
"KEEL_CLOUD_TOKEN": "
|
|
4754
|
+
"KEEL_CLOUD_TOKEN": "keel_….…",
|
|
4750
4755
|
"KEEL_CLOUD_URL": "https://app.keeljs.cloud"
|
|
4751
4756
|
}
|
|
4752
4757
|
}
|
|
@@ -4754,6 +4759,8 @@ also registered:
|
|
|
4754
4759
|
}
|
|
4755
4760
|
```
|
|
4756
4761
|
|
|
4762
|
+
The token binds to the user's **first team**. Switch teams in the dashboard before
|
|
4763
|
+
minting a token if you need a different team context.
|
|
4757
4764
|
### Resources
|
|
4758
4765
|
|
|
4759
4766
|
- `keel://overview` — the same orientation text as `keel_overview`
|
|
@@ -4772,8 +4779,11 @@ also registered:
|
|
|
4772
4779
|
|
|
4773
4780
|
1. `keel_cloud_create_site { name: "Acme", preset: "app" }`
|
|
4774
4781
|
2. Edit the returned `storage_path` (real Keel app + git)
|
|
4775
|
-
3. `
|
|
4776
|
-
4. `
|
|
4782
|
+
3. `keel_cloud_set_secret` for env the Worker needs
|
|
4783
|
+
4. `keel_cloud_preview { site_id }`
|
|
4784
|
+
5. `keel_cloud_publish { site_id, confirm: true }` after the user approves
|
|
4785
|
+
6. Optional Pro: `keel_cloud_set_custom_domain { hostname, attach: true }`
|
|
4786
|
+
7. Escape hatch anytime: `keel_cloud_export` + `keel_cloud_export_sql`
|
|
4777
4787
|
|
|
4778
4788
|
## `llms.txt` and `llms-full.txt`
|
|
4779
4789
|
|
package/package.json
CHANGED