@hongxianzhi/seedream-image-mcp 1.0.2

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/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 wearzdk(wear工程师) <hi@wearzdk.me>
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
package/README.md ADDED
@@ -0,0 +1,126 @@
1
+ # SeeDream Image MCP
2
+
3
+ 基于火山引擎 SeeDream 模型的 MCP (Model Context Protocol) 图片生成工具。
4
+
5
+ ## ✨ 特性
6
+
7
+ - 🎨 使用火山引擎 SeeDream 4.0 模型生成高质量图片
8
+ - 🔧 支持自定义尺寸、智能参考图等
9
+ - 📝 无需编写复杂提示词,AI自动根据需求生成生图提示词
10
+ - 🔌 MCP 协议支持,可在 Cursor、Claude Desktop 等客户端中使用
11
+
12
+ ## 📺 演示
13
+
14
+ <video src="https://github.com/user-attachments/assets/2b82a9d4-7799-4625-a140-2a48845b2e4a" autoplay muted loop playsinline controls width="100%" height="auto"></video>
15
+
16
+ ## 🚀 快速开始
17
+
18
+ ### 1. 获取火山引擎 API Key
19
+
20
+ 前往 [火山引擎->火山方舟控制台](https://console.volcengine.com/ark/region:ark+cn-beijing/apiKey) 开通服务并申请 API Key。
21
+
22
+ ### 2. 使用 npx 运行
23
+
24
+ ```bash
25
+ npx @hongxianzhi/seedream-image-mcp --ark-key=YOUR_API_KEY [--ark-model=MODEL_NAME] [--ark-endpoint=REQUEST_ENDPOINT]
26
+ ```
27
+
28
+ **参数说明:**
29
+ - `--ark-key` (必需) - 火山引擎 API Key
30
+ - `--ark-model` (可选) - 模型名称,默认 `doubao-seedream-4-5-251128`
31
+ - `--ark-endpoint` (可选) - 请求地址,默认 `https://ark.cn-beijing.volces.com/api/v3/images/generations`
32
+
33
+ ### 3. 在 Cursor、Claude Desktop 中配置
34
+
35
+ 编辑 `Cursor MCP配置` 或 `claude_desktop_config.json`:
36
+
37
+ ```json
38
+ {
39
+ "mcpServers": {
40
+ "seedream-image": {
41
+ "command": "npx",
42
+ "args": ["@hongxianzhi/seedream-image-mcp", "--ark-key=YOUR_API_KEY", "--ark-model=doubao-seedream-4-5-251128", "--ark-endpoint=https://ark.cn-beijing.volces.com/api/v3/images/generations"]
43
+ }
44
+ }
45
+ }
46
+ ```
47
+
48
+ ## 📖 使用示例
49
+
50
+ 在 AI Agent 工具中,你可以这样使用:
51
+
52
+ ```
53
+ 为这个页面添加合适的图片,避免过于单调
54
+ ```
55
+
56
+ AI 会自动调用工具完成生成。
57
+
58
+ ## 📌 注意事项
59
+
60
+ **图片链接时效性**:本项目使用火山引擎原始 API,生成的图片链接通常在 24 小时后失效。如果你需要长期保存图片,请及时下载到本地。
61
+
62
+ ## 🔄 两种使用方式
63
+
64
+ 你可以根据自己的需求选择:
65
+
66
+ ### 方式一:本地运行 🔧
67
+ - 需要自己申请火山引擎 API key
68
+ - 图片链接 24 小时后失效,需下载到本地使用。
69
+
70
+ ### 方式二:云端版本 ✨
71
+ - ✅ 无需申请 API key,开箱即用
72
+ - ✅ 图片支持永久存储在 CDN
73
+ - ✅ 支持 webp 压缩、背景移除、快速并发生成多张图片等功能
74
+ - ✅ 提供一定的免费额度
75
+ - ✅ 量大时价格更优惠
76
+
77
+ 👉 了解云端版本:[https://mcp.pixelark.art](https://mcp.pixelark.art)
78
+
79
+ ---
80
+
81
+
82
+ ## 🛠️ 开发
83
+
84
+ ### 安装依赖
85
+
86
+ ```bash
87
+ npm install
88
+ ```
89
+
90
+ ### 编译项目
91
+
92
+ ```bash
93
+ npm run build
94
+ ```
95
+
96
+ ### 全局安装
97
+
98
+ 如需全局安装此包以便在命令行中使用,可执行以下步骤:
99
+
100
+ ```bash
101
+ # 1. 正常编译
102
+ npm run build
103
+
104
+ # 2. 拷贝 dist/index.js 到全局 npm 目录
105
+ cp dist/index.js "$(npm prefix -g)/lib/node_modules/seedream-image-mcp/dist/index.js"
106
+
107
+ # 3. 创建符号链接到全局目录
108
+ ln -sf "$(npm prefix -g)/lib/node_modules/seedream-image-mcp/dist/index.js" "$(npm prefix -g)/bin/seedream-image-mcp"
109
+ ```
110
+
111
+ 或者使用 npm link(推荐):
112
+
113
+ ```bash
114
+ npm run build
115
+ npm link
116
+ ```
117
+
118
+ ## 📄 许可证
119
+
120
+ MIT
121
+
122
+ ## 🔗 相关链接
123
+
124
+ - [云端版本](https://mcp.pixelark.art)
125
+ - [火山引擎 SeeDream](https://www.volcengine.com/docs/ark/doubao-seedream)
126
+ - [MCP 协议](https://modelcontextprotocol.io)
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -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,156 @@
1
+ #!/usr/bin/env node
2
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
3
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
4
+ import { z } from "zod";
5
+ import { generateImage, setArkApiKey } from "./utils/vol.js";
6
+ // 解析命令行参数
7
+ function parseArgs() {
8
+ const args = process.argv.slice(2);
9
+ let arkKey = "";
10
+ let arkModel = "";
11
+ let arkEndpoint = "";
12
+ for (const arg of args) {
13
+ if (arg.startsWith("--ark-key=")) {
14
+ arkKey = arg.substring("--ark-key=".length);
15
+ }
16
+ else if (arg.startsWith("--ark-model=")) {
17
+ arkModel = arg.substring("--ark-model=".length);
18
+ }
19
+ else if (arg.startsWith("--ark-endpoint=")) {
20
+ arkEndpoint = arg.substring("--ark-endpoint=".length);
21
+ }
22
+ }
23
+ if (!arkKey) {
24
+ console.error("Error: --ark-key is required");
25
+ console.error("Usage: npx seedream-image-mcp --ark-key=YOUR_API_KEY [--ark-model=MODEL_NAME] [--ark-endpoint=REQUEST_ENDPOINT]");
26
+ process.exit(1);
27
+ }
28
+ return { arkKey, arkModel, arkEndpoint };
29
+ }
30
+ const { arkKey, arkModel, arkEndpoint } = parseArgs();
31
+ setArkApiKey(arkKey, arkModel, arkEndpoint);
32
+ const server = new McpServer({
33
+ name: "seedream-image-mcp",
34
+ version: "1.0.0",
35
+ });
36
+ // 注册图片生成工具
37
+ server.registerTool("generate-image", {
38
+ title: "生成图片",
39
+ description: "使用火山引擎 SeeDream 模型生成图片。支持文字描述生成、智能参考图等功能",
40
+ inputSchema: {
41
+ type: "object",
42
+ properties: {
43
+ prompt: {
44
+ type: "string",
45
+ minLength: 1,
46
+ maxLength: 5000,
47
+ description: `图片描述提示词
48
+
49
+ 【提示词编写建议】
50
+ 1. 基础结构:内容主题 → 视觉细节 → 风格氛围 → 技术质量
51
+ 2. 关键要素:
52
+ - 主体内容:明确要生成什么(场景/物体/氛围)
53
+ - 视觉细节:材质、光影、色彩、构图、景深
54
+ - 风格定调:写实/插画/3D/扁平/抽象等
55
+ - 技术要求:分辨率、构图方式、背景类型
56
+ 3. 语言规范:使用现代中文,逗号分隔关键词
57
+ 4. 质量提升:结尾添加"高清细节,杰作"等质量声明
58
+
59
+ 【重要约束】
60
+ - 默认添加"画面无文字";如需文字,明确标注"画面文字内容:XXX"
61
+ - 内容必须合法合规`,
62
+ },
63
+ size: {
64
+ type: "string",
65
+ description: `图片尺寸,格式为 WIDTHxHEIGHT,默认 2560x1440
66
+
67
+ 常用尺寸参考:
68
+ - 21:9 超宽屏: 3024x1296
69
+ - 16:9 横屏: 2560x1440
70
+ - 4:3 传统: 2304x1728
71
+ - 1:1 方形: 2048x2048
72
+ - 3:4 竖屏: 1728x2304
73
+ - 9:16 手机: 1440x2560`,
74
+ },
75
+ watermark: {
76
+ type: "boolean",
77
+ description: "是否添加AI生成水印,默认为 false",
78
+ },
79
+ images: {
80
+ type: "array",
81
+ items: {
82
+ type: "string",
83
+ },
84
+ description: "智能参考图片 URL 列表,支持多张图片作为参考",
85
+ },
86
+ },
87
+ required: ["prompt"],
88
+ },
89
+ }, async (args) => {
90
+ const prompt = args.prompt;
91
+ const size = args.size;
92
+ const watermark = args.watermark;
93
+ const images = args.images;
94
+ const result = await generateImage(prompt, {
95
+ size,
96
+ watermark,
97
+ images,
98
+ });
99
+ const output = {
100
+ success: result.success,
101
+ imageUrl: result.tempUri,
102
+ error: result.error,
103
+ };
104
+ if (result.success) {
105
+ const responseContent = [
106
+ {
107
+ type: "text",
108
+ text: `✅ 图片生成成功!
109
+
110
+ 🖼️ 图片URL: ${result.tempUri}
111
+
112
+ ⚠️ 重要提示:
113
+ 此链接通过 Base64 传递,已在下方直接显示。
114
+ 此 URL 链接通常在 24 小时后失效。
115
+ 如果你需要永久链接,可以考虑使用云端版本:https://mcp.pixelark.art`,
116
+ },
117
+ ];
118
+ // 如果有 base64 数据,添加 image 类型的 content
119
+ if (result.base64) {
120
+ responseContent.push({
121
+ type: "image",
122
+ data: result.base64,
123
+ mimeType: result.mimeType || "image/png",
124
+ });
125
+ }
126
+ return {
127
+ content: responseContent,
128
+ structuredContent: output,
129
+ };
130
+ }
131
+ return {
132
+ content: [
133
+ {
134
+ type: "text",
135
+ text: `❌ 图片生成失败: ${result.error}
136
+
137
+ 💡 遇到问题?试试商业版:
138
+ - 无需自己申请 API key
139
+ - 更稳定的服务和技术支持
140
+ - 注册即送 30 张免费额度
141
+ 👉 https://mcp.pixelark.art`,
142
+ },
143
+ ],
144
+ structuredContent: output,
145
+ };
146
+ });
147
+ // 启动服务器
148
+ async function main() {
149
+ const transport = new StdioServerTransport();
150
+ await server.connect(transport);
151
+ console.error("SeeDream Image MCP Server running on stdio");
152
+ }
153
+ main().catch((error) => {
154
+ console.error("Server error:", error);
155
+ process.exit(1);
156
+ });
@@ -0,0 +1,25 @@
1
+ /**
2
+ * 火山引擎图片生成相关工具函数
3
+ */
4
+ export interface ImageGenerationOptions {
5
+ model?: string;
6
+ size?: string;
7
+ watermark?: boolean;
8
+ images?: string[];
9
+ }
10
+ export interface ImageGenerationResult {
11
+ tempUri: string;
12
+ base64?: string;
13
+ mimeType?: string;
14
+ success: boolean;
15
+ error?: string;
16
+ }
17
+ export declare function setArkApiKey(apiKey: string, model?: string, endpoint?: string): void;
18
+ /**
19
+ * 使用火山引擎生成图片并存储到 OSS
20
+ * @param prompt 图片描述提示词
21
+ * @param options 可选配置项
22
+ * @returns 生成结果包含存储的 URI
23
+ */
24
+ export declare function generateImage(prompt: string, options?: ImageGenerationOptions): Promise<ImageGenerationResult>;
25
+ //# sourceMappingURL=vol.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vol.d.ts","sourceRoot":"","sources":["../../src/utils/vol.ts"],"names":[],"mappings":"AAGA;;GAEG;AAEH,MAAM,WAAW,sBAAsB;IACrC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAOD,wBAAgB,YAAY,CAC1B,MAAM,EAAE,MAAM,EACd,KAAK,CAAC,EAAE,MAAM,EACd,QAAQ,CAAC,EAAE,MAAM,QAKlB;AAuCD;;;;;GAKG;AACH,wBAAsB,aAAa,CACjC,MAAM,EAAE,MAAM,EACd,OAAO,GAAE,sBAA2B,GACnC,OAAO,CAAC,qBAAqB,CAAC,CA8HhC"}
@@ -0,0 +1,150 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ let ARK_ENDPOINT = "https://ark.cn-beijing.volces.com/api/v3/images/generations";
4
+ let ARK_MODEL = "doubao-seedream-4-5-251128";
5
+ let ARK_API_KEY = "";
6
+ export function setArkApiKey(apiKey, model, endpoint) {
7
+ ARK_API_KEY = apiKey;
8
+ if (model)
9
+ ARK_MODEL = model;
10
+ if (endpoint)
11
+ ARK_ENDPOINT = endpoint;
12
+ }
13
+ /**
14
+ * 处理图片,如果是本地路径则转换为 base64
15
+ */
16
+ async function processImage(imagePath) {
17
+ if (imagePath.startsWith("http://") ||
18
+ imagePath.startsWith("https://") ||
19
+ imagePath.startsWith("data:")) {
20
+ console.error(`[SeeDream] Using image URL/DataURI: ${imagePath.substring(0, 50)}...`);
21
+ return imagePath;
22
+ }
23
+ try {
24
+ // 尝试读取本地文件
25
+ const absolutePath = path.isAbsolute(imagePath)
26
+ ? imagePath
27
+ : path.resolve(process.cwd(), imagePath);
28
+ if (fs.existsSync(absolutePath)) {
29
+ console.error(`[SeeDream] Reading local image: ${absolutePath}`);
30
+ const bitmap = fs.readFileSync(absolutePath);
31
+ const base64 = Buffer.from(bitmap).toString("base64");
32
+ // 注意:有的 API 可能需要 data:image/xxx;base64, 前缀,如果报错请检查
33
+ return base64;
34
+ }
35
+ else {
36
+ console.error(`[SeeDream] Local image not found: ${absolutePath}`);
37
+ }
38
+ }
39
+ catch (error) {
40
+ console.error(`[SeeDream] Error processing image ${imagePath}:`, error);
41
+ }
42
+ return imagePath;
43
+ }
44
+ /**
45
+ * 使用火山引擎生成图片并存储到 OSS
46
+ * @param prompt 图片描述提示词
47
+ * @param options 可选配置项
48
+ * @returns 生成结果包含存储的 URI
49
+ */
50
+ export async function generateImage(prompt, options = {}) {
51
+ const { model = ARK_MODEL, watermark = false, images = [] } = options;
52
+ try {
53
+ // 构建请求参数
54
+ const requestBody = {
55
+ model,
56
+ prompt,
57
+ response_format: "url",
58
+ watermark,
59
+ // 智能组图
60
+ sequential_image_generation: "auto",
61
+ sequential_image_generation_options: {
62
+ max_images: 4,
63
+ },
64
+ };
65
+ // 只有当存在参考图时才添加 image 字段
66
+ if (images && images.length > 0) {
67
+ // 对图片进行处理,本地文件转 base64
68
+ const processedImages = await Promise.all(images.map((img) => processImage(img)));
69
+ requestBody.image = processedImages;
70
+ }
71
+ console.error("[SeeDream] Sending request to ARK API...");
72
+ // 打印请求体(隐藏 base64 以免日志过大)
73
+ const logBody = JSON.parse(JSON.stringify(requestBody));
74
+ if (logBody.image) {
75
+ logBody.image = logBody.image.map((img) => img.startsWith("http")
76
+ ? img
77
+ : `${img.substring(0, 30)}... (base64 trunced)`);
78
+ }
79
+ console.error("[SeeDream] Request Body Preview:", JSON.stringify(logBody, null, 2));
80
+ // 调用火山引擎 API 生成图片
81
+ const response = await fetch(ARK_ENDPOINT, {
82
+ method: "POST",
83
+ headers: {
84
+ "Content-Type": "application/json",
85
+ Authorization: `Bearer ${ARK_API_KEY}`,
86
+ },
87
+ body: JSON.stringify(requestBody),
88
+ });
89
+ if (!response.ok) {
90
+ const errorText = await response.text();
91
+ console.error(`[SeeDream] API Error Response (${response.status}):`, errorText);
92
+ try {
93
+ const error = JSON.parse(errorText);
94
+ return {
95
+ tempUri: "",
96
+ success: false,
97
+ error: `API Error: ${error.error.message || error.error.code}`,
98
+ };
99
+ }
100
+ catch (e) {
101
+ return {
102
+ tempUri: "",
103
+ success: false,
104
+ error: `HTTP ${response.status}: ${errorText}`,
105
+ };
106
+ }
107
+ }
108
+ const result = (await response.json());
109
+ const imageUrl = result.data?.[0]?.url;
110
+ if (!imageUrl) {
111
+ return {
112
+ tempUri: "",
113
+ success: false,
114
+ error: "No image URL returned from API",
115
+ };
116
+ }
117
+ console.error(`[SeeDream] Image generated: ${imageUrl}`);
118
+ // 获取图片并转换为 base64
119
+ try {
120
+ console.error("[SeeDream] Fetching image for base64 conversion...");
121
+ const imageResponse = await fetch(imageUrl);
122
+ if (!imageResponse.ok)
123
+ throw new Error(`Failed to fetch image: ${imageResponse.statusText}`);
124
+ const buffer = await imageResponse.arrayBuffer();
125
+ const base64 = Buffer.from(buffer).toString("base64");
126
+ const mimeType = imageResponse.headers.get("content-type") || "image/png";
127
+ console.error(`[SeeDream] Successfully converted to base64 (${mimeType})`);
128
+ return {
129
+ tempUri: imageUrl,
130
+ base64,
131
+ mimeType,
132
+ success: true,
133
+ };
134
+ }
135
+ catch (fetchError) {
136
+ console.error("[SeeDream] Base64 conversion failed, falling back to URL only:", fetchError);
137
+ return {
138
+ tempUri: imageUrl,
139
+ success: true,
140
+ };
141
+ }
142
+ }
143
+ catch (error) {
144
+ return {
145
+ tempUri: "",
146
+ success: false,
147
+ error: error instanceof Error ? error.message : "Unknown error occurred",
148
+ };
149
+ }
150
+ }
package/package.json ADDED
@@ -0,0 +1,55 @@
1
+ {
2
+ "name": "@hongxianzhi/seedream-image-mcp",
3
+ "version": "1.0.2",
4
+ "description": "基于火山引擎 SeeDream 模型的 MCP 图片生成工具,支持在 Cursor、Claude Desktop 等客户端中使用",
5
+ "type": "module",
6
+ "bin": {
7
+ "seedream-image-mcp": "./dist/index.js"
8
+ },
9
+ "main": "./dist/index.js",
10
+ "files": [
11
+ "dist",
12
+ "README.md",
13
+ "LICENSE"
14
+ ],
15
+ "scripts": {
16
+ "build": "tsc && chmod +x dist/index.js",
17
+ "prepublishOnly": "npm run build"
18
+ },
19
+ "keywords": [
20
+ "mcp",
21
+ "model-context-protocol",
22
+ "image-generation",
23
+ "ai",
24
+ "seedream",
25
+ "volcengine",
26
+ "claude",
27
+ "cursor",
28
+ "text-to-image",
29
+ "ai-image"
30
+ ],
31
+ "author": "PixelArk Team",
32
+ "license": "MIT",
33
+ "repository": {
34
+ "type": "git",
35
+ "url": "https://github.com/hongxianzhi/seedream-image-mcp.git"
36
+ },
37
+ "homepage": "https://mcp.pixelark.art",
38
+ "bugs": {
39
+ "url": "https://github.com/hongxianzhi/seedream-image-mcp/issues"
40
+ },
41
+ "engines": {
42
+ "node": ">=18.0.0"
43
+ },
44
+ "devDependencies": {
45
+ "@biomejs/biome": "^2.3.4",
46
+ "@types/bun": "latest"
47
+ },
48
+ "peerDependencies": {
49
+ "typescript": "^5"
50
+ },
51
+ "dependencies": {
52
+ "@modelcontextprotocol/sdk": "^1.21.1",
53
+ "zod": "^3.23.8"
54
+ }
55
+ }