slashvibe-mcp 0.3.21 → 0.3.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.
Files changed (229) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +280 -47
  3. package/config.js +36 -31
  4. package/crypto.js +1 -6
  5. package/discord.js +19 -19
  6. package/index.js +217 -207
  7. package/intelligence/index.js +2 -9
  8. package/intelligence/infer.js +10 -16
  9. package/intelligence/patterns.js +23 -18
  10. package/intelligence/proactive.js +16 -15
  11. package/intelligence/serendipity.js +57 -20
  12. package/memory.js +13 -8
  13. package/notify.js +39 -14
  14. package/package.json +27 -20
  15. package/presence.js +2 -2
  16. package/prompts.js +5 -9
  17. package/protocol/index.js +123 -87
  18. package/protocol/telegram-commands.js +36 -37
  19. package/store/api.js +358 -529
  20. package/store/local.js +9 -10
  21. package/store/profiles.js +48 -192
  22. package/store/reservations.js +2 -9
  23. package/store/skills.js +69 -71
  24. package/store/sqlite.js +355 -0
  25. package/tools/_actions.js +48 -387
  26. package/tools/_connection-queue.js +45 -56
  27. package/tools/_discovery-enhanced.js +52 -57
  28. package/tools/_discovery.js +87 -185
  29. package/tools/{l2-status.js → _experimental/l2-status.js} +68 -70
  30. package/tools/{shipback.js → _experimental/shipback.js} +4 -3
  31. package/tools/_proactive-discovery.js +60 -73
  32. package/tools/_shared/index.js +41 -64
  33. package/tools/admin-inbox.js +10 -15
  34. package/tools/agents.js +1 -1
  35. package/tools/artifact-create.js +13 -23
  36. package/tools/artifact-view.js +4 -4
  37. package/tools/{_deprecated/back.js → back.js} +1 -1
  38. package/tools/bye.js +3 -5
  39. package/tools/consent.js +2 -2
  40. package/tools/context.js +9 -10
  41. package/tools/crossword.js +3 -2
  42. package/tools/discover.js +94 -356
  43. package/tools/dm.js +27 -86
  44. package/tools/doctor.js +12 -41
  45. package/tools/drawing.js +34 -20
  46. package/tools/echo.js +11 -11
  47. package/tools/feed.js +30 -58
  48. package/tools/follow.js +64 -187
  49. package/tools/{_deprecated/forget.js → forget.js} +4 -7
  50. package/tools/game.js +144 -48
  51. package/tools/handoff.js +6 -8
  52. package/tools/help.js +3 -3
  53. package/tools/idea.js +15 -27
  54. package/tools/inbox.js +121 -293
  55. package/tools/init.js +54 -151
  56. package/tools/invite.js +8 -21
  57. package/tools/migrate.js +27 -24
  58. package/tools/multiplayer-game.js +50 -40
  59. package/tools/{_deprecated/mute.js → mute.js} +4 -3
  60. package/tools/notifications.js +58 -48
  61. package/tools/observe.js +12 -15
  62. package/tools/onboarding.js +8 -11
  63. package/tools/open.js +13 -144
  64. package/tools/party-game.js +23 -12
  65. package/tools/patterns.js +2 -1
  66. package/tools/ping.js +5 -7
  67. package/tools/react.js +28 -30
  68. package/tools/{_deprecated/recall.js → recall.js} +5 -10
  69. package/tools/release.js +4 -2
  70. package/tools/{_deprecated/remember.js → remember.js} +4 -6
  71. package/tools/report.js +2 -2
  72. package/tools/request.js +6 -26
  73. package/tools/reserve.js +1 -1
  74. package/tools/session-fork.js +97 -0
  75. package/tools/session-save.js +109 -0
  76. package/tools/settings.js +30 -99
  77. package/tools/ship.js +74 -56
  78. package/tools/{_deprecated/skills-exchange.js → skills-exchange.js} +38 -39
  79. package/tools/social-inbox.js +22 -28
  80. package/tools/social-post.js +24 -27
  81. package/tools/solo-game.js +54 -46
  82. package/tools/start.js +14 -148
  83. package/tools/status.js +21 -68
  84. package/tools/submit.js +4 -2
  85. package/tools/suggest-tags.js +36 -33
  86. package/tools/summarize.js +19 -16
  87. package/tools/tag-suggestions.js +72 -73
  88. package/tools/test.js +1 -1
  89. package/tools/{_deprecated/tictactoe.js → tictactoe.js} +26 -26
  90. package/tools/token.js +4 -4
  91. package/tools/update.js +1 -2
  92. package/tools/watch.js +132 -112
  93. package/tools/who.js +20 -40
  94. package/tools/{_deprecated/wordassociation.js → wordassociation.js} +23 -20
  95. package/tools/workshop-buddy.js +52 -53
  96. package/tools/x-mentions.js +0 -1
  97. package/tools/x-reply.js +0 -1
  98. package/twitter.js +14 -20
  99. package/version.json +8 -10
  100. package/analytics.js +0 -107
  101. package/auth-store.js +0 -148
  102. package/auto-update.js +0 -130
  103. package/bridges/bridge-monitor.js +0 -388
  104. package/bridges/discord-bot.js +0 -431
  105. package/bridges/farcaster.js +0 -299
  106. package/bridges/telegram.js +0 -261
  107. package/bridges/webhook-health.js +0 -420
  108. package/bridges/webhook-server.js +0 -437
  109. package/bridges/whatsapp.js +0 -441
  110. package/bridges/x-webhook.js +0 -423
  111. package/games/arcade.js +0 -406
  112. package/games/chess.js +0 -451
  113. package/games/colorguess.js +0 -343
  114. package/games/crossword-words.js +0 -171
  115. package/games/crossword.js +0 -461
  116. package/games/drawing.js +0 -347
  117. package/games/gameroulette.js +0 -300
  118. package/games/gamerouter.js +0 -336
  119. package/games/gamestatus.js +0 -337
  120. package/games/guessnumber.js +0 -209
  121. package/games/hangman.js +0 -279
  122. package/games/memory.js +0 -338
  123. package/games/multiplayer-tictactoe.js +0 -389
  124. package/games/pixelart.js +0 -399
  125. package/games/quickduel.js +0 -354
  126. package/games/riddle.js +0 -371
  127. package/games/rockpaperscissors.js +0 -291
  128. package/games/snake.js +0 -406
  129. package/games/storybuilder.js +0 -343
  130. package/games/tictactoe.js +0 -345
  131. package/games/twentyquestions.js +0 -286
  132. package/games/twotruths.js +0 -207
  133. package/games/werewolf.js +0 -508
  134. package/games/wordassociation.js +0 -247
  135. package/games/wordchain.js +0 -135
  136. package/intelligence/interests.js +0 -369
  137. package/notification-emitter.js +0 -77
  138. package/setup.js +0 -480
  139. package/smart-inbox.js +0 -276
  140. package/tools/_deprecated/auto-suggest-connections.js +0 -304
  141. package/tools/_deprecated/bootstrap-skills.js +0 -231
  142. package/tools/_deprecated/bridge-dashboard.js +0 -342
  143. package/tools/_deprecated/bridge-health.js +0 -400
  144. package/tools/_deprecated/bridge-live.js +0 -384
  145. package/tools/_deprecated/bridges.js +0 -383
  146. package/tools/_deprecated/colorguess.js +0 -281
  147. package/tools/_deprecated/discover-insights.js +0 -379
  148. package/tools/_deprecated/discover-momentum.js +0 -256
  149. package/tools/_deprecated/discovery-analytics.js +0 -345
  150. package/tools/_deprecated/discovery-auto-suggest.js +0 -275
  151. package/tools/_deprecated/discovery-bootstrap.js +0 -267
  152. package/tools/_deprecated/discovery-daily.js +0 -375
  153. package/tools/_deprecated/discovery-dashboard.js +0 -385
  154. package/tools/_deprecated/discovery-digest.js +0 -314
  155. package/tools/_deprecated/discovery-hub.js +0 -357
  156. package/tools/_deprecated/discovery-insights.js +0 -384
  157. package/tools/_deprecated/discovery-momentum.js +0 -281
  158. package/tools/_deprecated/discovery-monitor.js +0 -319
  159. package/tools/_deprecated/discovery-proactive.js +0 -300
  160. package/tools/_deprecated/draw.js +0 -317
  161. package/tools/_deprecated/farcaster.js +0 -307
  162. package/tools/_deprecated/games-catalog.js +0 -376
  163. package/tools/_deprecated/games.js +0 -313
  164. package/tools/_deprecated/guessnumber.js +0 -194
  165. package/tools/_deprecated/hangman.js +0 -129
  166. package/tools/_deprecated/multiplayer-tictactoe.js +0 -303
  167. package/tools/_deprecated/riddle.js +0 -240
  168. package/tools/_deprecated/run-bootstrap.js +0 -69
  169. package/tools/_deprecated/skills-analytics.js +0 -349
  170. package/tools/_deprecated/skills-bootstrap.js +0 -301
  171. package/tools/_deprecated/skills-dashboard.js +0 -268
  172. package/tools/_deprecated/skills.js +0 -380
  173. package/tools/_deprecated/smart-intro.js +0 -353
  174. package/tools/_deprecated/storybuilder.js +0 -331
  175. package/tools/_deprecated/telegram-bot.js +0 -183
  176. package/tools/_deprecated/telegram-setup.js +0 -214
  177. package/tools/_deprecated/twentyquestions.js +0 -143
  178. package/tools/_shared.js +0 -234
  179. package/tools/_work-context.js +0 -338
  180. package/tools/_work-context.manual-test.js +0 -199
  181. package/tools/_work-context.test.js +0 -260
  182. package/tools/activity.js +0 -220
  183. package/tools/agent-treasury.js +0 -288
  184. package/tools/analytics.js +0 -191
  185. package/tools/approve.js +0 -197
  186. package/tools/arcade.js +0 -173
  187. package/tools/artifacts-price.js +0 -107
  188. package/tools/ask-expert.js +0 -160
  189. package/tools/available.js +0 -120
  190. package/tools/become-expert.js +0 -150
  191. package/tools/broadcast.js +0 -325
  192. package/tools/chat.js +0 -202
  193. package/tools/collaborative-drawing.js +0 -286
  194. package/tools/connection-status.js +0 -178
  195. package/tools/earnings.js +0 -126
  196. package/tools/friends.js +0 -207
  197. package/tools/genesis.js +0 -233
  198. package/tools/gig-browse.js +0 -206
  199. package/tools/gig-complete.js +0 -144
  200. package/tools/health.js +0 -87
  201. package/tools/leaderboard.js +0 -117
  202. package/tools/lib/git-apply.js +0 -206
  203. package/tools/lib/git-bundle.js +0 -407
  204. package/tools/mint.js +0 -377
  205. package/tools/plan.js +0 -225
  206. package/tools/profile.js +0 -219
  207. package/tools/proof-of-work.js +0 -144
  208. package/tools/pulse.js +0 -218
  209. package/tools/reply.js +0 -166
  210. package/tools/reputation.js +0 -175
  211. package/tools/schedule.js +0 -367
  212. package/tools/search-messages.js +0 -123
  213. package/tools/session.js +0 -467
  214. package/tools/session_price.js +0 -128
  215. package/tools/smart-check.js +0 -201
  216. package/tools/social-processor.js +0 -445
  217. package/tools/streak.js +0 -147
  218. package/tools/stuck.js +0 -297
  219. package/tools/subscribe.js +0 -148
  220. package/tools/subscriptions.js +0 -134
  221. package/tools/tip.js +0 -193
  222. package/tools/wallet.js +0 -269
  223. package/tools/webhook-test.js +0 -388
  224. package/tools/withdraw.js +0 -145
  225. package/tools/work-summary.js +0 -96
  226. package/tools/workshop.js +0 -327
  227. /package/tools/{l2-bridge.js → _experimental/l2-bridge.js} +0 -0
  228. /package/tools/{l2.js → _experimental/l2.js} +0 -0
  229. /package/tools/{_deprecated/away.js → away.js} +0 -0
