meigen 0.1.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.
Files changed (83) hide show
  1. package/README.md +242 -0
  2. package/README.zh-CN.md +242 -0
  3. package/bin/meigen-mcp.js +2 -0
  4. package/data/trending-prompts.json +26737 -0
  5. package/dist/config.d.ts +24 -0
  6. package/dist/config.d.ts.map +1 -0
  7. package/dist/config.js +71 -0
  8. package/dist/config.js.map +1 -0
  9. package/dist/index.d.ts +6 -0
  10. package/dist/index.d.ts.map +1 -0
  11. package/dist/index.js +18 -0
  12. package/dist/index.js.map +1 -0
  13. package/dist/lib/meigen-api.d.ts +64 -0
  14. package/dist/lib/meigen-api.d.ts.map +1 -0
  15. package/dist/lib/meigen-api.js +118 -0
  16. package/dist/lib/meigen-api.js.map +1 -0
  17. package/dist/lib/prompt-library.d.ts +44 -0
  18. package/dist/lib/prompt-library.d.ts.map +1 -0
  19. package/dist/lib/prompt-library.js +130 -0
  20. package/dist/lib/prompt-library.js.map +1 -0
  21. package/dist/lib/prompts.d.ts +21 -0
  22. package/dist/lib/prompts.d.ts.map +1 -0
  23. package/dist/lib/prompts.js +116 -0
  24. package/dist/lib/prompts.js.map +1 -0
  25. package/dist/lib/providers/comfyui.d.ts +82 -0
  26. package/dist/lib/providers/comfyui.d.ts.map +1 -0
  27. package/dist/lib/providers/comfyui.js +436 -0
  28. package/dist/lib/providers/comfyui.js.map +1 -0
  29. package/dist/lib/providers/gemini.d.ts +13 -0
  30. package/dist/lib/providers/gemini.d.ts.map +1 -0
  31. package/dist/lib/providers/gemini.js +63 -0
  32. package/dist/lib/providers/gemini.js.map +1 -0
  33. package/dist/lib/providers/openai.d.ts +14 -0
  34. package/dist/lib/providers/openai.d.ts.map +1 -0
  35. package/dist/lib/providers/openai.js +75 -0
  36. package/dist/lib/providers/openai.js.map +1 -0
  37. package/dist/lib/providers/types.d.ts +22 -0
  38. package/dist/lib/providers/types.d.ts.map +1 -0
  39. package/dist/lib/providers/types.js +7 -0
  40. package/dist/lib/providers/types.js.map +1 -0
  41. package/dist/lib/semaphore.d.ts +13 -0
  42. package/dist/lib/semaphore.d.ts.map +1 -0
  43. package/dist/lib/semaphore.js +32 -0
  44. package/dist/lib/semaphore.js.map +1 -0
  45. package/dist/lib/upload.d.ts +17 -0
  46. package/dist/lib/upload.d.ts.map +1 -0
  47. package/dist/lib/upload.js +135 -0
  48. package/dist/lib/upload.js.map +1 -0
  49. package/dist/server.d.ts +7 -0
  50. package/dist/server.d.ts.map +1 -0
  51. package/dist/server.js +163 -0
  52. package/dist/server.js.map +1 -0
  53. package/dist/tools/comfyui-workflow.d.ts +17 -0
  54. package/dist/tools/comfyui-workflow.d.ts.map +1 -0
  55. package/dist/tools/comfyui-workflow.js +230 -0
  56. package/dist/tools/comfyui-workflow.js.map +1 -0
  57. package/dist/tools/enhance-prompt.d.ts +12 -0
  58. package/dist/tools/enhance-prompt.d.ts.map +1 -0
  59. package/dist/tools/enhance-prompt.js +27 -0
  60. package/dist/tools/enhance-prompt.js.map +1 -0
  61. package/dist/tools/generate-image.d.ts +23 -0
  62. package/dist/tools/generate-image.d.ts.map +1 -0
  63. package/dist/tools/generate-image.js +266 -0
  64. package/dist/tools/generate-image.js.map +1 -0
  65. package/dist/tools/get-inspiration.d.ts +12 -0
  66. package/dist/tools/get-inspiration.d.ts.map +1 -0
  67. package/dist/tools/get-inspiration.js +111 -0
  68. package/dist/tools/get-inspiration.js.map +1 -0
  69. package/dist/tools/list-models.d.ts +13 -0
  70. package/dist/tools/list-models.d.ts.map +1 -0
  71. package/dist/tools/list-models.js +104 -0
  72. package/dist/tools/list-models.js.map +1 -0
  73. package/dist/tools/search-gallery.d.ts +15 -0
  74. package/dist/tools/search-gallery.d.ts.map +1 -0
  75. package/dist/tools/search-gallery.js +78 -0
  76. package/dist/tools/search-gallery.js.map +1 -0
  77. package/dist/tools/upload-reference-image.d.ts +13 -0
  78. package/dist/tools/upload-reference-image.d.ts.map +1 -0
  79. package/dist/tools/upload-reference-image.js +69 -0
  80. package/dist/tools/upload-reference-image.js.map +1 -0
  81. package/package.json +45 -0
  82. package/skills/setup/SKILL.md +324 -0
  83. package/skills/visual-creative/SKILL.md +185 -0
