slashvibe-mcp 0.2.1 → 0.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (135) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +58 -40
  3. package/config.js +171 -3
  4. package/index.js +139 -16
  5. package/intelligence/index.js +38 -0
  6. package/intelligence/infer.js +316 -0
  7. package/intelligence/patterns.js +651 -0
  8. package/intelligence/proactive.js +358 -0
  9. package/intelligence/serendipity.js +306 -0
  10. package/notify.js +141 -18
  11. package/package.json +9 -4
  12. package/presence.js +5 -1
  13. package/prompts.js +141 -0
  14. package/protocol/index.js +88 -1
  15. package/protocol/telegram-commands.js +199 -0
  16. package/store/api.js +360 -25
  17. package/store/index.js +7 -7
  18. package/store/local.js +67 -11
  19. package/store/profiles.js +287 -0
  20. package/store/reservations.js +321 -0
  21. package/store/skills.js +378 -0
  22. package/tools/_actions.js +270 -14
  23. package/tools/_connection-queue.js +257 -0
  24. package/tools/_discovery-enhanced.js +290 -0
  25. package/tools/_discovery.js +346 -0
  26. package/tools/_proactive-discovery.js +301 -0
  27. package/tools/admin-inbox.js +218 -0
  28. package/tools/agent-treasury.js +288 -0
  29. package/tools/agents.js +122 -0
  30. package/tools/arcade.js +173 -0
  31. package/tools/artifact-create.js +236 -0
  32. package/tools/artifact-view.js +174 -0
  33. package/tools/ask-expert.js +160 -0
  34. package/tools/auto-suggest-connections.js +304 -0
  35. package/tools/away.js +68 -0
  36. package/tools/back.js +51 -0
  37. package/tools/become-expert.js +150 -0
  38. package/tools/bootstrap-skills.js +231 -0
  39. package/tools/bridge-dashboard.js +342 -0
  40. package/tools/bridge-health.js +400 -0
  41. package/tools/bridge-live.js +384 -0
  42. package/tools/bridges.js +383 -0
  43. package/tools/bye.js +4 -0
  44. package/tools/collaborative-drawing.js +286 -0
  45. package/tools/colorguess.js +281 -0
  46. package/tools/crossword.js +369 -0
  47. package/tools/discover-insights.js +379 -0
  48. package/tools/discover-momentum.js +256 -0
  49. package/tools/discover.js +395 -0
  50. package/tools/discovery-analytics.js +345 -0
  51. package/tools/discovery-auto-suggest.js +275 -0
  52. package/tools/discovery-bootstrap.js +267 -0
  53. package/tools/discovery-daily.js +375 -0
  54. package/tools/discovery-dashboard.js +385 -0
  55. package/tools/discovery-digest.js +314 -0
  56. package/tools/discovery-hub.js +357 -0
  57. package/tools/discovery-insights.js +384 -0
  58. package/tools/discovery-momentum.js +281 -0
  59. package/tools/discovery-monitor.js +319 -0
  60. package/tools/discovery-proactive.js +300 -0
  61. package/tools/dm.js +62 -9
  62. package/tools/draw.js +317 -0
  63. package/tools/drawing.js +310 -0
  64. package/tools/echo.js +16 -0
  65. package/tools/farcaster.js +307 -0
  66. package/tools/feed.js +196 -0
  67. package/tools/game.js +218 -110
  68. package/tools/games-catalog.js +376 -0
  69. package/tools/games.js +313 -0
  70. package/tools/genesis.js +233 -0
  71. package/tools/guessnumber.js +194 -0
  72. package/tools/handoff.js +239 -0
  73. package/tools/hangman.js +129 -0
  74. package/tools/help.js +269 -0
  75. package/tools/idea.js +210 -0
  76. package/tools/inbox.js +148 -25
  77. package/tools/init.js +651 -33
  78. package/tools/insights.js +123 -0
  79. package/tools/invite.js +142 -21
  80. package/tools/l2-bridge.js +272 -0
  81. package/tools/l2-status.js +217 -0
  82. package/tools/l2.js +206 -0
  83. package/tools/migrate.js +156 -0
  84. package/tools/mint.js +377 -0
  85. package/tools/multiplayer-game.js +275 -0
  86. package/tools/multiplayer-tictactoe.js +303 -0
  87. package/tools/mute.js +97 -0
  88. package/tools/notifications.js +415 -0
  89. package/tools/observe.js +200 -0
  90. package/tools/onboarding.js +147 -0
  91. package/tools/open.js +14 -2
  92. package/tools/party-game.js +314 -0
  93. package/tools/presence-agent.js +167 -0
  94. package/tools/profile.js +219 -0
  95. package/tools/pulse.js +218 -0
  96. package/tools/react.js +4 -0
  97. package/tools/release.js +83 -0
  98. package/tools/report.js +109 -0
  99. package/tools/reputation.js +175 -0
  100. package/tools/request.js +217 -0
  101. package/tools/reservations.js +116 -0
  102. package/tools/reserve.js +111 -0
  103. package/tools/riddle.js +240 -0
  104. package/tools/run-bootstrap.js +69 -0
  105. package/tools/settings.js +112 -0
  106. package/tools/ship.js +182 -0
  107. package/tools/shipback.js +326 -0
  108. package/tools/skills-analytics.js +349 -0
  109. package/tools/skills-bootstrap.js +301 -0
  110. package/tools/skills-dashboard.js +268 -0
  111. package/tools/skills-exchange.js +342 -0
  112. package/tools/skills.js +380 -0
  113. package/tools/smart-intro.js +353 -0
  114. package/tools/social-inbox.js +326 -69
  115. package/tools/social-post.js +251 -66
  116. package/tools/social-processor.js +445 -0
  117. package/tools/solo-game.js +390 -0
  118. package/tools/start.js +205 -83
  119. package/tools/storybuilder.js +331 -0
  120. package/tools/suggest-tags.js +186 -0
  121. package/tools/tag-suggestions.js +257 -0
  122. package/tools/telegram-bot.js +183 -0
  123. package/tools/telegram-setup.js +214 -0
  124. package/tools/tictactoe.js +155 -0
  125. package/tools/tip.js +120 -0
  126. package/tools/token.js +103 -0
  127. package/tools/twentyquestions.js +143 -0
  128. package/tools/wallet.js +127 -0
  129. package/tools/webhook-test.js +388 -0
  130. package/tools/who.js +118 -25
  131. package/tools/wordassociation.js +247 -0
  132. package/tools/workshop-buddy.js +394 -0
  133. package/tools/workshop.js +327 -0
  134. package/version.json +12 -3
  135. package/tools/board.js +0 -130
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Slash Vibe, Inc.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,69 +1,87 @@
1
- # vibe-mcp
1
+ # /vibe MCP Server
2
2
 
