@enfyra/mcp-server 0.0.21 → 0.0.22

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@enfyra/mcp-server",
3
- "version": "0.0.21",
3
+ "version": "0.0.22",
4
4
  "description": "MCP server for Enfyra - manage your Enfyra instance via Claude Code",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -84,6 +84,12 @@ export function buildMcpServerInstructions(apiBaseUrl) {
84
84
  '- **Right:** `"publishedMethods": [{"id": 1}]` (publishes GET). Multiple: `[{"id": 1}, {"id": 2}]` (publishes GET + POST).',
85
85
  '- **To unset:** pass empty array `"publishedMethods": []`.',
86
86
  '',
87
+ '### Dynamic script `$repos` mutation return shape',
88
+ '- In handler/hook/flow/websocket scripts, `$ctx.$repos.<table>.create({ data })` and `$ctx.$repos.<table>.update({ id, data })` return the same collection-shaped result as `find`: `{ data: [...], count? }`.',
89
+ '- The `data` field is always an array for `create`/`update`, even when exactly one record was created or updated. If the script needs the record object, it must read `result.data[0]` or `result.data?.[0] ?? null`.',
90
+ '- Wrong: `const id = result.data.id`, `return result.data`, or assuming `create`/`update` returns the bare row object when the script needs one record.',
91
+ '- Right: `const result = await @REPOS.main.create({ data: @BODY }); const record = result.data?.[0] ?? null; return record;`.',
92
+ '',
87
93
  '### Auth and publishedMethods (Enfyra server)',
88
94
  '- Each route has **publishedMethods** (which HTTP verbs are “public”) and **routePermissions** (roles/users for protected access).',
89
95
  '- If the **current request method** is listed in **publishedMethods** for that route, the server allows the call **without** a Bearer token (`RoleGuard`).',
@@ -94,6 +100,12 @@ export function buildMcpServerInstructions(apiBaseUrl) {
94
100
  '- **post-hooks always run** after the handler, including when the handler or a pre-hook throws — then `@ERROR` / `$ctx.$error` is set and `@DATA` is null.',
95
101
  '- You may **mutate** `@DATA` / `$ctx.$data` in place, or **return** a value: a non-`undefined` return replaces `$ctx.$data` as the response body.',
96
102
  '',
103
+ '### Dynamic script syntax preference',
104
+ '- When writing server-side Enfyra scripts, prefer template macros over raw `$ctx` access: use `@BODY`, `@QUERY`, `@PARAMS`, `@USER`, `@REPOS`, `@HELPERS`, `@SOCKET`, `@TRIGGER`, `@DATA`, `@ERROR`, and `@THROW400`–`@THROW503`.',
105
+ '- Use raw `$ctx` only when there is no template macro for the field or helper you need.',
106
+ '- Preferred: `const result = await @REPOS.main.create({ data: @BODY });`.',
107
+ '- Avoid: `const result = await $ctx.$repos.main.create({ data: $ctx.$body });` unless the script truly needs an unmapped `$ctx` property.',
108
+ '',
97
109
  '### OAuth login (browser / frontend — not the MCP `login` tool)',
98
110
  '- **MCP `login`** uses **email + password** → `POST {base}/auth/login`. It cannot complete OAuth (no browser redirect).',
99
111
  '- **Supported providers (server):** `google`, `facebook`, `github` only.',
@@ -552,6 +552,7 @@ server.tool(
552
552
  const payload = {
553
553
  transformer: {
554
554
  rule: 'Dynamic server scripts are transformed before sandbox execution. Macros expand to $ctx paths; comments are not transformed.',
555
+ preferredSyntax: 'Prefer template macros in generated Enfyra scripts. Use @BODY/@QUERY/@PARAMS/@USER/@REPOS/@HELPERS/@SOCKET/@TRIGGER/@DATA/@ERROR/@THROW* instead of raw $ctx access whenever a macro exists. Use raw $ctx only for fields without a macro.',
555
556
  coreMacros: {
556
557
  '@BODY': '$ctx.$body',
557
558
  '@QUERY': '$ctx.$query',
@@ -620,7 +621,12 @@ server.tool(
620
621
  },
621
622
  },
622
623
  helpers: {
623
- repos: '$repos.main enforces route main table behavior; $repos.secure.<table> enforces field permissions; $repos.<table> is trusted/internal.',
624
+ repos: {
625
+ scopes: '$repos.main enforces route main table behavior; $repos.secure.<table> enforces field permissions; $repos.<table> is trusted/internal.',
626
+ mutationReturnShape: '$repos.<table>.create({ data }) and $repos.<table>.update({ id, data }) return a collection-shaped result: { data: [...], count? }. data is always an array for create/update, even for one created/updated record. If a script needs the single record object, it must read result.data[0] or result.data?.[0] ?? null.',
627
+ preferredExample: 'const result = await @REPOS.main.create({ data: @BODY }); const record = result.data?.[0] ?? null; return record;',
628
+ wrongSingleRecordAccess: 'Do not use result.data.id, do not return result.data when one object is expected, and do not assume create/update returns the bare row object.',
629
+ },
624
630
  socketInHttpOrFlow: 'HTTP/flow context can emitToUser/emitToRoom/emitToGateway/broadcast, but cannot reply/join/leave/disconnect because there is no bound socket.',
625
631
  packages: 'Server packages installed through install_package are exposed as $ctx.$pkgs.packageName in server scripts.',
626
632
  files: 'Upload helpers are on $helpers; raw create_record on file_definition is not equivalent to multipart upload/storage rollback.',