synabun 1.3.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 (187) hide show
  1. package/CHANGELOG.md +665 -0
  2. package/LICENSE +191 -0
  3. package/README.md +853 -0
  4. package/hooks/claude-code/post-plan.mjs +391 -0
  5. package/hooks/claude-code/post-remember.mjs +239 -0
  6. package/hooks/claude-code/pre-compact.mjs +241 -0
  7. package/hooks/claude-code/pre-websearch.mjs +90 -0
  8. package/hooks/claude-code/prompt-submit.mjs +861 -0
  9. package/hooks/claude-code/session-start.mjs +494 -0
  10. package/hooks/claude-code/shared.mjs +368 -0
  11. package/hooks/claude-code/stop.mjs +646 -0
  12. package/hooks/claude-code/test-user-learning.mjs +531 -0
  13. package/mcp-server/package.json +38 -0
  14. package/mcp-server/run.mjs +10 -0
  15. package/mcp-server/src/config.ts +70 -0
  16. package/mcp-server/src/http.ts +93 -0
  17. package/mcp-server/src/index.ts +203 -0
  18. package/mcp-server/src/preload-http.ts +25 -0
  19. package/mcp-server/src/preload.ts +29 -0
  20. package/mcp-server/src/scripts/migrate-qdrant-to-sqlite.ts +506 -0
  21. package/mcp-server/src/services/categories.ts +429 -0
  22. package/mcp-server/src/services/discord.ts +702 -0
  23. package/mcp-server/src/services/file-checksums.ts +33 -0
  24. package/mcp-server/src/services/local-embeddings.ts +77 -0
  25. package/mcp-server/src/services/neural-interface.ts +344 -0
  26. package/mcp-server/src/services/sqlite.ts +823 -0
  27. package/mcp-server/src/tools/browser-advanced.ts +123 -0
  28. package/mcp-server/src/tools/browser-interact.ts +255 -0
  29. package/mcp-server/src/tools/browser-navigate.ts +77 -0
  30. package/mcp-server/src/tools/browser-observe.ts +1330 -0
  31. package/mcp-server/src/tools/browser.ts +107 -0
  32. package/mcp-server/src/tools/card-tools.ts +193 -0
  33. package/mcp-server/src/tools/card.ts +22 -0
  34. package/mcp-server/src/tools/category.ts +379 -0
  35. package/mcp-server/src/tools/discord-channel.ts +274 -0
  36. package/mcp-server/src/tools/discord-guild.ts +188 -0
  37. package/mcp-server/src/tools/discord-member.ts +158 -0
  38. package/mcp-server/src/tools/discord-message.ts +231 -0
  39. package/mcp-server/src/tools/discord-onboarding.ts +228 -0
  40. package/mcp-server/src/tools/discord-role.ts +209 -0
  41. package/mcp-server/src/tools/discord-thread.ts +110 -0
  42. package/mcp-server/src/tools/discord-webhook.ts +176 -0
  43. package/mcp-server/src/tools/discord.ts +40 -0
  44. package/mcp-server/src/tools/forget.ts +38 -0
  45. package/mcp-server/src/tools/git-tools.ts +141 -0
  46. package/mcp-server/src/tools/git.ts +13 -0
  47. package/mcp-server/src/tools/image-tools.ts +98 -0
  48. package/mcp-server/src/tools/image.ts +17 -0
  49. package/mcp-server/src/tools/leonardo-browser-tools.ts +281 -0
  50. package/mcp-server/src/tools/leonardo.ts +28 -0
  51. package/mcp-server/src/tools/loop.ts +348 -0
  52. package/mcp-server/src/tools/memories.ts +118 -0
  53. package/mcp-server/src/tools/recall.ts +323 -0
  54. package/mcp-server/src/tools/reflect.ts +145 -0
  55. package/mcp-server/src/tools/remember.ts +115 -0
  56. package/mcp-server/src/tools/response.ts +26 -0
  57. package/mcp-server/src/tools/restore.ts +34 -0
  58. package/mcp-server/src/tools/sync.ts +114 -0
  59. package/mcp-server/src/tools/tictactoe-tools.ts +98 -0
  60. package/mcp-server/src/tools/tictactoe.ts +13 -0
  61. package/mcp-server/src/tools/utils.ts +25 -0
  62. package/mcp-server/src/tools/whiteboard-tools.ts +260 -0
  63. package/mcp-server/src/tools/whiteboard.ts +22 -0
  64. package/mcp-server/src/tui.ts +940 -0
  65. package/mcp-server/src/types.ts +85 -0
  66. package/mcp-server/tsconfig.json +19 -0
  67. package/neural-interface/package.json +27 -0
  68. package/neural-interface/public/apple-touch-icon.png +0 -0
  69. package/neural-interface/public/category-logos/claude.svg +1 -0
  70. package/neural-interface/public/category-logos/gemini-color.svg +1 -0
  71. package/neural-interface/public/category-logos/openai.svg +1 -0
  72. package/neural-interface/public/category-logos/synabun.png +0 -0
  73. package/neural-interface/public/claude-chat.css +878 -0
  74. package/neural-interface/public/claude-chat.html +92 -0
  75. package/neural-interface/public/claude-chat.js +1168 -0
  76. package/neural-interface/public/favicon-16x16.png +0 -0
  77. package/neural-interface/public/favicon-32x32.png +0 -0
  78. package/neural-interface/public/gallery.svg +6 -0
  79. package/neural-interface/public/icon-192.png +0 -0
  80. package/neural-interface/public/icon-512.png +0 -0
  81. package/neural-interface/public/index-legacy.html +14677 -0
  82. package/neural-interface/public/index.html +212 -0
  83. package/neural-interface/public/index2d-legacy.html +8193 -0
  84. package/neural-interface/public/index2d.html +127 -0
  85. package/neural-interface/public/invite.html +351 -0
  86. package/neural-interface/public/leonardoai.svg +1 -0
  87. package/neural-interface/public/logo-synabun.png +0 -0
  88. package/neural-interface/public/logoHD.png +0 -0
  89. package/neural-interface/public/manifest.json +14 -0
  90. package/neural-interface/public/offline.html +299 -0
  91. package/neural-interface/public/onboarding.html +2335 -0
  92. package/neural-interface/public/openclaw-logo-text.png +0 -0
  93. package/neural-interface/public/pin-svgrepo-com.svg +25 -0
  94. package/neural-interface/public/sessionicon.svg +8 -0
  95. package/neural-interface/public/shared/ansi-parser.js +305 -0
  96. package/neural-interface/public/shared/api.js +1043 -0
  97. package/neural-interface/public/shared/colors.js +153 -0
  98. package/neural-interface/public/shared/constants.js +141 -0
  99. package/neural-interface/public/shared/html-shell.js +777 -0
  100. package/neural-interface/public/shared/html-term-renderer.js +1022 -0
  101. package/neural-interface/public/shared/i18n.js +147 -0
  102. package/neural-interface/public/shared/registry.js +82 -0
  103. package/neural-interface/public/shared/state.js +86 -0
  104. package/neural-interface/public/shared/storage.js +150 -0
  105. package/neural-interface/public/shared/styles.css +21212 -0
  106. package/neural-interface/public/shared/ui-automation-studio.js +3573 -0
  107. package/neural-interface/public/shared/ui-bookmarks.js +231 -0
  108. package/neural-interface/public/shared/ui-claude-panel.js +6333 -0
  109. package/neural-interface/public/shared/ui-command-runner.js +534 -0
  110. package/neural-interface/public/shared/ui-cost-widget.js +602 -0
  111. package/neural-interface/public/shared/ui-detail.js +1454 -0
  112. package/neural-interface/public/shared/ui-explorer.js +1356 -0
  113. package/neural-interface/public/shared/ui-file-explorer.js +2750 -0
  114. package/neural-interface/public/shared/ui-games.js +411 -0
  115. package/neural-interface/public/shared/ui-help.js +107 -0
  116. package/neural-interface/public/shared/ui-image-gallery.js +461 -0
  117. package/neural-interface/public/shared/ui-invite.js +519 -0
  118. package/neural-interface/public/shared/ui-keybinds.js +452 -0
  119. package/neural-interface/public/shared/ui-layouts.js +297 -0
  120. package/neural-interface/public/shared/ui-link.js +731 -0
  121. package/neural-interface/public/shared/ui-loading.js +255 -0
  122. package/neural-interface/public/shared/ui-menubar.js +499 -0
  123. package/neural-interface/public/shared/ui-multiselect.js +93 -0
  124. package/neural-interface/public/shared/ui-navbar.js +222 -0
  125. package/neural-interface/public/shared/ui-notifications.js +287 -0
  126. package/neural-interface/public/shared/ui-panels.js +309 -0
  127. package/neural-interface/public/shared/ui-resume.js +653 -0
  128. package/neural-interface/public/shared/ui-search.js +145 -0
  129. package/neural-interface/public/shared/ui-sessions.js +531 -0
  130. package/neural-interface/public/shared/ui-settings.js +5987 -0
  131. package/neural-interface/public/shared/ui-sidebar.js +1905 -0
  132. package/neural-interface/public/shared/ui-skills.js +2805 -0
  133. package/neural-interface/public/shared/ui-stats.js +38 -0
  134. package/neural-interface/public/shared/ui-sync.js +201 -0
  135. package/neural-interface/public/shared/ui-terminal.js +6385 -0
  136. package/neural-interface/public/shared/ui-tooltip.js +123 -0
  137. package/neural-interface/public/shared/ui-trash.js +439 -0
  138. package/neural-interface/public/shared/ui-tutorial-draw.js +875 -0
  139. package/neural-interface/public/shared/ui-tutorial-steps.js +2276 -0
  140. package/neural-interface/public/shared/ui-tutorial.js +1117 -0
  141. package/neural-interface/public/shared/ui-update.js +244 -0
  142. package/neural-interface/public/shared/ui-whiteboard.js +3262 -0
  143. package/neural-interface/public/shared/ui-workspaces.js +722 -0
  144. package/neural-interface/public/shared/utils.js +360 -0
  145. package/neural-interface/public/shared/vterm-buffer.js +1102 -0
  146. package/neural-interface/public/sw.js +52 -0
  147. package/neural-interface/public/synabun.png +0 -0
  148. package/neural-interface/public/toolbar-album.svg +8 -0
  149. package/neural-interface/public/toolbar-question.svg +6 -0
  150. package/neural-interface/public/toolbar-sessions.svg +6 -0
  151. package/neural-interface/public/variant/2d/background.js +113 -0
  152. package/neural-interface/public/variant/2d/context-menu.js +133 -0
  153. package/neural-interface/public/variant/2d/gfx.js +45 -0
  154. package/neural-interface/public/variant/2d/graph.js +1635 -0
  155. package/neural-interface/public/variant/2d/hulls.js +207 -0
  156. package/neural-interface/public/variant/2d/lasso.js +135 -0
  157. package/neural-interface/public/variant/2d/layout.js +594 -0
  158. package/neural-interface/public/variant/2d/main.js +521 -0
  159. package/neural-interface/public/variant/2d/minimap.js +312 -0
  160. package/neural-interface/public/variant/2d/settings-gfx.js +98 -0
  161. package/neural-interface/public/variant/3d/background.js +884 -0
  162. package/neural-interface/public/variant/3d/camera.js +661 -0
  163. package/neural-interface/public/variant/3d/gfx.js +116 -0
  164. package/neural-interface/public/variant/3d/graph.js +2399 -0
  165. package/neural-interface/public/variant/3d/main.js +500 -0
  166. package/neural-interface/public/variant/3d/settings-gfx.js +228 -0
  167. package/neural-interface/scripts/rebuild-pty.js +100 -0
  168. package/neural-interface/server.js +15000 -0
  169. package/neural-interface/templates/CLAUDE-template.md +211 -0
  170. package/package.json +53 -0
  171. package/postinstall.js +135 -0
  172. package/setup.js +260 -0
  173. package/skills/leonardo/SKILL.md +159 -0
  174. package/skills/leonardo/icon.svg +1 -0
  175. package/skills/leonardo/modules/browser-guide.md +378 -0
  176. package/skills/leonardo/modules/image-prompter.md +277 -0
  177. package/skills/leonardo/modules/model-advisor.md +100 -0
  178. package/skills/leonardo/modules/prompt-library.md +110 -0
  179. package/skills/leonardo/modules/style-guide.md +186 -0
  180. package/skills/leonardo/modules/video-prompter.md +311 -0
  181. package/skills/synabun/SKILL.md +185 -0
  182. package/skills/synabun/icon.png +0 -0
  183. package/skills/synabun/modules/audit.md +374 -0
  184. package/skills/synabun/modules/changelog.md +194 -0
  185. package/skills/synabun/modules/idea.md +144 -0
  186. package/skills/synabun/modules/memorize.md +188 -0
  187. package/skills/synabun/synabunicon.png +0 -0
