@amirhosseinnateghi/vibed-mcp 0.1.6 → 0.1.7

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 (2) hide show
  1. package/dist/index.js +93 -2
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -11191,9 +11191,94 @@ function formatReport(result) {
11191
11191
  out.push(` \u2022 \u2026and ${result.inlineWarnings.length - 12} more`);
11192
11192
  }
11193
11193
  }
11194
+ const usesBrowserStorage = [...result.warnings.map((w) => w.message), ...result.inlineWarnings].some(
11195
+ (m) => /BROWSER_STORAGE|localStorage|sessionStorage|indexedDB/i.test(m)
11196
+ );
11197
+ if (usesBrowserStorage) {
11198
+ out.push(
11199
+ "",
11200
+ "\u2139 Uses browser storage (blocked in the sandbox). Port it to `window.vibed.storage` \u2014 run `vibed storage` (or the vibed_storage_guide MCP tool) for the local + shared SDK."
11201
+ );
11202
+ }
11194
11203
  return out.join("\n");
11195
11204
  }
11196
11205
 
11206
+ // ../cli/src/storageGuide.ts
11207
+ var STORAGE_GUIDE = `# vibed storage \u2014 add persistence to a vibe (\`window.vibed.storage\`)
11208
+
11209
+ A vibe is ONE static sandboxed HTML file with no backend. \`localStorage\`,
11210
+ \`sessionStorage\`, \`indexedDB\`, and cookies are BLOCKED \u2014 they throw in the
11211
+ sandbox (\`vibed check\` warns \`BROWSER_STORAGE\`). For anything you'd persist,
11212
+ use the injected \`window.vibed.storage\` SDK instead. The platform is the
11213
+ backend; you write zero server code.
11214
+
11215
+ ## Two rules that apply to EVERY call
11216
+ 1. Every call returns a Promise that can reject \u2014 always guard it. When the vibe
11217
+ runs OUTSIDE vibed (e.g. a local file, your \`vibed draft\`/\`preview\`), calls
11218
+ reject with \`{ code: "no_host" }\`. The vibe must stay playable standalone, so
11219
+ treat missing storage as "no saved data yet", never a crash.
11220
+ 2. WRITES require the viewer to be signed in. If not, they reject with
11221
+ \`{ code: "unauthenticated" }\` \u2014 catch it and show a gentle "sign in to save"
11222
+ nudge. READS of shared data work for everyone.
11223
+
11224
+ Publishing auto-detects SDK usage and turns storage on for the post \u2014 no flags.
11225
+
11226
+ ## Tier 1 \u2014 \`vibed.storage.local\` (LOCAL: private, per-viewer, per-post)
11227
+ Each viewer gets their own private bucket for THIS post. Nobody else can read it.
11228
+ Use for: this player's high score, their settings, "resume where I left off".
11229
+ \`\`\`js
11230
+ await vibed.storage.local.set("best", 8200);
11231
+ const best = await vibed.storage.local.get("best"); // null if never set
11232
+ await vibed.storage.local.delete("best");
11233
+ \`\`\`
11234
+
11235
+ ## Tier 2 \u2014 \`vibed.storage.shared\` (GLOBAL: one collective store for the whole post)
11236
+ Data every viewer of the post shares \u2014 leaderboards, votes, guestbooks, shared
11237
+ state. Organized into named "collections" (like tables) you invent.
11238
+ \`\`\`js
11239
+ // key/value doc with optimistic concurrency
11240
+ await vibed.storage.shared.set("state", "doc", { phase: "open" }); // \u2192 { value, version, ... }
11241
+ await vibed.storage.shared.set("state", "doc", next, { ifVersion: 3 }); // rejects { code: "conflict" }
11242
+ const doc = await vibed.storage.shared.get("state", "doc"); // null if missing
11243
+ await vibed.storage.shared.delete("state", "doc");
11244
+
11245
+ // append-only list + query (guestbook, bets, submissions)
11246
+ await vibed.storage.shared.append("bets", { pick: "Argentina", stake: 50 });
11247
+ const mine = await vibed.storage.shared.query("bets", { mine: true });
11248
+ const feed = await vibed.storage.shared.query("bets", { sort: "-created", limit: 30 });
11249
+
11250
+ // counter (poll / reactions)
11251
+ const { num } = await vibed.storage.shared.increment("votes", "argentina", 1);
11252
+
11253
+ // leaderboard: submit a score (keep the best), read the top, get MY rank
11254
+ await vibed.storage.shared.submit("leaderboard", { score, keep: "max", meta: { emoji: "\u{1F427}" } });
11255
+ const top = await vibed.storage.shared.query("leaderboard", { sort: "-num", limit: 10 });
11256
+ const rank = await vibed.storage.shared.rank("leaderboard"); // { rank, of, score } | null
11257
+
11258
+ // live updates (polling now): re-renders when the collection changes; returns an unsubscribe fn
11259
+ const off = vibed.storage.shared.subscribe("leaderboard", (r) => render(r.rows), { intervalMs: 4000 });
11260
+ \`\`\`
11261
+
11262
+ ## Who is watching
11263
+ \`\`\`js
11264
+ const me = await vibed.storage.identity(); // { id, signedIn, name? } \u2014 stable per viewer; identify entries
11265
+ const m = await vibed.storage.meta(); // { postId, ... } \u2014 this post's context
11266
+ \`\`\`
11267
+
11268
+ ## Limits (free tier \u2014 design within these)
11269
+ - Each value must be JSON-serializable and under the per-value byte cap
11270
+ (rejects \`{ code: "too_large" }\`); \`invalid\` if it can't be JSON-stringified.
11271
+ - shared collections are for structured game/app state, NOT open chat/DM/messaging.
11272
+
11273
+ ## Porting a project that used browser storage (the \`BROWSER_STORAGE\` warning)
11274
+ 1. Find every \`localStorage\`/\`sessionStorage\`/\`indexedDB\`/cookie use.
11275
+ 2. Per-viewer state (settings, progress, personal best) \u2192 \`vibed.storage.local\`.
11276
+ 3. Anything others should see (scores to compare, shared counters, submissions)
11277
+ \u2192 the matching \`vibed.storage.shared\` primitive above.
11278
+ 4. Make every call \`await\` + \`try/catch\`, with a standalone fallback (no_host).
11279
+ 5. Re-run \`vibed check\` \u2014 the \`BROWSER_STORAGE\` warning should be gone.
11280
+ `;
11281
+
11197
11282
  // ../cli/src/login.ts