@@ -0,0 +1,78 @@
1
+ "use strict";
2
+ /**
3
+ * search_gallery Tool — free, no auth required
4
+ * Searches the local curated prompt library (1300+ high-quality prompts)
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.searchGallerySchema = void 0;
8
+ exports.registerSearchGallery = registerSearchGallery;
9
+ const zod_1 = require("zod");
10
+ const prompt_library_js_1 = require("../lib/prompt-library.js");
11
+ exports.searchGallerySchema = {
12
+ query: zod_1.z.string().optional()
13
+ .describe('Search keywords (e.g., "cyberpunk", "product photo", "portrait"). Leave empty to browse by category or get random picks.'),
14
+ category: zod_1.z.enum(['3D', 'App', 'Food', 'Girl', 'JSON', 'Other', 'Photograph', 'Product']).optional()
15
+ .describe('Filter by category. Available: 3D, App, Food, Girl, JSON, Other, Photograph, Product'),
16
+ limit: zod_1.z.number().min(1).max(20).optional().default(5)
17
+ .describe('Number of results (1-20, default 5)'),
18
+ offset: zod_1.z.number().min(0).optional().default(0)
19
+ .describe('Pagination offset'),
20
+ sortBy: zod_1.z.enum(['rank', 'likes', 'views', 'date']).optional().default('rank')
21
+ .describe('Sort order when browsing without search query (default: rank)'),
22
+ };
23
+ function registerSearchGallery(server) {
24
+ server.tool('search_gallery', 'Search 1300+ curated AI image prompts with preview images. Results include image URLs — render them as markdown images (![](url)) so users can visually browse and pick styles. Use when users need inspiration, want to explore styles, or say "generate an image" without a specific idea.', exports.searchGallerySchema, { readOnlyHint: true }, async ({ query, category, limit, offset, sortBy }) => {
25
+ // No search criteria — return random picks
26
+ if (!query && !category && offset === 0) {
27
+ const random = (0, prompt_library_js_1.getRandomPrompts)(limit);
28
+ const stats = (0, prompt_library_js_1.getLibraryStats)();
29
+ const header = `Curated Prompt Library: ${stats.total} trending prompts\nCategories: ${Object.entries(stats.categories).map(([k, v]) => `${k} (${v})`).join(', ')}\n\nHere are ${limit} random picks — show the preview images to the user:\n`;
30
+ return {
31
+ content: [{
32
+ type: 'text',
33
+ text: header + formatResults(random),
34
+ }],
35
+ };
36
+ }
37
+ const results = (0, prompt_library_js_1.searchPrompts)({ query, category, limit, offset, sortBy });
38
+ if (results.length === 0) {
39
+ const suggestion = category
40
+ ? `No results for "${query || ''}" in category "${category}". Try a different keyword or remove the category filter.`
41
+ : `No results for "${query}". Try broader keywords like "portrait", "landscape", "product", "anime".`;
42
+ return {
43
+ content: [{
44
+ type: 'text',
45
+ text: suggestion,
46
+ }],
47
+ };
48
+ }
49
+ const searchDesc = [
50
+ query ? `"${query}"` : null,
51
+ category ? `category: ${category}` : null,
52
+ ].filter(Boolean).join(', ');
53
+ const text = `Found ${results.length} results${searchDesc ? ` for ${searchDesc}` : ''}:\n\n${formatResults(results)}\n\nShow the preview images above to the user so they can visually browse. Use get_inspiration(imageId) to get the full prompt and all images for any entry the user likes.`;
54
+ return {
55
+ content: [{
56
+ type: 'text',
57
+ text,
58
+ }],
59
+ };
60
+ });
61
+ }
62
+ function formatResults(results) {
63
+ return results.map((item, i) => {
64
+ // Truncate prompt to first 150 chars for preview
65
+ const promptPreview = item.prompt.length > 150
66
+ ? item.prompt.slice(0, 150).replace(/\n/g, ' ') + '...'
67
+ : item.prompt.replace(/\n/g, ' ');
68
+ const parts = [
69
+ `${i + 1}. **#${item.rank}** by ${item.author_name} — ${item.categories.join(', ')}`,
70
+ ` ![Preview #${item.rank}](${item.image})`,
71
+ ` Prompt: ${promptPreview}`,
72
+ ` Stats: ${item.likes} likes, ${item.views.toLocaleString()} views`,
73
+ ` ID: ${item.id}`,
74
+ ];
75
+ return parts.join('\n');
76
+ }).join('\n\n');
77
+ }
78
+ //# sourceMappingURL=search-gallery.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search-gallery.js","sourceRoot":"","sources":["../../src/tools/search-gallery.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * upload_reference_image Tool
3
+ * Compresses a local image and uploads it to R2, returning a public URL
4
+ * for use as referenceImages in generate_image.
5
+ */
6
+ import { z } from 'zod';
7
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
8
+ import type { MeiGenConfig } from '../config.js';
9
+ export declare const uploadReferenceImageSchema: {
10
+ filePath: z.ZodString;
11
+ };
12
+ export declare function registerUploadReferenceImage(server: McpServer, config: MeiGenConfig): void;
13
+ //# sourceMappingURL=upload-reference-image.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"upload-reference-image.d.ts","sourceRoot":"","sources":["../../src/tools/upload-reference-image.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAA;AACxE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AAGhD,eAAO,MAAM,0BAA0B;;CAGtC,CAAA;AAED,wBAAgB,4BAA4B,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,YAAY,QAoDnF"}
@@ -0,0 +1,69 @@
1
+ "use strict";
2
+ /**
3
+ * upload_reference_image Tool
4
+ * Compresses a local image and uploads it to R2, returning a public URL
5
+ * for use as referenceImages in generate_image.
6
+ */
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ exports.uploadReferenceImageSchema = void 0;
9
+ exports.registerUploadReferenceImage = registerUploadReferenceImage;
10
+ const zod_1 = require("zod");
11
+ const fs_1 = require("fs");
12
+ const upload_js_1 = require("../lib/upload.js");
13
+ exports.uploadReferenceImageSchema = {
14
+ filePath: zod_1.z.string()
15
+ .describe('Absolute path to a local image file (JPEG, PNG, WebP, or GIF). The image will be automatically compressed if needed and uploaded for use as a reference image in generate_image.'),
16
+ };
17
+ function registerUploadReferenceImage(server, config) {
18
+ server.tool('upload_reference_image', 'Upload a local image for use as a reference in generate_image. Compresses large images (max 2MB, max 2048px) and returns a public URL. Call this when the user wants to use a local file as a reference image.', exports.uploadReferenceImageSchema, { readOnlyHint: false }, async ({ filePath }) => {
19
+ // Validate file exists
20
+ if (!(0, fs_1.existsSync)(filePath)) {
21
+ return {
22
+ content: [{
23
+ type: 'text',
24
+ text: `File not found: ${filePath}`,
25
+ }],
26
+ isError: true,
27
+ };
28
+ }
29
+ try {
30
+ const result = await (0, upload_js_1.processAndUploadImage)(filePath, config);
31
+ const compressed = result.originalSize !== result.compressedSize;
32
+ const sizeInfo = compressed
33
+ ? `Compressed: ${formatSize(result.originalSize)} → ${formatSize(result.compressedSize)}`
34
+ : `Size: ${formatSize(result.originalSize)} (no compression needed)`;
35
+ return {
36
+ content: [{
37
+ type: 'text',
38
+ text: [
39
+ `Reference image uploaded successfully.`,
40
+ ``,
41
+ `URL: ${result.publicUrl}`,
42
+ sizeInfo,
43
+ ``,
44
+ `Use this URL in generate_image's referenceImages parameter:`,
45
+ `generate_image(prompt="...", referenceImages=["${result.publicUrl}"])`,
46
+ ].join('\n'),
47
+ }],
48
+ };
49
+ }
50
+ catch (error) {
51
+ const message = error instanceof Error ? error.message : String(error);
52
+ return {
53
+ content: [{
54
+ type: 'text',
55
+ text: `Failed to upload reference image: ${message}`,
56
+ }],
57
+ isError: true,
58
+ };
59
+ }
60
+ });
61
+ }
62
+ function formatSize(bytes) {
63
+ if (bytes < 1024)
64
+ return `${bytes}B`;
65
+ if (bytes < 1024 * 1024)
66
+ return `${(bytes / 1024).toFixed(1)}KB`;
67
+ return `${(bytes / (1024 * 1024)).toFixed(1)}MB`;
68
+ }
69
+ //# sourceMappingURL=upload-reference-image.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"upload-reference-image.js","sourceRoot":"","sources":["../../src/tools/upload-reference-image.ts"],"names":[],"mappings":";AAAA;;;;GAIG;;;AAaH,oEAoDC;AA/DD,6BAAuB;AACvB,2BAA+B;AAG/B,gDAAwD;AAE3C,QAAA,0BAA0B,GAAG;IACxC,QAAQ,EAAE,OAAC,CAAC,MAAM,EAAE;SACjB,QAAQ,CAAC,kLAAkL,CAAC;CAChM,CAAA;AAED,SAAgB,4BAA4B,CAAC,MAAiB,EAAE,MAAoB;IAClF,MAAM,CAAC,IAAI,CACT,wBAAwB,EACxB,gNAAgN,EAChN,kCAA0B,EAC1B,EAAE,YAAY,EAAE,KAAK,EAAE,EACvB,KAAK,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE;QACrB,uBAAuB;QACvB,IAAI,CAAC,IAAA,eAAU,EAAC,QAAQ,CAAC,EAAE,CAAC;YAC1B,OAAO;gBACL,OAAO,EAAE,CAAC;wBACR,IAAI,EAAE,MAAe;wBACrB,IAAI,EAAE,mBAAmB,QAAQ,EAAE;qBACpC,CAAC;gBACF,OAAO,EAAE,IAAI;aACd,CAAA;QACH,CAAC;QAED,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,IAAA,iCAAqB,EAAC,QAAQ,EAAE,MAAM,CAAC,CAAA;YAE5D,MAAM,UAAU,GAAG,MAAM,CAAC,YAAY,KAAK,MAAM,CAAC,cAAc,CAAA;YAChE,MAAM,QAAQ,GAAG,UAAU;gBACzB,CAAC,CAAC,eAAe,UAAU,CAAC,MAAM,CAAC,YAAY,CAAC,MAAM,UAAU,CAAC,MAAM,CAAC,cAAc,CAAC,EAAE;gBACzF,CAAC,CAAC,SAAS,UAAU,CAAC,MAAM,CAAC,YAAY,CAAC,0BAA0B,CAAA;YAEtE,OAAO;gBACL,OAAO,EAAE,CAAC;wBACR,IAAI,EAAE,MAAe;wBACrB,IAAI,EAAE;4BACJ,wCAAwC;4BACxC,EAAE;4BACF,QAAQ,MAAM,CAAC,SAAS,EAAE;4BAC1B,QAAQ;4BACR,EAAE;4BACF,6DAA6D;4BAC7D,kDAAkD,MAAM,CAAC,SAAS,KAAK;yBACxE,CAAC,IAAI,CAAC,IAAI,CAAC;qBACb,CAAC;aACH,CAAA;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;YACtE,OAAO;gBACL,OAAO,EAAE,CAAC;wBACR,IAAI,EAAE,MAAe;wBACrB,IAAI,EAAE,qCAAqC,OAAO,EAAE;qBACrD,CAAC;gBACF,OAAO,EAAE,IAAI;aACd,CAAA;QACH,CAAC;IACH,CAAC,CACF,CAAA;AACH,CAAC;AAED,SAAS,UAAU,CAAC,KAAa;IAC/B,IAAI,KAAK,GAAG,IAAI;QAAE,OAAO,GAAG,KAAK,GAAG,CAAA;IACpC,IAAI,KAAK,GAAG,IAAI,GAAG,IAAI;QAAE,OAAO,GAAG,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAA;IAChE,OAAO,GAAG,CAAC,KAAK,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAA;AAClD,CAAC"}
package/package.json ADDED
@@ -0,0 +1,45 @@
1
+ {
2
+ "name": "meigen",
3
+ "version": "0.1.0",
4
+ "description": "Visual creative expert plugin — search inspiration, enhance prompts, and generate AI images with intelligent workflow orchestration",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "bin": {
8
+ "meigen": "bin/meigen-mcp.js",
9
+ "meigen-mcp": "bin/meigen-mcp.js"
10
+ },
11
+ "files": [
12
+ "bin/",
13
+ "dist/",
14
+ "data/",
15
+ "skills/"
16
+ ],
17
+ "scripts": {
18
+ "build": "tsc",
19
+ "dev": "tsx src/index.ts",
20
+ "typecheck": "tsc --noEmit"
21
+ },
22
+ "keywords": [
23
+ "mcp",
24
+ "ai",
25
+ "image-generation",
26
+ "claude",
27
+ "meigen",
28
+ "prompt-engineering"
29
+ ],
30
+ "license": "MIT",
31
+ "engines": {
32
+ "node": ">=18.0.0"
33
+ },
34
+ "dependencies": {
35
+ "@modelcontextprotocol/sdk": "^1.12.0",
36
+ "sharp": "^0.34.5",
37
+ "zod": "^3.25.0"
38
+ },
39
+ "devDependencies": {
40
+ "@types/node": "^20.0.0",
41
+ "@types/sharp": "^0.31.1",
42
+ "tsx": "^4.0.0",
43
+ "typescript": "^5.0.0"
44
+ }
45
+ }
@@ -0,0 +1,324 @@
1
+ ---
2
+ name: setup
3
+ description: >-
4
+ Configure MeiGen plugin provider and API keys. Use this when the user runs
5
+ /meigen:setup, asks to "configure meigen", "set up image generation",
6
+ "add API key", or needs help configuring the plugin.
7
+ disable-model-invocation: true
8
+ ---
9
+
10
+ # MeiGen Plugin Setup
11
+
12
+ You are guiding the user through configuring the MeiGen plugin for image generation. Follow this flow step by step.
13
+
14
+ ## Step 1: Welcome
15
+
16
+ First, check if a config file already exists:
17
+
18
+ ```bash
19
+ cat ~/.config/meigen/config.json 2>/dev/null
20
+ ```
21
+
22
+ Also check for existing ComfyUI workflows:
23
+
24
+ ```bash
25
+ ls ~/.config/meigen/workflows/*.json 2>/dev/null
26
+ ```
27
+
28
+ If config exists, show the current configuration (mask API keys: show first 10 chars + "...") and any saved workflows. Ask if they want to reconfigure.
29
+
30
+ If no config exists, present this introduction:
31
+
32
+ > **MeiGen Plugin Configuration**
33
+ >
34
+ > This is optional. Without configuration, you can still use free features:
35
+ > - Search gallery for inspiration and prompts
36
+ > - Enhance simple ideas into professional prompts
37
+ > - Browse available AI models
38
+ >
39
+ > Configuring a provider unlocks **image generation**.
40
+
41
+ Then proceed to Step 2.
42
+
43
+ ## Step 2: Choose Provider
44
+
45
+ Present these options to the user:
46
+
47
+ ### Option A: MeiGen Platform (Recommended)
48
+
49
+ - Supports **Nanobanana Pro**, **Seedream 4.5**, **Midjourney Niji7** and more
50
+ - Free daily credits included
51
+ - Reference image support for style transfer
52
+ - No additional accounts needed — just get a token from meigen.ai
53
+
54
+ ### Option B: ComfyUI (Local)
55
+
56
+ - Use your **local ComfyUI** installation for image generation
57
+ - Full control over models, samplers, and workflow settings
58
+ - No cloud API needed — runs entirely on your machine
59
+ - Import your own workflow from ComfyUI
60
+
61
+ ### Option C: Custom OpenAI-Compatible API
62
+
63
+ - Use your own **OpenAI**, **Together AI**, **Fireworks AI**, or any OpenAI-compatible service
64
+ - Bring your own API key and billing
65
+ - Supports any model that uses the OpenAI `/v1/images/generations` endpoint
66
+
67
+ ### Option D: Import from curl Example
68
+
69
+ - Already have a working curl command from your API provider's docs? Paste it directly!
70
+ - We'll automatically extract the API key, base URL, and model name
71
+
72
+ ### Option E: Skip image generation for now
73
+
74
+ - Free features still available (inspiration search, prompt enhancement, model listing)
75
+ - You can run `/meigen:setup` anytime later to enable image generation
76
+
77
+ If user chooses **Skip**, say goodbye and exit. Otherwise continue to the appropriate Step 3.
78
+
79
+ ## Step 3A: MeiGen Platform Setup
80
+
81
+ Ask the user:
82
+
83
+ > Do you already have a MeiGen API token, or do you need to create one?
84
+
85
+ ### If they need to create one:
86
+
87
+ Provide these instructions:
88
+
89
+ 1. Go to **https://www.meigen.ai**
90
+ 2. Sign in or create an account
91
+ 3. Navigate to **Settings** (click your avatar) → **API Keys**
92
+ 4. Click **Create API Key**, give it a name
93
+ 5. Copy the token (starts with `meigen_sk_`)
94
+
95
+ Then ask them to paste the token.
96
+
97
+ ### If they already have one:
98
+
99
+ Ask them to paste their `meigen_sk_...` token.
100
+
101
+ ### Validate the token:
102
+
103
+ - Must start with `meigen_sk_`
104
+ - Must be at least 30 characters long
105
+
106
+ If valid, proceed to **Step 4** with this config:
107
+
108
+ ```json
109
+ {
110
+ "meigenApiToken": "<the token>"
111
+ }
112
+ ```
113
+
114
+ ## Step 3B: ComfyUI (Local) Setup
115
+
116
+ ### 3B-1: Check Connection
117
+
118
+ Ask the user for their ComfyUI server URL:
119
+
120
+ > What is your ComfyUI server URL? (default: `http://localhost:8188`)
121
+
122
+ Test the connection:
123
+
124
+ ```bash
125
+ curl -s <URL>/system_stats | head -c 200
126
+ ```
127
+
128
+ - **Success**: Show confirmation and continue to 3B-2
129
+ - **Failure**: Tell the user:
130
+ > Cannot connect to ComfyUI at `<URL>`. Please make sure:
131
+ > 1. ComfyUI is running (start it with `python main.py` or your launcher)
132
+ > 2. The URL and port are correct
133
+ > 3. No firewall is blocking the connection
134
+
135
+ ### 3B-2: Import Workflow
136
+
137
+ Explain the workflow export process to the user:
138
+
139
+ > To use ComfyUI with this plugin, you need to export a workflow in **API format**:
140
+ >
141
+ > 1. Open ComfyUI in your browser (usually `http://localhost:8188`)
142
+ > 2. Load or create your preferred workflow
143
+ > 3. Click **⚙️ Settings** → enable **"Enable Dev mode options"**
144
+ > 4. Click the **"Save (API Format)"** button that appears
145
+ > 5. Save the downloaded `.json` file somewhere convenient
146
+
147
+ Then ask them to provide the file path:
148
+
149
+ > Please provide the path to your exported workflow JSON file:
150
+ > Example: `~/Downloads/workflow_api.json`
151
+
152
+ Use the `comfyui_workflow` tool with action `import` to import the workflow:
153
+
154
+ - Ask for a short name for the workflow (e.g., "txt2img", "anime", "realistic")
155
+ - Call: `comfyui_workflow import` with `filePath` and `name`
156
+ - Show the detected nodes and parameters to the user for confirmation
157
+
158
+ If the import succeeds, ask if they want to import additional workflows. If yes, repeat this step.
159
+
160
+ ### 3B-3: Save Configuration
161
+
162
+ Build the config JSON:
163
+
164
+ ```json
165
+ {
166
+ "comfyuiUrl": "<the URL, omit if http://localhost:8188>",
167
+ "comfyuiDefaultWorkflow": "<the first imported workflow name>"
168
+ }
169
+ ```
170
+
171
+ Proceed to **Step 4** to save. The workflow files are already saved by the import step.
172
+
173
+ ## Step 3C: Custom OpenAI-Compatible API Setup
174
+
175
+ Collect the following information. Present common presets first for convenience:
176
+
177
+ ### Quick Presets
178
+
179
+ | Service | Base URL | Default Model |
180
+ |---------|----------|---------------|
181
+ | **OpenAI** | `https://api.openai.com` (default) | `gpt-image-1` |
182
+ | **Together AI** | `https://api.together.xyz/v1` | (check their docs) |
183
+ | **Fireworks AI** | `https://api.fireworks.ai/inference/v1` | (check their docs) |
184
+
185
+ Ask the user to either pick a preset or provide custom values.
186
+
187
+ ### Required Fields
188
+
189
+ 1. **API Key** (required): Their API key for the service
190
+ - Example: `sk-...` for OpenAI
191
+
192
+ 2. **Base URL** (optional): API endpoint URL
193
+ - Default: `https://api.openai.com`
194
+ - Only needed if using a non-OpenAI service
195
+
196
+ 3. **Model Name** (optional): Which model to use
197
+ - Default: `gpt-image-1`
198
+ - Different services use different model names
199
+
200
+ ### Optional: Test the connection
201
+
202
+ After collecting the info, suggest testing with curl:
203
+
204
+ ```bash
205
+ curl -s <BASE_URL>/v1/models \
206
+ -H "Authorization: Bearer <API_KEY>" | head -c 500
207
+ ```
208
+
209
+ This helps catch invalid keys or wrong URLs before saving.
210
+
211
+ Proceed to **Step 4** with config from the collected fields (see bottom of this section for format).
212
+
213
+ Only include fields that differ from defaults. Omit `openaiBaseUrl` if it's `https://api.openai.com`, omit `openaiModel` if it's `gpt-image-1`.
214
+
215
+ ## Step 3D: Import from curl Example
216
+
217
+ Ask the user to paste their curl command. Common formats they might paste:
218
+
219
+ **Format 1: Image generation endpoint**
220
+ ```bash
221
+ curl https://api.openai.com/v1/images/generations \
222
+ -H "Authorization: Bearer sk-xxx" \
223
+ -H "Content-Type: application/json" \
224
+ -d '{"model": "gpt-image-1", "prompt": "a cat", "n": 1, "size": "1024x1024"}'
225
+ ```
226
+
227
+ **Format 2: Simple model list test**
228
+ ```bash
229
+ curl https://api.together.xyz/v1/models \
230
+ -H "Authorization: Bearer xxx"
231
+ ```
232
+
233
+ **Format 3: With -u flag or other auth styles**
234
+ ```bash
235
+ curl -u :sk-xxx https://api.fireworks.ai/inference/v1/images/generations \
236
+ -d '{"model": "accounts/fireworks/models/flux", "prompt": "a cat"}'
237
+ ```
238
+
239
+ ### Parse the curl command and extract:
240
+
241
+ 1. **Base URL**: The URL hostname + base path (strip `/v1/images/generations`, `/v1/models`, etc.)
242
+ - `https://api.openai.com/v1/images/generations` → `https://api.openai.com`
243
+ - `https://api.together.xyz/v1/models` → `https://api.together.xyz/v1`
244
+ - If URL ends with `/v1/...`, keep the `/v1` part only if it's NOT `api.openai.com`
245
+
246
+ 2. **API Key**: From `Authorization: Bearer <key>` header, or `-u :<key>` flag, or `--header` variants
247
+
248
+ 3. **Model**: From the JSON request body `"model": "<value>"` if present
249
+
250
+ ### Show parsed results for confirmation:
251
+
252
+ > I extracted the following from your curl command:
253
+ > - **API Key**: `sk-xxx...` (first 10 chars)
254
+ > - **Base URL**: `https://api.together.xyz/v1`
255
+ > - **Model**: `black-forest-labs/FLUX.1-schnell`
256
+ >
257
+ > Does this look correct?
258
+
259
+ If user confirms, proceed to **Step 4**. If not, let them correct individual fields.
260
+
261
+ ## Step 4: Save Configuration
262
+
263
+ Build the config JSON based on the chosen provider:
264
+
265
+ **For MeiGen:**
266
+ ```json
267
+ {
268
+ "meigenApiToken": "<the token>"
269
+ }
270
+ ```
271
+
272
+ **For ComfyUI:**
273
+ ```json
274
+ {
275
+ "comfyuiUrl": "<url, omit if default>",
276
+ "comfyuiDefaultWorkflow": "<workflow name>"
277
+ }
278
+ ```
279
+
280
+ **For OpenAI-compatible (manual or curl import):**
281
+ ```json
282
+ {
283
+ "openaiApiKey": "<the key>",
284
+ "openaiBaseUrl": "<base url, omit if default>",
285
+ "openaiModel": "<model, omit if default>"
286
+ }
287
+ ```
288
+
289
+ Create the config directory and write the file:
290
+
291
+ ```bash
292
+ mkdir -p ~/.config/meigen
293
+ ```
294
+
295
+ Then use the Write tool to write the JSON config to `~/.config/meigen/config.json`.
296
+
297
+ **Important**: If the user already has a config file with other providers configured, **merge** the new config into the existing one rather than overwriting. For example, a user might have both MeiGen and ComfyUI configured.
298
+
299
+ After writing, set permissions:
300
+
301
+ ```bash
302
+ chmod 600 ~/.config/meigen/config.json
303
+ ```
304
+
305
+ ## Step 5: Completion
306
+
307
+ Tell the user:
308
+
309
+ > Configuration saved! To activate the new settings, please **start a new Claude Code session** (close and reopen, or open a new terminal tab).
310
+ >
311
+ > After restarting, you can:
312
+ > - Use `generate_image` to create AI images
313
+ > - Run `list_models` to see available models and workflows
314
+ > - Try: "Generate a beautiful sunset over mountains"
315
+ >
316
+ > You can run `/meigen:setup` again anytime to change your configuration.
317
+
318
+ **For ComfyUI users**, additionally mention:
319
+
320
+ > ComfyUI tips:
321
+ > - Use `comfyui_workflow list` to see your saved workflows
322
+ > - Use `comfyui_workflow view` to see adjustable parameters (steps, CFG, sampler, etc.)
323
+ > - Ask me to change any workflow parameter — e.g., "increase steps to 30" or "switch sampler to dpmpp_2m"
324
+ > - You can import more workflows anytime with `comfyui_workflow import`