@@ -0,0 +1,107 @@
1
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+
3
+ import {
4
+ browserNavigateSchema, browserNavigateDescription, handleBrowserNavigate,
5
+ browserGoBackSchema, browserGoBackDescription, handleBrowserGoBack,
6
+ browserGoForwardSchema, browserGoForwardDescription, handleBrowserGoForward,
7
+ browserReloadSchema, browserReloadDescription, handleBrowserReload,
8
+ } from './browser-navigate.js';
9
+
10
+ import {
11
+ browserClickSchema, browserClickDescription, handleBrowserClick,
12
+ browserFillSchema, browserFillDescription, handleBrowserFill,
13
+ browserTypeSchema, browserTypeDescription, handleBrowserType,
14
+ browserHoverSchema, browserHoverDescription, handleBrowserHover,
15
+ browserSelectSchema, browserSelectDescription, handleBrowserSelect,
16
+ browserPressSchema, browserPressDescription, handleBrowserPress,
17
+ browserScrollSchema, browserScrollDescription, handleBrowserScroll,
18
+ browserUploadSchema, browserUploadDescription, handleBrowserUpload,
19
+ } from './browser-interact.js';
20
+
21
+ import {
22
+ browserSnapshotSchema, browserSnapshotDescription, handleBrowserSnapshot,
23
+ browserContentSchema, browserContentDescription, handleBrowserContent,
24
+ browserScreenshotSchema, browserScreenshotDescription, handleBrowserScreenshot,
25
+ browserExtractTweetsSchema, browserExtractTweetsDescription, handleBrowserExtractTweets,
26
+ browserExtractFbPostsSchema, browserExtractFbPostsDescription, handleBrowserExtractFbPosts,
27
+ browserExtractTiktokVideosSchema, browserExtractTiktokVideosDescription, handleBrowserExtractTiktokVideos,
28
+ browserExtractTiktokSearchSchema, browserExtractTiktokSearchDescription, handleBrowserExtractTiktokSearch,
29
+ browserExtractTiktokStudioSchema, browserExtractTiktokStudioDescription, handleBrowserExtractTiktokStudio,
30
+ browserExtractTiktokProfileSchema, browserExtractTiktokProfileDescription, handleBrowserExtractTiktokProfile,
31
+ browserExtractWaChatsSchema, browserExtractWaChatsDescription, handleBrowserExtractWaChats,
32
+ browserExtractWaMessagesSchema, browserExtractWaMessagesDescription, handleBrowserExtractWaMessages,
33
+ browserExtractIgFeedSchema, browserExtractIgFeedDescription, handleBrowserExtractIgFeed,
34
+ browserExtractIgProfileSchema, browserExtractIgProfileDescription, handleBrowserExtractIgProfile,
35
+ browserExtractIgPostSchema, browserExtractIgPostDescription, handleBrowserExtractIgPost,
36
+ browserExtractIgReelsSchema, browserExtractIgReelsDescription, handleBrowserExtractIgReels,
37
+ browserExtractIgSearchSchema, browserExtractIgSearchDescription, handleBrowserExtractIgSearch,
38
+ browserExtractLiFeedSchema, browserExtractLiFeedDescription, handleBrowserExtractLiFeed,
39
+ browserExtractLiProfileSchema, browserExtractLiProfileDescription, handleBrowserExtractLiProfile,
40
+ browserExtractLiPostSchema, browserExtractLiPostDescription, handleBrowserExtractLiPost,
41
+ browserExtractLiNotificationsSchema, browserExtractLiNotificationsDescription, handleBrowserExtractLiNotifications,
42
+ browserExtractLiMessagesSchema, browserExtractLiMessagesDescription, handleBrowserExtractLiMessages,
43
+ browserExtractLiSearchPeopleSchema, browserExtractLiSearchPeopleDescription, handleBrowserExtractLiSearchPeople,
44
+ browserExtractLiNetworkSchema, browserExtractLiNetworkDescription, handleBrowserExtractLiNetwork,
45
+ browserExtractLiJobsSchema, browserExtractLiJobsDescription, handleBrowserExtractLiJobs,
46
+ } from './browser-observe.js';
47
+
48
+ import {
49
+ browserEvaluateSchema, browserEvaluateDescription, handleBrowserEvaluate,
50
+ browserWaitSchema, browserWaitDescription, handleBrowserWait,
51
+ browserSessionSchema, browserSessionDescription, handleBrowserSession,
52
+ } from './browser-advanced.js';
53
+
54
+ /**
55
+ * Register all 39 browser MCP tools on the given server instance.
56
+ * Browser tools are static (no dynamic schema refresh needed).
57
+ */
58
+ export function registerBrowserTools(server: McpServer) {
59
+ // Navigation
60
+ server.tool('browser_navigate', browserNavigateDescription, browserNavigateSchema, handleBrowserNavigate);
61
+ server.tool('browser_go_back', browserGoBackDescription, browserGoBackSchema, handleBrowserGoBack);
62
+ server.tool('browser_go_forward', browserGoForwardDescription, browserGoForwardSchema, handleBrowserGoForward);
63
+ server.tool('browser_reload', browserReloadDescription, browserReloadSchema, handleBrowserReload);
64
+
65
+ // Interaction
66
+ server.tool('browser_click', browserClickDescription, browserClickSchema, handleBrowserClick);
67
+ server.tool('browser_fill', browserFillDescription, browserFillSchema, handleBrowserFill);
68
+ server.tool('browser_type', browserTypeDescription, browserTypeSchema, handleBrowserType);
69
+ server.tool('browser_hover', browserHoverDescription, browserHoverSchema, handleBrowserHover);
70
+ server.tool('browser_select', browserSelectDescription, browserSelectSchema, handleBrowserSelect);
71
+ server.tool('browser_press', browserPressDescription, browserPressSchema, handleBrowserPress);
72
+ server.tool('browser_scroll', browserScrollDescription, browserScrollSchema, handleBrowserScroll);
73
+ server.tool('browser_upload', browserUploadDescription, browserUploadSchema, handleBrowserUpload);
74
+
75
+ // Observation
76
+ server.tool('browser_snapshot', browserSnapshotDescription, browserSnapshotSchema, handleBrowserSnapshot);
77
+ server.tool('browser_content', browserContentDescription, browserContentSchema, handleBrowserContent);
78
+ server.tool('browser_screenshot', browserScreenshotDescription, browserScreenshotSchema, handleBrowserScreenshot);
79
+ server.tool('browser_extract_tweets', browserExtractTweetsDescription, browserExtractTweetsSchema, handleBrowserExtractTweets);
80
+ server.tool('browser_extract_fb_posts', browserExtractFbPostsDescription, browserExtractFbPostsSchema, handleBrowserExtractFbPosts);
81
+ server.tool('browser_extract_tiktok_videos', browserExtractTiktokVideosDescription, browserExtractTiktokVideosSchema, handleBrowserExtractTiktokVideos);
82
+ server.tool('browser_extract_tiktok_search', browserExtractTiktokSearchDescription, browserExtractTiktokSearchSchema, handleBrowserExtractTiktokSearch);
83
+ server.tool('browser_extract_tiktok_studio', browserExtractTiktokStudioDescription, browserExtractTiktokStudioSchema, handleBrowserExtractTiktokStudio);
84
+ server.tool('browser_extract_tiktok_profile', browserExtractTiktokProfileDescription, browserExtractTiktokProfileSchema, handleBrowserExtractTiktokProfile);
85
+ server.tool('browser_extract_wa_chats', browserExtractWaChatsDescription, browserExtractWaChatsSchema, handleBrowserExtractWaChats);
86
+ server.tool('browser_extract_wa_messages', browserExtractWaMessagesDescription, browserExtractWaMessagesSchema, handleBrowserExtractWaMessages);
87
+ server.tool('browser_extract_ig_feed', browserExtractIgFeedDescription, browserExtractIgFeedSchema, handleBrowserExtractIgFeed);
88
+ server.tool('browser_extract_ig_profile', browserExtractIgProfileDescription, browserExtractIgProfileSchema, handleBrowserExtractIgProfile);
89
+ server.tool('browser_extract_ig_post', browserExtractIgPostDescription, browserExtractIgPostSchema, handleBrowserExtractIgPost);
90
+ server.tool('browser_extract_ig_reels', browserExtractIgReelsDescription, browserExtractIgReelsSchema, handleBrowserExtractIgReels);
91
+ server.tool('browser_extract_ig_search', browserExtractIgSearchDescription, browserExtractIgSearchSchema, handleBrowserExtractIgSearch);
92
+
93
+ // LinkedIn
94
+ server.tool('browser_extract_li_feed', browserExtractLiFeedDescription, browserExtractLiFeedSchema, handleBrowserExtractLiFeed);
95
+ server.tool('browser_extract_li_profile', browserExtractLiProfileDescription, browserExtractLiProfileSchema, handleBrowserExtractLiProfile);
96
+ server.tool('browser_extract_li_post', browserExtractLiPostDescription, browserExtractLiPostSchema, handleBrowserExtractLiPost);
97
+ server.tool('browser_extract_li_notifications', browserExtractLiNotificationsDescription, browserExtractLiNotificationsSchema, handleBrowserExtractLiNotifications);
98
+ server.tool('browser_extract_li_messages', browserExtractLiMessagesDescription, browserExtractLiMessagesSchema, handleBrowserExtractLiMessages);
99
+ server.tool('browser_extract_li_search_people', browserExtractLiSearchPeopleDescription, browserExtractLiSearchPeopleSchema, handleBrowserExtractLiSearchPeople);
100
+ server.tool('browser_extract_li_network', browserExtractLiNetworkDescription, browserExtractLiNetworkSchema, handleBrowserExtractLiNetwork);
101
+ server.tool('browser_extract_li_jobs', browserExtractLiJobsDescription, browserExtractLiJobsSchema, handleBrowserExtractLiJobs);
102
+
103
+ // Advanced
104
+ server.tool('browser_evaluate', browserEvaluateDescription, browserEvaluateSchema, handleBrowserEvaluate);
105
+ server.tool('browser_wait', browserWaitDescription, browserWaitSchema, handleBrowserWait);
106
+ server.tool('browser_session', browserSessionDescription, browserSessionSchema, handleBrowserSession);
107
+ }
@@ -0,0 +1,193 @@
1
+ import { z } from 'zod';
2
+ import * as ni from '../services/neural-interface.js';
3
+ import { text, image } from './response.js';
4
+
5
+ // ═══════════════════════════════════════════
6
+ // card_list
7
+ // ═══════════════════════════════════════════
8
+
9
+ export const cardListSchema = {};
10
+
11
+ export const cardListDescription =
12
+ 'List all currently open memory cards in the Neural Interface. Returns each card\'s memory UUID, position, size, compact/pin state, content preview, and the current viewport dimensions (width x height). Use this before placing cards to know the available screen size.';
13
+
14
+ interface CardInfo {
15
+ memoryId: string;
16
+ panelId: string;
17
+ left: string;
18
+ top: string;
19
+ width: string;
20
+ height: string;
21
+ isCompact: boolean;
22
+ isPinned: boolean;
23
+ category?: string;
24
+ contentPreview?: string;
25
+ }
26
+
27
+ function describeCard(card: CardInfo, index: number): string {
28
+ const pos = `at (${card.left || '?'}, ${card.top || '?'})`;
29
+ const size = card.width ? `${card.width} x ${card.height || 'auto'}` : 'default';
30
+ const flags = [
31
+ card.isCompact && 'COMPACT',
32
+ card.isPinned && 'PINNED',
33
+ ].filter(Boolean).join(', ');
34
+ const flagStr = flags ? ` [${flags}]` : '';
35
+ const cat = card.category ? ` (${card.category})` : '';
36
+ const preview = card.contentPreview
37
+ ? `\n "${card.contentPreview.length > 80 ? card.contentPreview.slice(0, 80) + '...' : card.contentPreview}"`
38
+ : '';
39
+
40
+ return `${index + 1}. [${card.memoryId}] ${pos} ${size}${flagStr}${cat}${preview}`;
41
+ }
42
+
43
+ export async function handleCardList() {
44
+ const result = await ni.getCards();
45
+ if (result.error) {
46
+ return text(`Failed to read cards: ${result.error}`);
47
+ }
48
+
49
+ const cards = (result.cards || []) as CardInfo[];
50
+ const viewport = result.viewport as { width: number; height: number } | null;
51
+
52
+ if (cards.length === 0) {
53
+ let emptyText = 'No memory cards are currently open.';
54
+ if (viewport) emptyText += `\nViewport: ${viewport.width}x${viewport.height}`;
55
+ return text(emptyText);
56
+ }
57
+
58
+ let msg = `Open cards: ${cards.length}`;
59
+ if (viewport) msg += ` | Viewport: ${viewport.width}x${viewport.height}`;
60
+ msg += '\n\n';
61
+ msg += cards.map((c, i) => describeCard(c, i)).join('\n');
62
+
63
+ return text(msg);
64
+ }
65
+
66
+
67
+ // ═══════════════════════════════════════════
68
+ // card_open
69
+ // ═══════════════════════════════════════════
70
+
71
+ export const cardOpenSchema = {
72
+ memoryId: z.string().describe('UUID of the memory to open as a floating card'),
73
+ coordMode: z.enum(['px', 'pct']).optional().describe('Coordinate mode. "px" (default) = absolute pixels. "pct" = percentage of viewport (0-100). left:50 top:50 = center of screen.'),
74
+ left: z.number().optional().describe('X position from left edge. Omit for auto-cascade.'),
75
+ top: z.number().optional().describe('Y position from top edge. Omit for auto-cascade.'),
76
+ compact: z.boolean().optional().describe('Open in compact mode (220x120px mini-card). Default: false.'),
77
+ };
78
+
79
+ export const cardOpenDescription =
80
+ 'Open a memory as a floating card in the Neural Interface. Use card_list first to see viewport size.\n\nCoordinate modes (coordMode): "px" (default) = absolute pixels. "pct" = percentage of viewport (0-100), e.g. left:50 top:50 = center of screen.\n\nIf the card is already open, it is brought to the front. Omit left/top for auto-cascade positioning.';
81
+
82
+ export async function handleCardOpen(args: { memoryId: string; coordMode?: string; left?: number; top?: number; compact?: boolean }) {
83
+ const result = await ni.openCard(args.memoryId, {
84
+ left: args.left,
85
+ top: args.top,
86
+ compact: args.compact,
87
+ coordMode: args.coordMode,
88
+ });
89
+ if (result.error) {
90
+ return text(`Failed to open card: ${result.error}`);
91
+ }
92
+
93
+ const r = result.result as Record<string, unknown> | undefined;
94
+ const alreadyOpen = r?.alreadyOpen ? ' (was already open, brought to front)' : '';
95
+ const pos = r ? `at (${r.left}, ${r.top})` : '';
96
+ return text(`Card opened${alreadyOpen}: ${args.memoryId} ${pos}`);
97
+ }
98
+
99
+
100
+ // ═══════════════════════════════════════════
101
+ // card_close
102
+ // ═══════════════════════════════════════════
103
+
104
+ export const cardCloseSchema = {
105
+ memoryId: z.string().optional().describe('UUID of the card to close. Omit to close ALL open cards.'),
106
+ };
107
+
108
+ export const cardCloseDescription =
109
+ 'Close a memory card by its UUID, or close all open cards if no memoryId is provided. Use card_list first to see which cards are open.';
110
+
111
+ export async function handleCardClose(args: { memoryId?: string }) {
112
+ const result = await ni.closeCard(args.memoryId);
113
+ if (result.error) {
114
+ return text(`Failed to close card: ${result.error}`);
115
+ }
116
+
117
+ if (!args.memoryId) {
118
+ return text('All cards closed.');
119
+ }
120
+ return text(`Card closed: ${args.memoryId}`);
121
+ }
122
+
123
+
124
+ // ═══════════════════════════════════════════
125
+ // card_update
126
+ // ═══════════════════════════════════════════
127
+
128
+ export const cardUpdateSchema = {
129
+ memoryId: z.string().describe('UUID of the card to update (must be currently open)'),
130
+ coordMode: z.enum(['px', 'pct']).optional().describe('Coordinate mode for position/size values. "pct" = percentage of viewport.'),
131
+ left: z.number().optional().describe('New X position'),
132
+ top: z.number().optional().describe('New Y position'),
133
+ width: z.number().optional().describe('New width (ignored in compact mode)'),
134
+ height: z.number().optional().describe('New height (ignored in compact mode)'),
135
+ compact: z.boolean().optional().describe('true = switch to compact mode (220x120px), false = expand to full size'),
136
+ pinned: z.boolean().optional().describe('true = pin card (locked position, dimmed, z-index 180), false = unpin'),
137
+ };
138
+
139
+ export const cardUpdateDescription =
140
+ 'Update an open memory card\'s position, size, compact/expand state, or pin state. Set coordMode to "pct" to use percentage-based positioning. Only specified fields are changed; others remain untouched. Changes appear in real-time.';
141
+
142
+ export async function handleCardUpdate(args: {
143
+ memoryId: string;
144
+ coordMode?: string;
145
+ left?: number;
146
+ top?: number;
147
+ width?: number;
148
+ height?: number;
149
+ compact?: boolean;
150
+ pinned?: boolean;
151
+ }) {
152
+ const { memoryId, coordMode, ...updates } = args;
153
+
154
+ // Check at least one update field provided
155
+ const hasUpdate = Object.values(updates).some(v => v !== undefined);
156
+ if (!hasUpdate) {
157
+ return text('No update fields provided. Specify at least one of: left, top, width, height, compact, pinned.');
158
+ }
159
+
160
+ const result = await ni.updateCard(memoryId, updates, coordMode);
161
+ if (result.error) {
162
+ return text(`Failed to update card: ${result.error}`);
163
+ }
164
+
165
+ const r = result.result as Record<string, unknown> | undefined;
166
+ const parts: string[] = [];
167
+ if (r) {
168
+ if (r.left !== undefined) parts.push(`pos: (${r.left}, ${r.top})`);
169
+ if (r.isCompact !== undefined) parts.push(r.isCompact ? 'compact' : 'expanded');
170
+ if (r.isPinned !== undefined) parts.push(r.isPinned ? 'pinned' : 'unpinned');
171
+ if (r.width) parts.push(`size: ${r.width} x ${r.height || 'auto'}`);
172
+ }
173
+ return text(`Card updated: ${memoryId}${parts.length ? ' — ' + parts.join(', ') : ''}`);
174
+ }
175
+
176
+
177
+ // ═══════════════════════════════════════════
178
+ // card_screenshot
179
+ // ═══════════════════════════════════════════
180
+
181
+ export const cardScreenshotSchema = {};
182
+
183
+ export const cardScreenshotDescription =
184
+ 'Take a visual screenshot of the Neural Interface showing all open memory cards in their current positions. Returns a JPEG image. Requires the Neural Interface to be open in a browser.';
185
+
186
+ export async function handleCardScreenshot() {
187
+ const result = await ni.cardsScreenshot();
188
+ if (result.error) {
189
+ return text(`Screenshot failed: ${result.error}`);
190
+ }
191
+
192
+ return image(result.data as string, 'image/jpeg');
193
+ }
@@ -0,0 +1,22 @@
1
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+
3
+ import {
4
+ cardListSchema, cardListDescription, handleCardList,
5
+ cardOpenSchema, cardOpenDescription, handleCardOpen,
6
+ cardCloseSchema, cardCloseDescription, handleCardClose,
7
+ cardUpdateSchema, cardUpdateDescription, handleCardUpdate,
8
+ cardScreenshotSchema, cardScreenshotDescription, handleCardScreenshot,
9
+ } from './card-tools.js';
10
+
11
+ /**
12
+ * Register all 5 card MCP tools on the given server instance.
13
+ * These tools let Claude list, open, close, move/resize/compact/pin,
14
+ * and screenshot memory cards in the Neural Interface.
15
+ */
16
+ export function registerCardTools(server: McpServer) {
17
+ server.tool('card_list', cardListDescription, cardListSchema, handleCardList);
18
+ server.tool('card_open', cardOpenDescription, cardOpenSchema, handleCardOpen);
19
+ server.tool('card_close', cardCloseDescription, cardCloseSchema, handleCardClose);
20
+ server.tool('card_update', cardUpdateDescription, cardUpdateSchema, handleCardUpdate);
21
+ server.tool('card_screenshot', cardScreenshotDescription, cardScreenshotSchema, handleCardScreenshot);
22
+ }