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,331 lines (1,259 loc) • 108 kB
JavaScript
#!/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) {
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, context = '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, context = '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, context = '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: {