11198
11283
  import { spawn } from "node:child_process";
11199
11284
  import { platform } from "node:os";
@@ -11386,16 +11471,22 @@ async function deleteExperience(client, idOrUrl) {
11386
11471
  }
11387
11472
 
11388
11473
  // src/index.ts
11389
- var SERVER_INFO = { name: "vibed", version: "0.1.6" };
11474
+ var SERVER_INFO = { name: "vibed", version: "0.1.7" };
11390
11475
  var PROTOCOL_VERSION = "2024-11-05";
11391
11476
  var CATEGORIES2 = ["Game", "Invitation", "Story", "News", "Quiz", "Tool", "Art", "Other"];
11392
11477
  var pendingLogin = null;
11393
11478
  var str = (v, d = "") => typeof v === "string" ? v : d;
11394
11479
  var bool = (v, d) => typeof v === "boolean" ? v : d;
11395
11480
  var TOOLS = [
11481
+ {
11482
+ name: "vibed_storage_guide",
11483
+ description: "How to add PERSISTENCE to a vibe: leaderboards, votes/polls, saved progress/high scores, guestbooks, or any shared state. A vibe is one static sandboxed file \u2014 localStorage/sessionStorage/indexedDB/cookies and backend calls are BLOCKED \u2014 so use the injected window.vibed.storage SDK instead. Returns the full primer for both tiers: `local` (private, per-viewer) and `shared` (collective, per-post). Call this BEFORE writing any save/leaderboard/multiplayer feature, or when vibed_check warns BROWSER_STORAGE.",
11484
+ inputSchema: { type: "object", properties: {} },
11485
+ run: async () => STORAGE_GUIDE
11486
+ },
11396
11487
  {
11397
11488
  name: "vibed_check",
11398
- description: "Bundle the project into a single HTML file and validate it against vibed's sandbox rules (no network/auth). Returns whether it's publishable and, if not, the blockers to fix. Run this before vibed_publish.",
11489
+ description: "Bundle the project into a single HTML file and validate it against vibed's sandbox rules (no network/auth). Returns whether it's publishable and, if not, the blockers to fix. Run this before vibed_publish. If it warns BROWSER_STORAGE (localStorage etc. throw in the sandbox), call vibed_storage_guide and port to window.vibed.storage.",
11399
11490
  inputSchema: {
11400
11491
  type: "object",
11401
11492
  properties: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@amirhosseinnateghi/vibed-mcp",
3
- "version": "0.1.6",
3
+ "version": "0.1.7",
4
4
  "description": "vibed MCP server — make it vibed from any MCP client (Codex, Cursor, Gemini, …): check, login, and publish tools",
5
5
  "license": "MIT",
6
6
  "type": "module",