doubao-i2i-generator-mcp
Version:
MCP Server for generating images using Doubao Seedream 3.0 i2i (image-to-image) model
136 lines (121 loc) • 4.29 kB
JavaScript
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import { CallToolRequestSchema, ListToolsRequestSchema } from '@modelcontextprotocol/sdk/types.js';
import { spawn } from 'child_process';
// 创建MCP服务器
const server = new Server({
name: 'doubao-i2i-generator',
version: '1.0.0',
});
// 列出可用工具
server.setRequestHandler(ListToolsRequestSchema, async () => {
return {
tools: [
{
name: 'generate_i2i_image',
description: '使用豆包Seedream-3 i2i模型,根据文字提示和输入图片生成新图片',
inputSchema: {
type: 'object',
properties: {
model: { type: 'string', description: '模型ID', default: 'doubao-seededit-3-0-i2i-250628' },
prompt: { type: 'string', description: '文字提示词,描述想要生成的图片效果' },
image: { type: 'string', description: '输入图片的URL地址' },
response_format: { type: 'string', description: '输出格式:url 或 b64_json', default: 'url' },
size: { type: 'string', description: '图像尺寸', default: 'adaptive' },
seed: { type: 'number', description: '随机种子,用于控制生成结果的一致性', default: 21 },
guidance_scale: { type: 'number', description: '引导强度,控制生成图片与提示词的匹配程度', default: 5.5 },
watermark: { type: 'boolean', description: '是否添加水印', default: true }
},
required: ['prompt', 'image']
}
}
]
};
});
// 处理工具调用
server.setRequestHandler(CallToolRequestSchema, async (request) => {
const { name, arguments: args } = request.params;
try {
let result;
switch (name) {
case 'generate_i2i_image':
result = await generateI2IImage(args);
break;
default:
result = `未知工具: ${name}`;
}
return { content: [{ type: 'text', text: typeof result === 'string' ? result : JSON.stringify(result) }] };
} catch (error) {
return {
content: [
{
type: 'text',
text: `执行错误: ${error.message}`
}
]
};
}
});
// i2i图片生成工具:根据文字提示和输入图片生成新图片
async function generateI2IImage({
model = 'doubao-seededit-3-0-i2i-250628',
prompt,
image,
response_format = 'url',
size = 'adaptive',
seed = 21,
guidance_scale = 5.5,
watermark = true
}) {
const apiKey = process.env.ARK_API_KEY;
if (!apiKey) {
throw new Error('请设置 ARK_API_KEY');
}
const baseUrl = (process.env.ARK_BASE_URL || 'https://ark.cn-beijing.volces.com/api/v3').replace(/\/+$/,'');
const payload = {
model,
prompt,
image,
response_format,
size,
seed,
guidance_scale,
watermark
};
return new Promise((resolve, reject) => {
const hasFullEndpoint = /\/images\/generations$/.test(baseUrl);
const endpoint = hasFullEndpoint ? baseUrl : `${baseUrl}/images/generations`;
const args = [
'-sS',
'-X', 'POST', endpoint,
'-H', 'Content-Type: application/json',
'-H', `Authorization: Bearer ${apiKey}`,
'-d', JSON.stringify(payload)
];
const proc = spawn('curl', args, { stdio: ['ignore', 'pipe', 'pipe'] });
let stdout = '';
let stderr = '';
proc.stdout.on('data', (d) => { stdout += d.toString(); });
proc.stderr.on('data', (d) => { stderr += d.toString(); });
proc.on('close', (code) => {
if (code !== 0) {
return reject(new Error(`curl 执行失败,退出码 ${code}, 错误: ${stderr || '无'}`));
}
try {
const json = JSON.parse(stdout);
resolve(json);
} catch (e) {
reject(new Error(`解析响应失败: ${e.message}; 原始输出: ${stdout}`));
}
});
proc.on('error', (err) => reject(new Error(`启动curl失败: ${err.message}`)));
});
}
// 启动服务器
async function main() {
const transport = new StdioServerTransport();
await server.connect(transport);
console.error('Doubao I2I Image Generator MCP Server started');
}
main().catch(console.error);