@homespunapps/mcp 1.6.16 → 1.6.18
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/tools.js +16 -15
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +2 -2
- package/server.json +2 -2
package/dist/tools.js
CHANGED
|
@@ -170,7 +170,7 @@ const deployAppShape = {
|
|
|
170
170
|
dry_run: z
|
|
171
171
|
.boolean()
|
|
172
172
|
.optional()
|
|
173
|
-
.describe("Validate only: run the full manifest + asset-shape validation, the compat gate (for a redeploy), and the schedule-timezone advisory, then return { ok, warnings, compat?, breaks? } WITHOUT creating a version or mutating anything. An invalid manifest returns the SAME error a real deploy would; a
|
|
173
|
+
.describe("Validate only: run the full manifest + asset-shape validation, the compat gate (for a redeploy), and the schedule-timezone advisory, then return { ok, warnings, compat?, breaks? } WITHOUT creating a version or mutating anything. An invalid manifest returns the SAME error a real deploy would; a redeploy the compat gate would refuse reports the break instead of applying it. `check` is an accepted alias."),
|
|
174
174
|
check: z.boolean().optional().describe("Alias for `dry_run`."),
|
|
175
175
|
manifest: jsonObjectSchema.describe("The x-homespun-manifest capability document (a JSON object). Eight extension keys: app metadata; collections (+ per-collection write/update/read/delete role lists, where write gates creates and also updates unless the optional update list is declared); externalHosts (fetch allowlist); cdn (allow CDN scripts/styles); capabilities (Permissions-Policy opt-ins); embeds (iframe frame-src allowlist); notify (email-on-row rules); webhooks (signed HTTP POST on-row rules). Call get_skill for the full grammar before authoring one from scratch."),
|
|
176
176
|
visibility: z
|
|
@@ -184,7 +184,7 @@ const deployAppShape = {
|
|
|
184
184
|
force: z
|
|
185
185
|
.boolean()
|
|
186
186
|
.optional()
|
|
187
|
-
.describe("REDEPLOY only. Bypass the compat gate on a narrowing
|
|
187
|
+
.describe("REDEPLOY only. Bypass the compat gate, whether it fired on a stranded-rows narrowing or on a widening of what the install screen discloses (a removed collection is detached, never deleted)."),
|
|
188
188
|
assets: z
|
|
189
189
|
.array(z.union([
|
|
190
190
|
z.object({
|
|
@@ -336,7 +336,7 @@ const appsShape = {
|
|
|
336
336
|
const membersShape = {
|
|
337
337
|
action: z
|
|
338
338
|
.enum(["add", "list", "set_role", "remove", "roles"])
|
|
339
|
-
.describe("add: invite-or-attach a member by email (app_id+email; optional
|
|
339
|
+
.describe("add: invite-or-attach a member by email (app_id+email; optional custom_roles). list: the app's owner + members (app_id). set_role: replace an existing member's declared roles in place without signing them out (app_id+human_id+custom_roles, an empty list to clear). remove: drop a member (app_id+human_id). roles: the app's declared roles with what each one includes and, per collection, the EFFECTIVE access a holder has (separately for members and grant-link holders, whose role floors differ) plus how many members and live grant links hold each role (app_id)."),
|
|
340
340
|
app_id: z.string().min(1).describe("The app id."),
|
|
341
341
|
email: z
|
|
342
342
|
.string()
|
|
@@ -346,11 +346,10 @@ const membersShape = {
|
|
|
346
346
|
.enum(["member"])
|
|
347
347
|
.optional()
|
|
348
348
|
.describe("add only. Defaults to 'member' server-side — no other role is assignable via this API (ownership transfer is not available here)."),
|
|
349
|
-
|
|
350
|
-
.string()
|
|
351
|
-
.nullable()
|
|
349
|
+
custom_roles: z
|
|
350
|
+
.array(z.string())
|
|
352
351
|
.optional()
|
|
353
|
-
.describe("add (optional) and set_role (required).
|
|
352
|
+
.describe("add (optional) and set_role (required). The DECLARED roles (x-homespun-manifest.roles keys) attached to the member ALONGSIDE their base member powers. A member may hold several and holds the union of what each grants, plus everything those roles `includes`. A built-in/reserved role or an undeclared role is rejected. Omit on add for an ordinary member; pass [] on set_role to clear the roles back to a plain member."),
|
|
354
353
|
human_id: z
|
|
355
354
|
.string()
|
|
356
355
|
.optional()
|
|
@@ -765,7 +764,7 @@ export const TOOLS = [
|
|
|
765
764
|
// ----- v2 app lifecycle + data (discrete, hot-path) -----------------------
|
|
766
765
|
{
|
|
767
766
|
name: "deploy_app",
|
|
768
|
-
description: 'Deploy a v2 app: an HTML document + a capability manifest, hosted at its own URL. The manifest has eight extension keys: app metadata; collections (+ per-collection write/update/read/delete role lists, where write gates creates and also updates unless the optional update list is declared; declare update:["creator"] on any collection whose rows belong to one person, or every caller admitted by write can overwrite every row); externalHosts (fetch allowlist); cdn (allow CDN scripts/styles); capabilities (Permissions-Policy opt-ins); embeds (iframe frame-src allowlist); notify (email-on-row rules); webhooks (signed HTTP POST on-row rules). Pass EITHER no `app_id` (create, mints a slug + URL) OR `app_id` (redeploy an existing app with new content). Supply the HTML as INLINE `html` OR as `html_path` (an absolute path read on the MCP-SERVER host, which is the relay for a hosted connector or your CLI host for a locally-run one, NOT the remote agent\'s machine; use it to avoid retransmitting a large HTML file every deploy, but only a locally-run connector can read it, and if both are given inline `html` wins). Pass `dry_run:true` (alias `check`) to VALIDATE ONLY: it runs the full manifest + asset-shape validation, the redeploy compat gate, and the schedule-timezone advisory, then returns { ok, warnings, compat?, breaks? } WITHOUT creating a version or mutating anything. A redeploy
|
|
767
|
+
description: 'Deploy a v2 app: an HTML document + a capability manifest, hosted at its own URL. The manifest has eight extension keys: app metadata; collections (+ per-collection write/update/read/delete role lists, where write gates creates and also updates unless the optional update list is declared; declare update:["creator"] on any collection whose rows belong to one person, or every caller admitted by write can overwrite every row); externalHosts (fetch allowlist); cdn (allow CDN scripts/styles); capabilities (Permissions-Policy opt-ins); embeds (iframe frame-src allowlist); notify (email-on-row rules); webhooks (signed HTTP POST on-row rules). Pass EITHER no `app_id` (create, mints a slug + URL) OR `app_id` (redeploy an existing app with new content). Supply the HTML as INLINE `html` OR as `html_path` (an absolute path read on the MCP-SERVER host, which is the relay for a hosted connector or your CLI host for a locally-run one, NOT the remote agent\'s machine; use it to avoid retransmitting a large HTML file every deploy, but only a locally-run connector can read it, and if both are given inline `html` wins). Pass `dry_run:true` (alias `check`) to VALIDATE ONLY: it runs the full manifest + asset-shape validation, the redeploy compat gate, and the schedule-timezone advisory, then returns { ok, warnings, compat?, breaks? } WITHOUT creating a version or mutating anything. A redeploy is refused with manifest_incompatible_redeploy (unless force:true) when it would strand rows already written (drops a collection, tightens a schema, flips appendOnly) or when it would WIDEN what the app\'s install screen discloses (some collection reaching further than the live manifest, e.g. read going to ["anyone"]); the break quotes the sentence a user would now be asked to approve. Taking access away never asks: dropping a role, or adding update:["creator"] to a write:["anyone"] collection, redeploys clean. A removed collection is detached, never deleted. Ship images/fonts/audio/video/data FILES with the app in the SAME call via `assets[]`: each is validated + stored app-scoped and served at its `path` on the app\'s own origin, so the HTML references it by a stable same-origin path (`<img src="frames/000.jpg">`, `<video src="media/clip.mp4">`), media and font paths support HTTP Range for seeking. A redeploy\'s assets replace the previous version\'s set. BEFORE authoring: call get_skill for the manifest grammar. Returns { app_id, slug, url, version, visibility, created } (create) or { app_id, version, compat, breaks? } (redeploy).',
|
|
769
768
|
inputSchema: deployAppShape,
|
|
770
769
|
annotations: {
|
|
771
770
|
title: "Deploy App",
|
|
@@ -1119,8 +1118,10 @@ export const TOOLS = [
|
|
|
1119
1118
|
...(args["role"] !== undefined
|
|
1120
1119
|
? { role: args["role"] }
|
|
1121
1120
|
: {}),
|
|
1122
|
-
...(args["
|
|
1123
|
-
? {
|
|
1121
|
+
...(args["custom_roles"] !== undefined
|
|
1122
|
+
? {
|
|
1123
|
+
customRoles: args["custom_roles"].map(String),
|
|
1124
|
+
}
|
|
1124
1125
|
: {}),
|
|
1125
1126
|
}));
|
|
1126
1127
|
}
|
|
@@ -1132,14 +1133,14 @@ export const TOOLS = [
|
|
|
1132
1133
|
if (str(args, "human_id") === undefined) {
|
|
1133
1134
|
return invalidArgs("set_role requires `human_id`");
|
|
1134
1135
|
}
|
|
1135
|
-
// The key must be PRESENT:
|
|
1136
|
+
// The key must be PRESENT: [] means "clear the roles", which is a
|
|
1136
1137
|
// real instruction, so an omitted key cannot be read as one.
|
|
1137
|
-
const
|
|
1138
|
-
if (
|
|
1139
|
-
return invalidArgs("set_role requires `
|
|
1138
|
+
const roles = args["custom_roles"];
|
|
1139
|
+
if (!Array.isArray(roles)) {
|
|
1140
|
+
return invalidArgs("set_role requires `custom_roles` (a list of declared role names, or [] to clear them)");
|
|
1140
1141
|
}
|
|
1141
1142
|
return jsonResult(await client.setAppMemberRole(appId, String(args["human_id"]), {
|
|
1142
|
-
|
|
1143
|
+
customRoles: roles.map(String),
|
|
1143
1144
|
}));
|
|
1144
1145
|
}
|
|
1145
1146
|
case "remove": {
|
package/dist/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const VERSION = "1.6.
|
|
1
|
+
export declare const VERSION = "1.6.18";
|
package/dist/version.js
CHANGED
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@homespunapps/mcp",
|
|
3
3
|
"mcpName": "dev.homespun/homespun",
|
|
4
|
-
"version": "1.6.
|
|
4
|
+
"version": "1.6.18",
|
|
5
5
|
"description": "Model Context Protocol (stdio) server for Homespun: lets any MCP client (Claude Desktop, Cursor, …) deploy a multi-user web app with hosting, auth, a shared database and permissions included.",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"type": "module",
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
},
|
|
47
47
|
"dependencies": {
|
|
48
48
|
"@modelcontextprotocol/sdk": "^1.20.0",
|
|
49
|
-
"@homespunapps/core": "^1.6.
|
|
49
|
+
"@homespunapps/core": "^1.6.18",
|
|
50
50
|
"zod": "^4.4.3"
|
|
51
51
|
},
|
|
52
52
|
"devDependencies": {
|
package/server.json
CHANGED
|
@@ -3,14 +3,14 @@
|
|
|
3
3
|
"name": "dev.homespun/homespun",
|
|
4
4
|
"title": "Homespun",
|
|
5
5
|
"description": "Deploy a multi-user web app from your agent: hosting, auth, database, and permissions.",
|
|
6
|
-
"version": "1.6.
|
|
6
|
+
"version": "1.6.18",
|
|
7
7
|
"websiteUrl": "https://docs.homespun.dev",
|
|
8
8
|
"packages": [
|
|
9
9
|
{
|
|
10
10
|
"registryType": "npm",
|
|
11
11
|
"registryBaseUrl": "https://registry.npmjs.org",
|
|
12
12
|
"identifier": "@homespunapps/mcp",
|
|
13
|
-
"version": "1.6.
|
|
13
|
+
"version": "1.6.18",
|
|
14
14
|
"transport": {
|
|
15
15
|
"type": "stdio"
|
|
16
16
|
},
|