@enfyra/mcp-server 0.1.2 → 0.1.3

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.1.2",
3
+ "version": "0.1.3",
4
4
  "description": "MCP server for Enfyra - manage Enfyra instances from MCP-compatible coding tools",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -1694,7 +1694,7 @@ register({
1694
1694
  label: 'Notifications',
1695
1695
  icon: notificationIcon,
1696
1696
  description: notificationDescription,
1697
- badge: notificationBadge,
1697
+ count: notificationBadge,
1698
1698
  badgeColor: 'error',
1699
1699
  expanded,
1700
1700
  onToggle: () => {
@@ -1703,6 +1703,17 @@ register({
1703
1703
  contentComponent: NotificationList,
1704
1704
  })
1705
1705
 
1706
+ const { register: registerMenuNotification, unregister: unregisterMenuNotification } = useMenuNotificationRegistry()
1707
+ watchEffect(() => {
1708
+ registerMenuNotification({
1709
+ id: 'notifications-menu-unread',
1710
+ target: { path: '/notifications' },
1711
+ value: notificationBadge.value,
1712
+ color: unread.value > 0 ? 'error' : 'neutral',
1713
+ title: notificationDescription.value,
1714
+ })
1715
+ })
1716
+
1706
1717
  const { adminSocket } = useAdminSocket()
1707
1718
  const handleNotification = (payload) => {
1708
1719
  if (payload?.unread != null) unread.value = payload.unread
@@ -1710,6 +1721,7 @@ const handleNotification = (payload) => {
1710
1721
  adminSocket.on('notification:summary', handleNotification)
1711
1722
  onUnmounted(() => {
1712
1723
  adminSocket.off('notification:summary', handleNotification)
1724
+ unregisterMenuNotification('notifications-menu-unread')
1713
1725
  })
1714
1726
  </script>
1715
1727
  \`
@@ -1724,6 +1736,7 @@ ensure_global_extension({
1724
1736
  notes: [
1725
1737
  'Global extensions are mounted invisibly by Enfyra admin UI during layout init; do not create a menu and do not embed them with Widget.',
1726
1738
  'Use them for shell-level registrations, realtime listeners, notification counters, account panel rows, and background refresh bridges.',
1739
+ 'Use useMenuNotificationRegistry for sidebar menu counts/dots when notification state should be visible in the menu as well as the notification center.',
1727
1740
  'Keep the global extension template empty or hidden; visible UI should be registered into an existing shell registry or component slot.',
1728
1741
  'For account-panel UI, register data-driven row fields so Enfyra admin UI owns icon size, row spacing, badge placement, hover state, and expanded chrome.',
1729
1742
  'Use contentComponent only for expanded inner content; use raw component only as an escape hatch when the row cannot fit the shell contract.',
@@ -1739,7 +1752,7 @@ const expanded = ref(false)
1739
1752
 
1740
1753
  const label = 'Notifications'
1741
1754
  const icon = computed(() => unread.value > 0 ? 'lucide:bell-ring' : 'lucide:bell')
1742
- const badge = computed(() => unread.value > 0 ? String(unread.value) : null)
1755
+ const count = computed(() => unread.value > 0 ? String(unread.value) : null)
1743
1756
  const description = computed(() => unread.value > 0 ? 'Needs review' : 'All caught up')
1744
1757
 
1745
1758
  const NotificationPanelContent = defineComponent({
@@ -1756,7 +1769,7 @@ register({
1756
1769
  label,
1757
1770
  icon,
1758
1771
  description,
1759
- badge,
1772
+ count,
1760
1773
  badgeColor: 'error',
1761
1774
  expanded,
1762
1775
  onToggle: () => {
@@ -1767,6 +1780,7 @@ register({
1767
1780
  </script>`,
1768
1781
  notes: [
1769
1782
  'Prefer this contract for shell/account-panel items: data fields for the row, optional contentComponent for the expanded body.',
1783
+ 'Use count for the primary visible badge value. badge remains supported as a legacy alias, but count is what the account trigger aggregates.',
1770
1784
  'Do not draw a custom full row with page-scale cards, hero headings, large whitespace, or nested buttons unless the shell contract cannot express the UI.',
1771
1785
  'Let the Enfyra admin UI handle the row button, icon container, label, microcopy, badge, chevron, hover state, spacing, and expanded wrapper.',
1772
1786
  'Keep contentComponent compact; it is rendered inside account-panel chrome and should not create another large card around itself.',
@@ -304,6 +304,8 @@ function getExtensionThemeContract() {
304
304
  'The extension is already mounted inside the Enfyra app shell. Do not add a duplicate page header, centered page wrapper, or root-level page padding.',
305
305
  'Page extensions should be full-bleed, responsive, and split large operations into focused pages or UTabs.',
306
306
  'Use usePageHeaderRegistry for the shell title and useHeaderActionRegistry/useSubHeaderActionRegistry for page actions.',
307
+ 'Use useMenuNotificationRegistry from global extensions to register sidebar menu notification counts or dots. Register stable ids, target menus by id/path/route, use value for counts, omit value for a dot, and choose color from primary/success/warning/error/info/neutral.',
308
+ 'Use useAccountPanelRegistry for account panel rows. AccountPanelItem supports count as the preferred numeric/text badge value, badge as a legacy alias, and badgeColor primary/neutral/info/error/warning/success.',
307
309
  'For detail/form workflows that should stay left-aligned with empty space on the right, wrap the body in eapp-page-constrained; use eapp-page-constrained-wide only when the workflow genuinely needs more width.',
308
310
  'Card/list grids inside the default shell must account for the 280px desktop sidebar. Do not switch general card grids to three columns at lg; use md:grid-cols-2 xl:grid-cols-3 unless a local container proves three columns have enough width.',
309
311
  ],
@@ -359,6 +361,7 @@ function getExtensionThemeContract() {
359
361
  'Use CommonDrawer for side-panel editing. Open drawers immediately on user action and render loading/error/content inside the drawer instead of waiting for fetch before opening.',
360
362
  'Use UTabs for page sections and large grouped forms instead of custom tab bars; the app-level Nuxt UI override owns active and inactive indicators, focus rings, spacing, and theme contrast.',
361
363
  'Use UBadge or token-backed badge spans for status. Keep badges legible in both themes with tokenized background, text, and border.',
364
+ 'Use shell registries for shell badges: useAccountPanelRegistry for the account panel and useMenuNotificationRegistry for sidebar menus. Do not draw detached fixed-position badges over the app shell.',
362
365
  ],
363
366
  loadingAndLists: [
364
367
  'For first load of card/list pages, render calm skeleton cards with a slow pulse. Use USkeleton or shared loading components so the app-owned skeleton theme controls contrast and accent matching. For subsequent pagination/filter refreshes, keep the card shells mounted and skeletonize card content until the new list is ready.',
@@ -409,6 +412,11 @@ function getExtensionThemeContract() {
409
412
  },
410
413
  ],
411
414
  compactExample: '<template><section class="min-h-full w-full space-y-4"><article class="eapp-surface-card p-4"><div class="flex items-start justify-between gap-3"><div><p class="text-sm eapp-text-tertiary">Neutral KPI</p><p class="mt-2 text-2xl font-semibold eapp-text-primary">24</p></div><span class="eapp-primary-soft eapp-icon-tile"><UIcon name="lucide:square-stack" class="size-5 eapp-primary-text" /></span></div><div class="mt-3 h-1.5 overflow-hidden eapp-radius-pill eapp-surface-muted"><div class="eapp-primary-solid h-full w-1/2"></div></div></article><section class="eapp-surface-card p-4"><div class="flex items-center justify-between gap-3"><p class="font-semibold eapp-text-primary">Status block stays neutral</p><UBadge color="success" variant="soft">Healthy</UBadge></div></section></section></template>',
415
+ shellNotificationContract: {
416
+ menu: 'useMenuNotificationRegistry().register({ id, target: { id?, path?, route? }, value?, color?, title?, order? }). value renders a count/chip; omitting value renders a dot. Parent menus sum numeric child values.',
417
+ accountPanel: 'useAccountPanelRegistry().register({ id, label, description, icon, count?, badge?, badgeColor?, expanded?, onToggle?, contentComponent? }). count is preferred over badge and the account trigger sums numeric visible item counts, capped at 99+.',
418
+ lifecycle: 'Register from global extensions for app-wide notification state; stable ids replace previous registrations and component-owned registrations are removed on unmount.',
419
+ },
412
420
  contractAuthority: [
413
421
  'This is the authoritative Enfyra theme & color contract. Source of truth: documents/app/theme-color-contract.md. The app owns color through app/utils/primary-colors.ts (Material You seed-to-role generation), app/assets/css/theme.css (semantic variables and Nuxt UI ramps), app/assets/css/main.css (extension-safe semantic utilities), and app/app.config.ts (Nuxt UI component mapping). Pages and extensions only CONSUME classes/Nuxt UI props; they never define colors.',
414
422
  'Every color flows from two base layers: --md-* (Material You, runtime primary picker) and --st-* (status). Runtime primary roles are generated with SchemeTonalSpot. Success/warning/info stay fixed status quarts; error follows the generated Material error role through the single --danger-* lane. All Nuxt UI semantic colors (primary/secondary/success/warning/error/info/neutral) are re-pointed to these, so Nuxt UI is used per its docs but colors are decided by Enfyra. This applies to the shell, system pages, and compiled dynamic extensions.',
@@ -109,6 +109,7 @@ export function buildRequiredKnowledgePayload() {
109
109
  'Prefer FormEditor/FormEditorLazy for direct table-backed forms when the form maps to metadata fields.',
110
110
  'For long admin setup workflows, open CommonDrawer immediately and show loading/error/content inside it.',
111
111
  'Use Widget with numeric enfyra_extension widget ids; pass safe reactive props/events and keep page-level mutation ownership in the page unless the widget intentionally owns the workflow.',
112
+ 'Use useMenuNotificationRegistry for sidebar menu counts/dots and useAccountPanelRegistry count/badge fields for account panel notifications; register these from global extensions when they should update across the shell.',
112
113
  ],
113
114
  },
114
115
  ],