@gemmein/mcp 0.4.0 → 0.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.
Files changed (2) hide show
  1. package/dist/relays.js +28 -2
  2. package/package.json +2 -2
package/dist/relays.js CHANGED
@@ -34,11 +34,13 @@ const DURATION_RE = /^(\d{1,4})([hdw])$/;
34
34
  const MAX_MAP_ENTRIES = 20;
35
35
  const MAX_WHEN_ENTRIES = 20;
36
36
  const RECORD_KINDS = ["created", "updated", "deleted"];
37
- const ACTION_TYPES = ["write_record", "grant_access", "revoke_access", "email_person", "call_url", "grant_credits"];
37
+ const ACTION_TYPES = ["write_record", "grant_access", "revoke_access", "email_person", "call_url", "grant_credits", "fulfil_product", "refund_product"];
38
+ /** W9.5 — mirrors apps/api/src/relays/schema.ts. */
39
+ const PRODUCT_NAME_RE = /^[a-z0-9][a-z0-9 _.-]{0,39}$/i;
38
40
  // W9.3: a relay may grant a person up to 10,000 credits per action.
39
41
  const MAX_RELAY_CREDITS = 10000;
40
42
  const SCHEMES = ["hmac_sha256_header", "stripe", "svix", "shared_token"];
41
- const PERSON_ACTIONS = new Set(["grant_access", "grant_credits", "revoke_access", "email_person"]);
43
+ const PERSON_ACTIONS = new Set(["grant_access", "grant_credits", "revoke_access", "email_person", "fulfil_product", "refund_product"]);
42
44
  const ENTITLEMENT_KEY = /^access:[a-z0-9][a-z0-9._-]{0,63}$/;
43
45
  const RESERVED_FIELD_NAMES = new Set([
44
46
  "id", "appId", "app_id", "environmentId", "environment_id", "userId", "user_id", "ownerId", "ownerUserId", "owner_user_id",
@@ -310,6 +312,28 @@ function validateAction(raw, index, triggerKind) {
310
312
  const reason = optionalString(a, "reason", what, 200);
311
313
  return { type: "grant_credits", amount, ...(reason !== undefined ? { reason } : {}) };
312
314
  }
315
+ case "fulfil_product":
316
+ case "refund_product": {
317
+ // W9.5 — mirrors apps/api/src/relays/schema.ts (the lockstep test holds
318
+ // them equal): the product is a NAME, never a template; the payment
319
+ // reference may be a template, because it comes out of the event.
320
+ rejectUnknownKeys(a, ["type", "product", "ref"], what);
321
+ const product = a.product;
322
+ if (typeof product !== "string" || !PRODUCT_NAME_RE.test(product.trim())) {
323
+ refuse(`${what}.product must be a product name (1-40 letters, numbers, spaces, or -_.)`);
324
+ }
325
+ const rawRef = a.ref;
326
+ // A written ref that is empty is not the absent ref: absent means "make
327
+ // one from the event id", and a blank string would silently take that
328
+ // road instead of the one the founder wrote. Refused here.
329
+ if (rawRef !== undefined &&
330
+ rawRef !== null &&
331
+ (typeof rawRef !== "string" || rawRef.trim() === "" || rawRef.length > 200)) {
332
+ refuse(`${what}.ref must be text of at most 200 characters (templates allowed)`);
333
+ }
334
+ const ref = typeof rawRef === "string" ? rawRef : undefined;
335
+ return { type: a.type, product: product.trim(), ...(ref !== undefined ? { ref } : {}) };
336
+ }
313
337
  case "revoke_access": {
314
338
  rejectUnknownKeys(a, ["type", "entitlement"], what);
315
339
  return { type: "revoke_access", entitlement: validateEntitlementInput(a.entitlement, what) };
@@ -400,6 +424,8 @@ export function describeRelay(def) {
400
424
  case "write_record": return `write a ${a.collection} record${a.to === "person" ? " for the person" : ""}`;
401
425
  case "grant_access": return `grant ${entitlementWords(a.entitlement)}`;
402
426
  case "grant_credits": return `grant ${a.amount} credit${a.amount === 1 ? "" : "s"}`;
427
+ case "fulfil_product": return `fulfil ${a.product}`;
428
+ case "refund_product": return `refund ${a.product}`;
403
429
  case "revoke_access": return `revoke ${entitlementWords(a.entitlement)}`;
404
430
  case "email_person": return "email the person";
405
431
  case "call_url": return `call ${a.url}`;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gemmein/mcp",
3
- "version": "0.4.0",
3
+ "version": "0.5.0",
4
4
  "mcpName": "com.gemmein/mcp",
5
5
  "description": "Gemmein MCP server \u2014 gives coding agents the Gemmein guide, API reference, rule/error explainers, and a live integration check (reaffirm) as tools. Read-only: it never creates, edits, or deletes anything.",
6
6
  "license": "MIT",
@@ -34,7 +34,7 @@
34
34
  "prepublishOnly": "npm run build"
35
35
  },
36
36
  "dependencies": {
37
- "@gemmein/sdk": "^0.7.0",
37
+ "@gemmein/sdk": "^0.8.0",
38
38
  "@modelcontextprotocol/sdk": "^1.29.0"
39
39
  },
40
40
  "author": "Gemmein Limited",