back
🧠🥷How to make Meme Generating MCP (Cline and Cursor)

Intro

Hello! I'm Ninja Web Developer. Hi-Yah!🥷

I have been playing with studying MCP lately.↓
🧠🥷How to make AI controled Avatar 2 (Vroid MCP + Cline and Cursor + Unity)
🧠🥷How to make cool Ninja game (Unity MCP + Blender MCP (Cline and Cursor))
🧠🥷How to make cool Ninja (Blender MCP (Cline and Cursor))

First, I made an Image generation and editing Next.js Web App.↓
🧠🥷Gemini API 2 (Image generation and editing (free and fast))
Next, I changed it to an Image generation and editing MCP.↓
🧠🥷How to make Image generation and editing MCP (Gemini API + Cline and Cursor)
So this time, I will change it to a Meme Generating MCP!
OK! Let's begin!🚀

What is Meme?

Meme is a cultural phenomenon that spreads on the Internet, such as funny images, videos and text.
People who watch Meme will have benefit, such as reduce stress, sleep well, and laugh from bottom of heart.

Here is an interviews who watched Meme.

Web Developer C: After watching Meme, my old little brain is rebuild completely new, and I can find ways to solves the bugs in the code.

*Note: Effect of Meme has individual differences.

Consideration when making Meme MCP.

First, I prepared a famous Meme template.
However, I wanted to avoid illegal copy, so I changed it to an Anime style.↓
Image description
I still thought it is too similar to the original template, so I deleted the black jumping man mark in the T-shirt, and change the color of the hair and clothes.↓
Image description
For these edits, I used my Image generating and edit MCP or App that I made last time.

Outline of system

This system has a simple three layer structure.
Cline or Cursor → MCP → Next.js Web App
1️⃣ Cline or Cursor part will send the instruction to MCP.
2️⃣ MCP part will relay the instruction to Next.js Web App.
3️⃣ Next.js Web App part will display Meme on the browser.
Ok! Let's setup the Meme MCP.

How to set Next.js Web App

1️⃣ Make a Next.js project

npx create-next-app@latest
Enter fullscreen mode Exit fullscreen mode

https://nextjs.org/docs/app/getting-started/installation

2️⃣ Set the codes
Code of frontend (app/page.tsx)

"use client";

import { useState, useEffect } from "react";

