@gemmein/mcp 0.6.0 → 0.7.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 +8 -1
  2. package/package.json +2 -2
package/dist/relays.js CHANGED
@@ -41,6 +41,9 @@ const PRODUCT_NAME_RE = /^[a-z0-9][a-z0-9 _.-]{0,39}$/i;
41
41
  const MAX_RELAY_CREDITS = 10000;
42
42
  const SCHEMES = ["hmac_sha256_header", "stripe", "svix", "shared_token"];
43
43
  const PERSON_ACTIONS = new Set(["grant_access", "grant_credits", "revoke_access", "email_person", "fulfil_product", "refund_product"]);
44
+ /** W10 §1 E — mirrors apps/api/src/relays/schema.ts. */
45
+ const PERSON_MAP_KEYS = ["person_email", "person_id", "person_token"];
46
+ const PERSON_KEYS_SENTENCE = "person_email (their address, which invites someone who has never signed in), person_id (a gemmein person id) or person_token (the store account token their app filed with a store)";
44
47
  const ENTITLEMENT_KEY = /^access:[a-z0-9][a-z0-9._-]{0,63}$/;
45
48
  const RESERVED_FIELD_NAMES = new Set([
46
49
  "id", "appId", "app_id", "environmentId", "environment_id", "userId", "user_id", "ownerId", "ownerUserId", "owner_user_id",
@@ -179,6 +182,10 @@ function validateReceiver(t) {
179
182
  refuse(`trigger.map.${key} walks through "${path.split(".").find((seg) => isUnsafeName(seg))}", which is never a field`);
180
183
  map[key] = path;
181
184
  }
185
+ const named = PERSON_MAP_KEYS.filter((k) => k in map);
186
+ if (named.length > 1) {
187
+ refuse(`trigger.map names ${named.join(" and ")} — a map names the person ONE way: ${PERSON_KEYS_SENTENCE}. Keep the one your provider actually sends and delete the others.`);
188
+ }
182
189
  }
183
190
  let when;
184
191
  if (t.when !== undefined) {
@@ -263,7 +270,7 @@ function validateAction(raw, index, triggerKind) {
263
270
  refuse(`${what}.type "${type}" is not an action the engine has — the verbs are ${ACTION_TYPES.join(", ")}; anything else is compute, and compute runs on your own server behind call_url`);
264
271
  }
265
272
  if (triggerKind === "schedule" && PERSON_ACTIONS.has(type)) {
266
- refuse(`${what}: a schedule has no person, so ${type} has no one to act on — trigger it from a receiver whose map names person_email, or from a data_change on a collection whose records have an owner`);
273
+ refuse(`${what}: a schedule has no person, so ${type} has no one to act on — trigger it from a receiver whose map names ${PERSON_KEYS_SENTENCE}, or from a data_change on a collection whose records have an owner`);
267
274
  }
268
275
  switch (type) {
269
276
  case "write_record": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gemmein/mcp",
3
- "version": "0.6.0",
3
+ "version": "0.7.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.9.0",
37
+ "@gemmein/sdk": "^0.10.0",
38
38
  "@modelcontextprotocol/sdk": "^1.29.0"
39
39
  },
40
40
  "author": "Gemmein Limited",