Building Your Own Meme Generator with Model Context Protocol (MCP)
Model Context Protocol (MCP) has revolutionized how AI assistants interact with external tools and services. In this tutorial, I'll show you how to create a fun and practical Meme Generator MCP that works with AI assistants like Claude in Cursor or Cline.
What is MCP?
The Model Context Protocol (MCP) is a standard that allows AI assistants to interact with external tools, services, and data sources. By creating custom MCP servers, you can extend AI capabilities with specialized tools tailored to your needs.
Project Overview
Our Meme Generator MCP will have three main components:
- A Next.js web application that displays memes
- An MCP server that handles requests from AI assistants
- Configuration for AI tools like Cursor or Cline
Setting Up the Next.js Web App
First, let's create a Next.js project:
npx create-next-app@latest meme-generator
cd meme-generator
Now, let's create our main page in 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 Generator</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>
);
}
Next, we'll create an API route to handle meme generation in 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 },
});
}
Creating Meme Templates
You'll need two image templates:
-
template_no.png
- An image showing disappointment/rejection -
template_yes.png
- An image showing approval/happiness
Place these in the public
folder of your Next.js app.
Setting Up the MCP Server
Now, let's create our MCP server:
- Create a new directory for your MCP server:
mkdir meme-mcp-server
cd meme-mcp-server
- Initialize a Node.js project:
npm init -y
- Install the MCP SDK:
npm install @modelcontextprotocol/sdk
- Create a TypeScript configuration:
npm install typescript --save-dev
npx tsc --init
- Create an
index.ts
file:
#!/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);
- Build your TypeScript code:
npx tsc
Configuring Your AI Assistant
For Cursor
Create or edit ~/.cursor/mcp.json
:
{
"mcpServers": {
"meme-mcp-server": {
"command": "node",
"args": ["path/to/your/meme-mcp-server/index.js"]
}
}
}
For Cline
Create or edit ~/.config/cline/cline_mcp_settings.json
:
{
"mcpServers": {
"meme-mcp-server": {
"command": "node",
"args": ["path/to/your/meme-mcp-server/index.js"]
}
}
}
Using Your Meme Generator
- Start your Next.js app:
cd meme-generator
npm run dev
Open your browser to http://localhost:3000
In Cursor or Cline, you can now generate memes with commands like:
Use "generate_meme" tool of "meme-mcp-server",
and send "noText": "Coding without AI assistants"
and "yesText": "Coding with AI assistants".
Enhancing Your Meme Generator
Here are some ideas to take your meme generator to the next level:
- Add more templates - Create different meme formats by adding more template options
- Add AI-generated images - Integrate with image generation APIs to create custom meme backgrounds
- Add a gallery - Store generated memes and let users browse previously created ones
- Social sharing - Add buttons to share memes directly to social media
Conclusion
Building custom MCP tools lets you extend AI assistants with specialized capabilities. This meme generator is just the beginning - you can create MCP servers for virtually any task, from data analysis to workflow automation.
By mastering MCP development, you can create powerful, custom AI-powered tools that perfectly fit your specific needs and workflows.
What will you build next?
Top comments (0)