@enfyra/mcp-server 0.0.112 → 0.0.115

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.112",
3
+ "version": "0.0.115",
4
4
  "description": "MCP server for Enfyra - manage Enfyra instances from MCP-compatible coding tools",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -1531,7 +1531,7 @@ ensure_page_extension({
1531
1531
  name: "ReportsPage",
1532
1532
  description: "Reports dashboard",
1533
1533
  menuId: "<created-menu-id>",
1534
- code: "<template><section class=\\"min-h-full w-full space-y-4\\"><div class=\\"grid gap-4 md:grid-cols-2 xl:grid-cols-3\\"><article class=\\"surface-card p-4\\"><p class=\\"text-sm font-medium text-[var(--text-tertiary)]\\">Total</p><p class=\\"mt-2 text-2xl font-semibold text-[var(--text-primary)]\\">0</p></article></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', color: 'primary', variant: 'solid', onClick: () => {}, order: 0 }])</script>",
1534
+ code: "<template><section class=\\"min-h-full w-full space-y-4\\"><div class=\\"grid gap-4 md:grid-cols-2 xl:grid-cols-3\\"><article class=\\"surface-card p-4\\"><div class=\\"flex items-start justify-between gap-3\\"><div><p class=\\"text-sm font-medium text-[var(--text-tertiary)]\\">Total</p><p class=\\"mt-2 text-2xl font-semibold text-[var(--text-primary)]\\">0</p></div><span class=\\"eapp-identity-soft rounded-[var(--radius-control)] p-2\\"><span class=\\"eapp-identity-text\\">◆</span></span></div><div class=\\"mt-3 h-1.5 overflow-hidden rounded-[var(--radius-pill)] bg-[var(--surface-muted)]\\"><div class=\\"eapp-identity-solid h-full w-1/2\\"></div></div></article><article class=\\"eapp-identity-surface rounded-[var(--radius-panel)] border p-4\\"><p class=\\"text-sm font-semibold text-[var(--text-primary)]\\">Selected report</p><p class=\\"mt-1 text-sm text-[var(--text-tertiary)]\\">Only selected/current identity blocks use identity surface.</p></article></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: 'none', variant: 'minimal' }); registerHeaderActions([{ id: 'refresh-reports', label: 'Refresh', icon: 'lucide:refresh-cw', color: 'neutral', variant: 'outline', onClick: () => {}, order: 80 }])</script>",
1535
1535
  isEnabled: true
1536
1536
  })`,
1537
1537
  notes: [
@@ -1547,7 +1547,10 @@ ensure_page_extension({
1547
1547
  'Page extensions should be full-bleed by default and responsive from the first version.',
1548
1548
  'The extension root is already inside Enfyra admin page main; do not add root-level page padding.',
1549
1549
  'Use existing eApp theme variables for panels, rows, badges, borders, controls, radius, and text. Pair border/divide utilities with border-[var(--border-default)] or divide-[var(--border-default)] so light and dark themes stay consistent.',
1550
- 'Treat primary color as runtime-configurable: use UButton color="primary", var(--brand-*), --action-primary-*, and --badge-primary-* instead of hardcoded violet/purple/cyan.',
1550
+ 'Treat primary color as runtime-configurable by the app color picker. For Nuxt UI components, choose color="primary" by semantic intent. For custom extension UI, decide whether each element is neutral surface, runtime-primary identity, or status: regular panels/KPI cards/list rows use surface-card/surface-muted or --card-* tokens, while selected/current identity blocks, primary tiles, progress fills, primary icons, and primary CTA fills use eapp-identity-surface, eapp-identity-soft, eapp-identity-solid, or eapp-identity-text so the color picker controls them.',
1551
+ 'Pattern examples: KPI/metric cards should be surface-card with a small eapp-identity-soft icon tile; selected/current entity cards may use eapp-identity-surface; progress bars use bg-[var(--surface-muted)] tracks plus eapp-identity-solid fills; list rows use neutral surfaces/dividers and only small chips inside; primary scope actions use UButton color="primary" variant="solid"; secondary actions use neutral variants.',
1552
+ 'Status colors belong only in UBadge/token-backed badges, small icons, or short status text. Do not color large panels, alert-like success blocks, KPI cards, list containers, or attention/reconciliation blocks green/yellow/red because of state; keep the block neutral and place the status badge/icon inside.',
1553
+ 'Use PageHeader gradient: "none" for generated operational pages unless the user explicitly asks for a decorative page accent; do not hardcode cyan/violet/purple/blue/green gradients.',
1551
1554
  'For general card grids inside the shell, use md:grid-cols-2 xl:grid-cols-3 instead of lg:grid-cols-3 because the desktop sidebar leaves tablet-width content at 1024px.',
1552
1555
  'Do not use Nuxt UI neutral semantic classes such as bg-default, text-muted, text-dimmed, border-default, or divide-default inside extension code; use eApp tokens/classes.',
1553
1556
  'Do not pass ui.content: "surface-card" to UModal/CommonModal; modal content uses the app modal surface and caller content classes should only append z-index or width.',
@@ -1571,6 +1574,9 @@ const reportStatusWidgetCode = \`
1571
1574
  </div>
1572
1575
  <UButton type="button" color="neutral" variant="outline" @click.stop.prevent="emit('refresh')">Refresh</UButton>
1573
1576
  </div>
1577
+ <div class="mt-3 h-1.5 overflow-hidden rounded-[var(--radius-pill)] bg-[var(--surface-muted)]">
1578
+ <div class="eapp-identity-solid h-full" :style="{ width: progressWidth }"></div>
1579
+ </div>
1574
1580
  <UButton v-if="hasLatest" type="button" class="mt-3" color="primary" variant="solid" @click.stop.prevent="openLatest">Open latest</UButton>
1575
1581
  </section>
1576
1582
  </template>
@@ -1584,6 +1590,7 @@ const props = defineProps({
1584
1590
  const emit = defineEmits(['refresh'])
1585
1591
  const hasLatest = computed(() => props.rows.length > 0)
1586
1592
  const latestLabel = computed(() => hasLatest.value ? 'Latest: ' + (props.rows[0]?.title || props.rows[0]?.id || 'Untitled') : 'No reports yet')
1593
+ const progressWidth = computed(() => hasLatest.value ? '100%' : '0%')
1587
1594
  function openLatest() {
1588
1595
  if (typeof props.openDetails === 'function' && props.rows[0]) props.openDetails(props.rows[0])
1589
1596
  }
@@ -1601,7 +1608,7 @@ ensure_widget_extension({
1601
1608
  ensure_page_extension({
1602
1609
  name: "ReportsPage",
1603
1610
  menuId: "<reports-menu-id>",
1604
- code: "<template><section class=\\"min-h-full w-full space-y-4\\"><Widget :id=\\"<report-status-widget-id>\\" :total=\\"totalReports\\" :rows=\\"reportRows\\" :open-details=\\"openReportDetails\\" @refresh=\\"refresh\\" /><Widget :id=\\"<report-table-widget-id>\\" :rows=\\"reportRows\\" @refresh=\\"refresh\\" /></section></template><script setup>const { registerPageHeader } = usePageHeaderRegistry(); registerPageHeader({ title: 'Reports', description: 'Operational report overview.', leadingIcon: 'lucide:bar-chart-3', gradient: 'cyan', variant: 'minimal' }); const totalReports = ref(0); const reportRows = ref([]); function refresh() {} function openReportDetails(row) { navigateTo('/data/report?filter=' + encodeURIComponent(JSON.stringify({ id: { _eq: row.id } }))) }</script>",
1611
+ code: "<template><section class=\\"min-h-full w-full space-y-4\\"><Widget :id=\\"<report-status-widget-id>\\" :total=\\"totalReports\\" :rows=\\"reportRows\\" :open-details=\\"openReportDetails\\" @refresh=\\"refresh\\" /><Widget :id=\\"<report-table-widget-id>\\" :rows=\\"reportRows\\" @refresh=\\"refresh\\" /></section></template><script setup>const { registerPageHeader } = usePageHeaderRegistry(); registerPageHeader({ title: 'Reports', description: 'Operational report overview.', leadingIcon: 'lucide:bar-chart-3', gradient: 'none', variant: 'minimal' }); const totalReports = ref(0); const reportRows = ref([]); function refresh() {} function openReportDetails(row) { navigateTo('/data/report?filter=' + encodeURIComponent(JSON.stringify({ id: { _eq: row.id } }))) }</script>",
1605
1612
  isEnabled: true
1606
1613
  })`,
