Skip to main content
Glama
Sheshiyer

Framer Plugin MCP Server

by Sheshiyer

create_plugin

Build a Framer plugin project with integrated web3 features like wallet connections, contract interactions, and NFT displays. Specify the plugin name, description, and output path to get started.

Instructions

Create a new Framer plugin project with web3 capabilities

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
descriptionYesPlugin description
nameYesPlugin name
outputPathYesOutput directory path
web3FeaturesNoWeb3 features to include

Implementation Reference

  • The main handler function for the 'create_plugin' tool. It generates a complete Framer plugin project structure, including package.json with dependencies (optionally web3), TypeScript configs, Vite config, and a basic React component in src/index.tsx, with web3 wallet integration if specified.
      private async handleCreatePlugin(args: CreatePluginArgs) {
        try {
          const pluginDir = path.resolve(args.outputPath);
          await fs.ensureDir(pluginDir);
    
          // Create package.json
          const packageJson: PackageJson = {
            name: args.name,
            version: '1.0.0',
            description: args.description,
            main: 'dist/index.js',
            scripts: {
              build: 'vite build',
              dev: 'vite'
            },
            dependencies: {
              '@framer/framer.motion': '^10.0.0',
              'react': '^18.2.0',
              'react-dom': '^18.2.0'
            },
            devDependencies: {
              '@types/react': '^18.2.0',
              'typescript': '^5.0.0',
              'vite': '^4.0.0',
              '@vitejs/plugin-react': '^4.0.0'
            }
          };
    
          // Add web3 dependencies if features are requested
          if (args.web3Features?.includes('wallet-connect')) {
            packageJson.dependencies = {
              ...packageJson.dependencies,
              '@web3-react/core': '^8.2.0',
              '@web3-react/injected-connector': '^6.0.7',
              'ethers': '^6.7.0'
            };
          }
    
          await fs.writeJSON(path.join(pluginDir, 'package.json'), packageJson, { spaces: 2 });
    
          // Create tsconfig.json
          const tsConfig = {
            compilerOptions: {
              target: 'ES2020',
              lib: ['DOM', 'DOM.Iterable', 'ESNext'],
              module: 'ESNext',
              skipLibCheck: true,
              moduleResolution: 'bundler',
              allowImportingTsExtensions: true,
              resolveJsonModule: true,
              isolatedModules: true,
              noEmit: true,
              jsx: 'react-jsx',
              strict: true,
              noUnusedLocals: true,
              noUnusedParameters: true,
              noFallthroughCasesInSwitch: true
            },
            include: ['src'],
            references: [{ path: './tsconfig.node.json' }]
          };
    
          await fs.writeJSON(path.join(pluginDir, 'tsconfig.json'), tsConfig, { spaces: 2 });
    
          // Create tsconfig.node.json
          const tsNodeConfig = {
            compilerOptions: {
              composite: true,
              skipLibCheck: true,
              module: 'ESNext',
              moduleResolution: 'bundler',
              allowSyntheticDefaultImports: true
            },
            include: ['vite.config.ts']
          };
    
          await fs.writeJSON(path.join(pluginDir, 'tsconfig.node.json'), tsNodeConfig, { spaces: 2 });
    
          // Create vite.config.ts
          const viteConfig = `
    import { defineConfig } from 'vite';
    import react from '@vitejs/plugin-react';
    
    export default defineConfig({
      plugins: [react()],
      build: {
        lib: {
          entry: 'src/index.tsx',
          name: '${args.name}',
          formats: ['es'],
          fileName: 'index'
        },
        rollupOptions: {
          external: ['react', 'react-dom'],
          output: {
            globals: {
              react: 'React',
              'react-dom': 'ReactDOM'
            }
          }
        }
      }
    });
    `;
    
          await fs.writeFile(path.join(pluginDir, 'vite.config.ts'), viteConfig);
    
          // Create src directory and base files
          const srcDir = path.join(pluginDir, 'src');
          await fs.ensureDir(srcDir);
    
          // Create index.tsx
          let indexContent = `
    import { addPropertyControls, ControlType } from 'framer';
    import { motion } from 'framer-motion';
    import React from 'react';
    
    export default function ${args.name.replace(/-/g, '_')}() {
      return (
        <motion.div
          style={{
            width: 200,
            height: 200,
            backgroundColor: '#09F',
            borderRadius: 20,
          }}
          whileHover={{ scale: 1.1 }}
          whileTap={{ scale: 0.9 }}
        />
      );
    }
    
    addPropertyControls(${args.name.replace(/-/g, '_')}, {
      text: {
        type: ControlType.String,
        title: 'Text',
        defaultValue: 'Hello World',
      },
    });
    `;
    
          if (args.web3Features?.includes('wallet-connect')) {
            indexContent = `
    import { addPropertyControls, ControlType } from 'framer';
    import { motion } from 'framer-motion';
    import React from 'react';
    import { Web3ReactProvider, useWeb3React } from '@web3-react/core';
    import { InjectedConnector } from '@web3-react/injected-connector';
    import { ethers } from 'ethers';
    
    const injected = new InjectedConnector({
      supportedChainIds: [1, 3, 4, 5, 42],
    });
    
    function Web3Button() {
      const { activate, active, account, library } = useWeb3React();
    
      const connect = async () => {
        try {
          await activate(injected);
        } catch (error) {
          console.error('Error connecting:', error);
        }
      };
    
      return (
        <motion.button
          onClick={connect}
          whileHover={{ scale: 1.1 }}
          whileTap={{ scale: 0.9 }}
          style={{
            padding: '10px 20px',
            borderRadius: 8,
            backgroundColor: active ? '#4CAF50' : '#09F',
            color: 'white',
            border: 'none',
            cursor: 'pointer',
          }}
        >
          {active ? \`Connected: \${account?.slice(0, 6)}...\${account?.slice(-4)}\` : 'Connect Wallet'}
        </motion.button>
      );
    }
    
    export default function ${args.name.replace(/-/g, '_')}() {
      return (
        <Web3ReactProvider getLibrary={(provider) => new ethers.BrowserProvider(provider)}>
          <Web3Button />
        </Web3ReactProvider>
      );
    }
    
    addPropertyControls(${args.name.replace(/-/g, '_')}, {
      text: {
        type: ControlType.String,
        title: 'Text',
        defaultValue: 'Connect Wallet',
      },
    });
    `;
          }
    
          await fs.writeFile(path.join(srcDir, 'index.tsx'), indexContent);
    
          return {
            content: [
              {
                type: 'text',
                text: `Successfully created Framer plugin project at ${pluginDir}`
              }
            ]
          };
        } catch (error) {
          throw new McpError(
            ErrorCode.InternalError,
            `Failed to create plugin: ${error instanceof Error ? error.message : String(error)}`
          );
        }
      }
  • TypeScript interface defining the input arguments for the create_plugin tool.
    interface CreatePluginArgs {
      name: string;
      description: string;
      outputPath: string;
      web3Features?: string[];
    }
  • JSON schema defining the input parameters for the 'create_plugin' tool, used in tool registration.
    inputSchema: {
      type: 'object',
      properties: {
        name: {
          type: 'string',
          description: 'Plugin name'
        },
        description: {
          type: 'string',
          description: 'Plugin description'
        },
        outputPath: {
          type: 'string',
          description: 'Output directory path'
        },
        web3Features: {
          type: 'array',
          items: {
            type: 'string',
            enum: ['wallet-connect', 'contract-interaction', 'nft-display']
          },
          description: 'Web3 features to include'
        }
      },
      required: ['name', 'description', 'outputPath']
    }
  • src/index.ts:63-92 (registration)
    Tool registration in the ListTools handler, defining name, description, and input schema for 'create_plugin'.
    {
      name: 'create_plugin',
      description: 'Create a new Framer plugin project with web3 capabilities',
      inputSchema: {
        type: 'object',
        properties: {
          name: {
            type: 'string',
            description: 'Plugin name'
          },
          description: {
            type: 'string',
            description: 'Plugin description'
          },
          outputPath: {
            type: 'string',
            description: 'Output directory path'
          },
          web3Features: {
            type: 'array',
            items: {
              type: 'string',
              enum: ['wallet-connect', 'contract-interaction', 'nft-display']
            },
            description: 'Web3 features to include'
          }
        },
        required: ['name', 'description', 'outputPath']
      }
    },
  • src/index.ts:112-113 (registration)
    Dispatcher in CallToolRequest handler that routes 'create_plugin' calls to the handleCreatePlugin method.
    case 'create_plugin':
      return this.handleCreatePlugin(request.params.arguments as unknown as CreatePluginArgs);

Tool Definition Quality

Score is being calculated. Check back soon.

Install Server

Other Tools

Related Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Sheshiyer/framer-plugin-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server