export default function Home() {
  const [noText, setNoText] = useState("");
  const [yesText, setYesText] = useState("");
  const [error, setError] = useState<string | null>(null);

  const fetchMemeText = async () => {
    setError(null);
    try {
      const response = await fetch("/api/generate-meme", {
        method: "GET",
      });

      if (!response.ok) {
        const errorText = await response.text();
        throw new Error(
          `HTTP error! status: ${response.status}, body: ${errorText}`
        );
      }

      const data = await response.json();
      if (data.receivedText) {
        setNoText(data.receivedText.noText);
        setYesText(data.receivedText.yesText);
      }
    } catch (error) {
      console.error("Error fetching meme text:", error);
      const errorMessage =
        error instanceof Error ? error.message : "An unknown error occurred";
      setError(errorMessage);
    }
  };

  useEffect(() => {
    const intervalId = setInterval(() => {
      fetchMemeText();
    }, 4000);

    return () => clearInterval(intervalId);
  }, []);

  return (
    <div className="flex flex-col items-center justify-center min-h-screen py-2">
      <h1 className="text-6xl font-bold mb-4">Meme Generating MCP</h1>

      {error && <p className="text-red-500">Error: {error}</p>}

      {noText && yesText && (
        <div>
          <div className="flex items-center">
            <img src="/template_no.png" alt="template_no" className="mr-4" />
            <p className="text-6xl font-bold">{noText}</p>
          </div>
          <div className="flex items-center">
            <img src="/template_yes.png" alt="template_yes" className="mr-4" />
            <p className="text-6xl font-bold">{yesText}</p>
          </div>
        </div>
      )}
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

Code of meme generation (app/api/generate-meme/route.ts)

import { NextResponse } from "next/server";

let storedNoText: string = "";
let storedYesText: string = "";

export async function POST(request: Request) {
  try {
    const { noText, yesText } = await request.json();
    console.log("Received text in Next.js API:", { noText, yesText });

    storedNoText = noText;
    storedYesText = yesText;

    return NextResponse.json({
      message: "Text received successfully",
      receivedText: { noText, yesText },
    });
  } catch (error) {
    console.error("Error processing request in Next.js API:", error);
    const errorMessage =
      error instanceof Error ? error.message : "An unknown error occurred";
    return NextResponse.json(
      {
        message: "Error processing request",
        error: errorMessage,
      },
      { status: 500 }
    );
  }
}

export async function GET(request: Request) {
  return NextResponse.json({
    message: "Text retrieved successfully",
    receivedText: { noText: storedNoText, yesText: storedYesText },
  });
}
Enter fullscreen mode Exit fullscreen mode

Set template_no.png and template_yes.png inside public folder.
template_no.png↓
Image description
template_yes.png↓
Image description

How to set Meme MCP

1️⃣ Make a folder for Meme MCP Server and open it from your editor.

2️⃣ Make package.json.↓

npm init
Enter fullscreen mode Exit fullscreen mode

3️⃣ Install MCP SDK.↓

npm install @modelcontextprotocol/sdk
Enter fullscreen mode Exit fullscreen mode

4️⃣ Make tsconfig.json.↓

tsc --init
Enter fullscreen mode Exit fullscreen mode

5️⃣ Add "build": "tsc", to scripts of package.json.

6️⃣ Add index.ts of Meme MCP Server.↓

#!/usr/bin/env node
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import {
  CallToolRequestSchema,
  ErrorCode,
  ListToolsRequestSchema,
  McpError,
} from "@modelcontextprotocol/sdk/types.js";

class MemeServer {
  private server: Server;

  constructor() {
    this.server = new Server(
      {
        name: "meme-mcp-server",
        version: "0.1.0",
      },
      {
        capabilities: {
          resources: {},
          tools: {},
        },
      }
    );

    this.setupToolHandlers();

    this.server.onerror = (error) => console.error("[MCP Error]", error);
    process.on("SIGINT", async () => {
      await this.server.close();
      process.exit(0);
    });
  }

  private setupToolHandlers() {
    this.server.setRequestHandler(ListToolsRequestSchema, async () => ({
      tools: [
        {
          name: "generate_meme",
          description:
            "Generates a meme by sending text to the Next.js backend.",
          inputSchema: {
            type: "object",
            properties: {
              noText: {
                type: "string",
                description:
                  "The text to display at the top of the meme (No text).",
              },
              yesText: {
                type: "string",
                description:
                  "The text to display at the bottom of the meme (Yes text).",
              },
            },
            required: ["noText", "yesText"],
          },
        },
      ],
    }));

    this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
      if (request.params.name === "generate_meme") {
        const { noText, yesText } = request.params.arguments as {
          noText: string;
          yesText: string;
        };

        try {
          const response = await fetch(
            "http://localhost:3000/api/generate-meme",
            {
              method: "POST",
              headers: {
                "Content-Type": "application/json",
              },
              body: JSON.stringify({ noText, yesText }),
            }
          );

          return {
            content: [
              {
                type: "text",
                text: "Meme generated successfully",
              },
            ],
          };
        } catch (error: any) {
          console.error("Error calling Next.js API:", error);
          return {
            content: [
              {
                type: "text",
                text: `Error generating meme: ${error.message}`,
              },
            ],
            isError: true,
          };
        }
      }
      throw new McpError(
        ErrorCode.MethodNotFound,
        `Unknown tool: ${request.params.name}`
      );
    });
  }

  async run() {
    const transport = new StdioServerTransport();
    await this.server.connect(transport);
    console.error("Meme MCP server running on stdio");
    console.log("mcp ok!");
  }
}

const server = new MemeServer();
server.run().catch(console.error);
Enter fullscreen mode Exit fullscreen mode

7️⃣ Build index.ts to index.js.↓

run npm build
Enter fullscreen mode Exit fullscreen mode

8️⃣ Set cline_mcp_settings.json for Cline and mcp.json for Cursor.↓

{
  "mcpServers": {
    "meme-mcp-server": {
      "command": "node",
      "args": ["path to index.js"]
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

How to use

1️⃣ npm run dev, and start the Next.js App, and access http://localhost:3000.

2️⃣ Ask your Cline or Cursor to generate a Meme.
For example,

Use "generate_meme" tool of "meme-mcp-server",
 and send "noText": “Before watching Meme Monday”
 and “yesText”: “After watching Meme Monday”.
Enter fullscreen mode Exit fullscreen mode

Image description

3️⃣ Or ask your Cline or Cursor to think one of the text instead of you.
For example,

Use "generate_meme" tool of "meme-mcp-server",
 and send "noText": “”
 and “yesText”: “After watching Meme Monday”. 
Think the noText part and fill in the text.
Enter fullscreen mode Exit fullscreen mode

Image description

4️⃣ Or ask your Cline or Cursor to think both texts instead of you.
For example,

Use "generate_meme" tool of "meme-mcp-server",
 and send "noText": “Before watching Meme Monday”
 and “yesText”: “After watching Meme Monday”. 
Think unique and humorous texts and replace noText and yesText.
Enter fullscreen mode Exit fullscreen mode

Image description

5️⃣ Yay! We can generate Memes from Cline and Cursor.🎉

Future improvements

1️⃣ It would be more fun if there are other templates.
For example↓
Image description
Example of text↓

Boy: Web Developer
Girl in right: Concentrate on Work
Girl in left: Watch Meme Monday.
Enter fullscreen mode Exit fullscreen mode

2️⃣ Making the Meme image by AI would also be fun.

Outro

Meme will bring us little joy and happiness in our daily lives.😊
Trivial things around us might be a good idea for a new Meme.💡

I hope you will learn something from this post, or maybe learn nothing but enjoy a little.
Thank you for reading.
Happy AI coding!🤖 Hi-Yah!🥷