@vibevibes/mcp 0.2.0 → 0.3.1

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 CHANGED
@@ -1,21 +1,21 @@
1
- MIT License
2
-
3
- Copyright (c) 2025 vibevibes
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.
1
+ MIT License
2
+
3
+ Copyright (c) 2025 vibevibes
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,201 +1,69 @@
1
- # @vibevibes/mcp
2
-
3
- MCP server that connects AI agents to running vibevibes experiences. Agents join rooms, react with tools, and persist memory — as live participants, not request-response endpoints.
4
-
5
- ## Install
6
-
7
- ```bash
8
- # Local dev server (default: localhost:4321)
9
- npx vibevibes-mcp
10
-
11
- # Remote shared room
12
- npx vibevibes-mcp https://xyz.trycloudflare.com
13
-
14
- # With room token
15
- npx vibevibes-mcp https://xyz.trycloudflare.com?token=abc123
16
-
17
- # Via environment variable
18
- VIBEVIBES_SERVER_URL=https://xyz.trycloudflare.com npx vibevibes-mcp
19
- ```
20
-
21
- When using `@vibevibes/create-experience`, the MCP server is auto-registered via `.mcp.json` — no manual setup needed.
22
-
23
- ## The Agent Loop
24
-
25
- Agents are persistent participants in a shared room. The stop hook handles perception — it polls the server for new events and feeds them back as prompts, keeping the agent alive without needing to call `watch`.
26
-
27
- ```
28
- connect act → (stop hook fires with new events) → act → (stop hook fires) → act → ...
29
- ```
30
-
31
- The stop hook automatically delivers events from other participants, available tools per room, and participant lists.
32
-
33
- ## Tools
34
-
35
- ### `connect`
36
-
37
- Join the active room. Returns available tools, current state, participants, and the browser URL.
38
-
39
- ```
40
- connect()
41
- → { tools, sharedState, participants, browserUrl, config }
42
- ```
43
-
44
- Call this first. `act` will auto-connect if you haven't.
45
-
46
- ### `act`
47
-
48
- Execute a tool to mutate shared state.
49
-
50
- ```
51
- act(toolName, input?, roomId?)
52
- { output, sharedState }
53
- ```
54
-
55
- | Parameter | Type | Default | Description |
56
- |-----------|------|---------|-------------|
57
- | `toolName` | string | — | Tool to call, e.g. `"counter.increment"` |
58
- | `input` | object | `{}` | Tool input parameters |
59
- | `roomId` | string | `"local"` | Target room (for multi-room experiences) |
60
-
61
- ### `stream`
62
-
63
- Send high-frequency state updates (cursors, brushes, sliders) via the stream channel. Bypasses the full tool pipeline.
64
-
65
- ```
66
- stream(name, input?, roomId?)
67
- ```
68
-
69
- ### `spawn_room`
70
-
71
- Create a new room running any registered experience.
72
-
73
- ```
74
- spawn_room(experienceId?, name?, config?, initialState?, linkBack?, sourceRoomId?)
75
- → { roomId, url, config }
76
- ```
77
-
78
- | Parameter | Type | Default | Description |
79
- |-----------|------|---------|-------------|
80
- | `experienceId` | string | host | Experience to run in the new room |
81
- | `name` | string | auto | Room name |
82
- | `config` | object or string | — | Config values or preset name (e.g. `"boss-fight"`) |
83
- | `initialState` | object | — | Initial shared state |
84
- | `linkBack` | boolean | true | Store parent roomId in child state |
85
- | `sourceRoomId` | string | `"local"` | Parent room ID |
86
-
87
- ### `list_rooms`
88
-
89
- List all active rooms with participant counts and configurations.
90
-
91
- ```
92
- list_rooms()
93
- → [{ roomId, participants, events, config, parentRoomId, childRoomIds }]
94
- ```
95
-
96
- ### `list_experiences`
97
-
98
- Show available experiences — the host experience and any registered in `vibevibes.registry.json`.
99
-
100
- ```
101
- list_experiences()
102
- → [{ id, version, title, description, source, loaded, hasRoomConfig }]
103
- ```
104
-
105
- ### `room_config_schema`
106
-
107
- Get the configuration schema for an experience before spawning a room.
108
-
109
- ```
110
- room_config_schema(experienceId?)
111
- → { hasConfig, schema, defaults, presets, description }
112
- ```
113
-
114
- ### `memory`
115
-
116
- Persistent agent memory. Survives across tool calls within a session.
117
-
118
- ```
119
- memory(action: "get")
120
- → { ...currentMemory }
121
-
122
- memory(action: "set", updates: { key: value })
123
- → { ...updatedMemory }
124
- ```
125
-
126
- ### `screenshot`
127
-
128
- Capture a PNG of the browser canvas.
129
-
130
- ```
131
- screenshot(timeout?)
132
- → PNG image (base64)
133
- ```
134
-
135
- Requires the browser viewer to be open. Useful for agents with vision capabilities.
136
-
137
- ### `blob_set` / `blob_get`
138
-
139
- Store and retrieve binary blobs (pixel buffers, audio data, etc.).
140
-
141
- ```
142
- blob_set(key, data) # data is base64-encoded
143
- blob_get(key) → base64 data
144
- ```
145
-
146
- ## Configuration
147
-
148
- The server URL is resolved in this order:
149
-
150
- 1. CLI argument: `npx vibevibes-mcp https://...`
151
- 2. Environment variable: `VIBEVIBES_SERVER_URL`
152
- 3. Default: `http://localhost:4321`
153
-
154
- Room tokens are extracted from the URL query parameter (`?token=abc123`) and sent as `Authorization: Bearer` headers.
155
-
156
- ## Reliability
157
-
158
- - **Auto-reconnect** with exponential backoff on connection failures
159
- - **Health checks** to detect server restarts and re-join automatically
160
- - **Idempotency keys** on tool calls to prevent duplicate execution on retry
161
- - **Timeout handling** with configurable durations per tool
162
-
163
- ## Example: Agent in an Experience
164
-
165
- ```
166
- 1. connect()
167
- → See tools: [game.move, game.chat], state: {board: [...], turn: "white"}
168
-
169
- 2. (stop hook delivers: human moved game.move({from: "e2", to: "e4"}))
170
-
171
- 3. act(toolName="game.move", input={from: "e7", to: "e5"})
172
- → Board updated, turn switches
173
-
174
- 4. (stop hook delivers: human moved again...)
175
-
176
- 5. act(...)
177
- → ...forever
178
- ```
179
-
180
- ## Example: Cross-Experience Composition
181
-
182
- ```
183
- 1. connect()
184
- → Joined overworld room
185
-
186
- 2. list_experiences()
187
- → ["fallout-wasteland", "fallout-combat", "fallout-dialogue"]
188
-
189
- 3. room_config_schema(experienceId="fallout-combat")
190
- → { presets: ["radroach-nest", "raider-ambush"], schema: {...} }
191
-
192
- 4. spawn_room(experienceId="fallout-combat", config="raider-ambush")
193
- → { roomId: "room-abc", url: "http://localhost:4321/room/room-abc" }
194
-
195
- 5. act(toolName="combat.attack", input={target: 0}, roomId="room-abc")
196
- → Combat in child room
197
- ```
198
-
199
- ## License
200
-
201
- MIT
1
+ # @vibevibes/mcp
2
+
3
+ Runtime engine + MCP server for [vibevibes](https://github.com/vibevibes/sdk) experiences.
4
+
5
+ Agents connect via MCP. Humans connect via browser. Same room, same state, same tools.
6
+
7
+ [![npm](https://img.shields.io/npm/v/@vibevibes/mcp)](https://www.npmjs.com/package/@vibevibes/mcp)
8
+ [![license](https://img.shields.io/npm/l/@vibevibes/mcp)](./LICENSE)
9
+
10
+ ## Install
11
+
12
+ ```bash
13
+ npm install @vibevibes/mcp
14
+ ```
15
+
16
+ ## Quick Start
17
+
18
+ ```bash
19
+ # Serve an experience (Express + WebSocket + browser viewer)
20
+ npx vibevibes-serve ./my-experience
21
+
22
+ # Or run as an MCP server (for AI agents to connect)
23
+ npx vibevibes-mcp
24
+ ```
25
+
26
+ Open http://localhost:4321 in the browser. Connect an agent via MCP. Both are in the same room.
27
+
28
+ ## How It Works
29
+
30
+ 1. You define an experience with [@vibevibes/sdk](https://github.com/vibevibes/sdk) (tools + canvas)
31
+ 2. This server loads and runs it
32
+ 3. Agents connect via MCP tools (`connect`, `act`, `look`)
33
+ 4. Humans open the browser viewer to see the canvas
34
+ 5. Everyone shares the same state — tools are the only mutation path
35
+
36
+ ```
37
+ Browser (Canvas) <--WebSocket--> vibevibes-serve <--MCP--> AI Agent
38
+ ```
39
+
40
+ ## MCP Tools
41
+
42
+ | Tool | Purpose |
43
+ |------|---------|
44
+ | `connect` | Join the room. Returns available tools, current state, browser URL |
45
+ | `act` | Execute a tool — same tools the human uses via the canvas |
46
+ | `look` | Observe current state and recent events |
47
+ | `disconnect` | Leave the room |
48
+
49
+ ## Features
50
+
51
+ - **Hot reload** — edit `src/index.tsx`, save, see changes instantly
52
+ - **TypeScript bundling** esbuild compiles experiences on the fly
53
+ - **Tick engine** — optional fixed-rate game loop (`netcode: "tick"`)
54
+ - **Protocol mode** — load experiences from `manifest.json` + subprocess
55
+ - **Ephemeral state** per-actor transient data (cursors, typing indicators)
56
+ - **Agent memory** — persistent per-session key-value store
57
+
58
+ ## Ecosystem
59
+
60
+ | Package | Description |
61
+ |---------|-------------|
62
+ | [@vibevibes/sdk](https://github.com/vibevibes/sdk) | Define experiences — tools, canvas, state |
63
+ | **@vibevibes/mcp** | Runtime engine MCP server + WebSocket + viewer |
64
+ | [@vibevibes/create](https://github.com/vibevibes/create) | `npx @vibevibes/create` — scaffold in seconds |
65
+ | [experiences](https://github.com/vibevibes/experiences) | Example experiences — fork and remix |
66
+
67
+ ## License
68
+
69
+ MIT
package/bin/cli.js CHANGED
@@ -1,11 +1,11 @@
1
- #!/usr/bin/env node
2
-
3
- /**
4
- * @vibevibes/mcp CLI
5
- *
6
- * Usage:
7
- * npx @vibevibes/mcp # localhost:4321
8
- * npx @vibevibes/mcp https://xyz.trycloudflare.com # remote shared room
9
- */
10
-
11
- import "../dist/index.js";
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * @vibevibes/mcp CLI
5
+ *
6
+ * Usage:
7
+ * npx @vibevibes/mcp # localhost:4321
8
+ * npx @vibevibes/mcp https://xyz.trycloudflare.com # remote shared room
9
+ */
10
+
11
+ import "../dist/index.js";
@@ -0,0 +1,39 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Postinstall: writes .mcp.json into the project root so Claude Code
5
+ * can discover the vibevibes MCP server automatically.
6
+ *
7
+ * Skipped during self-install (e.g. when building the monorepo).
8
+ */
9
+
10
+ import { writeFileSync, existsSync } from "node:fs";
11
+ import { resolve } from "node:path";
12
+
13
+ // npm sets INIT_CWD to the directory where `npm install` was run
14
+ const projectRoot = process.env.INIT_CWD;
15
+ if (!projectRoot) process.exit(0);
16
+
17
+ // Skip if we're installing inside the vibevibes monorepo itself
18
+ const isMonorepo = existsSync(resolve(projectRoot, "sdk")) && existsSync(resolve(projectRoot, "mcp"));
19
+ if (isMonorepo) process.exit(0);
20
+
21
+ const mcpJsonPath = resolve(projectRoot, ".mcp.json");
22
+
23
+ // Don't overwrite an existing .mcp.json
24
+ if (existsSync(mcpJsonPath)) process.exit(0);
25
+
26
+ const config = {
27
+ mcpServers: {
28
+ vibevibes: {
29
+ command: "npx",
30
+ args: ["vibevibes-mcp"],
31
+ env: {
32
+ VIBEVIBES_SERVER_URL: "http://localhost:4321",
33
+ },
34
+ },
35
+ },
36
+ };
37
+
38
+ writeFileSync(mcpJsonPath, JSON.stringify(config, null, 2) + "\n");
39
+ console.log("vibevibes: wrote .mcp.json for Claude Code");
package/bin/serve.js ADDED
@@ -0,0 +1,41 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Start the vibevibes server for an experience.
5
+ *
6
+ * Usage:
7
+ * npx vibevibes-serve # serves from current directory
8
+ * npx vibevibes-serve ./my-exp # serves from a specific path
9
+ */
10
+
11
+ import { resolve } from "node:path";
12
+ import { writeFileSync, existsSync } from "node:fs";
13
+ import { execSync } from "node:child_process";
14
+ import { startServer } from "../dist/server.js";
15
+
16
+ const projectRoot = resolve(process.argv[2] || ".");
17
+ const port = parseInt(process.env.PORT || "4321", 10);
18
+
19
+ // Find git root (where Claude Code reads .mcp.json from)
20
+ let mcpJsonDir = projectRoot;
21
+ try {
22
+ mcpJsonDir = execSync("git rev-parse --show-toplevel", { cwd: projectRoot, encoding: "utf-8" }).trim();
23
+ } catch {}
24
+
25
+ // Auto-generate .mcp.json so Claude Code can connect via /mcp
26
+ const mcpJsonPath = resolve(mcpJsonDir, ".mcp.json");
27
+ if (!existsSync(mcpJsonPath)) {
28
+ const config = {
29
+ mcpServers: {
30
+ vibevibes: {
31
+ command: "npx",
32
+ args: ["vibevibes-mcp"],
33
+ env: { VIBEVIBES_SERVER_URL: `http://localhost:${port}` },
34
+ },
35
+ },
36
+ };
37
+ writeFileSync(mcpJsonPath, JSON.stringify(config, null, 2) + "\n");
38
+ console.log(` .mcp.json: wrote ${mcpJsonPath}`);
39
+ }
40
+
41
+ startServer({ projectRoot, port });
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Experience bundler — produces server and client bundles from src/index.tsx.
3
+ *
4
+ * Server bundle: CJS, eval'd via new Function() to extract tools + manifest.
5
+ * Client bundle: ESM, loaded in browser via blob URL + dynamic import().
6
+ *
7
+ * Extracted from create-experience/runtime/bundler.ts into @vibevibes/runtime.
8
+ */
9
+ /**
10
+ * Bundle for server-side tool execution (Node.js eval).
11
+ * Returns the raw ExperienceModule extracted via new Function().
12
+ */
13
+ export declare function bundleForServer(entryPath: string): Promise<string>;
14
+ /**
15
+ * Evaluate a server bundle and extract the ExperienceModule.
16
+ */
17
+ export declare function evalServerBundle(serverCode: string): Promise<unknown>;
18
+ /**
19
+ * Bundle for client-side Canvas rendering (browser).
20
+ * Returns pure ESM. External imports (react, zod, etc.) are left as-is —
21
+ * the viewer's import map resolves them in the browser.
22
+ */
23
+ export declare function bundleForClient(entryPath: string): Promise<string>;
24
+ /**
25
+ * Build both bundles from an entry file.
26
+ */
27
+ export declare function buildExperience(entryPath: string): Promise<{
28
+ serverCode: string;
29
+ clientCode: string;
30
+ }>;
31
+ /**
32
+ * Validate a client bundle for common issues.
33
+ * Lightweight — esbuild already validates syntax. This just checks the output exists.
34
+ * Returns null if OK, or an error message string.
35
+ */
36
+ export declare function validateClientBundle(code: string): string | null;