@enfyra/mcp-server 0.0.65 → 0.0.67

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.65",
3
+ "version": "0.0.67",
4
4
  "description": "MCP server for Enfyra - manage your Enfyra instance via Claude Code",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -213,13 +213,13 @@ window.location.href = url.toString()`,
213
213
  }
214
214
  ]),
215
215
  indexes: JSON.stringify([
216
- ["conversation", "createdAt"],
217
- ["sender", "createdAt"]
216
+ ["conversation", "createdAt"]
218
217
  ])
219
218
  })`,
220
219
  notes: [
221
220
  'Use user_definition as the user table.',
222
221
  'Do not add inverse relations on user_definition unless the user explicitly asks.',
222
+ 'createdAt, updatedAt, and custom date/datetime/timestamp fields already get auto-generated single-field indexes; add only compound indexes needed by hot filters.',
223
223
  'Do not provide physical FK column names; Enfyra derives them.',
224
224
  ],
225
225
  },
@@ -270,6 +270,7 @@ window.location.href = url.toString()`,
270
270
  })`,
271
271
  notes: [
272
272
  'Unread is per user and per message; do not put global read state on conversation.',
273
+ 'readAt is a datetime field and gets its own auto index; the explicit indexes here are compound unread lookup indexes.',
273
274
  'For chat-list UX, default to a boolean unread dot instead of exact counts.',
274
275
  ],
275
276
  },
@@ -998,7 +999,7 @@ create_extension({
998
999
  name: "ReportsPage",
999
1000
  description: "Reports dashboard",
1000
1001
  menuId: "<created-menu-id>",
1001
- code: "<template><section class=\\"min-h-full w-full space-y-4\\"><div class=\\"grid gap-4 md:grid-cols-3\\"><UCard><p class=\\"text-sm text-muted\\">Total</p><p class=\\"mt-2 text-2xl font-semibold\\">0</p></UCard></div></section></template><script setup>const { registerPageHeader } = usePageHeaderRegistry(); registerPageHeader({ title: 'Reports', description: 'Operational report overview.', leadingIcon: 'lucide:bar-chart-3', gradient: 'cyan', variant: 'minimal' }); useHeaderActionRegistry([{ id: 'refresh-reports', label: 'Refresh', icon: 'lucide:refresh-cw', onClick: () => {}, order: 0 }])</script>",
1002
+ code: "<template><section class=\\"min-h-full w-full space-y-4\\"><div class=\\"grid gap-4 md:grid-cols-3\\"><UCard><p class=\\"text-sm text-muted\\">Total</p><p class=\\"mt-2 text-2xl font-semibold\\">0</p></UCard></div></section></template><script setup>const { registerPageHeader } = usePageHeaderRegistry(); const { register: registerHeaderActions } = useHeaderActionRegistry(); registerPageHeader({ title: 'Reports', description: 'Operational report overview.', leadingIcon: 'lucide:bar-chart-3', gradient: 'cyan', variant: 'minimal' }); registerHeaderActions([{ id: 'refresh-reports', label: 'Refresh', icon: 'lucide:refresh-cw', onClick: () => {}, order: 0 }])</script>",
1002
1003
  isEnabled: true
1003
1004
  })`,
1004
1005
  notes: [
@@ -1009,7 +1010,7 @@ create_extension({
1009
1010
  'Page extensions must register the app-shell PageHeader with usePageHeaderRegistry instead of rendering a custom top header.',
1010
1011
  'Use variant: "minimal" for operational pages unless a larger header is intentionally needed.',
1011
1012
  'Do not put ordinary KPI cards in PageHeader.stats; render metrics in the extension body.',
1012
- 'Put page-level actions in useHeaderActionRegistry or useSubHeaderActionRegistry.',
1013
+ 'Put page-level actions in useHeaderActionRegistry or useSubHeaderActionRegistry, destructure register first, then call it with one action or an array.',
1013
1014
  'Page extensions should be full-bleed by default and responsive from the first version.',
1014
1015
  'The extension root is already inside eApp main; do not add root-level page padding.',
1015
1016
  'After saving, open eApp tabs should update through the server/eApp realtime reload contract; do not tell the user to refresh unless that contract is proven broken.',
@@ -1079,6 +1080,7 @@ create_extension({
1079
1080
  name: 'Page header and action button variants',
1080
1081
  code: `<script setup>
1081
1082
  const { registerPageHeader } = usePageHeaderRegistry()
1083
+ const { register: registerHeaderActions } = useHeaderActionRegistry()
1082
1084
 
