@homespunapps/mcp 1.4.3 → 1.5.0

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 CHANGED
@@ -348,13 +348,21 @@ const membersShape = {
348
348
  };
349
349
  const ingestShape = {
350
350
  action: z
351
- .enum(["list", "rotate"])
352
- .describe("list: the app's inbound catch-hooks, each with its full secret URL, current rule (collection/mode/wake/handshake), and per-status delivery counts (app_id). rotate: mint a fresh secret for one hook and return its new URL once, invalidating the old URL immediately (app_id+name)."),
351
+ .enum(["list", "rotate", "set_signing_secret", "clear_signing_secret"])
352
+ .describe("list: the app's inbound catch-hooks, each with its full secret URL, current rule (collection/mode/wake/handshake), and per-status delivery counts (app_id). rotate: mint a fresh URL secret for one hook and return its new URL once, invalidating the old URL immediately (app_id+name). set_signing_secret: provision or rotate a hook's OPT-IN signing secret, distinct from the URL secret (it is what a provider HMACs the body with); omit `secret` to mint one (returned ONCE) or pass `secret` to store a provider-generated value verbatim (never echoed) (app_id+name). clear_signing_secret: remove a hook's signing secret (app_id+name)."),
353
353
  app_id: z.string().min(1).describe("The app id."),
354
354
  name: z
355
355
  .string()
356
356
  .optional()
357
- .describe("rotate only. The manifest ingest hook name to rotate (an x-homespun-manifest.ingest[].name). See list's `name` field."),
357
+ .describe("rotate / set_signing_secret / clear_signing_secret. The manifest ingest hook name (an x-homespun-manifest.ingest[].name). See list's `name` field."),
358
+ secret: z
359
+ .string()
360
+ .optional()
361
+ .describe("set_signing_secret only. A provider-generated signing secret to store verbatim (the Stripe path). Omit to have the relay mint one (the GitHub path), returned ONCE in the response."),
362
+ grace_seconds: z
363
+ .number()
364
+ .optional()
365
+ .describe("set_signing_secret only. On a rotation, how long the previous secret stays valid so deliveries verify while you update the provider (default 3600, max 86400)."),
358
366
  };
359
367
  // ===========================================================================
360
368
  // Consolidated management tools
@@ -1219,7 +1227,7 @@ export const TOOLS = [
1219
1227
  // ----- consolidated management tools --------------------------------------
1220
1228
  {
1221
1229
  name: "ingest",
1222
- description: "Manage a v2 app's inbound catch-hooks (inbound-webhooks). A catch-hook lets an EXTERNAL system (Stripe, Zapier, Make, Home Assistant, an email router) POST JSON to a secret URL that writes into a declared collection, so the app receives data even with no agent online. Hooks are DECLARED IN THE MANIFEST (x-homespun-manifest.ingest) and materialized at deploy, so this tool has no create/delete: use it to READ BACK the URL and rotate a leaked one. ONE tool with an `action` enum: list (the app's hooks, each with its full secret URL, current rule collection/mode/wake/handshake, and per-status delivery counts) | rotate (mint a fresh secret for one hook by name and return its NEW url once; the old url stops working immediately, no redeploy needed). After deploying a manifest that declares a hook, run list and tell the owner the exact url to paste into the external system.",
1230
+ description: "Manage a v2 app's inbound catch-hooks (inbound-webhooks). A catch-hook lets an EXTERNAL system (Stripe, Zapier, Make, Home Assistant, an email router) POST JSON to a secret URL that writes into a declared collection, so the app receives data even with no agent online. Hooks are DECLARED IN THE MANIFEST (x-homespun-manifest.ingest) and materialized at deploy, so this tool has no create/delete: use it to READ BACK the URL, rotate a leaked one, and manage the opt-in signing secret. ONE tool with an `action` enum: list (the app's hooks, each with its full secret URL, current rule collection/mode/wake/handshake, per-status delivery counts, and signing-secret state) | rotate (mint a fresh URL secret for one hook by name and return its NEW url once; the old url stops working immediately, no redeploy needed) | set_signing_secret (provision/rotate a hook's signing secret, a DIFFERENT secret from the URL: what a provider HMACs the body with; omit `secret` to mint one returned ONCE, or pass `secret` to store a provider value verbatim, never echoed) | clear_signing_secret (remove it). Signature verification ships DARK for now: nothing verifies a signature yet. After deploying a manifest that declares a hook, run list and tell the owner the exact url to paste into the external system.",
1223
1231
  inputSchema: ingestShape,
1224
1232
  // Consolidated tool: read action (list) + a mutating one (rotate). Marked
1225
1233
  // destructive (not read-only) because rotate invalidates the old URL, which
@@ -1248,6 +1256,23 @@ export const TOOLS = [
1248
1256
  }
1249
1257
  return jsonResult(await client.rotateIngestHook(appId, String(args["name"])));
1250
1258
  }
1259
+ case "set_signing_secret": {
1260
+ if (str(args, "name") === undefined) {
1261
+ return invalidArgs("set_signing_secret requires `name`");
1262
+ }
1263
+ const secret = str(args, "secret");
1264
+ const grace = args["grace_seconds"];
1265
+ return jsonResult(await client.setIngestSigningSecret(appId, String(args["name"]), {
1266
+ ...(secret !== undefined ? { secret } : {}),
1267
+ ...(typeof grace === "number" ? { graceSeconds: grace } : {}),
1268
+ }));
1269
+ }
1270
+ case "clear_signing_secret": {
1271
+ if (str(args, "name") === undefined) {
1272
+ return invalidArgs("clear_signing_secret requires `name`");
1273
+ }
1274
+ return jsonResult(await client.clearIngestSigningSecret(appId, String(args["name"])));
1275
+ }
1251
1276
  default:
1252
1277
  return invalidArgs(`unknown ingest action '${action}'`);
1253
1278
  }
package/dist/version.d.ts CHANGED
@@ -1 +1 @@
1
- export declare const VERSION = "1.4.3";
1
+ export declare const VERSION = "1.5.0";
package/dist/version.js CHANGED
@@ -1,3 +1,3 @@
1
1
  // Single source of the package version, reported in the MCP server's
2
2
  // serverInfo. Kept in sync with package.json by the release tooling.
3
- export const VERSION = "1.4.3";
3
+ export const VERSION = "1.5.0";
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@homespunapps/mcp",
3
3
  "mcpName": "dev.homespun/homespun",
4
- "version": "1.4.3",
4
+ "version": "1.5.0",
5
5
  "description": "Model Context Protocol (stdio) server for Homespun: lets any MCP client (Claude Desktop, Cursor, …) hand a human a rich interactive UI by URL and get structured data back.",
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.4.3",
49
+ "@homespunapps/core": "^1.5.0",
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": "Hand a human a rich interactive UI by URL and get structured data back, from any MCP client.",
6
- "version": "1.4.3",
6
+ "version": "1.5.0",
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.4.3",
13
+ "version": "1.5.0",
14
14
  "transport": {
15
15
  "type": "stdio"
16
16
  },