slashvibe-mcp 0.3.21 → 0.3.23

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 (235) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +280 -47
  3. package/auto-update.js +10 -15
  4. package/config.js +36 -31
  5. package/crypto.js +1 -6
  6. package/debug.js +12 -0
  7. package/discord.js +19 -19
  8. package/eslint.config.js +54 -0
  9. package/index.js +217 -207
  10. package/intelligence/index.js +2 -9
  11. package/intelligence/infer.js +10 -16
  12. package/intelligence/patterns.js +23 -18
  13. package/intelligence/proactive.js +16 -15
  14. package/intelligence/serendipity.js +57 -20
  15. package/memory.js +13 -8
  16. package/migrate-v2.js +72 -0
  17. package/notification-emitter.js +2 -2
  18. package/notify.js +39 -14
  19. package/package.json +28 -29
  20. package/post-install.js +141 -0
  21. package/presence.js +2 -2
  22. package/prompts.js +5 -9
  23. package/protocol/index.js +123 -87
  24. package/protocol/telegram-commands.js +36 -37
  25. package/store/api.js +358 -529
  26. package/store/local.js +9 -10
  27. package/store/profiles.js +48 -192
  28. package/store/reservations.js +2 -9
  29. package/store/skills.js +69 -71
  30. package/store/sqlite.js +355 -0
  31. package/test-skills-bootstrap.js +20 -0
  32. package/test-v2-integration.js +385 -0
  33. package/tools/_actions.js +48 -387
  34. package/tools/_connection-queue.js +45 -56
  35. package/tools/_discovery-enhanced.js +52 -57
  36. package/tools/_discovery.js +87 -185
  37. package/tools/{l2-status.js → _experimental/l2-status.js} +68 -70
  38. package/tools/{shipback.js → _experimental/shipback.js} +4 -3
  39. package/tools/_proactive-discovery.js +60 -73
  40. package/tools/_shared/index.js +41 -64
  41. package/tools/admin-inbox.js +10 -15
  42. package/tools/agents.js +1 -1
  43. package/tools/artifact-create.js +13 -23
  44. package/tools/artifact-view.js +4 -4
  45. package/tools/{_deprecated/back.js → back.js} +1 -1
  46. package/tools/bye.js +3 -5
  47. package/tools/consent.js +2 -2
  48. package/tools/context.js +9 -10
  49. package/tools/crossword.js +3 -2
  50. package/tools/discover.js +94 -356
  51. package/tools/dm.js +27 -86
  52. package/tools/doctor.js +12 -41
  53. package/tools/drawing.js +34 -20
  54. package/tools/echo.js +11 -11
  55. package/tools/feed.js +30 -58
  56. package/tools/follow.js +64 -187
  57. package/tools/{_deprecated/forget.js → forget.js} +4 -7
  58. package/tools/game.js +144 -48
  59. package/tools/handoff.js +6 -8
  60. package/tools/help.js +3 -3
  61. package/tools/idea.js +15 -27
  62. package/tools/inbox.js +121 -293
  63. package/tools/init.js +54 -151
  64. package/tools/invite.js +8 -21
  65. package/tools/migrate.js +27 -24
  66. package/tools/multiplayer-game.js +50 -40
  67. package/tools/{_deprecated/mute.js → mute.js} +4 -3
  68. package/tools/notifications.js +58 -48
  69. package/tools/observe.js +12 -15
  70. package/tools/onboarding.js +8 -11
  71. package/tools/open.js +13 -144
  72. package/tools/party-game.js +23 -12
  73. package/tools/patterns.js +2 -1
  74. package/tools/ping.js +5 -7
  75. package/tools/react.js +28 -30
  76. package/tools/{_deprecated/recall.js → recall.js} +5 -10
  77. package/tools/release.js +4 -2
  78. package/tools/{_deprecated/remember.js → remember.js} +4 -6
  79. package/tools/report.js +2 -2
  80. package/tools/request.js +6 -26
  81. package/tools/reserve.js +1 -1
  82. package/tools/session-fork.js +97 -0
  83. package/tools/session-save.js +109 -0
  84. package/tools/settings.js +30 -99
  85. package/tools/ship.js +74 -56
  86. package/tools/{_deprecated/skills-exchange.js → skills-exchange.js} +38 -39
  87. package/tools/social-inbox.js +22 -28
  88. package/tools/social-post.js +24 -27
  89. package/tools/solo-game.js +54 -46
  90. package/tools/start.js +14 -148
  91. package/tools/status.js +21 -68
  92. package/tools/submit.js +4 -2
  93. package/tools/suggest-tags.js +36 -33
  94. package/tools/summarize.js +19 -16
  95. package/tools/tag-suggestions.js +72 -73
  96. package/tools/test.js +1 -1
  97. package/tools/{_deprecated/tictactoe.js → tictactoe.js} +26 -26
  98. package/tools/token.js +4 -4
  99. package/tools/update.js +1 -2
  100. package/tools/watch.js +132 -112
  101. package/tools/who.js +20 -40
  102. package/tools/{_deprecated/wordassociation.js → wordassociation.js} +23 -20
  103. package/tools/workshop-buddy.js +52 -53
  104. package/tools/x-mentions.js +0 -1
  105. package/tools/x-reply.js +0 -1
  106. package/twitter.js +14 -20
  107. package/version.json +8 -10
  108. package/webhook-runner.js +132 -0
  109. package/auth-store.js +0 -148
  110. package/bridges/bridge-monitor.js +0 -388
  111. package/bridges/discord-bot.js +0 -431
  112. package/bridges/farcaster.js +0 -299
  113. package/bridges/telegram.js +0 -261
  114. package/bridges/webhook-health.js +0 -420
  115. package/bridges/webhook-server.js +0 -437
  116. package/bridges/whatsapp.js +0 -441
  117. package/bridges/x-webhook.js +0 -423
  118. package/games/arcade.js +0 -406
  119. package/games/chess.js +0 -451
  120. package/games/colorguess.js +0 -343
  121. package/games/crossword-words.js +0 -171
  122. package/games/crossword.js +0 -461
  123. package/games/drawing.js +0 -347
  124. package/games/gameroulette.js +0 -300
  125. package/games/gamerouter.js +0 -336
  126. package/games/gamestatus.js +0 -337
  127. package/games/guessnumber.js +0 -209
  128. package/games/hangman.js +0 -279
  129. package/games/memory.js +0 -338
  130. package/games/multiplayer-tictactoe.js +0 -389
  131. package/games/pixelart.js +0 -399
  132. package/games/quickduel.js +0 -354
  133. package/games/riddle.js +0 -371
  134. package/games/rockpaperscissors.js +0 -291
  135. package/games/snake.js +0 -406
  136. package/games/storybuilder.js +0 -343
  137. package/games/tictactoe.js +0 -345
  138. package/games/twentyquestions.js +0 -286
  139. package/games/twotruths.js +0 -207
  140. package/games/werewolf.js +0 -508
  141. package/games/wordassociation.js +0 -247
  142. package/games/wordchain.js +0 -135
  143. package/intelligence/interests.js +0 -369
  144. package/setup.js +0 -480
  145. package/smart-inbox.js +0 -276
  146. package/tools/_deprecated/auto-suggest-connections.js +0 -304
  147. package/tools/_deprecated/bootstrap-skills.js +0 -231
  148. package/tools/_deprecated/bridge-dashboard.js +0 -342
  149. package/tools/_deprecated/bridge-health.js +0 -400
  150. package/tools/_deprecated/bridge-live.js +0 -384
  151. package/tools/_deprecated/bridges.js +0 -383
  152. package/tools/_deprecated/colorguess.js +0 -281
  153. package/tools/_deprecated/discover-insights.js +0 -379
  154. package/tools/_deprecated/discover-momentum.js +0 -256
  155. package/tools/_deprecated/discovery-analytics.js +0 -345
  156. package/tools/_deprecated/discovery-auto-suggest.js +0 -275
  157. package/tools/_deprecated/discovery-bootstrap.js +0 -267
  158. package/tools/_deprecated/discovery-daily.js +0 -375
  159. package/tools/_deprecated/discovery-dashboard.js +0 -385
  160. package/tools/_deprecated/discovery-digest.js +0 -314
  161. package/tools/_deprecated/discovery-hub.js +0 -357
  162. package/tools/_deprecated/discovery-insights.js +0 -384
  163. package/tools/_deprecated/discovery-momentum.js +0 -281
  164. package/tools/_deprecated/discovery-monitor.js +0 -319
  165. package/tools/_deprecated/discovery-proactive.js +0 -300
  166. package/tools/_deprecated/draw.js +0 -317
  167. package/tools/_deprecated/farcaster.js +0 -307
  168. package/tools/_deprecated/games-catalog.js +0 -376
  169. package/tools/_deprecated/games.js +0 -313
  170. package/tools/_deprecated/guessnumber.js +0 -194
  171. package/tools/_deprecated/hangman.js +0 -129
  172. package/tools/_deprecated/multiplayer-tictactoe.js +0 -303
  173. package/tools/_deprecated/riddle.js +0 -240
  174. package/tools/_deprecated/run-bootstrap.js +0 -69
  175. package/tools/_deprecated/skills-analytics.js +0 -349
  176. package/tools/_deprecated/skills-bootstrap.js +0 -301
  177. package/tools/_deprecated/skills-dashboard.js +0 -268
  178. package/tools/_deprecated/skills.js +0 -380
  179. package/tools/_deprecated/smart-intro.js +0 -353
  180. package/tools/_deprecated/storybuilder.js +0 -331
  181. package/tools/_deprecated/telegram-bot.js +0 -183
  182. package/tools/_deprecated/telegram-setup.js +0 -214
  183. package/tools/_deprecated/twentyquestions.js +0 -143
  184. package/tools/_shared.js +0 -234
  185. package/tools/_work-context.js +0 -338
  186. package/tools/_work-context.manual-test.js +0 -199
  187. package/tools/_work-context.test.js +0 -260
  188. package/tools/activity.js +0 -220
  189. package/tools/agent-treasury.js +0 -288
  190. package/tools/analytics.js +0 -191
  191. package/tools/approve.js +0 -197
  192. package/tools/arcade.js +0 -173
  193. package/tools/artifacts-price.js +0 -107
  194. package/tools/ask-expert.js +0 -160
  195. package/tools/available.js +0 -120
  196. package/tools/become-expert.js +0 -150
  197. package/tools/broadcast.js +0 -325
  198. package/tools/chat.js +0 -202
  199. package/tools/collaborative-drawing.js +0 -286
  200. package/tools/connection-status.js +0 -178
  201. package/tools/earnings.js +0 -126
  202. package/tools/friends.js +0 -207
  203. package/tools/genesis.js +0 -233
  204. package/tools/gig-browse.js +0 -206
  205. package/tools/gig-complete.js +0 -144
  206. package/tools/health.js +0 -87
  207. package/tools/leaderboard.js +0 -117
  208. package/tools/lib/git-apply.js +0 -206
  209. package/tools/lib/git-bundle.js +0 -407
  210. package/tools/mint.js +0 -377
  211. package/tools/plan.js +0 -225
  212. package/tools/profile.js +0 -219
  213. package/tools/proof-of-work.js +0 -144
  214. package/tools/pulse.js +0 -218
  215. package/tools/reply.js +0 -166
  216. package/tools/reputation.js +0 -175
  217. package/tools/schedule.js +0 -367
  218. package/tools/search-messages.js +0 -123
  219. package/tools/session.js +0 -467
  220. package/tools/session_price.js +0 -128
  221. package/tools/smart-check.js +0 -201
  222. package/tools/social-processor.js +0 -445
  223. package/tools/streak.js +0 -147
  224. package/tools/stuck.js +0 -297
  225. package/tools/subscribe.js +0 -148
  226. package/tools/subscriptions.js +0 -134
  227. package/tools/tip.js +0 -193
  228. package/tools/wallet.js +0 -269
  229. package/tools/webhook-test.js +0 -388
  230. package/tools/withdraw.js +0 -145
  231. package/tools/work-summary.js +0 -96
  232. package/tools/workshop.js +0 -327
  233. /package/tools/{l2-bridge.js → _experimental/l2-bridge.js} +0 -0
  234. /package/tools/{l2.js → _experimental/l2.js} +0 -0
  235. /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
  };