3
- Social layer for Claude Code. DMs, presence, and connection between AI-assisted developers.
3
+ The social layer for Claude Code. DMs, presence, and connection between AI developers.
4
+
5
+ ## What is /vibe?
6
+
7
+ /vibe brings social connection to the terminal. While you're building with Claude Code, /vibe lets you:
8
+
9
+ - **See who's online** - Know when other developers are in flow
10
+ - **Send DMs** - Message fellow builders without leaving your terminal
11
+ - **Share your presence** - Let others know what you're working on
12
+ - **Build reputation** - Your sessions become proof of work
4
13
 
5
14
  ## Installation
6
15
 
7
16
  ```bash
8
- # Install globally
9
- npm install -g vibe-mcp
10
-
11
- # Or add to Claude Code MCP config
12
- claude mcp add vibe-mcp
17
+ npx slashvibe-mcp
13
18
  ```
14
19
 
15
- ## Manual Setup
16
-
17
- Add to `~/.claude.json`:
20
+ Or add to your Claude Code MCP settings (`~/.claude.json`):
18
21
 
19
22
  ```json
20
23
  {
21
24
  "mcpServers": {
22
25
  "vibe": {
23
26
  "command": "npx",
24
- "args": ["vibe-mcp"],
25
- "env": {
26
- "VIBE_API_URL": "https://www.slashvibe.dev"
27
- }
27
+ "args": ["-y", "slashvibe-mcp"]
28
28
  }
29
29
  }
30
30
  }
31
31
  ```