package/index.js CHANGED
@@ -6,21 +6,80 @@
6
6
  * Identity, presence, DM. That's it.
7
7
  */
8
8
 
9
- // Handle "setup" command - redirect to setup.js
10
- if (process.argv.includes('setup')) {
11
- require('./setup.js');
12
- return;
13
- }
14
-
15
9
  const presence = require('./presence');
16
10
  const config = require('./config');
17
11
  const store = require('./store');
18
12
  const prompts = require('./prompts');
19
13
  const NotificationEmitter = require('./notification-emitter');
20
- const authStore = require('./auth-store');
14
+
15
+ /**
16
+ * MCP Tool Safety Annotations
17
+ *
18
+ * Required by Anthropic's MCP Directory for Plugin/Connectors review.
19
+ * Each tool must declare behavioral hints:
20
+ * readOnlyHint — tool only reads data, never modifies state
21
+ * destructiveHint — tool may delete data or perform irreversible actions
22
+ * idempotentHint — repeated calls with same args have no additional effect
23
+ * openWorldHint — tool interacts with external services (API, network)
24
+ *
25
+ * Spec: https://modelcontextprotocol.io/docs/concepts/tools
26
+ */
27
+ const TOOL_ANNOTATIONS = {
28
+ // ── Read-only tools ────────────────────────────────────────────
29
+ vibe_who: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true },
30
+ vibe_inbox: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true },
31
+ vibe_recall: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
32
+ vibe_help: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
33
+ vibe_feed: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true },
34
+ vibe_view_artifact: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true },
35
+ vibe_suggest_tags: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true },
36
+ vibe_doctor: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true },
37
+ vibe_reservations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true },
38
+ vibe_discover: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true },
39
+
40
+ // ── Write tools (non-destructive) ─────────────────────────────
41
+ vibe_start: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true },
42
+ vibe_init: { readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: true },
43
+ vibe_ping: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true },
44
+ vibe_follow: { readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: true },
45
+ vibe_unfollow: { readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: true },
46
+ vibe_watch: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true },
47
+ vibe_live: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true },
48
+ vibe_react: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true },
49
+ vibe_dm: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true },
50
+ vibe_open: { readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: true },
51
+ vibe_status: { readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: true },
52
+ vibe_context: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true },
53
+ vibe_summarize: { readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: false },
54
+ vibe_game: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true },
55
+ vibe_away: { readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: true },
56
+ vibe_back: { readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: true },
57
+ vibe_handoff: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true },
58
+ vibe_reserve: { readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: true },
59
+ vibe_remember: { readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: false },
60
+ vibe_report: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true },
61
+ vibe_invite: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true },
62
+ vibe_ship: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true },
63
+ vibe_session_save: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true },
64
+ vibe_session_fork: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true },
65
+ vibe_create_artifact: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true },
66
+ vibe_settings: { readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: false },
67
+ vibe_notifications: { readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: true },
68
+ vibe_presence_agent: { readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: true },
69
+
70
+ // ── Destructive tools ─────────────────────────────────────────
71
+ vibe_forget: { readOnlyHint: false, destructiveHint: true, idempotentHint: true, openWorldHint: false },
72
+ vibe_release: { readOnlyHint: false, destructiveHint: true, idempotentHint: true, openWorldHint: true },
73
+ vibe_bye: { readOnlyHint: false, destructiveHint: true, idempotentHint: true, openWorldHint: true },
74
+ vibe_mute: { readOnlyHint: false, destructiveHint: true, idempotentHint: true, openWorldHint: true },
75
+ vibe_update: { readOnlyHint: false, destructiveHint: true, idempotentHint: true, openWorldHint: true }
76
+ };
77
+
78
+ // Default annotations for any tool not explicitly mapped
79
+ const DEFAULT_ANNOTATIONS = { readOnlyHint: false, destructiveHint: false, openWorldHint: true };
21
80
 