1607
1614
  notes: [
@@ -1742,7 +1749,7 @@ registerPageHeader({
1742
1749
  title: 'Report detail',
1743
1750
  description: 'Review status, schedule, and delivery history.',
1744
1751
  leadingIcon: 'lucide:file-text',
1745
- gradient: 'cyan',
1752
+ gradient: 'none',
1746
1753
  variant: 'minimal'
1747
1754
  })
1748
1755
 
@@ -1770,8 +1777,8 @@ registerHeaderActions([
1770
1777
  id: 'refresh-report',
1771
1778
  label: 'Refresh',
1772
1779
  icon: 'lucide:refresh-cw',
1773
- color: 'primary',
1774
- variant: 'solid',
1780
+ color: 'neutral',
1781
+ variant: 'outline',
1775
1782
  order: 2,
1776
1783
  onClick: refresh
1777
1784
  }
@@ -1779,9 +1786,10 @@ registerHeaderActions([
1779
1786
  </script>`,
1780
1787
  notes: [
1781
1788
  'Use PageHeader for the title strip; do not render a duplicate header inside extension body.',
1789
+ 'Use gradient: "none" for generated operational pages; hardcoded named gradients are decorative and should be explicit user intent.',
1782
1790
  'Back/navigation actions should be neutral ghost so they read as navigation, not a primary operation.',
1783
1791
  'Visible secondary operations should be neutral outline; soft is only for low-emphasis chrome actions.',
1784
- 'The main page action should be primary solid.',
1792
+ 'The main page mutation action should be primary solid; refresh is neutral outline unless refresh is the actual primary workflow.',
1785
1793
  'Do not choose soft only because it looks acceptable in dark mode; light mode must remain clear too.',
1786
1794
  ],
1787
1795
  },
@@ -302,13 +302,18 @@ function getExtensionThemeContract() {
302
302
  ],
303
303
  theme: [
304
304
  'Use existing eApp theme variables/classes, not hardcoded light or dark colors. The app theme source of truth is CSS variables, including --brand-*, --surface-*, --card-*, --control-*, --action-*, --badge-*, --radius-*, --border-*, and --text-*.',
305
- 'Primary color is runtime-configurable and first-class. Use UButton color="primary", var(--brand-*), --action-primary-*, --state-primary-*, and --badge-primary-* instead of hardcoded violet/purple/cyan values.',
305
+ 'Primary color is runtime-configurable through the app color picker and must affect extension identity UI. For Nuxt UI components, choose color="primary" by semantic intent and let the app map it through the primary contract; do not choose a concrete palette. For custom extension UI, first choose whether the element is neutral surface, runtime-primary identity, or status. Regular panels, KPI cards, list rows, and large content blocks should use surface-card/surface-muted or --card-* tokens. Entity identity, selected/current state, active progress, primary tiles, primary icons, and primary CTA fills should use eapp-identity-surface, eapp-identity-soft, eapp-identity-solid, eapp-identity-text, or UButton/UBadge color="primary" so the color picker controls them.',
306
+ 'Use eapp-identity-surface only for larger entity/feature blocks, selected/current cards, tiles, or cards that should read like normal app cards with a very subtle active-primary tint; it is not a saturated selected-state fill and must not be applied broadly to every KPI/list wrapper. Add eapp-identity-surface-hover when that block is clickable. Use eapp-identity-soft for compact selected entity chips, pills, small icon tiles, and identity callouts; add eapp-identity-soft-hover when compact surfaces are clickable; use eapp-identity-solid only for primary identity fills; use eapp-identity-text for identity icons or inline text. The eapp-accent-* aliases are still available for the same runtime-primary intent, but eapp-identity-* is preferred when the UI element represents an entity or feature identity.',
307
+ 'Nuxt UI secondary is still a valid semantic color when the product intentionally wants a secondary action or state. Do not use color="secondary", from-secondary-*, bg-secondary-*, text-secondary-*, or cyan/purple/green palette utilities merely to approximate an entity accent; use eapp-identity-* and let the app decide the color.',
308
+ 'Do not make custom extension blocks with Tailwind palette utilities or raw primary utilities such as text-primary, bg-primary/10, border-primary, ring-primary/20, from-cyan-*, text-violet-*, bg-green-*, bg-emerald-*, text-green-*, border-green-*, or dark:bg-zinc-950. The app owns how eapp-identity-* and eapp-accent-* map to the active color picker value.',
309
+ 'Use UButton color="primary" only for the single main action for the current scope. Refresh, back, navigation, filters, and secondary actions should be neutral variants unless they are the main mutation.',
310
+ 'PageHeader gradient must be "none" for generated operational extensions unless the user explicitly asks for a decorative page accent. Do not hardcode cyan, violet, purple, blue, or green PageHeader gradients to force color variety.',
306
311
  'Do not inject global CSS, create theme guards, redefine the app palette, or solve one extension by overriding the whole app shell.',
307
312
  'For panels/cards, prefer surface-card, surface-card-hover, surface-muted, or explicit token classes such as bg-[var(--card-bg)] border-[var(--card-border)] shadow-[var(--card-shadow)]. Use text-[var(--text-primary|secondary|tertiary)] for copy.',
308
313
  'Never use Nuxt UI neutral semantic classes such as bg-default, bg-muted, border-default, divide-default, text-muted, text-dimmed, or hardcoded dark palettes such as dark:bg-zinc-950, bg-slate-*, text-gray-*, border-black, or black.',
309
314
  'Never use bare border/divide-y for panels or rows: pair them with border-[var(--border-default)] or divide-[var(--border-default)].',
310
315
  'Use radius tokens or mapped rounded utilities consistently: --radius-card for cards, --radius-panel for nested panels, --radius-control for buttons/inputs, --radius-subcontrol for compact inner controls, and --radius-pill for pills.',
311
- 'Status colors must remain readable in both themes. Use badge tokens such as --badge-success-soft-*, --badge-warning-soft-*, --badge-danger-soft-*, --badge-info-soft-*, --badge-neutral-soft-*, and --badge-primary-soft-* instead of neon translucent colors.',
316
+ 'Status colors must remain readable in both themes and must stay scoped to badges, small icons, or short status text. Use UBadge or badge tokens for non-primary statuses such as --badge-success-soft-*, --badge-warning-soft-*, --badge-danger-soft-*, --badge-info-soft-*, and --badge-neutral-soft-* instead of neon translucent colors. Do not color large panels, alert-like success blocks, KPI cards, list containers, or reconciliation/attention blocks green/yellow/red because the status is good/warning/error; use neutral app surfaces for the block and place a small status badge/icon inside.',
312
317
  'Keep dark and light contrast comparable. Do not make dark mode more neon or lower-contrast than light mode; prefer muted soft backgrounds with clear text and visible borders.',
313
318
  ],
314
319
  components: [
@@ -335,7 +340,39 @@ function getExtensionThemeContract() {
335
340
  'UI checks are only guidance; handlers/hooks must independently enforce owner/root-admin authorization.',
336
341
  'Use the most specific business route or MCP tool. Do not write directly to raw tables when a domain route exists.',
337
342
  ],
338
- compactExample: '<template><section class="min-h-full w-full space-y-4"><div class="surface-card"><div class="border-b border-[var(--border-default)] px-4 py-3"><h2 class="text-base font-semibold text-[var(--text-primary)]">Title</h2><p class="text-sm text-[var(--text-tertiary)]">Short operational context.</p></div><div class="divide-y divide-[var(--border-default)]"><button class="flex w-full cursor-pointer items-center justify-between px-4 py-3 text-left transition-colors hover:bg-[var(--surface-muted)] disabled:cursor-not-allowed disabled:opacity-60"><span class="text-sm font-medium text-[var(--text-primary)]">Row</span><span class="rounded-[var(--radius-pill)] bg-[var(--badge-primary-soft-bg)] px-2 py-0.5 text-xs font-semibold text-[var(--badge-primary-soft-text)] ring-1 ring-inset ring-[var(--badge-primary-soft-border)]">Open</span></button></div></div></section></template>',
343
+ patternExamples: [
344
+ {
345
+ useWhen: 'Ordinary KPI, metric, or summary card where the whole card is not selected/current identity.',
346
+ use: 'Neutral card surface; put runtime-primary only on a small identity icon tile, progress fill, or main CTA inside the card.',
347
+ snippet: '<article class="surface-card p-4"><div class="flex items-start justify-between gap-3"><div><p class="text-sm text-[var(--text-tertiary)]">Metric</p><p class="mt-2 text-2xl font-semibold text-[var(--text-primary)]">{{ value }}</p></div><span class="eapp-identity-soft rounded-[var(--radius-control)] p-2"><UIcon name="lucide:square-stack" class="size-5 eapp-identity-text" /></span></div></article>',
348
+ },
349
+ {
350
+ useWhen: 'Selected/current entity, active plan, chosen package, or the single block that represents the active identity.',
351
+ use: 'eapp-identity-surface for the selected/current block, with eapp-identity-soft/text for compact icon parts.',
352
+ snippet: '<article class="eapp-identity-surface eapp-identity-surface-hover rounded-[var(--radius-panel)] border p-4"><div class="flex items-center gap-3"><span class="eapp-identity-soft rounded-[var(--radius-control)] p-2"><UIcon name="lucide:box" class="size-5 eapp-identity-text" /></span><div><p class="font-semibold text-[var(--text-primary)]">{{ name }}</p><p class="text-sm text-[var(--text-tertiary)]">Currently selected</p></div></div></article>',
353
+ },
354
+ {
355
+ useWhen: 'Progress, active tab indicator, selected segment fill, or primary visual meter.',
356
+ use: 'Neutral track plus eapp-identity-solid fill so the app color picker controls the fill.',
357
+ snippet: '<div class="h-1.5 overflow-hidden rounded-[var(--radius-pill)] bg-[var(--surface-muted)]"><div class="eapp-identity-solid h-full" :style="{ width: progressWidth }"></div></div>',
358
+ },
359
+ {
360
+ useWhen: 'Success, warning, error, info, healthy, running, failed, pending, or attention status.',
361
+ use: 'UBadge/status badge tokens and optionally a small icon only. Keep large alert/panel/card backgrounds neutral unless the whole block is an identity block.',
362
+ snippet: '<section class="surface-card p-4"><div class="flex items-center justify-between gap-3"><p class="font-semibold text-[var(--text-primary)]">Reconciliation</p><UBadge color="success" variant="soft">Healthy</UBadge></div><p class="mt-1 text-sm text-[var(--text-tertiary)]">Latest report found no mismatches.</p></section>',
363
+ },
364
+ {
365
+ useWhen: 'List rows, table-like records, history rows, and secondary navigation rows.',
366
+ use: 'Neutral row surface, tokenized dividers, hover surface-muted, with small status/identity chips inside.',
367
+ snippet: '<div class="surface-card divide-y divide-[var(--border-default)]"><button class="flex w-full items-center justify-between px-4 py-3 text-left hover:bg-[var(--surface-muted)]"><span class="text-sm font-medium text-[var(--text-primary)]">{{ row.name }}</span><UBadge color="neutral" variant="soft">{{ row.state }}</UBadge></button></div>',
368
+ },
369
+ {
370
+ useWhen: 'Primary action for the current scope, such as create/save/apply/open-current.',
371
+ use: 'UButton color="primary" variant="solid"; secondary actions stay neutral.',
372
+ snippet: '<div class="flex justify-end gap-2"><UButton color="neutral" variant="outline">Cancel</UButton><UButton color="primary" variant="solid" icon="lucide:save">Save</UButton></div>',
373
+ },
374
+ ],
375
+ compactExample: '<template><section class="min-h-full w-full space-y-4"><article class="surface-card p-4"><div class="flex items-start justify-between gap-3"><div><p class="text-sm text-[var(--text-tertiary)]">Neutral KPI</p><p class="mt-2 text-2xl font-semibold text-[var(--text-primary)]">24</p></div><span class="eapp-identity-soft rounded-[var(--radius-control)] p-2"><UIcon name="lucide:square-stack" class="size-5 eapp-identity-text" /></span></div><div class="mt-3 h-1.5 overflow-hidden rounded-[var(--radius-pill)] bg-[var(--surface-muted)]"><div class="eapp-identity-solid h-full w-1/2"></div></div></article><section class="surface-card p-4"><div class="flex items-center justify-between gap-3"><p class="font-semibold text-[var(--text-primary)]">Status block stays neutral</p><UBadge color="success" variant="soft">Healthy</UBadge></div></section></section></template>',
339
376
  };
340
377
  }
341
378