1083
1085
  registerPageHeader({
1084
1086
  title: 'Report detail',
@@ -1088,7 +1090,7 @@ registerPageHeader({
1088
1090
  variant: 'minimal'
1089
1091
  })
1090
1092
 
1091
- useHeaderActionRegistry([
1093
+ registerHeaderActions([
1092
1094
  {
1093
1095
  id: 'back-to-reports',
1094
1096
  label: 'Reports',
@@ -84,6 +84,7 @@ export function buildMcpServerInstructions(apiBaseUrl) {
84
84
  '- MCP **`create_table` supports creating columns and relations in the same call**: pass `columns` and `relations` as JSON arrays. Use `create_relation` only when adding a relation to an existing table later.',
85
85
  '- MCP **`create_table` supports `isSingleRecord` directly**. Set `isSingleRecord: true` in the create call for settings/config tables that should keep only one record; do not create first and then patch only for this flag.',
86
86
  '- MCP **`create_table` and `update_table` support `indexes` and `uniques`** as JSON arrays of logical field groups. Use compound indexes for hot filters and unread/read state, e.g. `indexes: [["member","isRead","conversation"],["conversation","member","isRead"]]` and `uniques: [["message","member"]]`. Relation property names are allowed; Enfyra resolves them to physical FK columns for SQL and Mongo.',
87
+ '- Enfyra auto-generates single-field indexes for `createdAt`, `updatedAt`, and scalar time columns with type `date`, `datetime`, or `timestamp`. SQL appends `id` as the stable tie-breaker, and Mongo appends `_id`. Do not add duplicate single-field indexes for these time fields; add explicit compound indexes only when a hot query combines the time field with other filters such as status, owner, tenant, or relation fields.',
87
88
  '- MCP **`create_table` does not accept `alias`**. Do not invent or send alias during table creation; default route/schema behavior is based on `name`. Use `update_table` later only when alias truly needs to change.',
88
89
  '- In `create_table.relations`, each relation uses `targetTable` (table id or `{id}`), `type`, `propertyName`, optional `inversePropertyName` or `mappedBy`, `isNullable`, `onDelete`, and `description`. The target table must already exist.',
89
90
  '- **Use `user_definition` as the only user table.** Do not create app-specific user/profile mapping tables such as `chat_profile`, `app_user`, `customer_user`, or tables that only mirror/link Enfyra users. If an app needs extra user fields or user relations, add columns/relations directly on `user_definition`.',
@@ -315,7 +316,7 @@ export function buildMcpServerInstructions(apiBaseUrl) {
315
316
  '- **Page layout default:** page extensions should render full-bleed inside the app shell by default. The extension root is already inside the eApp page `<main>`, so do not add root-level page padding such as `p-4 sm:p-6 xl:p-8`; use spacing between internal sections only. Do not wrap the entire page in a centered card/container unless explicitly requested. Use responsive grids/stacks from the first version so the page works on desktop, tablet, and mobile.',
316
317
  '- **PageHeader is mandatory for page extensions:** eApp already renders `CommonPageHeader` from `usePageHeaderRegistry()` in the app shell. Page extensions must call `const { registerPageHeader } = usePageHeaderRegistry()` and register app-level context such as `{ title, description, leadingIcon, gradient, variant }` instead of rendering their own top `<header>` inside extension content. Use `variant: "minimal"` for operational/admin detail pages unless the page intentionally needs a larger title strip.',
317
318
  '- **Do not misuse PageHeader stats:** `PageHeader.stats` renders prominent stat cards inside the shell header. Do not put normal operational KPIs, capacity totals, billing totals, or detail metrics there by default; keep those as body cards/tables where the operator can scan them with the page content. Only use PageHeader stats for a deliberately compact overview page where the stats are truly header-level context.',
318
- '- **Page actions belong in registries:** Move page-level buttons into `useHeaderActionRegistry` or `useSubHeaderActionRegistry`; keep the extension body for operational content only. Sensitive registry actions must include a `permission` condition, for example `{ id: "create", label: "Create report", permission: { and: [{ route: "/report_definition", methods: ["POST"] }] }, onClick }`.',
319
+ '- **Page actions belong in registries:** Move page-level buttons into `useHeaderActionRegistry` or `useSubHeaderActionRegistry`; keep the extension body for operational content only. Destructure `register` first, then call it with one action or an array, for example `const { register: registerHeaderActions } = useHeaderActionRegistry(); registerHeaderActions([{ id: "create", label: "Create report", permission: { and: [{ route: "/report_definition", methods: ["POST"] }] }, onClick }])`. Sensitive registry actions must include a `permission` condition.',
319
320
  '- **Header action button variants:** choose the button variant by intent. Use `color: "primary", variant: "solid"` for the main page action. Use `color: "neutral", variant: "ghost"` for back/navigation actions and `color: "neutral", variant: "outline"` for visible secondary actions. `variant: "soft"` is only for low-emphasis secondary/chrome actions; do not use soft for critical or primary header actions just because it looks acceptable in dark mode.',
320
321
  '- **HTTP method management:** use the dedicated MCP tools `list_methods`, `create_method`, `update_method`, and preview-first `delete_method` for `method_definition`. The backend field is `method_definition.name`, unique per method; do not send `method_definition.method`. The eApp UI for the same records is `/settings/methods`. Method color fields are `buttonColor` for badge background and `textColor` for badge text, both full hex colors. Do not use generic `create_record` on `method_definition` unless the dedicated tool is unavailable.',
321
322
  '- **Extension navigation:** prefer `NuxtLink` or Nuxt UI components with `:to` for visible navigation links and drill-down cards/buttons. Use `navigateTo(...)` only for imperative navigation after submit, confirm, mutation, or another side effect.',
@@ -355,8 +356,8 @@ export function buildMcpServerInstructions(apiBaseUrl) {
355
356
  '- **useGlobalState:** Global app state. Returns `{ settings, storageConfigs, aiConfigs, appPackages, sidebarVisible, sidebarCollapsed, routeLoading, toggleSidebar(), setRouteLoading(), fetchAppPackages(), packageCacheState }`.',
356
357
  '- **useScreen:** Responsive helpers. Returns `{ width, height, isMobile, isTablet, isDesktop, isLargeDesktop, screenType }`.',
357
358
  '- **useConfirm:** Confirmation dialogs. Returns `{ confirm({ title, content, confirmText, cancelText }), isVisible, options, onConfirm, onCancel }`.',
358
- '- **useHeaderActionRegistry:** Register header actions. Pass array: `useHeaderActionRegistry([{ id, label, onClick, color, icon, order, side, global, permission }])`. Action has `{ id, label, onClick, color, icon, order, side: \'left\'|\'right\', global, component, permission }`; admin actions should set `permission` by default.',
359
- '- **useSubHeaderActionRegistry:** Same as header but for sub-header.',
359
+ '- **useHeaderActionRegistry:** Register header actions. Use `const { register: registerHeaderActions } = useHeaderActionRegistry(); registerHeaderActions([{ id, label, onClick, color, icon, order, side, global, permission }])`. Action has `{ id, label, onClick, color, icon, order, side: \'left\'|\'right\', global, component, permission }`; admin actions should set `permission` by default.',
360
+ '- **useSubHeaderActionRegistry:** Same as header but for sub-header: destructure `register` first, then call it with one action or an array.',
360
361
  '- **usePageHeaderRegistry:** Page title strip. `{ registerPageHeader, clearPageHeader, pageHeader, hasPageHeader }`. Config: `title`, optional `description`, `stats`, `variant`, `gradient` (`purple`|`blue`|`cyan`|`none` — horizontal strip + leading icon tint), `leadingIcon` (icon name), `hideLeadingIcon`. Call `registerPageHeader` again when title/stats must update (plain object snapshot, not refs inside the config).',
361
362
  '- **useMenuRegistry:** Menu management. Returns `{ menuItems, menuGroups, registerMenuItem, unregisterMenuItem, getMenuItemsBySidebar, findParentMenuIdByPath }`.',
362
363
  '- **useMenuApi:** Low-level menu API.',
@@ -406,7 +407,7 @@ export function buildMcpServerInstructions(apiBaseUrl) {
406
407
  '',
407
408
  '#### Important patterns:',
408
409
  '- **useApi:** Must call `execute()` — does NOT auto-run. Supports batch operations with `ids` or `files` options.',
409
- '- **Header actions:** `useHeaderActionRegistry([{ id: \'back\', label: \'Hosts\', icon: \'lucide:arrow-left\', color: \'neutral\', variant: \'ghost\', order: 0, onClick: goBack }, { id: \'refresh\', label: \'Refresh\', icon: \'lucide:refresh-cw\', color: \'primary\', variant: \'solid\', order: 1, onClick: refresh }])`',
410
+ '- **Header actions:** `const { register: registerHeaderActions } = useHeaderActionRegistry(); registerHeaderActions([{ id: \'back\', label: \'Hosts\', icon: \'lucide:arrow-left\', color: \'neutral\', variant: \'ghost\', order: 0, onClick: goBack }, { id: \'refresh\', label: \'Refresh\', icon: \'lucide:refresh-cw\', color: \'primary\', variant: \'solid\', order: 1, onClick: refresh }])`',
410
411
  '- **Schema:** Call `fetchSchema()` first, then use `definition.value`, `editableFields.value`, `getField(\'fieldName\')`.',
411
412
  '- **Permissions:** Use `checkPermissionCondition({ or: [{ route: \'/posts\', methods: [\'GET\'] }] })` for complex rules. In templates, wrap sensitive controls with `<PermissionGate :condition="{ and: [{ route: \'/admin/action\', methods: [\'POST\'] }] }">...</PermissionGate>` instead of only disabling them visually.',
412
413
  '- **After menu/extension create/update:** open eApp tabs should update through the `$system:reload` contract. Do not tell the user to press F5 unless you have verified the natural reload event failed or the server/eApp version does not support menu/extension reload yet.',