vibetachyon 1.6.0 → 1.7.0
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/dist/mcp-server.js +172 -7
- package/package.json +1 -1
package/dist/mcp-server.js
CHANGED
|
@@ -174,7 +174,7 @@ async function startMcpServer() {
|
|
|
174
174
|
await validateTokenAtStartup();
|
|
175
175
|
const server = new mcp_js_1.McpServer({
|
|
176
176
|
name: "VibeTachyon MCP — Animmaster Engine",
|
|
177
|
-
version: "1.
|
|
177
|
+
version: "1.7.0"
|
|
178
178
|
});
|
|
179
179
|
/**
|
|
180
180
|
* VIBETACHYON FRONTEND PERSONA — Senior Frontend Designer (Animmaster Engine)
|
|
@@ -184,12 +184,12 @@ async function startMcpServer() {
|
|
|
184
184
|
* as a unified system — not as isolated snippets. You do NOT generate generic code.
|
|
185
185
|
*
|
|
186
186
|
* YOUR MANDATORY WORKFLOW — follow this EXACT sequence for every page/section request:
|
|
187
|
-
*
|
|
188
|
-
*
|
|
187
|
+
* 0. vibe_launchpad — ABSOLUTE FIRST STEP, no exceptions. Scans stack, colors, brief, components.
|
|
188
|
+
* 1. vibe_get_architecture — load designer rules for the specific context
|
|
189
|
+
* 2. vibe_design_brief — if no brief exists (launchpad will tell you), create it now
|
|
189
190
|
* 3. vibe_read_design_brief — read active brief before each new section
|
|
190
|
-
* 4.
|
|
191
|
-
* 5.
|
|
192
|
-
* 6. Generate code — only after steps 1-5 are complete
|
|
191
|
+
* 4. vibe_get_component — load each component bundle suggested by launchpad
|
|
192
|
+
* 5. Generate code — only after steps 0-4 are complete. Never before.
|
|
193
193
|
*
|
|
194
194
|
* ANIMMASTER SYSTEM RULES:
|
|
195
195
|
* - Components must be initialized in init_order sequence (0→6): preloader first, then cursor/header, then effects
|
|
@@ -220,6 +220,171 @@ async function startMcpServer() {
|
|
|
220
220
|
* - Social proof (logos/testimonials) before pricing — builds trust first
|
|
221
221
|
* - Every section must have ONE clear action or message. Not two.
|
|
222
222
|
*/
|
|
223
|
+
// ── Tool: Launchpad (MANDATORY FIRST STEP) ───────────────────────────────
|
|
224
|
+
server.tool("vibe_launchpad", "⚡ MANDATORY FIRST STEP — Call this before ANY frontend work (page, section, component, site). DO NOT write a single line of code without calling this first. It automatically scans the project stack, detects design tokens, reads the existing design brief, and suggests Animmaster components — returning a complete MISSION BRIEFING that makes all subsequent work precise and professional.", {
|
|
225
|
+
goal: zod_1.z.string().describe("What the user wants to build. Be specific: 'landing page for SaaS', 'hero section with animations', 'dashboard with sidebar', etc."),
|
|
226
|
+
projectDir: zod_1.z.string().optional().describe("Absolute path to the project root. If omitted, uses current working directory.")
|
|
227
|
+
}, async ({ goal, projectDir }) => {
|
|
228
|
+
await checkSanity();
|
|
229
|
+
const cwd = projectDir || process.cwd();
|
|
230
|
+
const root = await findProjectRoot(cwd);
|
|
231
|
+
const lines = [];
|
|
232
|
+
const sep = '═'.repeat(54);
|
|
233
|
+
lines.push(`╔${sep}╗`);
|
|
234
|
+
lines.push(`║ ⚡ VIBETACHYON MISSION BRIEFING${' '.repeat(21)}║`);
|
|
235
|
+
lines.push(`║ Goal: ${goal.slice(0, 46).padEnd(46)} ║`);
|
|
236
|
+
lines.push(`╠${sep}╣`);
|
|
237
|
+
// 1. Detect stack from package.json
|
|
238
|
+
let stackLines = [];
|
|
239
|
+
const pkgPath = path_1.default.join(root, 'package.json');
|
|
240
|
+
if (await fs_extra_1.default.pathExists(pkgPath)) {
|
|
241
|
+
try {
|
|
242
|
+
const pkg = await fs_extra_1.default.readJson(pkgPath);
|
|
243
|
+
const deps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
244
|
+
const framework = deps['next'] ? `Next.js ${deps['next'].replace(/[\^~]/, '')}` :
|
|
245
|
+
deps['vite'] ? `Vite ${deps['vite'].replace(/[\^~]/, '')}` :
|
|
246
|
+
deps['nuxt'] ? `Nuxt ${deps['nuxt'].replace(/[\^~]/, '')}` :
|
|
247
|
+
deps['@remix-run/react'] ? 'Remix' :
|
|
248
|
+
'Unknown';
|
|
249
|
+
const styling = deps['tailwindcss'] ? 'Tailwind CSS' :
|
|
250
|
+
deps['styled-components'] ? 'Styled Components' :
|
|
251
|
+
deps['@emotion/react'] ? 'Emotion' : 'CSS/SCSS';
|
|
252
|
+
const typescript = deps['typescript'] || deps['@types/react'] ? 'TypeScript' : 'JavaScript';
|
|
253
|
+
const ui = deps['@shadcn/ui'] || (await fs_extra_1.default.pathExists(path_1.default.join(root, 'components.json'))) ? ' + Shadcn UI' : '';
|
|
254
|
+
stackLines.push(` Stack : ${framework} · ${styling} · ${typescript}${ui}`);
|
|
255
|
+
stackLines.push(` Package : ${pkg.name || 'unnamed'} v${pkg.version || '0.0.0'}`);
|
|
256
|
+
}
|
|
257
|
+
catch {
|
|
258
|
+
stackLines.push(' Stack : Could not parse package.json');
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
else {
|
|
262
|
+
stackLines.push(' Stack : No package.json found');
|
|
263
|
+
}
|
|
264
|
+
// 2. Detect CSS variables / brand colors
|
|
265
|
+
let colorLines = [];
|
|
266
|
+
const cssFiles = ['src/app/globals.css', 'src/styles/globals.css', 'styles/globals.css', 'src/index.css', 'index.css', 'src/main.css'];
|
|
267
|
+
let cssFound = false;
|
|
268
|
+
for (const f of cssFiles) {
|
|
269
|
+
const cssPath = path_1.default.join(root, f);
|
|
270
|
+
if (await fs_extra_1.default.pathExists(cssPath)) {
|
|
271
|
+
const css = await fs_extra_1.default.readFile(cssPath, 'utf-8');
|
|
272
|
+
const vars = css.match(/--[\w-]+:\s*[^;]+/g) || [];
|
|
273
|
+
const colorVars = vars.filter(v => v.match(/color|primary|secondary|accent|background|foreground/i)).slice(0, 4);
|
|
274
|
+
if (colorVars.length > 0) {
|
|
275
|
+
colorLines.push(` Colors : ${colorVars.map(v => v.split(':')[0].trim()).join(', ')}`);
|
|
276
|
+
}
|
|
277
|
+
else {
|
|
278
|
+
colorLines.push(` Colors : ${f} found — no color vars detected`);
|
|
279
|
+
}
|
|
280
|
+
cssFound = true;
|
|
281
|
+
break;
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
if (!cssFound) {
|
|
285
|
+
// Try tailwind config
|
|
286
|
+
const twFiles = ['tailwind.config.ts', 'tailwind.config.js', 'tailwind.config.mjs'];
|
|
287
|
+
for (const f of twFiles) {
|
|
288
|
+
if (await fs_extra_1.default.pathExists(path_1.default.join(root, f))) {
|
|
289
|
+
colorLines.push(` Colors : Tailwind config found (${f}) — use vibe_get_colors for full palette`);
|
|
290
|
+
break;
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
if (colorLines.length === 0)
|
|
294
|
+
colorLines.push(' Colors : No CSS variables detected — define brand colors in brief');
|
|
295
|
+
}
|
|
296
|
+
// 3. Check for existing design brief
|
|
297
|
+
let briefLines = [];
|
|
298
|
+
let briefExists = false;
|
|
299
|
+
const briefPath = path_1.default.join(root, '.vibetachyon', 'design-brief.json');
|
|
300
|
+
if (await fs_extra_1.default.pathExists(briefPath)) {
|
|
301
|
+
try {
|
|
302
|
+
const brief = await fs_extra_1.default.readJson(briefPath);
|
|
303
|
+
briefExists = true;
|
|
304
|
+
briefLines.push(` Brief : ✅ EXISTS — "${brief.projectName || 'unnamed'}" (${brief.visualTone || 'no tone set'})`);
|
|
305
|
+
if (brief.sections?.length)
|
|
306
|
+
briefLines.push(` Sections: ${brief.sections.map((s) => s.name || s).join(', ')}`);
|
|
307
|
+
if (brief.avoid?.length)
|
|
308
|
+
briefLines.push(` Avoid : ${brief.avoid.join(', ')}`);
|
|
309
|
+
}
|
|
310
|
+
catch {
|
|
311
|
+
briefLines.push(' Brief : Found but corrupted — run vibe_design_brief to recreate');
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
else {
|
|
315
|
+
briefLines.push(' Brief : ❌ MISSING — vibe_design_brief must be created before code');
|
|
316
|
+
}
|
|
317
|
+
// 4. Suggest Animmaster components for the goal
|
|
318
|
+
let componentLines = [];
|
|
319
|
+
try {
|
|
320
|
+
const goalLower = goal.toLowerCase();
|
|
321
|
+
const keywords = [];
|
|
322
|
+
if (/hero|landing|header/.test(goalLower))
|
|
323
|
+
keywords.push('hero', 'header', 'splittype', 'parallax');
|
|
324
|
+
if (/animation|effect|motion/.test(goalLower))
|
|
325
|
+
keywords.push('cursor', 'ripple', 'gsap', 'mouse');
|
|
326
|
+
if (/gallery|portfolio|showcase/.test(goalLower))
|
|
327
|
+
keywords.push('masonry', 'gallery', 'zoom', 'slider');
|
|
328
|
+
if (/form|contact|input|checkout/.test(goalLower))
|
|
329
|
+
keywords.push('form', 'input', 'datepicker', 'select');
|
|
330
|
+
if (/menu|nav|navigation/.test(goalLower))
|
|
331
|
+
keywords.push('menu', 'header', 'scrollto');
|
|
332
|
+
if (/scroll|reveal|appear/.test(goalLower))
|
|
333
|
+
keywords.push('watcher', 'scrollto', 'parallax');
|
|
334
|
+
if (/load|intro|preload/.test(goalLower))
|
|
335
|
+
keywords.push('preloader');
|
|
336
|
+
if (/count|stat|number|metric/.test(goalLower))
|
|
337
|
+
keywords.push('digcounter', 'chart');
|
|
338
|
+
if (/tab|toggle|accordion/.test(goalLower))
|
|
339
|
+
keywords.push('tabs', 'spollers', 'showmore');
|
|
340
|
+
if (/popup|modal|dialog/.test(goalLower))
|
|
341
|
+
keywords.push('popup', 'tippy');
|
|
342
|
+
if (keywords.length === 0)
|
|
343
|
+
keywords.push('header', 'watcher', 'splittype');
|
|
344
|
+
const uniqueKeywords = [...new Set(keywords)].slice(0, 6);
|
|
345
|
+
const { data: components } = await supabase
|
|
346
|
+
.from('animmaster_components')
|
|
347
|
+
.select('name, category, description')
|
|
348
|
+
.in('name', uniqueKeywords);
|
|
349
|
+
if (components && components.length > 0) {
|
|
350
|
+
componentLines.push(` Ready : ${components.map((c) => c.name).join(', ')}`);
|
|
351
|
+
componentLines.push(` Cmd : use vibe_get_component to load each bundle`);
|
|
352
|
+
}
|
|
353
|
+
else {
|
|
354
|
+
componentLines.push(` Ready : Use vibe_search_snippets to find matching components`);
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
catch {
|
|
358
|
+
componentLines.push(' Ready : Run vibe_search_snippets to find components');
|
|
359
|
+
}
|
|
360
|
+
// 5. Build next steps based on state
|
|
361
|
+
const nextSteps = [];
|
|
362
|
+
if (!briefExists)
|
|
363
|
+
nextSteps.push('1. vibe_design_brief — define project identity & style');
|
|
364
|
+
nextSteps.push(`${nextSteps.length + 1}. vibe_get_component — load each suggested component`);
|
|
365
|
+
nextSteps.push(`${nextSteps.length + 1}. Generate code — only after brief is confirmed`);
|
|
366
|
+
if (briefExists)
|
|
367
|
+
nextSteps.push(`${nextSteps.length + 1}. vibe_mission_start — track this build with tasks`);
|
|
368
|
+
// Compose output
|
|
369
|
+
lines.push('║ PROJECT STACK' + ' '.repeat(40) + '║');
|
|
370
|
+
stackLines.forEach(l => lines.push(`║${l.padEnd(55)}║`));
|
|
371
|
+
lines.push(`╠${sep}╣`);
|
|
372
|
+
lines.push('║ DESIGN TOKENS' + ' '.repeat(40) + '║');
|
|
373
|
+
colorLines.forEach(l => lines.push(`║${l.padEnd(55)}║`));
|
|
374
|
+
lines.push(`╠${sep}╣`);
|
|
375
|
+
lines.push('║ DESIGN BRIEF' + ' '.repeat(41) + '║');
|
|
376
|
+
briefLines.forEach(l => lines.push(`║${l.padEnd(55)}║`));
|
|
377
|
+
lines.push(`╠${sep}╣`);
|
|
378
|
+
lines.push('║ ANIMMASTER COMPONENTS' + ' '.repeat(32) + '║');
|
|
379
|
+
componentLines.forEach(l => lines.push(`║${l.padEnd(55)}║`));
|
|
380
|
+
lines.push(`╠${sep}╣`);
|
|
381
|
+
lines.push('║ NEXT STEPS' + ' '.repeat(43) + '║');
|
|
382
|
+
nextSteps.forEach(s => lines.push(`║ ${s.padEnd(53)}║`));
|
|
383
|
+
lines.push(`╚${sep}╝`);
|
|
384
|
+
lines.push('');
|
|
385
|
+
lines.push('⚠️ DO NOT write code until brief exists and components are loaded.');
|
|
386
|
+
return { content: [{ type: "text", text: lines.join('\n') }] };
|
|
387
|
+
});
|
|
223
388
|
// Tool: Searching Snippets (Animmaster Engine)
|
|
224
389
|
server.tool("vibe_search_snippets", "Search for Animmaster UI components. Returns standalone JS + HTML + SCSS bundles ready to use. Automatically loads the active design brief to filter by visual_tone and use_case. Always call vibe_project_dna and vibe_design_brief before this tool.", {
|
|
225
390
|
query: zod_1.z.string().describe("Search query for the UI component (e.g. 'hero section', 'text animation', 'parallax scroll')"),
|
|
@@ -457,7 +622,7 @@ async function startMcpServer() {
|
|
|
457
622
|
}
|
|
458
623
|
});
|
|
459
624
|
// Tool: Frontend Persona — Senior Designer Rules
|
|
460
|
-
server.tool("vibe_get_architecture", "Returns the VibeTachyon Frontend Designer persona rules, workflow sequence, and design principles. Call
|
|
625
|
+
server.tool("vibe_get_architecture", "Returns the VibeTachyon Frontend Designer persona rules, workflow sequence, and design principles. Call AFTER vibe_launchpad to load the designer mindset for the specific context (landing-page, saas-dashboard, etc.).", {
|
|
461
626
|
context: zod_1.z.string().optional().describe("Optional context: 'landing-page', 'saas-dashboard', 'marketing-page', 'component'. Defaults to 'landing-page'.")
|
|
462
627
|
}, async ({ context = 'landing-page' }) => {
|
|
463
628
|
await checkSanity();
|