thumbnail-generator-mcp 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +44 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +276 -0
- package/dist/index.js.map +1 -0
- package/package.json +31 -0
package/README.md
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# YouTube Thumbnail Generator — MCP Server
|
|
2
|
+
|
|
3
|
+
Generate professional YouTube thumbnails directly inside Claude Desktop.
|
|
4
|
+
|
|
5
|
+
## Setup
|
|
6
|
+
|
|
7
|
+
1. **Install Node.js** — download from [nodejs.org](https://nodejs.org) (LTS version)
|
|
8
|
+
2. **Get a free Gemini API key** — [aistudio.google.com/app/apikey](https://aistudio.google.com/app/apikey)
|
|
9
|
+
3. **Add to Claude Desktop config** — open `~/Library/Application Support/Claude/claude_desktop_config.json` and add:
|
|
10
|
+
|
|
11
|
+
```json
|
|
12
|
+
{
|
|
13
|
+
"mcpServers": {
|
|
14
|
+
"thumbnail-generator": {
|
|
15
|
+
"command": "npx",
|
|
16
|
+
"args": ["-y", "thumbnail-generator-mcp"],
|
|
17
|
+
"env": {
|
|
18
|
+
"LICENSE_KEY": "YOUR-LICENSE-KEY-HERE",
|
|
19
|
+
"GEMINI_API_KEY": "your-gemini-key-here"
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
4. **Restart Claude Desktop**
|
|
27
|
+
5. Ask Claude: *"Make me a YouTube thumbnail with the text 'I MADE $10K' and a dramatic dark background"*
|
|
28
|
+
|
|
29
|
+
## Usage
|
|
30
|
+
|
|
31
|
+
Thumbnails are saved to your Desktop automatically.
|
|
32
|
+
|
|
33
|
+
**With a selfie photo:**
|
|
34
|
+
> "Make me a thumbnail. Here's my photo: [drag photo into chat]. Text: 'THIS CHANGED EVERYTHING'. Dark dramatic office background."
|
|
35
|
+
|
|
36
|
+
**Text-only (no photo):**
|
|
37
|
+
> "Generate a thumbnail. Subject: confident man in suit, shocked expression. Text: 'I ALMOST QUIT'. Background: city skyline at night."
|
|
38
|
+
|
|
39
|
+
**Multiple variations:**
|
|
40
|
+
> "Make 3 variations of my thumbnail so I can pick the best one."
|
|
41
|
+
|
|
42
|
+
## License
|
|
43
|
+
|
|
44
|
+
Activates on up to 2 devices. Contact support to transfer to a new device.
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
3
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
4
|
+
import { CallToolRequestSchema, ListToolsRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
|
|
5
|
+
import { GoogleGenerativeAI } from "@google/generative-ai";
|
|
6
|
+
import { machineIdSync } from "node-machine-id";
|
|
7
|
+
import * as fs from "fs";
|
|
8
|
+
import * as path from "path";
|
|
9
|
+
import * as os from "os";
|
|
10
|
+
// ─── Config ─────────────────────────────────────────────────────────────────
|
|
11
|
+
const LICENSE_KEY = (process.env.LICENSE_KEY ?? "").trim().toUpperCase();
|
|
12
|
+
const GEMINI_API_KEY = process.env.GEMINI_API_KEY ?? "";
|
|
13
|
+
const VALIDATE_URL = process.env.VALIDATE_URL ??
|
|
14
|
+
"https://thumbnail.automationhackers.net/api/licenses/validate";
|
|
15
|
+
const IMAGE_MODEL = "gemini-3-pro-image-preview";
|
|
16
|
+
let cachedProducts = null;
|
|
17
|
+
async function validateLicense() {
|
|
18
|
+
if (cachedProducts)
|
|
19
|
+
return cachedProducts;
|
|
20
|
+
let machineId;
|
|
21
|
+
try {
|
|
22
|
+
machineId = machineIdSync(true); // hashed, privacy-safe
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
machineId = `fallback-${os.hostname()}-${os.userInfo().username}`;
|
|
26
|
+
}
|
|
27
|
+
let res;
|
|
28
|
+
try {
|
|
29
|
+
res = await fetch(VALIDATE_URL, {
|
|
30
|
+
method: "POST",
|
|
31
|
+
headers: { "Content-Type": "application/json" },
|
|
32
|
+
body: JSON.stringify({ license_key: LICENSE_KEY, machine_id: machineId }),
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
catch (err) {
|
|
36
|
+
throw new Error(`Could not reach license server. Check your internet connection. (${err instanceof Error ? err.message : err})`);
|
|
37
|
+
}
|
|
38
|
+
const data = (await res.json());
|
|
39
|
+
if (!data.valid) {
|
|
40
|
+
const msg = data.message ??
|
|
41
|
+
(data.reason === "machine_limit"
|
|
42
|
+
? "License already activated on 2 devices. Contact support to transfer."
|
|
43
|
+
: data.reason === "revoked"
|
|
44
|
+
? "License revoked. Contact support."
|
|
45
|
+
: "Invalid license key. Check your LICENSE_KEY and try again.");
|
|
46
|
+
throw new Error(msg);
|
|
47
|
+
}
|
|
48
|
+
cachedProducts = data.products ?? ["front_end"];
|
|
49
|
+
return cachedProducts;
|
|
50
|
+
}
|
|
51
|
+
// ─── Prompt builders ─────────────────────────────────────────────────────────
|
|
52
|
+
function buildPhotoEditPrompt(opts) {
|
|
53
|
+
const { background, textOverlay, textPosition, textColor, outfitChange } = opts;
|
|
54
|
+
return `TASK: Transform this selfie into a professional YouTube thumbnail.
|
|
55
|
+
|
|
56
|
+
=== PRESERVE EXACTLY — DO NOT CHANGE THESE ===
|
|
57
|
+
- Face: exact facial structure, bone structure, skin tone, eye color, eyebrows, nose shape, mouth shape, jawline
|
|
58
|
+
- Hair: exact color, length, texture, style
|
|
59
|
+
- Expression: intensify the existing expression — do NOT change it to something neutral
|
|
60
|
+
- Any accessories already visible (glasses, earrings, etc.)
|
|
61
|
+
|
|
62
|
+
=== CHANGE ===
|
|
63
|
+
Background: ${background}
|
|
64
|
+
Lighting: cinematic, strong rim light, high contrast, dramatic — light source from top-front
|
|
65
|
+
Skin: smooth, professional retouching, keep natural skin tone
|
|
66
|
+
${outfitChange ? `Outfit: ${outfitChange}` : "Outfit: keep as-is, ensure it looks polished"}
|
|
67
|
+
|
|
68
|
+
=== ADD ===
|
|
69
|
+
Text overlay: "${textOverlay}" — massive bold block letters (Impact or similar), ${textColor} fill, thick black outline 4px, drop shadow, placed ${textPosition} of image
|
|
70
|
+
Composition: person takes up 60-70% of frame, slightly off-center to leave room for text
|
|
71
|
+
|
|
72
|
+
=== OUTPUT REQUIREMENTS ===
|
|
73
|
+
- Dimensions: 1280×720 (16:9)
|
|
74
|
+
- Style: hyper-realistic, vibrant colors, NOT illustrated or painted
|
|
75
|
+
- Quality: ultra-sharp, professional YouTube thumbnail quality
|
|
76
|
+
- The person's face must be the focal point — do NOT obscure it with text`;
|
|
77
|
+
}
|
|
78
|
+
function buildTextOnlyPrompt(opts) {
|
|
79
|
+
const { subject, background, textOverlay, textPosition, textColor } = opts;
|
|
80
|
+
return `Create a professional YouTube thumbnail (1280×720, 16:9).
|
|
81
|
+
|
|
82
|
+
Subject: ${subject}
|
|
83
|
+
Background: ${background}
|
|
84
|
+
Style: cinematic, vibrant, high contrast, dramatic lighting
|
|
85
|
+
|
|
86
|
+
Text overlay: "${textOverlay}" — massive bold block letters (Impact or similar), ${textColor} fill, thick black outline 4px, drop shadow, placed ${textPosition} of image
|
|
87
|
+
|
|
88
|
+
Requirements:
|
|
89
|
+
- Hyper-realistic, NOT illustrated or painted
|
|
90
|
+
- Ultra-sharp, professional YouTube thumbnail quality
|
|
91
|
+
- Text must be large and immediately readable at small sizes
|
|
92
|
+
- Vibrant, eye-catching colors`;
|
|
93
|
+
}
|
|
94
|
+
// ─── Gemini image call ────────────────────────────────────────────────────────
|
|
95
|
+
async function generateImage(prompt, imageBase64, imageMimeType) {
|
|
96
|
+
const genAI = new GoogleGenerativeAI(GEMINI_API_KEY);
|
|
97
|
+
const model = genAI.getGenerativeModel({
|
|
98
|
+
model: IMAGE_MODEL,
|
|
99
|
+
generationConfig: {
|
|
100
|
+
// @ts-expect-error — responseModalities not yet in types
|
|
101
|
+
responseModalities: ["Text", "Image"],
|
|
102
|
+
},
|
|
103
|
+
});
|
|
104
|
+
const parts = [];
|
|
105
|
+
if (imageBase64 && imageMimeType) {
|
|
106
|
+
parts.push({
|
|
107
|
+
inlineData: { data: imageBase64, mimeType: imageMimeType },
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
parts.push({ text: prompt });
|
|
111
|
+
const result = await model.generateContent(parts);
|
|
112
|
+
const response = result.response;
|
|
113
|
+
for (const part of response.candidates?.[0]?.content?.parts ?? []) {
|
|
114
|
+
if (part.inlineData?.data) {
|
|
115
|
+
return {
|
|
116
|
+
base64: part.inlineData.data,
|
|
117
|
+
mimeType: part.inlineData.mimeType ?? "image/png",
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
throw new Error("Gemini returned no image. Check your API key and billing.");
|
|
122
|
+
}
|
|
123
|
+
// ─── Save to desktop ──────────────────────────────────────────────────────────
|
|
124
|
+
function saveToDesktop(base64, mimeType) {
|
|
125
|
+
const ext = mimeType.split("/")[1] ?? "png";
|
|
126
|
+
const timestamp = new Date()
|
|
127
|
+
.toISOString()
|
|
128
|
+
.replace(/[:.]/g, "-")
|
|
129
|
+
.slice(0, 19);
|
|
130
|
+
const filename = `thumbnail-${timestamp}.${ext}`;
|
|
131
|
+
const desktop = path.join(os.homedir(), "Desktop");
|
|
132
|
+
const outPath = path.join(desktop, filename);
|
|
133
|
+
fs.writeFileSync(outPath, Buffer.from(base64, "base64"));
|
|
134
|
+
return outPath;
|
|
135
|
+
}
|
|
136
|
+
// ─── MCP Server ───────────────────────────────────────────────────────────────
|
|
137
|
+
const server = new Server({ name: "thumbnail-generator", version: "1.0.0" }, { capabilities: { tools: {} } });
|
|
138
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
139
|
+
tools: [
|
|
140
|
+
{
|
|
141
|
+
name: "generate_thumbnail",
|
|
142
|
+
description: "Generate a YouTube thumbnail (1280×720). Optionally provide a selfie photo to edit. Returns the file path of the saved image on the Desktop.",
|
|
143
|
+
inputSchema: {
|
|
144
|
+
type: "object",
|
|
145
|
+
properties: {
|
|
146
|
+
background: {
|
|
147
|
+
type: "string",
|
|
148
|
+
description: "Describe the background scene (e.g. 'dark dramatic office with city lights', 'bright outdoor park', 'stock market charts on screens behind me')",
|
|
149
|
+
},
|
|
150
|
+
text_overlay: {
|
|
151
|
+
type: "string",
|
|
152
|
+
description: "The text to display on the thumbnail in bold (e.g. 'I LOST EVERYTHING', 'THIS CHANGED MY LIFE', '$10K/MONTH')",
|
|
153
|
+
},
|
|
154
|
+
text_position: {
|
|
155
|
+
type: "string",
|
|
156
|
+
enum: ["left", "right", "top", "bottom", "top-left", "top-right", "bottom-left", "bottom-right"],
|
|
157
|
+
description: "Where to place the text overlay",
|
|
158
|
+
default: "left",
|
|
159
|
+
},
|
|
160
|
+
text_color: {
|
|
161
|
+
type: "string",
|
|
162
|
+
description: "Text color (e.g. 'white', 'yellow', 'red')",
|
|
163
|
+
default: "white",
|
|
164
|
+
},
|
|
165
|
+
photo_path: {
|
|
166
|
+
type: "string",
|
|
167
|
+
description: "Absolute path to a selfie/photo to use as the base image for editing. If omitted, generates from text description only.",
|
|
168
|
+
},
|
|
169
|
+
subject_description: {
|
|
170
|
+
type: "string",
|
|
171
|
+
description: "Required only when photo_path is omitted. Describe the person or subject to generate (e.g. 'professional man in his 30s, dark suit, surprised expression').",
|
|
172
|
+
},
|
|
173
|
+
outfit_change: {
|
|
174
|
+
type: "string",
|
|
175
|
+
description: "Optional. Describe an outfit change (e.g. 'dark navy suit, no tie'). Only applies when photo_path is provided.",
|
|
176
|
+
},
|
|
177
|
+
variations: {
|
|
178
|
+
type: "number",
|
|
179
|
+
description: "Number of variations to generate (1–4). Default 1.",
|
|
180
|
+
minimum: 1,
|
|
181
|
+
maximum: 4,
|
|
182
|
+
default: 1,
|
|
183
|
+
},
|
|
184
|
+
},
|
|
185
|
+
required: ["background", "text_overlay"],
|
|
186
|
+
},
|
|
187
|
+
},
|
|
188
|
+
],
|
|
189
|
+
}));
|
|
190
|
+
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
191
|
+
if (request.params.name !== "generate_thumbnail") {
|
|
192
|
+
return { content: [{ type: "text", text: `Unknown tool: ${request.params.name}` }], isError: true };
|
|
193
|
+
}
|
|
194
|
+
// Validate license (cached after first call)
|
|
195
|
+
try {
|
|
196
|
+
await validateLicense();
|
|
197
|
+
}
|
|
198
|
+
catch (err) {
|
|
199
|
+
return {
|
|
200
|
+
content: [{ type: "text", text: `License error: ${err instanceof Error ? err.message : err}` }],
|
|
201
|
+
isError: true,
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
const args = request.params.arguments;
|
|
205
|
+
const { background, text_overlay, text_position = "left", text_color = "white", photo_path, subject_description, outfit_change, variations = 1, } = args;
|
|
206
|
+
if (!photo_path && !subject_description) {
|
|
207
|
+
return {
|
|
208
|
+
content: [{ type: "text", text: "Provide either photo_path (selfie) or subject_description." }],
|
|
209
|
+
isError: true,
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
const savedPaths = [];
|
|
213
|
+
const count = Math.min(Math.max(Math.floor(variations), 1), 4);
|
|
214
|
+
for (let i = 0; i < count; i++) {
|
|
215
|
+
let imageBase64;
|
|
216
|
+
let imageMimeType;
|
|
217
|
+
if (photo_path) {
|
|
218
|
+
try {
|
|
219
|
+
const buf = fs.readFileSync(photo_path);
|
|
220
|
+
imageBase64 = buf.toString("base64");
|
|
221
|
+
const ext = path.extname(photo_path).toLowerCase().replace(".", "");
|
|
222
|
+
imageMimeType = ext === "jpg" ? "image/jpeg" : ext === "png" ? "image/png" : "image/jpeg";
|
|
223
|
+
}
|
|
224
|
+
catch (err) {
|
|
225
|
+
return {
|
|
226
|
+
content: [{ type: "text", text: `Could not read photo: ${err instanceof Error ? err.message : err}` }],
|
|
227
|
+
isError: true,
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
const prompt = photo_path
|
|
232
|
+
? buildPhotoEditPrompt({ background, textOverlay: text_overlay, textPosition: text_position, textColor: text_color, outfitChange: outfit_change })
|
|
233
|
+
: buildTextOnlyPrompt({ subject: subject_description, background, textOverlay: text_overlay, textPosition: text_position, textColor: text_color });
|
|
234
|
+
let result;
|
|
235
|
+
try {
|
|
236
|
+
result = await generateImage(prompt, imageBase64, imageMimeType);
|
|
237
|
+
}
|
|
238
|
+
catch (err) {
|
|
239
|
+
return {
|
|
240
|
+
content: [{ type: "text", text: `Gemini error: ${err instanceof Error ? err.message : err}` }],
|
|
241
|
+
isError: true,
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
const savedPath = saveToDesktop(result.base64, result.mimeType);
|
|
245
|
+
savedPaths.push(savedPath);
|
|
246
|
+
}
|
|
247
|
+
const pathList = savedPaths.map((p) => `• ${p}`).join("\n");
|
|
248
|
+
return {
|
|
249
|
+
content: [
|
|
250
|
+
{
|
|
251
|
+
type: "text",
|
|
252
|
+
text: `Thumbnail${savedPaths.length > 1 ? "s" : ""} saved to your Desktop:\n${pathList}\n\nOpen the file${savedPaths.length > 1 ? "s" : ""} to review. Ask me to regenerate with different text, background, or position if needed.`,
|
|
253
|
+
},
|
|
254
|
+
],
|
|
255
|
+
};
|
|
256
|
+
});
|
|
257
|
+
// ─── Startup ─────────────────────────────────────────────────────────────────
|
|
258
|
+
async function main() {
|
|
259
|
+
if (!LICENSE_KEY) {
|
|
260
|
+
console.error("ERROR: LICENSE_KEY environment variable is not set.");
|
|
261
|
+
console.error("Add it to your Claude Desktop config under the thumbnail-generator mcpServer env block.");
|
|
262
|
+
process.exit(1);
|
|
263
|
+
}
|
|
264
|
+
if (!GEMINI_API_KEY) {
|
|
265
|
+
console.error("ERROR: GEMINI_API_KEY environment variable is not set.");
|
|
266
|
+
console.error("Get a free key at https://aistudio.google.com/app/apikey");
|
|
267
|
+
process.exit(1);
|
|
268
|
+
}
|
|
269
|
+
const transport = new StdioServerTransport();
|
|
270
|
+
await server.connect(transport);
|
|
271
|
+
}
|
|
272
|
+
main().catch((err) => {
|
|
273
|
+
console.error("Fatal:", err instanceof Error ? err.message : err);
|
|
274
|
+
process.exit(1);
|
|
275
|
+
});
|
|
276
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "thumbnail-generator-mcp",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "YouTube thumbnail generator MCP server for Claude Desktop",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"bin": {
|
|
8
|
+
"thumbnail-generator-mcp": "dist/index.js"
|
|
9
|
+
},
|
|
10
|
+
"scripts": {
|
|
11
|
+
"build": "tsc",
|
|
12
|
+
"dev": "tsc --watch",
|
|
13
|
+
"start": "node dist/index.js"
|
|
14
|
+
},
|
|
15
|
+
"dependencies": {
|
|
16
|
+
"@google/generative-ai": "^0.21.0",
|
|
17
|
+
"@modelcontextprotocol/sdk": "^1.0.0",
|
|
18
|
+
"node-machine-id": "^1.1.12"
|
|
19
|
+
},
|
|
20
|
+
"devDependencies": {
|
|
21
|
+
"@types/node": "^22.0.0",
|
|
22
|
+
"typescript": "^5.6.0"
|
|
23
|
+
},
|
|
24
|
+
"engines": {
|
|
25
|
+
"node": ">=18"
|
|
26
|
+
},
|
|
27
|
+
"files": [
|
|
28
|
+
"dist"
|
|
29
|
+
],
|
|
30
|
+
"license": "SEE LICENSE IN LICENSE"
|
|
31
|
+
}
|