22
81
  // Tools that shouldn't show presence footer (would be redundant/noisy)
23
- const SKIP_FOOTER_TOOLS = ['vibe_init', 'vibe_doctor', 'vibe_test', 'vibe_update', 'vibe_settings', 'vibe_notifications'];
82
+ const SKIP_FOOTER_TOOLS = ['vibe_init', 'vibe_doctor', 'vibe_update', 'vibe_settings', 'vibe_notifications'];
24
83
 
25
84
  // Infer user prompt from tool arguments (for pattern logging)
26
85
  function inferPromptFromArgs(toolName, args) {
@@ -32,42 +91,66 @@ function inferPromptFromArgs(toolName, args) {
32
91
  const reaction = args.reaction || '';
33
92
 
34
93
  switch (action) {
35
- case 'start': return 'start vibing';
36
- case 'who': return 'who is online';
37
- case 'ping': return `ping ${handle} ${note}`.trim();
38
- case 'react': return `react ${reaction} to ${handle}`.trim();
39
- case 'dm': return `message ${handle} ${message}`.trim();
40
- case 'inbox': return 'check inbox';
41
- case 'open': return `open thread with ${handle}`;
42
- case 'status': return `set status to ${mood}`;
43
- case 'context': return 'share context';
44
- case 'summarize': return 'summarize session';
45
- case 'bye': return 'end session';
46
- case 'board': return args.content ? 'post to board' : 'view board';
47
- case 'observe': return args.content ? 'record observation' : 'view observations';
48
- case 'invite': return 'generate invite';
49
- case 'echo': return 'send feedback';
50
- case 'x_mentions': return 'check x mentions';
51
- case 'x_reply': return 'reply on x';
52
- case 'handoff': return `handoff task to ${handle}`;
53
- case 'reserve': return args.paths ? `reserve ${args.paths.join(', ')}` : 'reserve files';
54
- case 'release': return `release ${args.reservation_id || 'reservation'}`;
55
- case 'reservations': return 'list reservations';
56
- case 'solo_game': return `play ${args.game || 'game'}`;
57
- case 'game': return `play ${args.game || 'game'} with ${handle}`;
58
- case 'multiplayer_game': return `multiplayer ${args.game || 'game'}`;
59
- case 'drawing': return args.action ? `drawing ${args.action}` : 'collaborative drawing';
60
- case 'crossword': return `crossword ${args.action || 'daily'}`;
61
- case 'discover': return `discover ${args.command || 'suggest'}`;
62
- case 'suggest_tags': return `suggest tags ${args.command || 'suggest'}`;
63
- case 'settings': return args.mute ? `mute for ${args.mute}` : 'view settings';
64
- case 'create_artifact': return `create ${args.template || 'artifact'}: ${args.title || 'untitled'}`;
65
- case 'view_artifact': return args.slug ? `view artifact ${args.slug}` : `list ${args.list || 'artifacts'}`;
66
- case 'broadcast': return args.action ? `broadcast ${args.action}` : 'broadcast status';
67
- case 'watch': return args.target ? `watch ${args.target}` : 'list live broadcasts';
68
- case 'session': return args.action ? `session ${args.action}` : 'list sessions';
69
- case 'chat': return args.message ? `chat "${args.message.slice(0, 30)}..."` : 'view chat';
70
- default: return `${action} ${handle}`.trim() || null;
94
+ case 'start':
95
+ return 'start vibing';
96
+ case 'who':
97
+ return 'who is online';
98
+ case 'ping':
99
+ return `ping ${handle} ${note}`.trim();
100
+ case 'react':
101
+ return `react ${reaction} to ${handle}`.trim();
102
+ case 'dm':
103
+ return `message ${handle} ${message}`.trim();
104
+ case 'inbox':
105
+ return 'check inbox';
106
+ case 'open':
107
+ return `open thread with ${handle}`;
108
+ case 'status':
109
+ return `set status to ${mood}`;
110
+ case 'context':
111
+ return 'share context';
112
+ case 'summarize':
113
+ return 'summarize session';
114
+ case 'bye':
115
+ return 'end session';
116
+ case 'remember':
117
+ return `remember about ${handle}`;
118
+ case 'recall':
119
+ return `recall ${handle}`;
120
+ case 'forget':
121
+ return `forget ${handle}`;
122
+ case 'invite':
123
+ return 'generate invite';
124
+ case 'handoff':
125
+ return `handoff task to ${handle}`;
126
+ case 'reserve':
127
+ return args.paths ? `reserve ${args.paths.join(', ')}` : 'reserve files';
128
+ case 'release':
129
+ return `release ${args.reservation_id || 'reservation'}`;
130
+ case 'reservations':
131
+ return 'list reservations';
132
+ case 'game':
133
+ return `play ${args.game || 'game'} ${handle}`.trim();
134
+ case 'away':
135
+ return args.message ? `set away: "${args.message}"` : 'go away';
136
+ case 'back':
137
+ return 'come back';
138
+ case 'discover':
139
+ return `discover ${args.command || 'suggest'}`;
140
+ case 'suggest_tags':
141
+ return `suggest tags ${args.command || 'suggest'}`;
142
+ case 'ship':
143
+ return `ship ${args.type || ''} ${args.what || ''}`.trim();
144
+ case 'session_save':
145
+ return `save session "${args.title || ''}"`.trim();
146
+ case 'session_fork':
147
+ return `fork session ${args.session_id || ''}`.trim();
148
+ case 'create_artifact':
149
+ return `create ${args.template || 'artifact'}: ${args.title || 'untitled'}`;
150
+ case 'view_artifact':
151
+ return args.slug ? `view artifact ${args.slug}` : `list ${args.list || 'artifacts'}`;
152
+ default:
153
+ return `${action} ${handle}`.trim() || null;
71
154
  }
72
155
  }
73
156
 
@@ -99,11 +182,10 @@ async function getPresenceFooter() {
99
182
  const handle = config.getHandle();
100
183
  if (!handle) return '';
101
184
 
102
- // Fetch presence, unread, and live broadcasts in parallel
103
- const [users, unreadCount, liveCount] = await Promise.all([
185
+ // Fetch presence and unread in parallel
186
+ const [users, unreadCount] = await Promise.all([
104
187
  store.getActiveUsers().catch(() => []),
105
- store.getUnreadCount(handle).catch(() => 0),
106
- store.getLiveBroadcastCount().catch(() => 0)
188
+ store.getUnreadCount(handle).catch(() => 0)
107
189
  ]);
108
190
 
109
191
  // Filter out self
@@ -126,7 +208,7 @@ async function getPresenceFooter() {
126
208
  // Build the visible footer
127
209
  let footer = '\n\n────────────────────────────────────────\n';
128
210
 
129
- // Line 1: vibe · X online · Y unread · Z live
211
+ // Line 1: vibe · X online · Y unread
130
212
  const parts = ['vibe'];
131
213
  if (onlineCount > 0) {
132
214
  parts.push(`${onlineCount} online`);
@@ -134,9 +216,6 @@ async function getPresenceFooter() {
134
216
  if (unreadCount > 0) {
135
217
  parts.push(`**${unreadCount} unread**`);
136
218
  }
137
- if (liveCount > 0) {
138
- parts.push(`🔴 ${liveCount} live`);
139
- }
140
219
  footer += parts.join(' · ');
141
220
 
142
221
  // Line 2: Activity hints (if anyone is online)
@@ -158,10 +237,8 @@ async function getPresenceFooter() {
158
237
  }
159
238
  });
160
239
  footer += hints.join(' · ');
161
- } else if (unreadCount === 0 && liveCount === 0) {
162
- footer += '\n_room is quiet · `vibe broadcast start` to go live_';
163
- } else if (unreadCount === 0 && liveCount > 0) {
164
- footer += '\n_no messages · watch live broadcasts with `vibe watch`_';
240
+ } else if (unreadCount === 0) {
241
+ footer += '\n_room is quiet_';
165
242
  }
166
243
 
167
244
  footer += '\n────────────────────────────────────────';
@@ -174,148 +251,71 @@ async function getPresenceFooter() {
174
251
  }
175
252
  }
176
253
 
177
- // Load core tools (always available)
178
- const coreTools = {
179
- // Entry point
254
+ // Load all tools (~37 registered)
255
+ const tools = {
256
+ // Core — Identity & Session
180
257
  vibe_start: require('./tools/start'),
181
- // Core
182
258
  vibe_init: require('./tools/init'),
183
- vibe_token: require('./tools/token'), // GitHub OAuth token setter
184
- vibe_migrate: require('./tools/migrate'), // Migrate existing handle to GitHub auth
185
- vibe_who: require('./tools/who'),
186
- vibe_ping: require('./tools/ping'),
187
- vibe_react: require('./tools/react'),
259
+ vibe_bye: require('./tools/bye'),
260
+ // Core Messaging
188
261
  vibe_dm: require('./tools/dm'),
189
- vibe_reply: require('./tools/reply'), // Quick reply to most recent unread
190
262
  vibe_inbox: require('./tools/inbox'),
191
- vibe_search_messages: require('./tools/search-messages'), // Search DM history
192
- vibe_connection_status: require('./tools/connection-status'), // Check connection health
193
- vibe_smart_check: require('./tools/smart-check'), // Smart inbox check at natural breaks
263
+ vibe_ping: require('./tools/ping'),
264
+ vibe_follow: require('./tools/follow').follow,
265
+ vibe_unfollow: require('./tools/follow').unfollow,
266
+ // Watch / Live
267
+ vibe_watch: require('./tools/watch').watch,
268
+ vibe_live: require('./tools/watch').live,
269
+ vibe_react: require('./tools/react'),
194
270
  vibe_open: require('./tools/open'),
271
+ // Presence
272
+ vibe_who: require('./tools/who'),
195
273
  vibe_status: require('./tools/status'),
274
+ vibe_away: require('./tools/away'),
275
+ vibe_back: require('./tools/back'),
276
+ // Creative
277
+ vibe_ship: require('./tools/ship'),
278
+ vibe_session_save: require('./tools/session-save'),
279
+ vibe_session_fork: require('./tools/session-fork'),
280
+ vibe_feed: require('./tools/feed'),
196
281
  vibe_context: require('./tools/context'),
197
- vibe_work_summary: require('./tools/work-summary'), // Ambient context for composing messages
198
- vibe_summarize: require('./tools/summarize'),
199
- vibe_bye: require('./tools/bye'),
282
+ // Discovery
283
+ vibe_discover: require('./tools/discover'),
284
+ vibe_invite: require('./tools/invite'),
285
+ // Memory
286
+ vibe_remember: require('./tools/remember'),
287
+ vibe_recall: require('./tools/recall'),
288
+ vibe_forget: require('./tools/forget'),
289
+ // Games (single entry point for all 27 games)
200
290
  vibe_game: require('./tools/game'),
201
- vibe_solo_game: require('./tools/solo-game'),
202
- vibe_party_game: require('./tools/party-game'),
203
- vibe_multiplayer_game: require('./tools/multiplayer-game'),
204
- vibe_drawing: require('./tools/drawing'),
205
- vibe_crossword: require('./tools/crossword'),
206
- // AIRC Handoff (v1) — context portability
207
- vibe_handoff: require('./tools/handoff'),
208
- // File reservations (advisory locks)
291
+ // Artifacts
292
+ vibe_create_artifact: require('./tools/artifact-create'),
293
+ vibe_view_artifact: require('./tools/artifact-view'),
294
+ // File Coordination
209
295
  vibe_reserve: require('./tools/reserve'),
210
296
  vibe_release: require('./tools/release'),
211
297
  vibe_reservations: require('./tools/reservations'),
212
- // Memory tools removed — simplified UX
213
- // Consent (AIRC compliance)
214
- vibe_consent: require('./tools/consent'),
215
- // Trust & Safety
298
+ // Infrastructure
299
+ vibe_handoff: require('./tools/handoff'),
216
300
  vibe_report: require('./tools/report'),
217
- // Support
218
- vibe_help: require('./tools/help'),
219
- vibe_agents: require('./tools/agents'),
220
- // Community
221
- vibe_invite: require('./tools/invite'),
222
- vibe_submit: require('./tools/submit'),
223
- vibe_observe: require('./tools/observe'),
224
- // Creative Layer — Ideas, Requests, Ships
225
- vibe_idea: require('./tools/idea'),
226
- vibe_request: require('./tools/request'),
227
- vibe_ship: require('./tools/ship'),
228
- vibe_feed: require('./tools/feed'),
229
- vibe_insights: require('./tools/insights'),
230
- // Launch Analytics — Real-time metrics dashboard
231
- vibe_analytics: require('./tools/analytics'),
232
- // Activity Feed — Real-time community activity
233
- vibe_activity: require('./tools/activity'),
234
- // Artifacts — Just-in-time social objects
235
- vibe_create_artifact: require('./tools/artifact-create'),
236
- vibe_view_artifact: require('./tools/artifact-view'),
237
- // Plans — Async approval workflow
238
- vibe_plan: require('./tools/plan'),
239
- vibe_approve: require('./tools/approve'),
240
- // Discovery & Matchmaking
241
- vibe_discover: require('./tools/discover'),
242
301
  vibe_suggest_tags: require('./tools/suggest-tags'),
243
- // Follow system
244
- vibe_follow: require('./tools/follow'),
245
- // GitHub friends import (Plaxo move)
246
- vibe_friends: require('./tools/friends'),
247
- // Scheduling
248
- vibe_schedule: require('./tools/schedule'),
249
- // @echo feedback agent (by Flynn)
250
- vibe_echo: require('./tools/echo'),
251
- // X/Twitter bridge
252
- vibe_x_mentions: require('./tools/x-mentions'),
253
- vibe_x_reply: require('./tools/x-reply'),
254
- // Unified social inbox (Phase 1a)
255
- vibe_social_inbox: require('./tools/social-inbox'),
256
- vibe_social_post: require('./tools/social-post'),
302
+ // Diagnostics
303
+ vibe_help: require('./tools/help'),
304
+ vibe_doctor: require('./tools/doctor'),
305
+ vibe_update: require('./tools/update'),
257
306
  // Settings
258
307
  vibe_settings: require('./tools/settings'),
259
- // External notification channels
260
308
  vibe_notifications: require('./tools/notifications'),
261
- // Background presence agent (Claude Code 2.1)
262
309
  vibe_presence_agent: require('./tools/presence-agent'),
263
- // Onboarding checklist
264
- vibe_onboarding: require('./tools/onboarding'),
265
- // VIBE L2 tools
266
- vibe_l2: require('./tools/l2'),
267
- vibe_l2_status: require('./tools/l2-status'),
268
- vibe_shipback: require('./tools/shipback'),
269
- vibe_bridge: require('./tools/l2-bridge'),
270
- // Gig Marketplace & Proof-of-Work
271
- vibe_gig_browse: require('./tools/gig-browse'),
272
- vibe_gig_complete: require('./tools/gig-complete'),
273
- vibe_proof_of_work: require('./tools/proof-of-work'),
274
- vibe_artifacts_price: require('./tools/artifacts-price'),
275
- // Watch Me Code — Live broadcasting & sessions
276
- vibe_broadcast: require('./tools/broadcast'),
277
- vibe_watch: require('./tools/watch'),
278
- vibe_session: require('./tools/session'),
279
- vibe_chat: require('./tools/chat'),
280
- // Help Signal — Symbiosis layer
281
- vibe_stuck: require('./tools/stuck'),
282
- // Availability — Signal openness to chat
283
- vibe_available: require('./tools/available'),
284
- // VIBE Economy — Tips, Earnings, Withdrawals, Subscriptions
285
- vibe_tip: require('./tools/tip'),
286
- vibe_earnings: require('./tools/earnings'),
287
- vibe_withdraw: require('./tools/withdraw'),
288
- vibe_session_price: require('./tools/session_price'),
289
- vibe_subscribe: require('./tools/subscribe'),
290
- vibe_subscriptions: require('./tools/subscriptions'),
291
- // NFT Minting — Mint artifacts to VIBE L2, Base, or Ethereum
292
- vibe_mint: require('./tools/mint'),
293
- // Platform Status — Health, leaderboard, streaks
294
- vibe_health: require('./tools/health'),
295
- vibe_leaderboard: require('./tools/leaderboard'),
296
- vibe_streak: require('./tools/streak')
310
+ vibe_mute: require('./tools/mute'),
311
+ vibe_summarize: require('./tools/summarize')
297
312
  };
298
313
 
299
- // Admin tools (only loaded when VIBE_ADMIN=true)
300
- const adminTools = process.env.VIBE_ADMIN === 'true' ? {
301
- vibe_admin_inbox: require('./tools/admin-inbox'),
302
- vibe_test: require('./tools/test'),
303
- vibe_doctor: require('./tools/doctor'),
304
- vibe_update: require('./tools/update'),
305
- vibe_patterns: require('./tools/patterns'),
306
- } : {};
307
-
308
- // Combine tools
309
- const tools = { ...coreTools, ...adminTools };
310
-
311
314
  /**
312
315
  * MCP Protocol Handler
313
316
  */
314
317
  class VibeMCPServer {
315
318
  constructor() {
316
- // Hydrate auth state from disk FIRST (before any tools need it)
317
- authStore.hydrate();
318
-
319
319
  // Initialize notification emitter
320
320
  this.notifier = new NotificationEmitter(this);
321
321
 
@@ -364,7 +364,10 @@ class VibeMCPServer {
364
364
  jsonrpc: '2.0',
365
365
  id,
366
366
  result: {
367
- tools: Object.values(tools).map(t => t.definition)
367
+ tools: Object.values(tools).map(t => ({
368
+ ...t.definition,
369
+ annotations: TOOL_ANNOTATIONS[t.definition.name] || DEFAULT_ANNOTATIONS
370
+ }))
368
371
  }
369
372
  };
370
373
 
@@ -396,10 +399,15 @@ class VibeMCPServer {
396
399
  // Emit list_changed notification for state-changing tools
397
400
  // This triggers Claude to refresh without reconnection
398
401
  const stateChangingTools = [
399
- 'vibe_dm', 'vibe_ping', 'vibe_react',
400
- 'vibe_status', 'vibe_context', 'vibe_handoff',
401
- 'vibe_reserve', 'vibe_release',
402
- 'vibe_broadcast', 'vibe_session', 'vibe_chat'
402
+ 'vibe_dm',
403
+ 'vibe_ping',
404
+ 'vibe_react',
405
+ 'vibe_remember',
406
+ 'vibe_status',
407
+ 'vibe_context',
408
+ 'vibe_handoff',
409
+ 'vibe_reserve',
410
+ 'vibe_release'
403
411
  ];
404
412
  if (stateChangingTools.includes(params.name)) {
405
413
  // Debounced notification (prevents spam)
@@ -412,14 +420,32 @@ class VibeMCPServer {
412
420
  footer = await getPresenceFooter();
413
421
  }
414
422
 
423
+ // Build simplified hint indicator for Claude (human-readable)
424
+ let hintIndicator = '';
425
+ if (result.hint) {
426
+ // Simple format: <!-- vibe: hint_type @handle (count) -->
427
+ const hint = result.hint;
428
+ const handle = result.suggestion?.handle || result.for_handle || '';
429
+ const count = result.unread_count || '';
430
+
431
+ // Build minimal hint string
432
+ const hintParts = [hint];
433
+ if (handle) hintParts.push(`@${handle.replace('@', '')}`);
434
+ if (count) hintParts.push(`(${count})`);
435
+
436
+ hintIndicator = `\n\n<!-- vibe: ${hintParts.join(' ')} -->`;
437
+ }
438
+
415
439
  return {
416
440
  jsonrpc: '2.0',
417
441
  id,
418
442
  result: {
419
- content: [{
420
- type: 'text',
421
- text: (result.display || JSON.stringify(result, null, 2)) + footer
422
- }]
443
+ content: [
444
+ {
445
+ type: 'text',
446
+ text: (result.display || JSON.stringify(result, null, 2)) + hintIndicator + footer
447
+ }
448
+ ]
423
449
  }
424
450
  };
425
451
  } catch (e) {
@@ -443,7 +469,7 @@ class VibeMCPServer {
443
469
  process.stdin.setEncoding('utf8');
444
470
  let buffer = '';
445
471
 
446
- process.stdin.on('data', async (chunk) => {
472
+ process.stdin.on('data', async chunk => {
447
473
  buffer += chunk;
448
474
  const lines = buffer.split('\n');
449
475
  buffer = lines.pop() || '';
@@ -464,42 +490,26 @@ class VibeMCPServer {
464
490
 
465
491
  process.stdin.on('end', () => {
466
492
  presence.stop();
493
+ // Close SQLite to flush WAL and prevent corruption
494
+ try {
495
+ require('./store/sqlite').close();
496
+ } catch (e) {}
467
497
  process.exit(0);
468
498
  });
469
499
 
470
500
  // Welcome message
471
501
  process.stderr.write('\n/vibe ready.\n');
472
502
  process.stderr.write('vibe init → set identity\n');
473
- process.stderr.write('vibe who → see who\'s around\n');
503
+ process.stderr.write("vibe who → see who's around\n");
474
504
  process.stderr.write('vibe dm → send a message\n\n');
475
505
 
476
506
  // Check for updates (non-blocking)
477
507
  this.checkForUpdates();
478
-
479
- // Auto-presence: if authenticated, broadcast presence on connect
480
- this.autoPresence();
481
- }
482
-
483
- async autoPresence() {
484
- try {
485
- const handle = config.getHandle();
486
- if (!handle) return; // Not authenticated yet
487
-
488
- const one_liner = config.getOneLiner() || '';
489
-
490
- // Start presence heartbeat
491
- presence.start(handle, one_liner);
492
-
493
- // Log quietly (only to stderr, not intrusive)
494
- process.stderr.write(`🟢 Auto-connected as @${handle}\n`);
495
- } catch (error) {
496
- // Silent fail - don't block startup
497
- }
498
508
  }
499
509
 
500
510
  async checkForUpdates() {
501
511
  try {
502
- const { checkForUpdates, formatUpdateNotification } = require('./auto-update');
512
+ const { checkForUpdates, formatUpdateNotification } = await import('./auto-update.js');
503
513
  const update = await checkForUpdates();
504
514
 
505
515
  if (update) {
@@ -514,4 +524,4 @@ class VibeMCPServer {
514
524
 
515
525
  // Start
516
526
  const server = new VibeMCPServer();
517
- server.start();
527
+ server.start();
@@ -1,19 +1,17 @@
1
1
  /**
2
2
  * Intelligence Module — Ambient Social Awareness
3
3
  *
4
- * Five layers of intelligence:
4
+ * Four layers of intelligence:
5
5
  * 1. Infer — Smart state detection from context signals
6
6
  * 2. Serendipity — Surface meaningful coincidences
7
7
  * 3. Proactive — Background agent for social moments
8
8
  * 4. Patterns — Persistent behavioral memory (work, social, creative)
9
- * 5. Interests — Live interest inference from context (Phase 2)
10
9
  */
11
10
 
12
11
  const infer = require('./infer');
13
12
  const serendipity = require('./serendipity');
14
13
  const proactive = require('./proactive');
15
14
  const patterns = require('./patterns');
16
- const interests = require('./interests');
17
15
 
18
16
  module.exports = {
19
17
  // Inference
@@ -36,10 +34,5 @@ module.exports = {
36
34
  setSessionStart: proactive.setSessionStart,
37
35
 
38
36
  // Patterns (persistent behavioral memory)
39
- patterns,
40
-
41
- // Interests (live context inference - Phase 2)
42
- inferLiveInterests: interests.inferLiveInterests,
43
- mergeInterests: interests.mergeInterests,
44
- formatLiveInterests: interests.formatLiveInterests
37
+ patterns
45
38
  };