slashvibe-mcp 0.2.2 → 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.
- package/LICENSE +21 -0
- package/README.md +58 -40
- package/config.js +171 -3
- package/index.js +136 -16
- package/intelligence/index.js +38 -0
- package/intelligence/infer.js +316 -0
- package/intelligence/patterns.js +651 -0
- package/intelligence/proactive.js +358 -0
- package/intelligence/serendipity.js +306 -0
- package/notify.js +141 -18
- package/package.json +8 -4
- package/presence.js +5 -1
- package/protocol/index.js +88 -1
- package/protocol/telegram-commands.js +199 -0
- package/store/api.js +360 -25
- package/store/index.js +7 -7
- package/store/local.js +67 -11
- package/store/profiles.js +287 -0
- package/store/reservations.js +321 -0
- package/store/skills.js +378 -0
- package/tools/_actions.js +270 -14
- package/tools/_connection-queue.js +257 -0
- package/tools/_discovery-enhanced.js +290 -0
- package/tools/_discovery.js +346 -0
- package/tools/_proactive-discovery.js +301 -0
- package/tools/admin-inbox.js +218 -0
- package/tools/agent-treasury.js +288 -0
- package/tools/agents.js +122 -0
- package/tools/arcade.js +173 -0
- package/tools/artifact-create.js +236 -0
- package/tools/artifact-view.js +174 -0
- package/tools/ask-expert.js +160 -0
- package/tools/auto-suggest-connections.js +304 -0
- package/tools/away.js +68 -0
- package/tools/back.js +51 -0
- package/tools/become-expert.js +150 -0
- package/tools/bootstrap-skills.js +231 -0
- package/tools/bridge-dashboard.js +342 -0
- package/tools/bridge-health.js +400 -0
- package/tools/bridge-live.js +384 -0
- package/tools/bridges.js +383 -0
- package/tools/bye.js +4 -0
- package/tools/collaborative-drawing.js +286 -0
- package/tools/colorguess.js +281 -0
- package/tools/crossword.js +369 -0
- package/tools/discover-insights.js +379 -0
- package/tools/discover-momentum.js +256 -0
- package/tools/discover.js +395 -0
- package/tools/discovery-analytics.js +345 -0
- package/tools/discovery-auto-suggest.js +275 -0
- package/tools/discovery-bootstrap.js +267 -0
- package/tools/discovery-daily.js +375 -0
- package/tools/discovery-dashboard.js +385 -0
- package/tools/discovery-digest.js +314 -0
- package/tools/discovery-hub.js +357 -0
- package/tools/discovery-insights.js +384 -0
- package/tools/discovery-momentum.js +281 -0
- package/tools/discovery-monitor.js +319 -0
- package/tools/discovery-proactive.js +300 -0
- package/tools/dm.js +62 -9
- package/tools/draw.js +317 -0
- package/tools/drawing.js +310 -0
- package/tools/echo.js +16 -0
- package/tools/farcaster.js +307 -0
- package/tools/feed.js +196 -0
- package/tools/game.js +218 -110
- package/tools/games-catalog.js +376 -0
- package/tools/games.js +313 -0
- package/tools/genesis.js +233 -0
- package/tools/guessnumber.js +194 -0
- package/tools/hangman.js +129 -0
- package/tools/help.js +269 -0
- package/tools/idea.js +210 -0
- package/tools/inbox.js +148 -25
- package/tools/init.js +651 -33
- package/tools/insights.js +123 -0
- package/tools/invite.js +142 -21
- package/tools/l2-bridge.js +272 -0
- package/tools/l2-status.js +217 -0
- package/tools/l2.js +206 -0
- package/tools/migrate.js +156 -0
- package/tools/mint.js +377 -0
- package/tools/multiplayer-game.js +275 -0
- package/tools/multiplayer-tictactoe.js +303 -0
- package/tools/mute.js +97 -0
- package/tools/notifications.js +415 -0
- package/tools/observe.js +200 -0
- package/tools/onboarding.js +147 -0
- package/tools/open.js +14 -2
- package/tools/party-game.js +314 -0
- package/tools/presence-agent.js +167 -0
- package/tools/profile.js +219 -0
- package/tools/pulse.js +218 -0
- package/tools/react.js +4 -0
- package/tools/release.js +83 -0
- package/tools/report.js +109 -0
- package/tools/reputation.js +175 -0
- package/tools/request.js +217 -0
- package/tools/reservations.js +116 -0
- package/tools/reserve.js +111 -0
- package/tools/riddle.js +240 -0
- package/tools/run-bootstrap.js +69 -0
- package/tools/settings.js +112 -0
- package/tools/ship.js +182 -0
- package/tools/shipback.js +326 -0
- package/tools/skills-analytics.js +349 -0
- package/tools/skills-bootstrap.js +301 -0
- package/tools/skills-dashboard.js +268 -0
- package/tools/skills-exchange.js +342 -0
- package/tools/skills.js +380 -0
- package/tools/smart-intro.js +353 -0
- package/tools/social-inbox.js +326 -69
- package/tools/social-post.js +251 -66
- package/tools/social-processor.js +445 -0
- package/tools/solo-game.js +390 -0
- package/tools/start.js +205 -83
- package/tools/storybuilder.js +331 -0
- package/tools/suggest-tags.js +186 -0
- package/tools/tag-suggestions.js +257 -0
- package/tools/telegram-bot.js +183 -0
- package/tools/telegram-setup.js +214 -0
- package/tools/tictactoe.js +155 -0
- package/tools/tip.js +120 -0
- package/tools/token.js +103 -0
- package/tools/twentyquestions.js +143 -0
- package/tools/wallet.js +127 -0
- package/tools/webhook-test.js +388 -0
- package/tools/who.js +118 -25
- package/tools/wordassociation.js +247 -0
- package/tools/workshop-buddy.js +394 -0
- package/tools/workshop.js +327 -0
- package/version.json +12 -3
- 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
|
|
1
|
+
# /vibe MCP Server
|
|
2
2
|
|
|
3
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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": ["
|
|
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
|
-
##
|
|
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
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
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
|
-
##
|
|
54
|
+
## The Platform
|
|
42
55
|
|
|
43
|
-
|
|
56
|
+
This MCP server connects to [slashvibe.dev](https://slashvibe.dev), where:
|
|
44
57
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
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
|
-
##
|
|
62
|
+
## Philosophy
|
|
55
63
|
|
|
56
|
-
The
|
|
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
|
-
|
|
66
|
+
**Empathy. Collaboration. Shared value creation.**
|
|
62
67
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
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
|
-
|
|
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,11 +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';
|
|
46
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'}`;
|
|
47
66
|
default: return `${action} ${handle}`.trim() || null;
|
|
48
67
|
}
|
|
49
68
|
}
|
|
@@ -151,6 +170,8 @@ const tools = {
|
|
|
151
170
|
vibe_start: require('./tools/start'),
|
|
152
171
|
// Core
|
|
153
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
|
|
154
175
|
vibe_who: require('./tools/who'),
|
|
155
176
|
vibe_ping: require('./tools/ping'),
|
|
156
177
|
vibe_react: require('./tools/react'),
|
|
@@ -162,18 +183,53 @@ const tools = {
|
|
|
162
183
|
vibe_summarize: require('./tools/summarize'),
|
|
163
184
|
vibe_bye: require('./tools/bye'),
|
|
164
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'),
|
|
165
196
|
// AIRC Handoff (v1) — context portability
|
|
166
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'),
|
|
167
202
|
// Memory tools (Tier 1 — Collaborative Memory)
|
|
168
203
|
vibe_remember: require('./tools/remember'),
|
|
169
204
|
vibe_recall: require('./tools/recall'),
|
|
170
205
|
vibe_forget: require('./tools/forget'),
|
|
171
206
|
// Consent (AIRC compliance)
|
|
172
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'),
|
|
173
213
|
// Community
|
|
174
214
|
vibe_invite: require('./tools/invite'),
|
|
175
|
-
vibe_board: require('./tools/board'),
|
|
176
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'),
|
|
177
233
|
// Diagnostics
|
|
178
234
|
vibe_test: require('./tools/test'),
|
|
179
235
|
vibe_doctor: require('./tools/doctor'),
|
|
@@ -187,7 +243,21 @@ const tools = {
|
|
|
187
243
|
vibe_social_inbox: require('./tools/social-inbox'),
|
|
188
244
|
vibe_social_post: require('./tools/social-post'),
|
|
189
245
|
// Language evolution
|
|
190
|
-
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')
|
|
191
261
|
};
|
|
192
262
|
|
|
193
263
|
/**
|
|
@@ -195,10 +265,30 @@ const tools = {
|
|
|
195
265
|
*/
|
|
196
266
|
class VibeMCPServer {
|
|
197
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
|
+
|
|
198
274
|
// Start presence heartbeat
|
|
199
275
|
presence.start();
|
|
200
276
|
}
|
|
201
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
|
+
|
|
202
292
|
async handleRequest(request) {
|
|
203
293
|
const { method, params, id } = request;
|
|
204
294
|
|
|
@@ -252,25 +342,38 @@ class VibeMCPServer {
|
|
|
252
342
|
|
|
253
343
|
const result = await tool.handler(args);
|
|
254
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
|
+
|
|
255
357
|
// Add ambient presence footer (unless tool is in skip list)
|
|
256
358
|
let footer = '';
|
|
257
359
|
if (!SKIP_FOOTER_TOOLS.includes(params.name)) {
|
|
258
360
|
footer = await getPresenceFooter();
|
|
259
361
|
}
|
|
260
362
|
|
|
261
|
-
// Build hint indicator for Claude
|
|
363
|
+
// Build simplified hint indicator for Claude (human-readable)
|
|
262
364
|
let hintIndicator = '';
|
|
263
|
-
if (result.hint
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
};
|
|
273
|
-
|
|
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(' ')} -->`;
|
|
274
377
|
}
|
|
275
378
|
|
|
276
379
|
return {
|
|
@@ -333,9 +436,26 @@ class VibeMCPServer {
|
|
|
333
436
|
process.stderr.write('vibe init → set identity\n');
|
|
334
437
|
process.stderr.write('vibe who → see who\'s around\n');
|
|
335
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
|
+
}
|
|
336
456
|
}
|
|
337
457
|
}
|
|
338
458
|
|
|
339
459
|
// Start
|
|
340
460
|
const server = new VibeMCPServer();
|
|
341
|
-
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
|
+
};
|