32
32
 
33
- ## Features
33
+ ## Quick Start
34
+
35
+ 1. Install the MCP server
36
+ 2. Authenticate: `vibe_auth` tool will guide you
37
+ 3. Check who's online: `vibe_presence`
38
+ 4. Send a message: `vibe_dm`
39
+
40
+ ## Available Tools
34
41
 
35
- - **Presence** - See who's online building with Claude Code
36
- - **DMs** - Direct messages between developers
37
- - **Memory** - Remember context about connections
38
- - **Status** - Share what you're working on
39
- - **Games** - Play tic-tac-toe while coding
42
+ | Tool | Description |
43
+ |------|-------------|
44
+ | `vibe_auth` | Authenticate with slashvibe.dev |
45
+ | `vibe_presence` | See who's online now |
46
+ | `vibe_dm` | Send a direct message |
47
+ | `vibe_inbox` | Check your messages |
48
+ | `vibe_ship` | Announce what you shipped |
49
+ | `vibe_idea` | Share an idea with the community |
50
+ | `vibe_discover` | Find interesting builders |
51
+ | `vibe_remember` | Save context about a connection |
52
+ | `vibe_recall` | Recall memories about someone |
40
53
 
41
- ## Commands
54
+ ## The Platform
42
55
 
43
- Once installed, use these in Claude Code:
56
+ This MCP server connects to [slashvibe.dev](https://slashvibe.dev), where:
44
57
 
45
- | Command | Description |
46
- |---------|-------------|
47
- | `vibe` | Check inbox and see who's online |
48
- | `vibe who` | List online users |
49
- | `vibe dm @handle "message"` | Send a DM |
50
- | `vibe status shipping` | Set your status |
51
- | `vibe remember @handle "note"` | Save a memory |
52
- | `vibe recall @handle` | Recall memories |
58
+ - Your identity persists across sessions
59
+ - Your work builds reputation over time
60
+ - The community grows through genuine connection
53
61
 
54
- ## API
62
+ ## Philosophy
55
63
 
56
- The MCP server connects to `slashvibe.dev` for:
57
- - User presence and discovery
58
- - Message routing
59
- - Identity verification
64
+ We believe AI development should be social, not solitary. The terminal is where real work happens - decisions, debugging, breakthroughs. /vibe makes that visible and connectable.
60
65
 
61
- ## Related
66
+ **Empathy. Collaboration. Shared value creation.**
62
67
 
63
- - [slashvibe.dev](https://slashvibe.dev) - Web presence
64
- - [Spirit Protocol](https://spiritprotocol.io) - Parent ecosystem
65
- - [AIRC](https://airc.chat) - Agent identity protocol
68
+ ## Contributing
69
+
70
+ We welcome contributions! Please read our [Contributor License Agreement](./CLA.md) before submitting pull requests.
71
+
72
+ - Report bugs via [GitHub Issues](https://github.com/VibeCodingInc/vibe-mcp/issues)
73
+ - Propose features via [Discussions](https://github.com/VibeCodingInc/vibe-mcp/discussions)
74
+ - Submit PRs for review
66
75
 
67
76
  ## License
68
77
 
69
- MIT
78
+ MIT - see [LICENSE](./LICENSE)
79
+
80
+ ## Links
81
+
82
+ - [slashvibe.dev](https://slashvibe.dev) - The platform
83
+ - [Twitter](https://twitter.com/slashvibe) - Updates
84
+
85
+ ---
86
+
87
+ Built with obsession by [Slash Vibe, Inc.](https://slashvibe.dev)
package/config.js CHANGED
@@ -66,7 +66,15 @@ function save(config) {
66
66
  publicKey: config.publicKey || existing.publicKey || null,
67
67
  privateKey: config.privateKey || existing.privateKey || null,
68
68
  // Guided mode (AskUserQuestion menus)
69
- guided_mode: config.guided_mode !== undefined ? config.guided_mode : existing.guided_mode
69
+ guided_mode: config.guided_mode !== undefined ? config.guided_mode : existing.guided_mode,
70
+ // Notification level
71
+ notifications: config.notifications || existing.notifications || null,
72
+ // GitHub Activity settings
73
+ github_activity_enabled: config.github_activity_enabled !== undefined ? config.github_activity_enabled : existing.github_activity_enabled,
74
+ github_activity_privacy: config.github_activity_privacy || existing.github_activity_privacy || null,
75
+ // Privy OAuth token (persisted across MCP process restarts)
76
+ privyToken: config.privyToken || existing.privyToken || null,
77
+ authMethod: config.authMethod || existing.authMethod || null
70
78
  };
71
79
  fs.writeFileSync(PRIMARY_CONFIG, JSON.stringify(data, null, 2));
72
80
  }
@@ -203,8 +211,77 @@ function setAuthToken(token, sessionId = null) {
203
211
  }
204
212
 
205
213
  function getAuthToken() {
214
+ // First check session data
215
+ const data = getSessionData();
216
+ if (data?.token) return data.token;
217
+
218
+ // Fall back to shared config (persisted across MCP process restarts)
219
+ const cfg = load();
220
+ return cfg?.privyToken || null;
221
+ }
222
+
223
+ /**
224
+ * Save Privy JWT token (used after browser OAuth flow)
225
+ * @param {string} token - Privy access token
226
+ */
227
+ function savePrivyToken(token) {
228
+ // Save to session data
229
+ const data = getSessionData() || {};
230
+ saveSessionData({
231
+ ...data,
232
+ sessionId: data.sessionId || generateSessionId(),
233
+ token,
234
+ authMethod: 'privy' // Track that this is a Privy token
235
+ });
236
+
237
+ // Also save to shared config for persistence across MCP restarts
238
+ const cfg = load();
239
+ cfg.privyToken = token;
240
+ cfg.authMethod = 'privy';
241
+ save(cfg);
242
+ }
243
+
244
+ /**
245
+ * Check if user has Privy auth (vs legacy keypair)
246
+ */
247
+ function hasPrivyAuth() {
206
248
  const data = getSessionData();
207
- return data?.token || null;
249
+ if (data?.authMethod === 'privy' && data?.token) return true;
250
+
251
+ const cfg = load();
252
+ return cfg?.authMethod === 'privy' && cfg?.privyToken;
253
+ }
254
+
255
+ /**
256
+ * Remove keypair after migration to Privy
257
+ * Clears private key from config (security improvement)
258
+ */
259
+ function removeKeypair() {
260
+ const cfg = load();
261
+ delete cfg.publicKey;
262
+ delete cfg.privateKey;
263
+ save(cfg);
264
+
265
+ // Also clear from session
266
+ const data = getSessionData();
267
+ if (data) {
268
+ delete data.publicKey;
269
+ delete data.privateKey;
270
+ saveSessionData(data);
271
+ }
272
+ }
273
+
274
+ /**
275
+ * Get auth URL for browser-based GitHub OAuth
276
+ * @param {string|null} handle - Custom handle (optional - defaults to GitHub username)
277
+ */
278
+ function getAuthUrl(handle = null) {
279
+ const apiUrl = getApiUrl();
280
+ if (handle) {
281
+ return `${apiUrl}/api/auth/github?handle=${encodeURIComponent(handle)}`;
282
+ }
283
+ // No handle = use GitHub username as handle
284
+ return `${apiUrl}/api/auth/github`;
208
285
  }
209
286
 
210
287
  function clearSession() {
@@ -228,6 +305,81 @@ function setGuidedMode(enabled) {
228
305
  save(config);
229
306
  }
230
307
 
308
+ // Notification settings
309
+ // Levels: "all" | "mentions" | "off"
310
+ // - all: desktop + bell for unread, mentions, presence (default)
311
+ // - mentions: only @mentions trigger notifications
312
+ // - off: no notifications
313
+ function getNotifications() {
314
+ const config = load();
315
+ return config.notifications || 'all';
316
+ }
317
+
318
+ function setNotifications(level) {
319
+ const validLevels = ['all', 'mentions', 'off'];
320
+ if (!validLevels.includes(level)) {
321
+ throw new Error(`Invalid notification level. Use: ${validLevels.join(', ')}`);
322
+ }
323
+ const config = load();
324
+ config.notifications = level;
325
+ save(config);
326
+ }
327
+
328
+ // GitHub Activity settings
329
+ // Shows shipping status based on GitHub commit activity
330
+ // Default: false (opt-in for privacy)
331
+ function getGithubActivityEnabled() {
332
+ const config = load();
333
+ return config.github_activity_enabled === true;
334
+ }
335
+
336
+ function setGithubActivityEnabled(enabled) {
337
+ const config = load();
338
+ config.github_activity_enabled = enabled;
339
+ save(config);
340
+ }
341
+
342
+ // GitHub Activity privacy level
343
+ // Levels: "full" | "status_only" | "off"
344
+ // - full: Show repos, commit counts, tech stack (default when enabled)
345
+ // - status_only: Just show shipping badge (🔥/⚡), no details
346
+ // - off: Disabled completely
347
+ function getGithubActivityPrivacy() {
348
+ const config = load();
349
+ return config.github_activity_privacy || 'full';
350
+ }
351
+
352
+ function setGithubActivityPrivacy(level) {
353
+ const validLevels = ['full', 'status_only', 'off'];
354
+ if (!validLevels.includes(level)) {
355
+ throw new Error(`Invalid privacy level. Use: ${validLevels.join(', ')}`);
356
+ }
357
+ const config = load();
358
+ config.github_activity_privacy = level;
359
+ save(config);
360
+ }
361
+
362
+ // API URL — central endpoint for all API calls
363
+ function getApiUrl() {
364
+ return process.env.VIBE_API_URL || 'https://www.slashvibe.dev';
365
+ }
366
+
367
+ // ─────────────────────────────────────────────────────────────
368
+ // Generic key-value store for ephemeral session state
369
+ // Used by presence-agent, mute, and other tools for runtime state
370
+ // NOT persisted to disk — resets when MCP server restarts
371
+ // ─────────────────────────────────────────────────────────────
372
+ const sessionState = {};
373
+
374
+ function get(key, defaultValue = null) {
375
+ return sessionState[key] !== undefined ? sessionState[key] : defaultValue;
376
+ }
377
+
378
+ function set(key, value) {
379
+ sessionState[key] = value;
380
+ return value;
381
+ }
382
+
231
383
  module.exports = {
232
384
  VIBE_DIR,
233
385
  CONFIG_FILE,
@@ -248,5 +400,21 @@ module.exports = {
248
400
  clearSession,
249
401
  generateSessionId,
250
402
  getGuidedMode,
251
- setGuidedMode
403
+ setGuidedMode,
404
+ getNotifications,
405
+ setNotifications,
406
+ // GitHub Activity settings
407
+ getGithubActivityEnabled,
408
+ setGithubActivityEnabled,
409
+ getGithubActivityPrivacy,
410
+ setGithubActivityPrivacy,
411
+ getApiUrl,
412
+ // Privy OAuth helpers
413
+ savePrivyToken,
414
+ hasPrivyAuth,
415
+ removeKeypair,
416
+ getAuthUrl,
417
+ // Generic key-value for ephemeral session state
418
+ get,
419
+ set
252
420
  };
package/index.js CHANGED
@@ -10,9 +10,10 @@ const presence = require('./presence');
10
10
  const config = require('./config');
11
11
  const store = require('./store');
12
12
  const prompts = require('./prompts');
13
+ const NotificationEmitter = require('./notification-emitter');
13
14
 
14
15
  // Tools that shouldn't show presence footer (would be redundant/noisy)
15
- const SKIP_FOOTER_TOOLS = ['vibe_init', 'vibe_doctor', 'vibe_test', 'vibe_update'];
16
+ const SKIP_FOOTER_TOOLS = ['vibe_init', 'vibe_doctor', 'vibe_test', 'vibe_update', 'vibe_settings', 'vibe_notifications'];
16
17
 
17
18
  // Infer user prompt from tool arguments (for pattern logging)
18
19
  function inferPromptFromArgs(toolName, args) {
@@ -39,10 +40,29 @@ function inferPromptFromArgs(toolName, args) {
39
40
  case 'recall': return `recall ${handle}`;
40
41
  case 'forget': return `forget ${handle}`;
41
42
  case 'board': return args.content ? 'post to board' : 'view board';
43
+ case 'observe': return args.content ? 'record observation' : 'view observations';
42
44
  case 'invite': return 'generate invite';
43
45
  case 'echo': return 'send feedback';
44
46
  case 'x_mentions': return 'check x mentions';
45
47
  case 'x_reply': return 'reply on x';
48
+ case 'handoff': return `handoff task to ${handle}`;
49
+ case 'reserve': return args.paths ? `reserve ${args.paths.join(', ')}` : 'reserve files';
50
+ case 'release': return `release ${args.reservation_id || 'reservation'}`;
51
+ case 'reservations': return 'list reservations';
52
+ case 'solo_game': return `play ${args.game || 'game'}`;
53
+ case 'tictactoe': return `play tic-tac-toe ${args.difficulty || ''}`.trim();
54
+ case 'wordassociation': return args.word ? `word association: ${args.word}` : 'play word association';
55
+ case 'multiplayer_game': return `multiplayer ${args.game || 'game'}`;
56
+ case 'drawing': return args.action ? `drawing ${args.action}` : 'collaborative drawing';
57
+ case 'crossword': return `crossword ${args.action || 'daily'}`;
58
+ case 'away': return args.message ? `set away: "${args.message}"` : 'go away';
59
+ case 'back': return 'come back';
60
+ case 'discover': return `discover ${args.command || 'suggest'}`;
61
+ case 'suggest_tags': return `suggest tags ${args.command || 'suggest'}`;
62
+ case 'skills_exchange': return `skills exchange ${args.command || 'browse'}`;
63
+ case 'workshop_buddy': return `workshop buddy ${args.command || 'find'}`;
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'}`;
46
66
  default: return `${action} ${handle}`.trim() || null;
47
67
  }
48
68
  }
@@ -150,6 +170,8 @@ const tools = {
150
170
  vibe_start: require('./tools/start'),
151
171
  // Core
152
172
  vibe_init: require('./tools/init'),
173
+ vibe_token: require('./tools/token'), // Privy OAuth token setter
174
+ vibe_migrate: require('./tools/migrate'), // Migrate existing handle to GitHub auth
153
175
  vibe_who: require('./tools/who'),
154
176
  vibe_ping: require('./tools/ping'),
155
177
  vibe_react: require('./tools/react'),
@@ -161,16 +183,53 @@ const tools = {
161
183
  vibe_summarize: require('./tools/summarize'),
162
184
  vibe_bye: require('./tools/bye'),
163
185
  vibe_game: require('./tools/game'),
186
+ vibe_solo_game: require('./tools/solo-game'),
187
+ vibe_party_game: require('./tools/party-game'),
188
+ vibe_tictactoe: require('./tools/tictactoe'),
189
+ vibe_wordassociation: require('./tools/wordassociation'),
190
+ vibe_multiplayer_game: require('./tools/multiplayer-game'),
191
+ vibe_drawing: require('./tools/drawing'),
192
+ // Nostalgia Stack
193
+ vibe_crossword: require('./tools/crossword'),
194
+ vibe_away: require('./tools/away'),
195
+ vibe_back: require('./tools/back'),
196
+ // AIRC Handoff (v1) — context portability
197
+ vibe_handoff: require('./tools/handoff'),
198
+ // File reservations (advisory locks)
199
+ vibe_reserve: require('./tools/reserve'),
200
+ vibe_release: require('./tools/release'),
201
+ vibe_reservations: require('./tools/reservations'),
164
202
  // Memory tools (Tier 1 — Collaborative Memory)
165
203
  vibe_remember: require('./tools/remember'),
166
204
  vibe_recall: require('./tools/recall'),
167
205
  vibe_forget: require('./tools/forget'),
168
206
  // Consent (AIRC compliance)
169
207
  vibe_consent: require('./tools/consent'),
208
+ // Trust & Safety
209
+ vibe_report: require('./tools/report'),
210
+ // Support
211
+ vibe_help: require('./tools/help'),
212
+ vibe_agents: require('./tools/agents'),
170
213
  // Community
171
214
  vibe_invite: require('./tools/invite'),
172
- vibe_board: require('./tools/board'),
173
215
  vibe_submit: require('./tools/submit'),
216
+ vibe_observe: require('./tools/observe'),
217
+ // Creative Layer — Ideas, Requests, Ships
218
+ vibe_idea: require('./tools/idea'),
219
+ vibe_request: require('./tools/request'),
220
+ vibe_ship: require('./tools/ship'),
221
+ vibe_feed: require('./tools/feed'),
222
+ vibe_insights: require('./tools/insights'),
223
+ // Artifacts — Just-in-time social objects
224
+ vibe_create_artifact: require('./tools/artifact-create'),
225
+ vibe_view_artifact: require('./tools/artifact-view'),
226
+ // Discovery & Matchmaking
227
+ vibe_discover: require('./tools/discover'),
228
+ vibe_suggest_tags: require('./tools/suggest-tags'),
229
+ vibe_skills_exchange: require('./tools/skills-exchange'),
230
+ vibe_workshop_buddy: require('./tools/workshop-buddy'),
231
+ // Admin tools
232
+ vibe_admin_inbox: require('./tools/admin-inbox'),
174
233
  // Diagnostics
175
234
  vibe_test: require('./tools/test'),
176
235
  vibe_doctor: require('./tools/doctor'),
@@ -184,7 +243,21 @@ const tools = {
184
243
  vibe_social_inbox: require('./tools/social-inbox'),
185
244
  vibe_social_post: require('./tools/social-post'),
186
245
  // Language evolution
187
- vibe_patterns: require('./tools/patterns')
246
+ vibe_patterns: require('./tools/patterns'),
247
+ // Settings
248
+ vibe_settings: require('./tools/settings'),
249
+ // External notification channels
250
+ vibe_notifications: require('./tools/notifications'),
251
+ // Background presence agent (Claude Code 2.1)
252
+ vibe_presence_agent: require('./tools/presence-agent'),
253
+ vibe_mute: require('./tools/mute'),
254
+ // Onboarding checklist
255
+ vibe_onboarding: require('./tools/onboarding'),
256
+ // VIBE L2 tools
257
+ vibe_l2: require('./tools/l2'),
258
+ vibe_l2_status: require('./tools/l2-status'),
259
+ vibe_shipback: require('./tools/shipback'),
260
+ vibe_bridge: require('./tools/l2-bridge')
188
261
  };
189
262
 
190
263
  /**
@@ -192,10 +265,30 @@ const tools = {
192
265
  */
193
266
  class VibeMCPServer {
194
267
  constructor() {
268
+ // Initialize notification emitter
269
+ this.notifier = new NotificationEmitter(this);
270
+
271
+ // Make notifier globally accessible for tools and store layer
272
+ global.vibeNotifier = this.notifier;
273
+
195
274
  // Start presence heartbeat
196
275
  presence.start();
197
276
  }
198
277
 
278
+ /**
279
+ * Send MCP notification
280
+ * Called by NotificationEmitter to push list_changed events
281
+ */
282
+ notification(payload) {
283
+ // Send notification via stdout (MCP protocol)
284
+ const notification = {
285
+ jsonrpc: '2.0',
286
+ method: payload.method,
287
+ params: payload.params || {}
288
+ };
289
+ process.stdout.write(JSON.stringify(notification) + '\n');
290
+ }
291
+
199
292
  async handleRequest(request) {
200
293
  const { method, params, id } = request;
201
294
 
@@ -249,25 +342,38 @@ class VibeMCPServer {
249
342
 
250
343
  const result = await tool.handler(args);
251
344
 
345
+ // Emit list_changed notification for state-changing tools
346
+ // This triggers Claude to refresh without reconnection
347
+ const stateChangingTools = [
348
+ 'vibe_dm', 'vibe_ping', 'vibe_react', 'vibe_remember',
349
+ 'vibe_status', 'vibe_context', 'vibe_handoff',
350
+ 'vibe_reserve', 'vibe_release'
351
+ ];
352
+ if (stateChangingTools.includes(params.name)) {
353
+ // Debounced notification (prevents spam)
354
+ global.vibeNotifier?.emitChange(params.name);
355
+ }
356
+
252
357
  // Add ambient presence footer (unless tool is in skip list)
253
358
  let footer = '';
254
359
  if (!SKIP_FOOTER_TOOLS.includes(params.name)) {
255
360
  footer = await getPresenceFooter();
256
361
  }
257
362
 
258
- // Build hint indicator for Claude to trigger dashboard flows
363
+ // Build simplified hint indicator for Claude (human-readable)
259
364
  let hintIndicator = '';
260
- if (result.hint || result.actions) {
261
- const hintData = {
262
- ...(result.hint && { hint: result.hint }),
263
- ...(result.suggestion && { suggestion: result.suggestion }),
264
- ...(result.unread_count && { unread_count: result.unread_count }),
265
- ...(result.for_handle && { for_handle: result.for_handle }),
266
- ...(result.memories && { memories: result.memories }),
267
- ...(result.threads && { threads: result.threads }),
268
- ...(result.actions && { actions: result.actions })
269
- };
270
- hintIndicator = `\n\n<!-- vibe:dashboard ${JSON.stringify(hintData)} -->`;
365
+ if (result.hint) {
366
+ // Simple format: <!-- vibe: hint_type @handle (count) -->
367
+ const hint = result.hint;
368
+ const handle = result.suggestion?.handle || result.for_handle || '';
369
+ const count = result.unread_count || '';
370
+
371
+ // Build minimal hint string
372
+ let hintParts = [hint];
373
+ if (handle) hintParts.push(`@${handle.replace('@', '')}`);
374
+ if (count) hintParts.push(`(${count})`);
375
+
376
+ hintIndicator = `\n\n<!-- vibe: ${hintParts.join(' ')} -->`;
271
377
  }
272
378
 
273
379
  return {
@@ -330,9 +436,26 @@ class VibeMCPServer {
330
436
  process.stderr.write('vibe init → set identity\n');
331
437
  process.stderr.write('vibe who → see who\'s around\n');
332
438
  process.stderr.write('vibe dm → send a message\n\n');
439
+
440
+ // Check for updates (non-blocking)
441
+ this.checkForUpdates();
442
+ }
443
+
444
+ async checkForUpdates() {
445
+ try {
446
+ const { checkForUpdates, formatUpdateNotification } = await import('./auto-update.js');
447
+ const update = await checkForUpdates();
448
+
449
+ if (update) {
450
+ const notification = formatUpdateNotification(update);
451
+ process.stderr.write(notification);
452
+ }
453
+ } catch (error) {
454
+ // Silent fail - don't block startup
455
+ }
333
456
  }
334
457
  }
335
458
 
336
459
  // Start
337
460
  const server = new VibeMCPServer();
338
- server.start();
461
+ server.start();
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Intelligence Module — Ambient Social Awareness
3
+ *
4
+ * Four layers of intelligence:
5
+ * 1. Infer — Smart state detection from context signals
6
+ * 2. Serendipity — Surface meaningful coincidences
7
+ * 3. Proactive — Background agent for social moments
8
+ * 4. Patterns — Persistent behavioral memory (work, social, creative)
9
+ */
10
+
11
+ const infer = require('./infer');
12
+ const serendipity = require('./serendipity');
13
+ const proactive = require('./proactive');
14
+ const patterns = require('./patterns');
15
+
16
+ module.exports = {
17
+ // Inference
18
+ inferState: infer.inferState,
19
+ enhanceUserWithInference: infer.enhanceUserWithInference,
20
+ enhanceUsersWithInference: infer.enhanceUsersWithInference,
21
+ STATES: infer.STATES,
22
+
23
+ // Serendipity
24
+ findSerendipity: serendipity.findSerendipity,
25
+ getTopSerendipity: serendipity.getTopSerendipity,
26
+ getAllSerendipity: serendipity.getAllSerendipity,
27
+
28
+ // Proactive
29
+ generateProactiveSuggestions: proactive.generateProactiveSuggestions,
30
+ getProactiveSummary: proactive.getProactiveSummary,
31
+ checkProactiveOpportunities: proactive.checkProactiveOpportunities,
32
+ markAway: proactive.markAway,
33
+ markBack: proactive.markBack,
34
+ setSessionStart: proactive.setSessionStart,
35
+
36
+ // Patterns (persistent behavioral memory)
37
+ patterns
38
+ };