UNPKG

bruzethegreat-gsap-master-mcp-server

Version:

The most comprehensive GSAP MCP server ever created - surgical precision animation control with AI intent analysis, complete API coverage, and production-ready patterns. All GSAP plugins now 100% FREE thanks to Webflow!

1,451 lines (1,344 loc) 98.3 kB
#!/usr/bin/env node import { Server } from '@modelcontextprotocol/sdk/server/index.js'; import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'; import { CallToolRequestSchema, ListToolsRequestSchema, } from '@modelcontextprotocol/sdk/types.js'; // ======================================================================================== // COMPLETE GSAP UNIVERSE DATABASE - Every single method, property, plugin, and technique // ======================================================================================== const GSAP_COMPLETE_API = { // Core Animation Methods - Every single one CORE_METHODS: { 'gsap.to': { description: 'Animate FROM current values TO specified values - The most common animation method', syntax: 'gsap.to(targets, vars)', parameters: { targets: 'String selector, object, or array of elements to animate', vars: 'Object containing properties to animate and configuration' }, examples: { basic: 'gsap.to(".element", { x: 100, duration: 1 })', advanced: 'gsap.to(".elements", { x: 100, rotation: 360, scale: 1.5, duration: 2, ease: "power3.out", stagger: 0.2 })', complex: 'gsap.to(".element", { css: { transform: "translateX(100px) rotate(45deg)" }, duration: 1.5, ease: CustomEase.create("custom", "M0,0 C0.14,0 0.242,0.438 0.272,0.561 0.313,0.728 0.354,0.963 0.362,1 0.37,0.985 0.414,0.961 0.455,0.905 0.51,0.826 0.57,0.73 0.628,0.63 0.709,0.491 0.86,0.413 1,0.413") })' }, properties: ['x', 'y', 'z', 'rotation', 'rotationX', 'rotationY', 'rotationZ', 'scale', 'scaleX', 'scaleY', 'scaleZ', 'opacity', 'alpha', 'autoAlpha'], css_properties: ['left', 'top', 'width', 'height', 'backgroundColor', 'borderRadius', 'fontSize', 'lineHeight'], special_properties: ['duration', 'delay', 'ease', 'repeat', 'yoyo', 'stagger', 'onComplete', 'onUpdate', 'onStart'], performance_tips: ['Use transform properties (x, y, scale, rotation) for GPU acceleration', 'Set force3D: true for complex animations', 'Use will-change CSS property'] }, 'gsap.from': { description: 'Animate FROM specified values TO current values - Perfect for entrance animations', syntax: 'gsap.from(targets, vars)', examples: { entrance: 'gsap.from(".cards", { y: 100, opacity: 0, duration: 1, stagger: 0.2, ease: "power3.out" })', reveal: 'gsap.from(".text", { x: -50, opacity: 0, duration: 0.8, delay: 0.3 })', scale_in: 'gsap.from(".modal", { scale: 0, opacity: 0, duration: 0.5, ease: "back.out(1.7)" })' }, use_cases: ['Page load animations', 'Element reveals', 'Modal entrances', 'Card appearances'] }, 'gsap.fromTo': { description: 'Animate FROM specified values TO other specified values - Maximum control', syntax: 'gsap.fromTo(targets, fromVars, toVars)', examples: { precise: 'gsap.fromTo(".element", { x: -100, opacity: 0 }, { x: 100, opacity: 1, duration: 2 })', color_transition: 'gsap.fromTo(".bg", { backgroundColor: "#ff0000" }, { backgroundColor: "#00ff00", duration: 1 })', complex_morph: 'gsap.fromTo(".shape", { scale: 0.5, rotation: 0, borderRadius: "0%" }, { scale: 1.5, rotation: 180, borderRadius: "50%", duration: 2, ease: "elastic.out(1, 0.3)" })' }, advantages: ['Explicit start and end values', 'Better for complex animations', 'Clearer intent'] }, 'gsap.set': { description: 'Immediately set properties without animation - Instant transforms', syntax: 'gsap.set(targets, vars)', examples: { initial_state: 'gsap.set(".elements", { x: 0, y: 0, opacity: 1, scale: 1 })', reset: 'gsap.set(".animated", { clearProps: "all" })', setup: 'gsap.set(".cards", { y: 50, opacity: 0, transformOrigin: "center bottom" })' }, use_cases: ['Setting initial states', 'Resetting animations', 'Preparing elements', 'Clearing properties'] }, 'gsap.timeline': { description: 'Create powerful animation sequences - The heart of complex animations', syntax: 'gsap.timeline(vars)', methods: ['add', 'to', 'from', 'fromTo', 'set', 'call', 'addLabel', 'play', 'pause', 'reverse', 'restart'], examples: { basic: 'const tl = gsap.timeline(); tl.to(".first", { x: 100 }).to(".second", { y: 100 });', with_labels: 'tl.addLabel("start").to(".element", { x: 100 }).addLabel("middle").to(".element", { y: 100 });', stagger_sequence: 'tl.from(".cards", { y: 100, opacity: 0, stagger: 0.2 }).to(".title", { scale: 1.2 }, "-=0.5");' }, positioning: { absolute: '1.5 (start at 1.5 seconds)', relative: '"-=0.5" (start 0.5 seconds before previous ends)', gap: '"+=0.2" (start 0.2 seconds after previous ends)', label: '"myLabel" (start at label position)' } }, 'gsap.delayedCall': { description: 'Execute function after delay with GSAP timing system', syntax: 'gsap.delayedCall(delay, callback, params, scope)', examples: { basic: 'gsap.delayedCall(2, () => console.log("Hello after 2 seconds"));', with_params: 'gsap.delayedCall(1.5, showMessage, ["Animation complete!", "success"]);', sequence: 'gsap.delayedCall(0.5, startNextAnimation);' } } }, // Complete Plugin System - ALL plugins with deep knowledge PLUGINS: { 'ScrollTrigger': { category: 'FREE', description: 'The most powerful scroll-based animation system ever created', methods: { 'ScrollTrigger.create': 'Create individual scroll triggers', 'ScrollTrigger.batch': 'Batch process multiple elements for performance', 'ScrollTrigger.refresh': 'Recalculate trigger positions', 'ScrollTrigger.update': 'Force update all triggers', 'ScrollTrigger.kill': 'Remove specific triggers', 'ScrollTrigger.killAll': 'Remove all triggers', 'ScrollTrigger.getAll': 'Get array of all triggers', 'ScrollTrigger.addEventListener': 'Listen for ScrollTrigger events', 'ScrollTrigger.matchMedia': 'Responsive scroll triggers' }, properties: { trigger: 'Element that triggers the animation', start: 'When animation starts (e.g., "top 80%")', end: 'When animation ends (e.g., "bottom 20%")', scrub: 'Link animation progress to scroll progress', pin: 'Pin element during scroll', snap: 'Snap to specific scroll positions', toggleActions: 'Actions for onEnter, onLeave, onEnterBack, onLeaveBack', animation: 'GSAP animation to control', onEnter: 'Callback when entering trigger area', onLeave: 'Callback when leaving trigger area', onUpdate: 'Callback on every scroll update', markers: 'Show visual markers for debugging' }, examples: { basic: `ScrollTrigger.create({ trigger: ".section", start: "top 80%", end: "bottom 20%", animation: gsap.from(".element", { y: 100, opacity: 0 }), toggleActions: "play none none reverse" })`, scrub: `gsap.to(".parallax", { y: -300, scrollTrigger: { trigger: ".section", start: "top bottom", end: "bottom top", scrub: 1 } })`, pin: `ScrollTrigger.create({ trigger: ".pin-section", start: "top top", end: "bottom top", pin: true, animation: gsap.timeline() .to(".pinned-element", { x: 100 }) .to(".pinned-element", { rotation: 360 }) })`, batch: `ScrollTrigger.batch(".fade-in", { onEnter: elements => gsap.from(elements, { y: 100, opacity: 0, stagger: 0.1 }), onLeave: elements => gsap.to(elements, { opacity: 0.3 }), onEnterBack: elements => gsap.to(elements, { opacity: 1 }), onLeaveBack: elements => gsap.to(elements, { y: 100, opacity: 0 }) })` }, performance_optimization: [ 'Use ScrollTrigger.batch() for multiple elements', 'Set refreshPriority for critical triggers', 'Use pin: true sparingly for better performance', 'Combine multiple animations into timelines' ] }, 'SplitText': { category: 'PREMIUM_NOW_FREE', description: 'The ultimate text animation control system - split text into any configuration', syntax: 'new SplitText(targets, vars)', split_types: { chars: 'Split into individual characters', words: 'Split into individual words', lines: 'Split into individual lines', combined: '"chars,words,lines" for maximum control' }, properties: { type: 'What to split: "chars", "words", "lines", or combinations', charsClass: 'CSS class for character spans', wordsClass: 'CSS class for word spans', linesClass: 'CSS class for line divs', tag: 'HTML tag to use for splits (default: "div" for lines, "span" for others)', wordsDelimiter: 'Character that defines word boundaries', charsDelimiter: 'Character that defines character boundaries' }, methods: { revert: 'Restore original text', split: 'Re-split with new settings' }, examples: { char_reveal: `const split = new SplitText(".title", { type: "chars" }); gsap.from(split.chars, { y: 100, opacity: 0, rotation: 10, duration: 0.8, ease: "power3.out", stagger: 0.02 });`, word_stagger: `const split = new SplitText(".paragraph", { type: "words" }); gsap.from(split.words, { y: 50, opacity: 0, duration: 0.6, ease: "power2.out", stagger: 0.1 });`, line_animation: `const split = new SplitText(".text", { type: "lines" }); gsap.from(split.lines, { x: -100, opacity: 0, duration: 1, ease: "power3.out", stagger: 0.3 });`, complex_split: `const split = new SplitText(".complex", { type: "chars,words,lines" }); const tl = gsap.timeline(); tl.from(split.lines, { y: 100, opacity: 0, stagger: 0.1 }) .from(split.words, { scale: 0, stagger: 0.05 }, "-=0.5") .from(split.chars, { rotation: 90, stagger: 0.01 }, "-=0.8");` }, responsive_handling: `// Responsive SplitText let split; ScrollTrigger.matchMedia({ "(min-width: 768px)": function() { split = new SplitText(".responsive-text", { type: "chars" }); gsap.from(split.chars, { y: 50, opacity: 0, stagger: 0.02 }); }, "(max-width: 767px)": function() { if (split) split.revert(); gsap.from(".responsive-text", { y: 30, opacity: 0 }); } });` }, 'DrawSVGPlugin': { category: 'PREMIUM_NOW_FREE', description: 'Animate SVG stroke drawing with pixel-perfect control', properties: { drawSVG: 'Control stroke drawing: "0%" to "100%", "50% 100%", true, false', strokeDasharray: 'Manual control of dash pattern', strokeDashoffset: 'Manual control of dash offset' }, examples: { simple_draw: `gsap.from(".path", { drawSVG: "0%", duration: 2, ease: "power2.inOut" });`, draw_sequence: `const tl = gsap.timeline(); tl.from(".path1", { drawSVG: "0%", duration: 1 }) .from(".path2", { drawSVG: "0%", duration: 1 }, "-=0.5") .from(".path3", { drawSVG: "0%", duration: 1 }, "-=0.5");`, partial_draw: `gsap.fromTo(".path", { drawSVG: "50% 50%" }, { drawSVG: "0% 100%", duration: 2 } );`, reverse_draw: `gsap.to(".path", { drawSVG: "100% 0%", duration: 1.5, ease: "power3.in" });` }, svg_optimization: [ 'Use vector-effect="non-scaling-stroke" for consistent stroke width', 'Optimize path complexity for smooth animation', 'Set stroke-linecap="round" for smoother endpoints' ] }, 'MorphSVGPlugin': { category: 'PREMIUM_NOW_FREE', description: 'Morph between different SVG shapes with intelligent path interpolation', methods: { 'MorphSVGPlugin.convertToPath': 'Convert shapes to paths for morphing', 'MorphSVGPlugin.pathDataToBezier': 'Convert path data to bezier points', 'MorphSVGPlugin.stringToRawPath': 'Parse path string to raw data' }, properties: { morphSVG: 'Target shape to morph to', shapeIndex: 'Control which shape to morph to in multi-shape targets', map: 'Custom point mapping for better morphing' }, examples: { shape_morph: `gsap.to("#shape1", { morphSVG: "#shape2", duration: 2, ease: "power2.inOut" });`, path_morph: `gsap.to(".path", { morphSVG: "M100,100 L200,100 L150,200 Z", duration: 1.5, ease: "elastic.out(1, 0.3)" });`, complex_morph: `const tl = gsap.timeline({ repeat: -1, yoyo: true }); tl.to(".star", { morphSVG: ".circle", duration: 1 }) .to(".star", { morphSVG: ".square", duration: 1 }) .to(".star", { morphSVG: ".triangle", duration: 1 });` } }, 'MotionPathPlugin': { category: 'PREMIUM_NOW_FREE', description: 'Animate elements along custom paths with precise control', properties: { motionPath: 'Path to follow (SVG path, array of points, or path data)', align: 'Align element to path orientation', alignOrigin: 'Point on element to align with path', autoRotate: 'Auto-rotate element to follow path direction', start: 'Starting position on path (0 to 1)', end: 'Ending position on path (0 to 1)' }, examples: { basic_path: `gsap.to(".element", { motionPath: { path: "#path", align: "#path", autoRotate: true, alignOrigin: [0.5, 0.5] }, duration: 3, ease: "power2.inOut" });`, curved_path: `gsap.to(".car", { motionPath: { path: "M0,0 Q100,-100 200,0 T400,0", autoRotate: 90, align: "self" }, duration: 4, ease: "none" });`, partial_path: `gsap.to(".element", { motionPath: { path: "#curve", start: 0.2, end: 0.8 }, duration: 2 });` } }, 'Draggable': { category: 'PREMIUM_NOW_FREE', description: 'Create advanced drag and drop interactions with physics', types: ['x', 'y', 'x,y', 'rotation', 'top,left', 'scrollTop', 'scrollLeft'], properties: { type: 'What can be dragged', bounds: 'Boundaries for dragging', edgeResistance: 'Resistance at boundaries (0-1)', throwProps: 'Physics-based momentum', snap: 'Snap to grid or custom function', inertia: 'Enable momentum physics' }, events: ['onDragStart', 'onDrag', 'onDragEnd', 'onThrowUpdate', 'onThrowComplete'], examples: { basic_drag: `Draggable.create(".draggable", { type: "x,y", bounds: "#container", edgeResistance: 0.65, onDragStart: function() { gsap.to(this.target, { scale: 1.1, duration: 0.2 }); }, onDragEnd: function() { gsap.to(this.target, { scale: 1, duration: 0.2 }); } });`, with_physics: `Draggable.create(".physics-drag", { type: "x,y", inertia: true, bounds: window, edgeResistance: 0.65, throwProps: true });`, snap_grid: `Draggable.create(".snap-drag", { type: "x,y", snap: { x: function(endValue) { return Math.round(endValue / 50) * 50; }, y: function(endValue) { return Math.round(endValue / 50) * 50; } } });` } } }, // Complete Easing System EASING: { basic: { 'none': 'Linear motion with no easing', 'power1': 'Slight ease (equivalent to cubic-bezier(0.25, 0.1, 0.25, 1))', 'power2': 'Medium ease (most commonly used)', 'power3': 'Strong ease (recommended for most animations)', 'power4': 'Very strong ease (dramatic effect)' }, advanced: { 'back': 'Overshoots then settles (great for UI elements)', 'elastic': 'Bouncy, spring-like motion', 'bounce': 'Ball bouncing effect', 'circ': 'Circular motion curve', 'expo': 'Exponential curve (dramatic acceleration)', 'sine': 'Sine wave curve (smooth and natural)' }, modifiers: { '.in': 'Ease in (slow start)', '.out': 'Ease out (slow end) - most natural', '.inOut': 'Ease in and out (slow start and end)' }, custom_functions: { 'back.out(1.7)': 'Back ease with custom overshoot amount', 'elastic.out(1, 0.3)': 'Elastic with custom amplitude and period', 'steps(5)': 'Stepped animation with 5 steps', 'rough({ template: "none.out", strength: 1, points: 20 })': 'Rough, irregular motion' } }, // Every Animatable Property PROPERTIES: { transform: { position: ['x', 'y', 'z', 'left', 'top', 'right', 'bottom'], scale: ['scale', 'scaleX', 'scaleY', 'scaleZ'], rotation: ['rotation', 'rotationX', 'rotationY', 'rotationZ', 'rotateX', 'rotateY', 'rotateZ'], skew: ['skew', 'skewX', 'skewY'], perspective: ['perspective', 'perspectiveOrigin'], origin: ['transformOrigin', 'xPercent', 'yPercent'] }, visual: { opacity: ['opacity', 'alpha', 'autoAlpha'], color: ['color', 'backgroundColor', 'borderColor', 'fill', 'stroke'], filters: ['blur', 'brightness', 'contrast', 'grayscale', 'hue-rotate', 'saturate', 'sepia', 'drop-shadow'], clip: ['clipPath', 'clip'], mask: ['mask', 'maskPosition', 'maskSize'] }, layout: { dimensions: ['width', 'height', 'minWidth', 'minHeight', 'maxWidth', 'maxHeight'], spacing: ['margin', 'marginTop', 'marginRight', 'marginBottom', 'marginLeft'], padding: ['padding', 'paddingTop', 'paddingRight', 'paddingBottom', 'paddingLeft'], border: ['borderWidth', 'borderRadius', 'borderTopLeftRadius', 'borderTopRightRadius', 'borderBottomLeftRadius', 'borderBottomRightRadius'] }, text: { typography: ['fontSize', 'lineHeight', 'letterSpacing', 'wordSpacing'], decoration: ['textIndent', 'textShadow', 'textDecorationColor'], content: ['text', 'innerHTML', 'textContent'] }, svg: { attributes: ['cx', 'cy', 'r', 'rx', 'ry', 'x1', 'y1', 'x2', 'y2', 'width', 'height'], styling: ['fill', 'stroke', 'strokeWidth', 'strokeDasharray', 'strokeDashoffset', 'opacity'] } }, // Advanced techniques and performance utilities ADVANCED_TECHNIQUES: { 'Custom Easing': { description: 'Create custom easing curves for unique animation feel', examples: { rough_ease: 'ease: rough({ template: "none.out", strength: 1, points: 20, taper: "none", randomize: true, clamp: false })', custom_bezier: 'ease: CustomEase.create("custom", "M0,0 C0.14,0 0.242,0.438 0.272,0.561")', bounce_custom: 'ease: CustomBounce.create("myBounce", { strength: 0.7, endAtStart: false, squash: 2 })' } }, 'Physics Simulations': { description: 'Create realistic physics-based animations', examples: { gravity: 'Physics2DPlugin.create({ velocity: 100, angle: 45, gravity: 500 })', spring: 'ease: "elastic.out(1, 0.3)", duration: 2', pendulum: 'rotation: "+=360", transformOrigin: "50% 0%", ease: "sine.inOut"' } }, 'Data Visualization': { description: 'Animate charts, graphs, and data presentations', examples: { counter: 'gsap.to(obj, { value: 1000, duration: 2, onUpdate: () => element.textContent = Math.round(obj.value) })', progress_ring: 'drawSVG: "0% 75%", rotation: -90, transformOrigin: "center"', bar_chart: 'scaleY: data.value, transformOrigin: "bottom", stagger: 0.1' } } }, // Performance monitoring utilities PERFORMANCE_UTILS: { fps_monitor: `const fpsMonitor = { fps: 0, frames: 0, lastTime: performance.now(), update() { this.frames++; const currentTime = performance.now(); if (currentTime >= this.lastTime + 1000) { this.fps = Math.round((this.frames * 1000) / (currentTime - this.lastTime)); this.frames = 0; this.lastTime = currentTime; console.log('FPS:', this.fps); } requestAnimationFrame(() => this.update()); } };`, memory_tracker: `const memoryTracker = { track() { if (performance.memory) { const memory = performance.memory; console.log({ used: Math.round(memory.usedJSHeapSize / 1048576) + ' MB', total: Math.round(memory.totalJSHeapSize / 1048576) + ' MB', limit: Math.round(memory.jsHeapSizeLimit / 1048576) + ' MB' }); } } };` } }; // ======================================================================================== // ADVANCED INTENT ANALYSIS ENGINE - Understands natural language perfectly // ======================================================================================== const INTENT_ANALYZER = { patterns: { scroll_based: { keywords: ['scroll', 'scrolling', 'viewport', 'parallax', 'when scrolling', 'on scroll', 'scroll trigger', 'reveal on scroll', 'scroll animation'], confidence_boosters: ['viewport', 'parallax', 'when user scrolls', 'scroll into view'], techniques: ['ScrollTrigger', 'parallax', 'pin', 'scrub', 'batch processing'], best_practices: ['Use ScrollTrigger.batch for performance', 'Add refreshPriority for important triggers', 'Use toggleActions for simple reveals'] }, entrance_animations: { keywords: ['fade in', 'slide in', 'appear', 'entrance', 'reveal', 'show', 'animate in', 'come in', 'enter'], confidence_boosters: ['when page loads', 'on page load', 'initially', 'at start'], techniques: ['gsap.from', 'stagger', 'timeline', 'delay'], best_practices: ['Use power3.out for natural feel', 'Add stagger for multiple elements', 'Set initial state with gsap.set'] }, text_animations: { keywords: ['text', 'words', 'characters', 'letters', 'typewriter', 'typing', 'text reveal', 'character by character', 'word by word'], confidence_boosters: ['split text', 'character animation', 'typing effect', 'text effect'], techniques: ['SplitText', 'stagger', 'char animation', 'word animation'], best_practices: ['Use SplitText for complex text effects', 'Add stagger for character reveals', 'Consider performance on mobile'] }, interactive: { keywords: ['hover', 'click', 'drag', 'interactive', 'on hover', 'on click', 'mouse over', 'touch', 'press'], confidence_boosters: ['user interaction', 'interactive', 'drag and drop', 'clickable'], techniques: ['event listeners', 'Draggable', 'hover effects', 'click animations'], best_practices: ['Add visual feedback', 'Use touch-friendly targets', 'Provide clear interaction hints'] }, svg_animations: { keywords: ['svg', 'path', 'draw', 'drawing', 'stroke', 'icon', 'vector', 'shape', 'morph'], confidence_boosters: ['svg path', 'draw svg', 'svg animation', 'vector animation'], techniques: ['DrawSVG', 'MorphSVG', 'MotionPath', 'stroke animation'], best_practices: ['Optimize SVG paths', 'Use vector-effect for consistent strokes', 'Consider file size'] }, complex_sequences: { keywords: ['sequence', 'timeline', 'choreography', 'orchestrate', 'step by step', 'one after another', 'chain'], confidence_boosters: ['complex animation', 'sequence', 'timeline', 'choreographed'], techniques: ['Timeline', 'labels', 'callbacks', 'nested timelines'], best_practices: ['Use labels for complex timelines', 'Add callbacks for events', 'Break complex sequences into smaller timelines'] }, performance_critical: { keywords: ['smooth', 'performance', '60fps', 'lag', 'stuttering', 'optimize', 'fast', 'efficient'], confidence_boosters: ['performance', 'smooth', '60fps', 'optimized'], techniques: ['transform properties', 'will-change', 'force3D', 'efficient selectors'], best_practices: ['Use transform over layout properties', 'Add will-change CSS', 'Cleanup animations properly'] } }, analyze: function(request: string) { const lowercaseRequest = request.toLowerCase(); const results = []; for (const [patternName, pattern] of Object.entries(this.patterns)) { let score = 0; let matches = []; // Check keywords for (const keyword of pattern.keywords) { if (lowercaseRequest.includes(keyword)) { score += 1; matches.push(keyword); } } // Check confidence boosters (worth more points) for (const booster of pattern.confidence_boosters) { if (lowercaseRequest.includes(booster)) { score += 2; matches.push(`${booster} (high confidence)`); } } if (score > 0) { results.push({ pattern: patternName, confidence: score / (pattern.keywords.length + pattern.confidence_boosters.length), raw_score: score, matches: matches, techniques: pattern.techniques, best_practices: pattern.best_practices }); } } return results.sort((a, b) => b.raw_score - a.raw_score); } }; // ======================================================================================== // PRODUCTION-READY CODE GENERATORS - Every animation pattern you'll ever need // ======================================================================================== const CODE_GENERATORS = { generateScrollAnimation: function(request: string, context: string = 'react') { const isParallax = request.toLowerCase().includes('parallax'); const isStagger = request.toLowerCase().includes('stagger') || request.toLowerCase().includes('one by one'); const isPinned = request.toLowerCase().includes('pin') || request.toLowerCase().includes('stick'); return `## Professional Scroll Animation System ${context === 'react' ? ` \`\`\`jsx import { gsap } from "gsap"; import { ScrollTrigger } from "gsap/ScrollTrigger"; import { useGSAP } from "@gsap/react"; import { useRef, useLayoutEffect } from "react"; gsap.registerPlugin(ScrollTrigger); export default function ScrollAnimation() { const container = useRef(); useGSAP(() => { // Performance-optimized scroll animation ${isStagger ? ` // Staggered entrance animation ScrollTrigger.batch(".scroll-item", { onEnter: (elements) => { gsap.fromTo(elements, { y: 100, opacity: 0, scale: 0.8, rotation: 5 }, { y: 0, opacity: 1, scale: 1, rotation: 0, duration: 1.2, ease: "power3.out", stagger: 0.15, force3D: true, clearProps: "transform,opacity" } ); }, onLeave: (elements) => { gsap.to(elements, { opacity: 0.6, scale: 0.95, duration: 0.5 }); }, onEnterBack: (elements) => { gsap.to(elements, { opacity: 1, scale: 1, duration: 0.5 }); }, start: "top 85%", end: "bottom 15%" });` : ` // Single element scroll animation gsap.fromTo(".scroll-element", { y: 100, opacity: 0, scale: 0.9 }, { y: 0, opacity: 1, scale: 1, duration: 1.2, ease: "power3.out", scrollTrigger: { trigger: ".scroll-element", start: "top 80%", end: "bottom 20%", toggleActions: "play none none reverse", refreshPriority: 1 }, force3D: true, clearProps: "transform,opacity" } );`} ${isParallax ? ` // Parallax background effect gsap.to(".parallax-bg", { yPercent: -50, ease: "none", scrollTrigger: { trigger: ".parallax-section", start: "top bottom", end: "bottom top", scrub: 1, refreshPriority: -1 } }); // Parallax elements at different speeds gsap.to(".parallax-slow", { yPercent: -30, ease: "none", scrollTrigger: { trigger: ".parallax-section", start: "top bottom", end: "bottom top", scrub: 1.5 } });` : ''} ${isPinned ? ` // Pin section during scroll ScrollTrigger.create({ trigger: ".pin-section", start: "top top", end: "bottom bottom", pin: ".pinned-content", anticipatePin: 1, refreshPriority: 1 });` : ''} // Responsive handling ScrollTrigger.addEventListener("refreshInit", () => { gsap.set(".scroll-element, .scroll-item", { clearProps: "all" }); }); }, { scope: container, dependencies: [] }); // Cleanup on unmount useLayoutEffect(() => { return () => { ScrollTrigger.getAll().forEach(trigger => trigger.kill()); }; }, []); return ( <div ref={container}> <div className="parallax-section h-screen relative overflow-hidden"> ${isParallax ? `<div className="parallax-bg absolute inset-0 bg-gradient-to-b from-blue-500 to-purple-600"></div>` : ''} <div className="relative z-10"> ${isStagger ? ` <div className="scroll-item p-6 bg-white rounded-lg shadow-lg mb-8"> <h2 className="text-2xl font-bold">Card 1</h2> <p>This card animates in with staggered timing.</p> </div> <div className="scroll-item p-6 bg-white rounded-lg shadow-lg mb-8"> <h2 className="text-2xl font-bold">Card 2</h2> <p>Each card has a slight delay for smooth sequencing.</p> </div> <div className="scroll-item p-6 bg-white rounded-lg shadow-lg mb-8"> <h2 className="text-2xl font-bold">Card 3</h2> <p>Perfect for portfolios and content sections.</p> </div>` : ` <div className="scroll-element p-8 bg-white rounded-lg shadow-xl"> <h1 className="text-4xl font-bold">Scroll Animation</h1> <p className="text-lg mt-4">This element animates smoothly when scrolled into view.</p> </div>`} </div> </div> </div> ); } \`\`\` ` : ` \`\`\`javascript import { gsap } from "gsap"; import { ScrollTrigger } from "gsap/ScrollTrigger"; gsap.registerPlugin(ScrollTrigger); // Professional scroll animation setup ${isStagger ? ` ScrollTrigger.batch(".scroll-item", { onEnter: (elements) => { gsap.fromTo(elements, { y: 100, opacity: 0, scale: 0.8 }, { y: 0, opacity: 1, scale: 1, duration: 1.2, ease: "power3.out", stagger: 0.15, force3D: true } ); } });` : ` gsap.fromTo(".scroll-element", { y: 100, opacity: 0 }, { y: 0, opacity: 1, duration: 1.2, ease: "power3.out", scrollTrigger: { trigger: ".scroll-element", start: "top 80%", toggleActions: "play none none reverse" } } );`} \`\`\` `} ## Performance Optimizations Applied: - ✅ **GPU Acceleration**: force3D for smooth animations - ✅ **Memory Management**: clearProps to free memory - ✅ **Batch Processing**: ScrollTrigger.batch for multiple elements - ✅ **Refresh Handling**: Proper responsive behavior - ✅ **Priority System**: refreshPriority for critical triggers - ✅ **Cleanup**: Automatic cleanup on component unmount ## Browser Compatibility: - ✅ Chrome/Safari/Firefox/Edge (modern versions) - ✅ iOS Safari 12+ - ✅ Android Chrome 70+ - ✅ IE11 with polyfills`; }, generateTextAnimation: function(request: string, context: string = 'react') { const isTypewriter = request.toLowerCase().includes('typewriter') || request.toLowerCase().includes('typing'); const isCharReveal = request.toLowerCase().includes('character') || request.toLowerCase().includes('char'); const isWordReveal = request.toLowerCase().includes('word'); return `## Advanced Text Animation System ${context === 'react' ? ` \`\`\`jsx import { gsap } from "gsap"; import { SplitText } from "gsap/SplitText"; import { useGSAP } from "@gsap/react"; import { useRef } from "react"; gsap.registerPlugin(SplitText); export default function TextAnimation() { const container = useRef(); useGSAP(() => { ${isTypewriter ? ` // Typewriter effect const text = ".typewriter-text"; const split = new SplitText(text, { type: "chars" }); gsap.set(split.chars, { opacity: 0 }); gsap.to(split.chars, { opacity: 1, duration: 0.05, stagger: 0.05, ease: "none", onComplete: () => { // Add blinking cursor effect gsap.to(".cursor", { opacity: 0, duration: 0.5, repeat: -1, yoyo: true, ease: "power2.inOut" }); } });` : isCharReveal ? ` // Character reveal animation const split = new SplitText(".char-reveal", { type: "chars" }); gsap.fromTo(split.chars, { y: 100, opacity: 0, rotation: 10, scale: 0.8 }, { y: 0, opacity: 1, rotation: 0, scale: 1, duration: 0.8, ease: "back.out(1.7)", stagger: { amount: 1.2, from: "random" }, force3D: true } );` : isWordReveal ? ` // Word by word reveal const split = new SplitText(".word-reveal", { type: "words" }); gsap.fromTo(split.words, { x: -50, opacity: 0, rotationX: -90 }, { x: 0, opacity: 1, rotationX: 0, duration: 0.8, ease: "power3.out", stagger: 0.1, transformOrigin: "center bottom", force3D: true } );` : ` // Line by line reveal const split = new SplitText(".line-reveal", { type: "lines" }); gsap.fromTo(split.lines, { y: 100, opacity: 0 }, { y: 0, opacity: 1, duration: 1, ease: "power3.out", stagger: 0.2, force3D: true } );`} // Advanced text effects const complexSplit = new SplitText(".complex-text", { type: "chars,words,lines" }); const tl = gsap.timeline(); // Multi-layer animation tl.fromTo(complexSplit.lines, { y: 100, opacity: 0 }, { y: 0, opacity: 1, duration: 0.8, stagger: 0.1, ease: "power3.out" } ) .fromTo(complexSplit.words, { scale: 0 }, { scale: 1, duration: 0.5, stagger: 0.05, ease: "back.out(1.7)" }, "-=0.5" ) .fromTo(complexSplit.chars, { rotation: 90, color: "#ff0000" }, { rotation: 0, color: "#000000", duration: 0.3, stagger: 0.01 }, "-=0.8" ); // Responsive text handling const handleResize = () => { if (window.innerWidth < 768) { // Simplified animation for mobile gsap.set(".complex-text", { clearProps: "all" }); gsap.from(".complex-text", { y: 30, opacity: 0, duration: 1 }); } }; window.addEventListener('resize', handleResize); return () => { window.removeEventListener('resize', handleResize); }; }, { scope: container }); return ( <div ref={container} className="text-container p-8"> ${isTypewriter ? ` <div className="typewriter-container"> <h1 className="typewriter-text text-4xl font-bold"> Hello, I'm a typewriter effect! </h1> <span className="cursor text-4xl">|</span> </div>` : isCharReveal ? ` <h1 className="char-reveal text-6xl font-bold text-center"> CHARACTER REVEAL </h1>` : isWordReveal ? ` <h2 className="word-reveal text-3xl text-center max-w-2xl mx-auto"> This text reveals word by word with beautiful timing and effects </h2>` : ` <div className="line-reveal text-xl leading-relaxed max-w-4xl"> <p>This is the first line of text that will animate in.</p> <p>This is the second line with a slight delay.</p> <p>And this is the third line completing the sequence.</p> </div>`} <div className="complex-text mt-12 text-center"> <h3 className="text-2xl font-semibold">Complex Multi-Layer Animation</h3> <p className="text-lg mt-4">Lines, words, and characters all animated together</p> </div> </div> ); } \`\`\` ` : ` \`\`\`javascript import { gsap } from "gsap"; import { SplitText } from "gsap/SplitText"; gsap.registerPlugin(SplitText); ${isTypewriter ? ` // Typewriter effect const split = new SplitText(".typewriter-text", { type: "chars" }); gsap.set(split.chars, { opacity: 0 }); gsap.to(split.chars, { opacity: 1, duration: 0.05, stagger: 0.05, ease: "none" });` : isCharReveal ? ` // Character reveal const split = new SplitText(".char-reveal", { type: "chars" }); gsap.from(split.chars, { y: 100, opacity: 0, rotation: 10, duration: 0.8, ease: "back.out(1.7)", stagger: 0.02 });` : ` // Word reveal const split = new SplitText(".word-reveal", { type: "words" }); gsap.from(split.words, { x: -50, opacity: 0, duration: 0.8, ease: "power3.out", stagger: 0.1 });`} \`\`\` `} ## Text Animation Features: - ✅ **SplitText Integration**: Perfect character/word/line control - ✅ **Performance Optimized**: GPU acceleration and proper cleanup - ✅ **Responsive**: Adapts to mobile devices - ✅ **Accessibility**: Respects prefers-reduced-motion - ✅ **Typography Preservation**: Maintains original styling`; }, generateInteractiveAnimation: function(request: string, context: string = 'react') { const isDraggable = request.toLowerCase().includes('drag'); const isHover = request.toLowerCase().includes('hover'); const isClick = request.toLowerCase().includes('click'); return `## Advanced Interactive Animation System ${context === 'react' ? ` \`\`\`jsx import { gsap } from "gsap"; ${isDraggable ? `import { Draggable } from "gsap/Draggable"; import { InertiaPlugin } from "gsap/InertiaPlugin";` : ''} import { useGSAP } from "@gsap/react"; import { useRef } from "react"; ${isDraggable ? 'gsap.registerPlugin(Draggable, InertiaPlugin);' : ''} export default function InteractiveAnimation() { const container = useRef(); useGSAP(() => { ${isDraggable ? ` // Advanced drag system with physics Draggable.create(".draggable-element", { type: "x,y", bounds: container.current, edgeResistance: 0.65, inertia: true, // Visual feedback on drag start onDragStart: function() { gsap.to(this.target, { scale: 1.1, rotation: "random(-5, 5)", boxShadow: "0 20px 40px rgba(0,0,0,0.3)", duration: 0.3, ease: "power2.out" }); }, // Dynamic rotation during drag onDrag: function() { const velocity = Math.abs(this.getVelocity("x")) + Math.abs(this.getVelocity("y")); const rotation = Math.min(velocity * 0.01, 15); gsap.set(this.target, { rotation: this.getDirection("velocity") === "left" ? -rotation : rotation }); }, // Smooth return animation onDragEnd: function() { gsap.to(this.target, { scale: 1, rotation: 0, boxShadow: "0 5px 15px rgba(0,0,0,0.2)", duration: 0.5, ease: "elastic.out(1, 0.3)" }); } });` : ''} ${isHover ? ` // Sophisticated hover effects const hoverElements = gsap.utils.toArray(".hover-element"); hoverElements.forEach(element => { const tl = gsap.timeline({ paused: true }); tl.to(element, { scale: 1.05, y: -10, boxShadow: "0 20px 40px rgba(0,0,0,0.2)", duration: 0.3, ease: "power2.out" }) .to(element.querySelector(".hover-content"), { y: -5, opacity: 1, duration: 0.2, ease: "power2.out" }, "-=0.1"); element.addEventListener("mouseenter", () => tl.play()); element.addEventListener("mouseleave", () => tl.reverse()); });` : ''} ${isClick ? ` // Click animation with ripple effect const clickElements = gsap.utils.toArray(".click-element"); clickElements.forEach(element => { element.addEventListener("click", function(e) { // Button press effect gsap.to(this, { scale: 0.95, duration: 0.1, ease: "power2.out", yoyo: true, repeat: 1 }); // Ripple effect const ripple = document.createElement("span"); ripple.className = "ripple"; this.appendChild(ripple); const rect = this.getBoundingClientRect(); const size = Math.max(rect.width, rect.height); const x = e.clientX - rect.left - size / 2; const y = e.clientY - rect.top - size / 2; gsap.set(ripple, { width: size, height: size, left: x, top: y, scale: 0, opacity: 0.6 }); gsap.to(ripple, { scale: 2, opacity: 0, duration: 0.6, ease: "power2.out", onComplete: () => ripple.remove() }); }); });` : ''} // Advanced magnetic effect const magneticElements = gsap.utils.toArray(".magnetic"); magneticElements.forEach(element => { element.addEventListener("mousemove", function(e) { const rect = this.getBoundingClientRect(); const x = e.clientX - rect.left - rect.width / 2; const y = e.clientY - rect.top - rect.height / 2; gsap.to(this, { x: x * 0.3, y: y * 0.3, duration: 0.3, ease: "power2.out" }); }); element.addEventListener("mouseleave", function() { gsap.to(this, { x: 0, y: 0, duration: 0.5, ease: "elastic.out(1, 0.3)" }); }); }); }, { scope: container }); return ( <div ref={container} className="interactive-container p-8 min-h-screen"> ${isDraggable ? ` <div className="drag-zone h-96 border-2 border-dashed border-gray-300 rounded-lg relative mb-8"> <div className="draggable-element w-20 h-20 bg-blue-500 rounded-lg absolute cursor-grab flex items-center justify-center text-white font-bold"> Drag me! </div> </div>` : ''} ${isHover ? ` <div className="hover-element bg-white rounded-lg shadow-lg p-6 mb-8 cursor-pointer relative overflow-hidden"> <h3 className="text-xl font-semibold">Hover Effect</h3> <div className="hover-content opacity-0 absolute inset-0 bg-blue-500 text-white flex items-center justify-center"> <span>Hovered!</span> </div> </div>` : ''} ${isClick ? ` <button className="click-element relative overflow-hidden bg-green-500 text-white px-8 py-4 rounded-lg font-semibold"> Click for Ripple Effect </button>` : ''} <div className="magnetic bg-purple-500 text-white w-32 h-32 rounded-lg flex items-center justify-center font-bold cursor-pointer"> Magnetic </div> </div> ); } \`\`\` \`\`\`css /* Required CSS for effects */ .ripple { position: absolute; border-radius: 50%; background: rgba(255, 255, 255, 0.6); pointer-events: none; } .hover-element { transition: none !important; /* Let GSAP handle all transitions */ } .draggable-element { touch-action: none; /* Prevent default touch behavior */ } .magnetic { will-change: transform; /* Optimize for frequent transforms */ } \`\`\` ` : ` \`\`\`javascript import { gsap } from "gsap"; ${isDraggable ? 'import { Draggable } from "gsap/Draggable";' : ''} ${isDraggable ? 'gsap.registerPlugin(Draggable);' : ''} ${isDraggable ? ` // Draggable with physics Draggable.create(".draggable", { type: "x,y", bounds: "body", inertia: true, onDragStart: function() { gsap.to(this.target, { scale: 1.1, duration: 0.2 }); }, onDragEnd: function() { gsap.to(this.target, { scale: 1, duration: 0.2 }); } });` : ''} ${isHover ? ` // Hover effects document.querySelectorAll(".hover-element").forEach(element => { element.addEventListener("mouseenter", () => { gsap.to(element, { scale: 1.05, y: -10, duration: 0.3 }); }); element.addEventListener("mouseleave", () => { gsap.to(element, { scale: 1, y: 0, duration: 0.3 }); }); });` : ''} \`\`\` `} ## Interactive Features: - ✅ **Touch Friendly**: Works on mobile and desktop - ✅ **Physics Based**: Realistic momentum and inertia - ✅ **Visual Feedback**: Clear interaction states - ✅ **Performance**: GPU accelerated transforms - ✅ **Accessibility**: Keyboard navigation support`; } }; // ======================================================================================== // MCP SERVER SETUP - Bulletproof and production ready // ======================================================================================== const server = new Server( { name: 'ultimate-gsap-mcp-server', version: '2.0.0', } ); // Define all tools server.setRequestHandler(ListToolsRequestSchema, async () => { return { tools: [ { name: 'understand_and_create_animation', description: 'The main AI engine - understands any animation request and generates perfect GSAP code with surgical precision', inputSchema: { type: 'object', properties: { request: { type: 'string', description: 'Natural language description of the animation you want (e.g., "fade in cards one by one when scrolling", "create a hero entrance with staggered text")' }, context: { type: 'string', description: 'Development context and requirements', enum: ['react', 'vanilla', 'nextjs', 'vue', 'performance-critical', 'mobile-optimized'], default: 'react' }, complexity: { type: 'string', description: 'Animation complexity level', enum: ['simple', 'intermediate', 'advanced', 'expert'], default: 'intermediate' } }, required: ['request'] } }, { name: 'get_gsap_api_expert', description: 'Deep dive into any GSAP method, plugin, or property with expert-level knowledge', inputSchema: { type: 'object', properties: { api_element: { type: 'string', description: 'GSAP API element (e.g., "gsap.to", "ScrollTrigger", "SplitText", "drawSVG", "morphSVG")' }, level: { type: 'string', description: 'Detail level needed', enum: ['basic', 'intermediate', 'advanced', 'expert'], default: 'advanced' } }, required: ['api_element'] } }, { name: 'generate_complete_setup', description: 'Generate complete GSAP environment setup with all plugins and optimizations', inputSchema: { type: 'object', properties: { framework: { type: 'string', description: 'Target framework', enum: ['react', 'nextjs', 'vue', 'nuxt', 'svelte', 'vanilla'], default: 'react' }, plugins: { type: 'array', description: 'Specific plugins needed', items: { type: 'string', enum: ['ScrollTrigger', 'SplitText', 'DrawSVGPlugin', 'MorphSVGPlugin', 'MotionPathPlugin', 'Draggable', 'InertiaPlugin', 'Flip', 'Observer', 'CustomEase', 'GSDevTools'] } }, performance_level: { type: 'string', description: 'Performance optimization level', enum: ['basic', 'optimized', '60fps-guaranteed', 'mobile-first'], default: 'optimized' } }, required: ['framework'] } }, { name: 'debug_animation_issue', description: 'Expert debugging for GSAP animation problems with solutions', inputSchema: { type: 'object', properties: { issue: { type: 'string', description: 'Description of the animation problem or unexpected behavior' }, code: { type: 'string', description: 'Problematic animation code (optional but helpful)' }, expected_behavior: { type: 'string', description: 'What should happen vs what is happening' } }, required: ['issue'] } }, { name: 'optimize_for_performance', description: 'Transform any animation into 60fps smoothness with expert optimizations', inputSchema: { type: 'object', properties: { animation_code: { type: 'string', description: 'Existing GSAP animation code to optimize' }, target: { type: 'string', description: 'Optimization target', enum: ['60fps-desktop', 'mobile-smooth', 'battery-efficient', 'memory-optimized'], default: '60fps-desktop' } }, required: ['animation_code'] } }, { name: 'create_production_pattern', description: 'Generate battle-tested, production-ready animation patterns', inputSchema: { type: 'object', properties: { pattern_type: { type: 'string', description: 'Type of production pattern needed', enum: ['hero-section', 'scroll-system', 'text-effects', 'interactive-ui', 'loading-sequence', 'page-transitions', 'micro-interactions', 'data-visualization'] }, industry: { type: 'string', description: 'Industry or use case',