关于 media-gen-mcp
media-gen-mcp 是一个 TypeScript MCP 服务,可通过 OpenAI 和 Google GenAI 生成及编辑图像、生成视频,也能从网址或本地文件获取媒体和文档,并按 MCP 客户端需要组织输出。
主要功能
- 01使用 OpenAI 模型生成和编辑图像
- 02创建和管理 Sora 视频任务
- 03生成 Veo 视频并获取结果
- 04从网址或文件获取并压缩图像
- 05以 MCP 资源形式返回媒体和文档
适用场景
- 01根据文本提示创建或修改图像
- 02创建、混剪或查看 Sora 视频任务
- 03生成 Veo 视频并下载完成的视频
- 04为 MCP 客户端载入并优化图像文件
MCP 相关
向 MCP 客户端提供图像、视频和文件获取工具。媒体可作为内联内容或资源链接返回,并支持结构化结果和 MCP 错误处理。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
npx -y @strato-space/media-gen-mcpOPENAI_API_KEY密钥OpenAI API key (required for OpenAI image/video tools).GEMINI_API_KEY密钥Gemini API key (alternative to GOOGLE_API_KEY).GOOGLE_API_KEY密钥Google GenAI API key for Veo video tools.GOOGLE_GENAI_USE_VERTEXAISet to true to use Vertex AI for Google GenAI.GOOGLE_CLOUD_PROJECTGCP project id for Vertex AI.GOOGLE_CLOUD_LOCATIONGCP region for Vertex AI (e.g. us-central1).AZURE_OPENAI_API_KEY密钥Azure OpenAI API key (optional).AZURE_OPENAI_ENDPOINTAzure OpenAI endpoint hostname.OPENAI_API_VERSIONAzure OpenAI API version.AZURE_OPENAI_DEPLOYMENTAzure OpenAI deployment name.MEDIA_GEN_DIRSComma-separated output directories for media files.MEDIA_GEN_URLSComma-separated URL prefixes allowed for fetch tools.MEDIA_GEN_MCP_URL_PREFIXESPublic URL prefixes for mapping local output files.MEDIA_GEN_MCP_TEST_SAMPLE_DIRPath to sample images for the test-images tool.本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。
工具
13收录的工具列表 · 更新于 2 周前
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| n | integer | 否 | |
| size | enum | 否 | 1024x1024 | 1536x1024 | 1024x1536 | auto |
| user | string | 否 | |
| model | enum | 否 | gpt-image-1.5 | gpt-image-1 |
| prompt | string | 是 | |
| quality | enum | 否 | auto | high | medium | low |
| background | enum | 否 | transparent | opaque | auto |
| moderation | enum | 否 | auto | low |
| tool_result | enum | 否 | 控制 content[] 的形态:'resource_link'(默认)会生成 ResourceLink 项,'image' 会生成 base64 ImageContent 块。resource_link | image |
| output_format | enum | 否 | png | jpeg | webp |
| response_format | enum | 否 | 控制 structuredContent 的形态:'url'(默认)会生成 data[].url,'b64_json' 会生成 data[].b64_json。url | b64_json |
| output_compression | integer | 否 |
详细介绍
media-gen-mcp
Media Gen MCP 是一个采用 严格 TypeScript 编写的模型上下文协议(MCP)服务,适用于 OpenAI Images(gpt-image-1.5、gpt-image-1)、OpenAI Videos(Sora)和 Google GenAI Videos(Veo):生成和编辑图像、创建和混剪视频任务,并通过 URL 或磁盘获取媒体;支持智能选择 resource_link 或内嵌 image 输出,以及可选的 sharp 处理。专注于生产环境(完整严格类型检查、ESLint 和 Vitest CI)。兼容 fast-agent、Claude Desktop、ChatGPT、Cursor、VS Code、Windsurf 及任何兼容 MCP 的客户端。
**设计原则:**规范优先、类型安全的图像工具——严格遵循 OpenAI Images API 和 MCP 规范,使用完全静态的 TypeScript 类型,并灵活选择结果位置和响应格式,以适配不同客户端。
- 生成图像:使用 OpenAI 的
gpt-image-1.5模型,根据文本提示词生成图像(兼容gpt-image-1,并计划在未来版本中支持 DALL·E)。 - 编辑图像(局部重绘、扩图、合成):一次可处理 1 到 16 张图像,并提供高级提示词控制。
- 生成视频:通过 OpenAI Videos(
sora-2、sora-2-pro)创建、混剪、列出、检索和删除任务,并下载素材。 - 生成视频:通过 Google GenAI(Veo)生成视频,支持轮询操作状态并优先下载文件。
- 获取并压缩图像:从 HTTP(S) URL 或本地文件路径获取图像,并智能优化大小和质量。
- 获取文档:从 HTTP(S) URL 或本地文件路径获取文档,并返回
resource_link/resource输出。 - 调试 MCP 输出格式:使用
test-images工具,模拟生产环境中的结果位置(content、structuredContent、toplevel)。 - 集成支持:fast-agent、Windsurf、Claude Desktop、Cursor、VS Code 以及任何兼容 MCP 的客户端。
✨ 功能
-
严格支持 MCP 规范
工具输出是最新 MCP 架构中的一等CallToolResult对象,包括:content项(text、image、resource_link、resource)、可选的structuredContent、可选的顶层files,以及失败时使用的isError标志。 -
全面支持 gpt-image-1.5 和 sora-2/sora-2-pro 参数(生成与编辑)
openai-images-generate对应 OpenAI ImagescreateAPI,适用于gpt-image-1.5(以及gpt-image-1)(background、moderation、size、quality、output_format、output_compression、n、user等)。openai-images-edit对应 OpenAI ImagescreateEditAPI,适用于gpt-image-1.5(以及gpt-image-1)(image、mask、n、quality、size、user)。
-
OpenAI 视频(Sora)任务工具(创建 / 混剪 / 列出 / 检索 / 删除 / 内容)
openai-videos-create对应videos/create,并可选择等待任务完成。openai-videos-remix对应videos/remix。openai-videos-list对应videos/list。openai-videos-retrieve对应videos/retrieve。openai-videos-delete对应videos/delete。openai-videos-retrieve-content对应videos/content,并将video/thumbnail/spritesheet资源下载到磁盘,返回 MCPresource_link(默认)或嵌入式resource块(通过tool_result)。
-
Google GenAI(Veo)操作与下载(生成 / 检索操作 / 检索内容)
google-videos-generate启动长时间运行的操作(ai.models.generateVideos),并可选择等待完成及下载.mp4输出文件。Veo 模型参考google-videos-retrieve-operation轮询现有操作。google-videos-retrieve-content从已完成的操作下载.mp4,返回 MCPresource_link(默认)或嵌入式resource块(通过tool_result)。
-
从 URL 或文件获取并处理图像
fetch-images工具从 HTTP(S) URL 或本地文件路径加载图像,并支持由用户控制的可选压缩(默认禁用)。支持并行处理最多 20 张图像。 -
从 URL 或文件获取视频
fetch-videos工具列出本地视频,或将远程视频 URL 下载到磁盘,并返回 MCPresource_link(默认)或嵌入式resource块(通过tool_result)。 -
从 URL 或文件获取文档
fetch-document工具下载远程文件或复用本地路径,并返回 MCPresource_link(默认)或嵌入式resource块(通过tool_result)。 -
混合和编辑最多 16 张图像
openai-images-edit接受单个字符串或包含 1–16 个文件路径 / base64 字符串的数组作为image,符合 GPT Image 模型(gpt-image-1.5、gpt-image-1)的图像编辑规范。 -
智能图像压缩
内置基于 sharp 的压缩功能——通过迭代降低质量和尺寸,使图像符合 MCP 载荷限制,同时保持视觉质量。 -
通过
resource_link实现资源感知型文件输出- 当响应总大小超过安全阈值时,自动从内联 base64 切换为
file。 - 输出文件会写入磁盘,文件名格式为
output_<time_t>_media-gen__<tool>_<id>.<ext>(图像/文档使用生成的 UUID;视频使用 OpenAIvideo_id),并根据tool_result通过content[]提供给 MCP 客户端(图像使用resource_link/image,视频/文档下载使用resource_link/resource)。
- 当响应总大小超过安全阈值时,自动从内联 base64 切换为
-
内置测试图像工具,便于调试 MCP 客户端
test-images会从配置的目录读取示例图像,并使用与生产工具相同的结果构建逻辑返回图像。使用tool_result和response_format参数,测试不同 MCP 客户端如何处理content[]和structuredContent。 -
结构化 MCP 错误处理
所有工具错误(验证、OpenAI API 故障、I/O)都会作为 MCP 错误返回,其中包含isError: true和content: [{ type: "text", text: <error message> }],便于在 MCP 客户端中解析和显示故障。
🚀 安装
git clone https://github.com/strato-space/media-gen-mcp.git
cd media-gen-mcp
npm install
npm run build
构建模式:
npm run build– 严格的 TypeScript 构建,启用所有严格标志,包括skipLibCheck: false。通过.tsbuildinfo进行增量构建(预热缓存后约需 2-3 秒)。npm run esbuild– 通过 esbuild 快速打包(不进行类型检查,适合快速迭代)。
开发模式(无需构建)
适用于开发,或因内存限制导致 TypeScript 编译失败的情况:
npm run dev # Uses tsx to run TypeScript directly
质量检查
npm run lint # ESLint with typescript-eslint
npm run typecheck # Strict tsc --noEmit
npm run test # Unit tests (vitest)
npm run test:watch # Watch mode for TDD
npm run ci # lint + typecheck + test
单元测试
项目使用 vitest 进行单元测试。测试位于 test/ 中。
覆盖的模块:
| 模块 | 测试数 | 说明 |
|---|---|---|
compression | 12 | 图像格式检测、缓冲区处理、文件 I/O |
helpers | 31 | URL/路径验证、输出解析、结果放置、资源链接 |
env | 19 | 配置解析、环境变量验证、默认值 |
logger | 10 | 结构化日志 + 截断安全性 |
pricing | 5 | Sora 价格估算辅助函数 |
schemas | 69 | 所有工具的 Zod schema 验证、类型推断 |
fetch-images(集成) | 3 | 端到端 MCP 工具调用行为 |
fetch-videos(集成) | 3 | 端到端 MCP 工具调用行为 |
测试类别:
- compression —
isCompressionAvailable、detectImageFormat、processBufferWithCompression、readAndProcessImage - helpers —
isHttpUrl、isAbsolutePath、isBase64Image、ensureDirectoryWritable、resolveOutputPath、getResultPlacement、buildResourceLinks - env —
MEDIA_GEN_*/MEDIA_GEN_MCP_*设置的配置加载和验证 - logger — 截断和错误格式化行为
- schemas —
openai-images-*、openai-videos-*、fetch-images、fetch-videos、test-images输入的验证,以及边界测试(提示词长度、图像数量限制、路径验证)
npm run test
# ✓ test/compression.test.ts (12 tests)
# ✓ test/helpers.test.ts (31 tests)
# ✓ test/env.test.ts (19 tests)
# ✓ test/logger.test.ts (10 tests)
# ✓ test/pricing.test.ts (5 tests)
# ✓ test/schemas.test.ts (69 tests)
# ✓ test/fetch-images.integration.test.ts (3 tests)
# ✓ test/fetch-videos.integration.test.ts (3 tests)
# Tests: 152 passed
通过 npx 直接运行(无需本地克隆)
你也可以使用 npx 直接从远程仓库运行服务:
npx -y github:strato-space/media-gen-mcp --env-file /path/to/media-gen.env
--env-file 参数用于告知服务要加载哪个 env 文件(例如,当你将机密信息保存在克隆目录之外时)。该文件应包含 OPENAI_API_KEY、可选的 Azure 变量,以及任何 MEDIA_GEN_MCP_* 设置。
secrets.yaml(可选)
你可以将 API 密钥(以及可选的 Google Vertex AI 设置)保存在 secrets.yaml 文件中(兼容 fast-agent secrets 模板):
openai:
api_key: <your-api-key-here>
anthropic:
api_key: <your-api-key-here>
google:
api_key: <your-api-key-here>
vertex_ai:
enabled: true
project_id: your-gcp-project-id
location: europe-west4
media-gen-mcp 会从当前工作目录(或通过 --secrets-file /path/to/secrets.yaml 指定的位置)加载 secrets.yaml,并将其应用到环境变量;secrets.yaml 中的值会覆盖 env,且 <your-api-key-here> 占位符会被忽略。
⚡ 快速开始(fast-agent 和 Windsurf)
fast-agent
在 fast-agent 中,MCP 服务配置在 fastagent.config.yaml 的 mcp.servers 部分(参见 fast-agent 文档)。
要通过 npx 从 GitHub 添加 media-gen-mcp 作为 MCP 服务:
# fastagent.config.yaml
mcp:
servers:
# your existing servers (e.g. fetch, filesystem, huggingface, ...)
media-gen-mcp:
command: "npx"
args: ["-y", "github:strato-space/media-gen-mcp", "--env-file", "/path/to/media-gen.env"]
将 OPENAI_API_KEY 和其他设置写入 media-gen.env(参见本仓库中的 .env.sample)。
Windsurf
使用以下 JSON 格式添加一个通过 npx 从 GitHub 运行 media-gen-mcp 的 MCP 服务(类似于 Claude Desktop / VS Code):
{
"mcpServers": {
"media-gen-mcp": {
"command": "npx",
"args": ["-y", "github:strato-space/media-gen-mcp", "--env-file", "/path/to/media-gen.env"]
}
}
}
🔑 配置
添加到你的 MCP 客户端配置中(fast-agent、Windsurf、Claude Desktop、Cursor、VS Code):
{
"mcpServers": {
"media-gen-mcp": {
"command": "npx",
"args": ["-y", "github:strato-space/media-gen-mcp"],
"env": { "OPENAI_API_KEY": "sk-..." }
}
}
}
也支持 Azure 部署:
{
"mcpServers": {
"media-gen-mcp": {
"command": "npx",
"args": ["-y", "github:strato-space/media-gen-mcp"],
"env": {
// "AZURE_OPENAI_API_KEY": "sk-...",
// "AZURE_OPENAI_ENDPOINT": "my.endpoint.com",
"OPENAI_API_VERSION": "2024-12-01-preview"
}
}
}
}
环境变量:
- 在运行
node dist/index.js的进程环境中设置OPENAI_API_KEY(以及可选的AZURE_OPENAI_API_KEY、AZURE_OPENAI_ENDPOINT、OPENAI_API_VERSION)(shell、systemd unit、Docker env 等)。 - 如果存在本地
.env文件,服务会选择性地从其工作目录加载该文件(不会覆盖已设置的环境变量)。 - 启动服务时也可以传入
--env-file /path/to/env(包括通过npx启动);该文件会在工具运行前通过dotenv加载,同样不会覆盖已设置的环境变量。
日志记录和 base64 截断
为避免大量图像负载淹没日志,内置日志记录器会对传递给
log.debug/info/warn/error 的结构化 data 应用仅用于日志的清理:
- 将已配置的字符串字段(例如
b64_json、base64、字符串形式的data、image_url)截断为简短预览;预览长度由LOG_TRUNCATE_DATA_MAX控制(默认值:64 个字符)。默认键列表 在src/lib/logger.ts中定义为LOG_SANITIZE_KEYS,并可通过MEDIA_GEN_MCP_LOG_SANITIZE_KEYS(以逗号分隔的字段名称列表)覆盖。 - 清理操作仅应用于日志序列化;返回给 MCP 客户端的工具结果不会被修改。
通过环境变量控制:
MEDIA_GEN_MCP_LOG_SANITIZE_IMAGES(默认值:true)1、true、yes、on– 启用截断(默认行为)。0、false、no、off– 禁用截断并记录完整负载。
字段列表和限制通过 src/lib/logger.ts 中的
LOG_SANITIZE_KEYS 和 LOG_TRUNCATE_DATA_MAX 配置。
安全性和本地文件访问
- 允许的目录:所有工具都仅限访问与
MEDIA_GEN_DIRS匹配的路径。如果未设置,默认为/tmp/media-gen-mcp(Windows 上为%TEMP%/media-gen-mcp)。 - 测试样例:
MEDIA_GEN_MCP_TEST_SAMPLE_DIR会将一个目录添加到允许列表,并启用test-images工具。 - 本地读取:
fetch-images和fetch-document接受文件路径(绝对路径或相对路径)。相对路径会以第一个MEDIA_GEN_DIRS条目为基准解析,并且仍须匹配允许的模式。 - 远程读取:HTTP(S) 获取会根据
MEDIA_GEN_URLS模式进行筛选。为空 = 全部允许。 - 写入:
openai-images-generate、openai-images-edit、fetch-images、fetch-videos和fetch-document会在MEDIA_GEN_DIRS的第一个条目下写入。test-images只读,不会创建新文件。
Glob 模式
MEDIA_GEN_DIRS 和 MEDIA_GEN_URLS 都支持 glob 通配符:
| 模式 | 匹配内容 | 示例 |
|---|---|---|
* | 任意单个片段(不含 /) | /home/*/media/ 匹配 /home/user1/media/ |
** | 任意数量的片段 | /data/**/images/ 匹配 /data/a/b/images/ |
URL 示例:
MEDIA_GEN_URLS=https://*.cdn.example.com/,https://storage.example.com/**/assets/
路径示例:
MEDIA_GEN_DIRS=/home/*/media-gen/output/,/data/**/images/
⚠️ 警告:没有分隔符的尾随通配符(例如 /home/user/* 或 https://cdn.com/**)会开放整个子树,并在启动时触发控制台警告。
建议的缓解措施
- 使用专用 OS 用户运行,并仅授予其访问允许目录的权限。
- 将允许列表保持在最小范围。避免在主目录或系统路径中使用
*。 - 对远程获取使用明确的
MEDIA_GEN_URLS前缀。 - 通过 OS ACL 或备份监控允许的目录。
工具结果参数:tool_result 和 response_format
图像工具(openai-images-*、fetch-images、test-images)支持两个参数,用于控制 MCP 工具结果的结构:
| 参数 | 可选值 | 默认值 | 描述 |
|---|---|---|---|
tool_result | resource_link、image | resource_link | 控制 content[] 的结构 |
response_format | url、path、b64_json | url | 控制 structuredContent 的结构(OpenAI ImagesResponse 格式) |
视频/文档下载工具(下载时的 openai-videos-create/openai-videos-remix、openai-videos-retrieve-content、下载时的 google-videos-generate、google-videos-retrieve-content、fetch-videos、fetch-document)支持:
| 参数 | 可选值 | 默认值 | 描述 |
|---|---|---|---|
tool_result | resource_link、resource | resource_link | 控制 content[] 的结构 |
Google 视频工具(google-videos-*)也支持:
| 参数 | 可选值 | 默认值 | 描述 |
|---|---|---|---|
response_format | url、b64_json | url | 控制 structuredContent.response.generatedVideos[].video 的结构(uri 或 videoBytes) |
tool_result — 控制 content[]
- 图像(
openai-images-*、fetch-images、test-images)resource_link(默认):输出带有file://或https://URI 的ResourceLink项image:输出 base64ImageContent块
- 视频(下载视频数据的工具)
resource_link(默认):输出带有file://或https://URI 的ResourceLink项resource:输出包含 base64resource.blob的EmbeddedResource块
- 文档(
fetch-document)resource_link(默认):输出带有file://或https://URI 的ResourceLink项resource:输出包含 base64resource.blob的EmbeddedResource块
response_format — 控制 structuredContent
对于 OpenAI 图像,structuredContent 始终包含一个符合 OpenAI ImagesResponse 格式的对象:
{
"created": 1234567890,
"data": [
{ "url": "https://..." } // or { "path": "/abs/path.png" } / { "b64_json": "..." } depending on response_format
]
}
url(默认):data[].url包含文件 URLpath:data[].path包含本地文件系统路径b64_json:data[].b64_json包含 base64 编码的图像数据
对于 Google 视频,response_format 控制 structuredContent.response.generatedVideos[].video 优先采用:
url(默认):video.uri(并移除video.videoBytes)b64_json:video.videoBytes(并移除video.uri)
向后兼容性(MCP 5.2.6)
根据 MCP 规范 5.2.6,content[] 中也会包含一个带有序列化 JSON 的 TextContent 块(data[] 始终使用 URL),以兼容不支持 structuredContent 的客户端。
工具结果结构示例:
{
"content": [
// ResourceLink or ImageContent based on tool_result
{ "type": "resource_link", "uri": "https://...", "name": "image.png", "mimeType": "image/png" },
// Serialized JSON for backward compatibility (MCP 5.2.6)
{ "type": "text", "text": "{ \"created\": 1234567890, \"data\": [{ \"url\": \"https://...\" }] }" }
],
"structuredContent": {
"created": 1234567890,
"data": [{ "url": "https://..." }]
}
}
ChatGPT MCP 客户端行为(chatgpt.com,截至 2025-12-01):
- ChatGPT 目前优先使用
structuredContent,忽略content[]中的图像数据。 - 对于 ChatGPT,请使用
response_format: "url",并将第一个MEDIA_GEN_MCP_URL_PREFIXES条目配置为公开的 HTTPS 前缀(例如MEDIA_GEN_MCP_URL_PREFIXES=https://media-gen.example.com/media)。
对于 Anthropic 客户端(Claude Desktop 等),默认配置即可正常使用。
通过 mcp-proxy(SSE)进行网络访问
如需通过网络访问 SSE,可使用 mcp-proxy 或其同类工具,将 media-gen-mcp 接入前端。此设置已通过 TypeScript SSE 代理实现 punkpeye/mcp-proxy 进行测试。
例如,可以使用一行命令:
mcp-proxy --host=0.0.0.0 --port=99 --server=sse --sseEndpoint=/ --shell 'npx -y github:strato-space/media-gen-mcp --env-file /path/to/media-gen.env'
在生产环境中,通常会通过 systemd 模板单元来配置此项,并从 EnvironmentFile= 加载 PORT/SHELL_CMD(参见 server/mcp/[email protected] 风格的设置)。
🛠 工具签名
openai-images-generate
参数(输入架构):
prompt(字符串,必填)- 描述所需图像的文本提示词。
- 最大长度:32,000 个字符。
background("transparent" | "opaque" | "auto",可选)- 背景处理模式。
- 如果
background为"transparent",则output_format必须为"png"或"webp"。
model("gpt-image-1.5" | "gpt-image-1",可选,默认值:"gpt-image-1.5")moderation("auto" | "low",可选)- 内容审核行为,会传递给 Images API。
n(整数,可选)- 要生成的图像数量。
- 最小值:1,最大值:10。
output_compression(整数,可选)- 压缩级别(0–100)。
- 仅在
output_format为"jpeg"或"webp"时应用。
output_format("png" | "jpeg" | "webp",可选)- 输出图像格式。
- 如果省略,服务端会将输出视为 PNG 语义。
quality("auto" | "high" | "medium" | "low",默认值:"high")size("1024x1024" | "1536x1024" | "1024x1536" | "auto",默认值:"1024x1536")user(字符串,可选)- 转发给 OpenAI 用于监控的用户标识符。
response_format("url" | "path" | "b64_json",默认值:"url")- 响应格式(与 OpenAI Images API 对齐):
"url":基于文件/URL 的输出(resource_link 项、image_url字段,以及api放置方式中的data[].url)。"path":data[].path中的本地文件系统路径(用于本地 skill 工作流)。"b64_json":内联 base64 图像数据(图像内容,以及api放置方式中的data[].b64_json)。
tool_result("resource_link" | "image",默认值:"resource_link")- 控制
content[]的结构:"resource_link"会输出 ResourceLink 项(基于文件/URL)"image"会输出 base64 ImageContent 块
- 控制
- 响应格式(与 OpenAI Images API 对齐):
行为说明:
- 服务端默认使用 OpenAI
gpt-image-1.5(设置model: "gpt-image-1"可使用旧版行为)。 - 如果所有 base64 图像的总大小超过配置的负载阈值(默认约为 50MB,通过
MCP_MAX_CONTENT_BYTES配置),服务端会自动将实际输出模式切换为基于文件/URL 的模式,并将图像保存到MEDIA_GEN_DIRS的首个条目(默认值:/tmp/media-gen-mcp)。 - 即使明确请求
response_format: "b64_json",服务端仍会将文件写入磁盘(用于静态托管、缓存或后续复用)。工具结果中是否会暴露文件路径/URL,取决于MEDIA_GEN_MCP_RESULT_PLACEMENT和单次调用的result_placement(见下文)。
输出(MCP CallToolResult,当放置方式包含 "content" 时):
- 当实际
output模式为"base64"时:content是一个数组,可能包含:- 图像项:
{ type: "image", data: <base64 字符串>, mimeType: <"image/png" | "image/jpeg" | "image/webp"> }
- 可选的文本项,包含 Images API 返回的修订后提示词(适用于支持此功能的模型,例如 DALL·E 3):
{ type: "text", text: <revised_prompt 字符串> }
- 图像项:
- 当实际
output模式为"file"时:content中每个文件对应一个resource_link项,另加包含修订后提示词的相同可选text项:{ type: "resource_link", uri: "file:///absolute-path-1.png", name: "absolute-path-1.png", mimeType: <图像 mime 类型> }
- 对于
gpt-image-1.5和gpt-image-1,还会附加一行定价估算(基于structuredContent.usage),而structuredContent.pricing则包含完整的定价明细。
当 result_placement 包含 "api" 时,openai-images-generate 会改为返回一个类似 OpenAI Images API 的对象,不包含 MCP 封装:
{
"created": 1764599500,
"data": [
{ "b64_json": "..." } // or { "url": "https://.../media/file.png" } when output: "file"
],
"background": "opaque",
"output_format": "png",
"size": "1024x1024",
"quality": "high"
}
openai-images-edit
参数(输入架构):
image(字符串或字符串数组,必需)- 单个图像文件的绝对路径(
.png、.jpg、.jpeg、.webp), base64 编码的图像字符串(可选用data:image/...;base64,...URL), 或指向可公开访问图像的 HTTP(S) URL, 或包含 1–16 个此类字符串的数组(用于多图像编辑)。 - 提供 HTTP(S) URL 时,服务端会获取图像并将其转换为 base64,然后发送给 OpenAI。
- 单个图像文件的绝对路径(
prompt(字符串,必需)- 对所需编辑效果的文字描述。
- 最大长度:32,000 个字符。
mask(字符串,可选)- 蒙版图像的绝对路径、base64 字符串或 HTTP(S) URL(PNG < 4MB,尺寸与源图像相同)。透明区域表示要编辑的区域。
model("gpt-image-1.5" | "gpt-image-1",可选,默认值:"gpt-image-1.5")n(整数,可选)- 要生成的图像数量。
- 最小值:1,最大值:10。
quality("auto" | "high" | "medium" | "low",默认值:"high")size("1024x1024" | "1536x1024" | "1024x1536" | "auto",默认值:"1024x1536")user(字符串,可选)- 转发给 OpenAI 用于监控的用户标识符。
response_format("url" | "path" | "b64_json",默认值:"url")- 响应格式(与 OpenAI Images API 一致):
"url":基于文件/URL 的输出(resource_link项、image_url字段,以及apiplacement 中的data[].url)。"path":data[].path中的本地文件系统路径(用于本地 skill 工作流)。"b64_json":内联 base64 图像数据(图像内容,以及apiplacement 中的data[].b64_json)。
- 响应格式(与 OpenAI Images API 一致):
tool_result("resource_link" | "image",默认值:"resource_link")- 控制
content[]的形态:"resource_link"输出 ResourceLink 项(基于文件/URL)"image"输出 base64 ImageContent 块
- 控制
行为说明:
- 服务端接受绝对路径、base64/data URL 或 HTTP(S) URL 形式的
image和mask。 - 提供 HTTP(S) URL 时,服务端会获取图像,并在调用 OpenAI 前将其转换为 base64 data URL。
- 编辑操作输出图像时,服务端始终采用 PNG 语义(mime 类型为
image/png)。
输出(MCP CallToolResult):
- 有效的
output模式为"base64"时:content是一个数组,可能包含:- 图像项:
{ type: "image", data: <base64 string>, mimeType: "image/png" }
- 可选的文本项,其中包含修订后的提示词(底层模型返回时):
{ type: "text", text: <revised_prompt string> }
- 图像项:
- 有效的
output模式为"file"时:content包含每个文件对应的一个resource_link项,以及相同的可选文本项,其中包含修订后的提示词:{ type: "resource_link", uri: "file:///absolute-path-1.png", name: "absolute-path-1.png", mimeType: "image/png" }
- 对于
gpt-image-1.5和gpt-image-1,还会额外包含一行定价估算(基于structuredContent.usage),而structuredContent.pricing则包含完整的定价明细。
当 result_placement 包含 "api" 时,openai-images-edit 遵循与 openai-images-generate 相同的原始 API 格式(顶层字段 created、data[]、background、output_format、size、quality;base64 输出使用 b64_json,文件输出使用 url)。
错误处理(两种工具均适用):
- 工具处理程序内部发生错误(校验、OpenAI API 失败、I/O 等)时,服务端会返回标记为错误的 CallToolResult:
isError: truecontent: [{ type: "text", text: <error message string> }]
- 错误消息文本直接取自底层异常消息,服务端不会添加额外说明;完整详情会记录到服务端控制台。
openai-videos-create
使用 OpenAI Videos API(videos.create)创建视频生成任务。
参数(输入架构):
prompt(字符串,必填)— 描述视频的文本提示词(最多 32K 个字符)。input_reference(字符串,可选)— 可选的图像参考(HTTP(S) URL、base64/数据 URL 或文件路径)。input_reference_fit("match" | "cover" | "contain" | "stretch",默认值:"contain")- 如何将
input_reference调整到请求的视频size:match:要求尺寸完全相同(不匹配时立即失败)cover:调整尺寸并居中裁剪以填满contain:调整尺寸并填充边框以适配(默认值)stretch:拉伸调整尺寸,可能导致变形
- 如何将
input_reference_background("blur" | "black" | "white" | "#RRGGBB" | "#RRGGBBAA",默认值:"blur")- 当
input_reference_fit="contain"时使用的填充背景。
- 当
model("sora-2" | "sora-2-pro",默认值:"sora-2-pro")seconds("4" | "8" | "12",可选)size("720x1280" | "1280x720" | "1024x1792" | "1792x1024",可选)1024x1792和1792x1024需要使用sora-2-pro。- 如果省略
input_reference和size,则使用 API 默认值。
wait_for_completion(布尔值,默认值:true)- 为 true 时,服务会轮询
openai-videos-retrieve,直到状态为completed或failed(或超时),然后下载资源。
- 为 true 时,服务会轮询
timeout_ms(整数,默认值:900000)poll_interval_ms(整数,默认值:2000)download_variants(字符串[],默认值:["video"])- 允许的值:
"video" | "thumbnail" | "spritesheet"。
- 允许的值:
tool_result("resource_link"|"resource",默认值:"resource_link")- 控制下载资源的
content[]结构:"resource_link"会输出 ResourceLink 项(基于文件/URL)"resource"会输出带有 base64resource.blob的 EmbeddedResource 块
- 控制下载资源的
输出(MCP CallToolResult):
structuredContent:OpenAIVideo对象(任务元数据;当wait_for_completion=true时为最终状态)。content:包含resource_link(默认)或下载资源的嵌入式resource块(按需提供),以及带有 JSON 的文本块。- 包含摘要 JSON 块:
{ "video_id": "...", "pricing": { "currency": "USD", "model": "...", "size": "...", "seconds": 4, "price": 0.1, "cost": 0.4 } | null }(等待时则为:{ "video_id": "...", "assets": [...], "pricing": ... })。
- 包含摘要 JSON 块:
openai-videos-remix
基于现有 video_id 创建混剪任务(videos.remix)。
参数(输入架构):
video_id(字符串,必填)prompt(字符串,必填)wait_for_completion、timeout_ms、poll_interval_ms、download_variants、tool_result— 与openai-videos-create的语义相同(默认等待值为 true)。
openai-videos-list
列出视频任务(videos.list)。
参数(输入架构):
after(字符串,可选)— 游标(视频 ID),用于列出其后的任务。limit(整数,可选)order("asc" | "desc",可选)
输出:
structuredContent:OpenAI 列表响应结构{ data, has_more, last_id }。content:包含序列化 JSON 的文本块。
openai-videos-retrieve
获取任务状态(videos.retrieve)。
video_id(字符串,必填)
openai-videos-delete
删除视频任务(videos.delete)。
video_id(字符串,必填)
openai-videos-retrieve-content
获取已完成任务的资源(videos.downloadContent,REST GET /videos/{video_id}/content),将其写入允许的 MEDIA_GEN_DIRS 下,并返回 MCP resource_link(默认)或嵌入式 resource 块(通过 tool_result 指定)。
参数(输入架构):
video_id(字符串,必填)variant("video" | "thumbnail" | "spritesheet",默认值:"video")tool_result("resource_link"|"resource",默认值:"resource_link")
输出(MCP CallToolResult):
structuredContent:OpenAIVideo对象。content:包含resource_link(或嵌入式resource)、摘要 JSON 块{ video_id, variant, uri, pricing },以及完整的视频 JSON。
google-videos-generate
使用 Google GenAI SDK(@google/genai)的 ai.models.generateVideos 创建 Google 视频生成操作。
参数(输入架构):
prompt(字符串,可选)input_reference(字符串,可选)——图像转视频输入(HTTP(S) URL、base64/数据 URL,或MEDIA_GEN_DIRS下的文件路径)input_reference_mime_type(字符串,可选)——覆盖input_reference的 MIME 类型(必须为image/*)input_video_reference(字符串,可选)——视频扩展输入(HTTP(S) URL 或MEDIA_GEN_DIRS下的文件路径;不能与input_reference同时使用)model(字符串,默认值:"veo-3.1-generate-001")number_of_videos(整数,默认值:1)aspect_ratio("16:9" | "9:16",可选)duration_seconds(整数,可选)- Veo 2 模型:5–8 秒(默认值:8)
- Veo 3 模型:4、6 或 8 秒(默认值:8)
- 使用
referenceImages时:8 秒
person_generation("DONT_ALLOW" | "ALLOW_ADULT" | "ALLOW_ALL",可选)wait_for_completion(布尔值,默认值:true)timeout_ms(整数,默认值:900000)poll_interval_ms(整数,默认值:10000)download_when_done(布尔值,可选;等待时默认值为true)tool_result("resource_link" | "resource",默认值:"resource_link")- 控制下载生成视频时
content[]的形状。
- 控制下载生成视频时
response_format("url" | "b64_json",默认值:"url")- 控制
structuredContent.response.generatedVideos[].video字段:"url"优先使用video.uri(并移除video.videoBytes)"b64_json"优先使用video.videoBytes(并移除video.uri)
- 控制
要求:
- Gemini Developer API:设置
GEMINI_API_KEY(或GOOGLE_API_KEY),或在secrets.yaml中设置google.api_key。 - Vertex AI:设置
GOOGLE_GENAI_USE_VERTEXAI=true、GOOGLE_CLOUD_PROJECT和GOOGLE_CLOUD_LOCATION(或在secrets.yaml中设置google.vertex_ai.*)。
输出:
structuredContent:Google 操作对象(包含name、done,以及可用时的response.generatedVideos[])。content:状态文本、可选的.mp4resource_link(默认)或嵌入式resource块(下载后),以及用于兼容性的 JSON 文本块。
google-videos-retrieve-operation
检索/轮询现有的 Google 视频操作(ai.operations.getVideosOperation)。
operation_name(字符串,必填)response_format("url" | "b64_json",默认值:"url")
输出:
structuredContent:Google 操作对象。content:JSON 文本块,包含简短摘要和完整操作。
google-videos-retrieve-content
下载已完成操作的 .mp4 内容,并以文件优先的 MCP resource_link(默认)或嵌入式 resource 块(通过 tool_result)返回。
operation_name(字符串,必填)index(整数,默认值:0)——选择response.generatedVideos[index]tool_result("resource_link" | "resource",默认值:"resource_link")response_format("url" | "b64_json",默认值:"url")
推荐工作流:
- 调用
google-videos-generate并设置wait_for_completion=true(默认值)以获取已完成的操作并下载视频;只有在需要立即获取操作 ID 时才设为 false。 - 轮询
google-videos-retrieve-operation,直到done=true。 - 调用
google-videos-retrieve-content下载.mp4并接收resource_link(或嵌入式resource)。
fetch-images
从 URL 或本地文件路径获取并处理图像,可选择压缩。
参数(输入架构):
sources(string[],可选)- 图像来源数组:HTTP(S) URL 或文件路径(绝对路径,或相对于第一个
MEDIA_GEN_DIRS条目的路径)。 - 最少:1 张,最多:20 张图像。
- 不能与
ids和n同时使用。
- 图像来源数组:HTTP(S) URL 或文件路径(绝对路径,或相对于第一个
ids(string[],可选)- 图像 ID 数组,用于在主
MEDIA_GEN_DIRS[0]目录下按本地文件名匹配获取图像。 - ID 必须安全(仅限
[A-Za-z0-9_-];不能包含..、*、?、斜杠)。 - 匹配文件名中包含
_{id}_或_{id}.的文件(支持单张输出和_1.png等多张输出后缀)。 - 使用
ids时不支持compression和file(不会创建新文件)。 - 不能与
sources和n同时使用。
- 图像 ID 数组,用于在主
n(integer,可选)- 设置后,返回主
MEDIA_GEN_DIRS[0]目录中最后的 N 个图像文件。 - 文件按修改时间排序(最近修改的排在最前面)。
- 不能与
sources和ids同时使用。
- 设置后,返回主
compression(object,可选)max_size(integer,可选):最大尺寸,单位为像素。超过此尺寸的图像将被调整大小。max_bytes(integer,可选):目标最大文件大小,单位为字节。默认值:819200(800KB)。quality(integer,可选):JPEG/WebP 质量,范围为 1-100。默认值:85。format("jpeg" | "png" | "webp",可选):输出格式。默认值:jpeg。
response_format("url" | "path" | "b64_json",默认值:"url")- 响应格式:基于文件/URL(
url)、本地路径(path)或内嵌的 base64(b64_json)。
- 响应格式:基于文件/URL(
tool_result("resource_link" | "image",默认值:"resource_link")- 控制
content[]的结构:"resource_link"会输出 ResourceLink 项(基于文件/URL)"image"会输出 base64 ImageContent 块
- 控制
file(string,可选)- 输出文件的基础路径。如果有多张图像,会添加索引后缀。
行为说明:
- 图像会并行处理,以最大限度提高吞吐量。
- 只有提供
compression选项时才会进行压缩。 - 启用压缩后,会使用 sharp 迭代降低质量/尺寸。
- 部分成功:如果部分来源处理失败,仍会返回成功处理的图像,并在响应中列出错误。
- 提供
n时,只有在MEDIA_GEN_MCP_ALLOW_FETCH_LAST_N_IMAGES环境变量设置为true时才会生效。否则,调用会因验证错误而失败。 - 有时,MCP 客户端(例如 ChargeGPT)可能会因超时而不等待
media-gen-mcp的响应。在需要快速获取最新openai-images-generate/openai-images-edit输出的创作环境中,可以使用带n参数的fetch-images。当MEDIA_GEN_MCP_ALLOW_FETCH_LAST_N_IMAGES=true环境变量设置后,即使原始生成或编辑操作在 MCP 客户端一侧超时,fetch-images也会返回MEDIA_GEN_DIRS[0]中最后的 N 个文件。
fetch-videos
从 HTTP(S) URL 或本地文件路径获取视频。
参数(输入架构):
sources(string[],可选)- 视频源数组:HTTP(S) URL 或文件路径(绝对路径,或相对于第一个
MEDIA_GEN_DIRS条目的路径)。 - 最少:1 个,最多:20 个视频。
- 不能与
ids和n同时使用。
- 视频源数组:HTTP(S) URL 或文件路径(绝对路径,或相对于第一个
ids(string[],可选)- 视频 ID 数组,根据主
MEDIA_GEN_DIRS[0]目录下的本地文件名匹配来获取视频。 - ID 必须安全(仅允许
[A-Za-z0-9_-];不能包含..、*、?或斜杠)。 - 匹配文件名中包含
_{id}_或_{id}.的文件(支持单个输出,以及_thumbnail.webp等多资源后缀)。 - 使用
ids时不支持file(不会下载;返回现有文件)。 - 不能与
sources和n同时使用。
- 视频 ID 数组,根据主
n(integer,可选)- 设置后,返回主
MEDIA_GEN_DIRS[0]目录中最新的 N 个视频文件。 - 文件按修改时间排序(最近修改的排在最前面)。
- 不能与
sources和ids同时使用。
- 设置后,返回主
tool_result("resource_link"|"resource",默认值:"resource_link")- 控制
content[]的结构:"resource_link"会生成 ResourceLink 项(基于文件或 URL)"resource"会生成 EmbeddedResource 块,其中包含 base64 格式的resource.blob
- 控制
file(string,可选)- 输出文件的基础路径(从 URL 下载时使用)。如果下载多个视频,会添加索引后缀。
输出:
content:每个已解析的视频对应一个resource_link(默认)或内嵌的resource块,此外还可能包含一个错误摘要文本块。structuredContent:{ data: [{ source, uri, file, mimeType, name, downloaded }], errors?: string[] }。
行为说明:
- 仅当 URL 与
MEDIA_GEN_URLS匹配时(如果已设置),才允许下载 URL。 - 如果提供了
n,仅当环境变量MEDIA_GEN_MCP_ALLOW_FETCH_LAST_N_VIDEOS设置为true时才会生效。否则,调用会因验证错误而失败。
fetch-document
从 HTTP(S) URL 或本地文件路径获取文档。
参数(输入架构):
sources(string[])- 文档源数组:HTTP(S) URL 或文件路径(绝对路径,或相对于第一个
MEDIA_GEN_DIRS条目的路径)。 - 最少:1 个,最多:20 个文档。
- 文档源数组:HTTP(S) URL 或文件路径(绝对路径,或相对于第一个
tool_result("resource_link"|"resource",默认值:"resource_link")- 控制
content[]的结构:"resource_link"会生成 ResourceLink 项(基于文件或 URL)"resource"会生成 EmbeddedResource 块,其中包含 base64 格式的resource.blob
- 控制
file(string,可选)- 输出文件的基础路径(从 URL 下载时使用)。如果下载多个文档,会添加索引后缀。
输出:
content:每个已解析的文档对应一个resource_link(默认)或内嵌的resource块,此外还可能包含一个错误摘要文本块。structuredContent:{ data: [{ source, uri, file, mimeType, name, downloaded }], errors?: string[] }。
行为说明:
- 仅当 URL 与
MEDIA_GEN_URLS匹配时(如果已设置),才允许下载 URL。 - 本地路径会根据
MEDIA_GEN_DIRS进行验证,也可以用file://URL 提供。 - 如果省略
file,默认文件名格式为output_<time_t>_media-gen__fetch-document_<uuid>.<ext>。
test-images
用于测试 MCP 结果放置方式的调试工具,不会调用 OpenAI API。
仅当设置了 MEDIA_GEN_MCP_TEST_SAMPLE_DIR 时启用。该工具会从此目录读取现有图像,不会创建新文件。
参数(输入架构):
response_format("url" | "path" | "b64_json",默认值:"url")result_placement("content" | "api" | "structured" | "toplevel" 或这些值组成的数组,可选)- 为本次调用覆盖
MEDIA_GEN_MCP_RESULT_PLACEMENT。
- 为本次调用覆盖
compression(对象,可选)- 与
fetch-images使用相同的逻辑调优参数,但键采用 camelCase:
- 与
tool_result("resource_link" | "image",默认值:"resource_link")- 控制
content[]的结构:"resource_link"会生成 ResourceLink 项(基于文件/URL)"image"会生成 base64 ImageContent 块maxSize(整数,可选):最大像素尺寸。maxBytes(整数,可选):目标最大文件大小,单位为字节。quality(整数,可选):JPEG/WebP 质量,范围为 1–100。format("jpeg" | "png" | "webp",可选):输出格式。
- 控制
行为说明:
-
从示例目录读取最多 10 张图像(不排序——按文件系统顺序)。
-
使用与
openai-images-generate和openai-images-edit相同的结果构建逻辑(包括result_placement覆盖项)。 -
当
output == "base64"且提供了compression时,会读取示例文件并使用sharp在内存中压缩;不会修改磁盘上的原始文件。 -
可用于测试不同 MCP 客户端如何处理各种结果结构。
-
当
result_placement包含"api"时,该工具会返回模拟 OpenAI Images API 风格的对象:- 顶层:
created、data[]、background、output_format、size、quality。 - 对于
response_format: "b64_json",每个data[i]都包含b64_json。 - 对于
response_format: "path",每个data[i]都包含path。 - 对于
response_format: "url",每个data[i]都包含url,而非b64_json。
- 顶层:
test-images 的调试 CLI 辅助脚本
本地调试时,有两个辅助脚本可直接调用 test-images:
-
npm run test-images– 使用debug/debug-call.ts,并打印 MCP SDK 客户端看到的已验证CallToolResult。用法:npm run test-images -- [placement] [--response_format url|path|b64_json] # examples: # npm run test-images -- structured --response_format b64_json # npm run test-images -- structured --response_format path # npm run test-images -- structured --response_format url -
npm run test-images:raw– 使用debug/debug-call-raw.ts,并打印原始 JSON-RPCresult(底层的CallToolResult,不含额外包装)。CLI 标志与上面相同。
两个脚本都会截断较大的字段,以便阅读:
image_url→ 前 80 个字符,然后是...(N chars);b64_json和data(当其为 base64 字符串时)→ 前 25 个字符,然后是...(N chars)。
🧩 版本策略
语义化版本(SemVer)
此软件包遵循 SemVer:MAJOR.MINOR.PATCH(x.y.z)。
MAJOR— 破坏性变更(工具名称、输入架构、输出结构)。MINOR— 新增工具或向后兼容的扩展(新的可选参数、响应中的新字段)。PATCH— 错误修复和内部重构,不会有意改变行为。
自 1.0.0 起,本项目遵循标准 SemVer 规则:破坏性变更会提升 MAJOR 版本(npm 的 ^1.0.0 允许 1.x,但不允许 2.0.0)。
依赖策略
本仓库旨在与当前稳定版本保持紧密同步:
- MCP SDK:以最新稳定版
@modelcontextprotocol/sdk和 schema 为目标。 - OpenAI SDK:定期更新到最新稳定版
openai包。 - Zod:使用 Zod 4.x 系列(当前为
^4.1.3)。本项目之前使用 Zod 3.x,与 MCP TypeScript SDK 类型定义组合时,将.shape传入inputSchema会触发大量 TypeScript 错误,尤其是 TS2589("type instantiation is excessively deep and possibly infinite")和 TS2322(schema shape not assignable toAnySchema | ZodRawShapeCompat)。我们持续关注上游讨论 modelcontextprotocol/typescript-sdk#494 以及相关的 Zod 类型改进 colinhacks/zod#5222,并让技术栈保持在能够可靠通过完整严格模式编译的组合上。 - 工具链(Node.js、TypeScript 等):使用近期的 LTS 版/当前版本开发和测试,并配有专用的
tsconfig-strict.json,用于启用所有严格 TypeScript 检查(strict、noUnusedLocals、noUnusedParameters、exactOptionalPropertyTypes、noUncheckedIndexedAccess、noPropertyAccessFromIndexSignature等)。
如果你的环境有需要,可以固定或降级 Node.js、TypeScript、OpenAI SDK、Zod 或技术栈中的其他组件,但请注意:
- 我们主要针对最新技术栈进行测试和调整;
- 仅在较旧运行时/SDK 版本上复现的问题,我们可能更难调查和支持;
- 上游兼容性首先根据最新 MCP 规范和 OpenAI Images API 进行验证。
本项目有意保持一定的前瞻性:它会跟进 MCP 和 OpenAI 工具中出现的新功能(尤其是通过 MCP 提供稳健的多模态/图像支持,以及 ChatGPT UI 中的相关支持)。参考资料部分列出了一份关于 ChatGPT 中 MCP 图像渲染的详细真实案例错误报告和分析,作为案例研究。
如果你需要长期稳定的技术栈,请在自己的分支中固定确切版本,并在你的环境中仔细验证。
🧩 类型化工具回调
所有工具处理程序都使用通过 z.input<typeof schema> 从 Zod schema 派生的强类型回调参数:
// Schema definition
const openaiImagesGenerateBaseSchema = z.object({
prompt: z.string().max(32000),
background: z.enum(["transparent", "opaque", "auto"]).optional(),
// ... more fields
});
// Type alias
type OpenAIImagesGenerateArgs = z.input<typeof openaiImagesGenerateBaseSchema>;
// Strictly typed callback
server.registerTool(
"openai-images-generate",
{ inputSchema: openaiImagesGenerateBaseSchema.shape, ... },
async (args: OpenAIImagesGenerateArgs, _extra: unknown) => {
const validated = openaiImagesGenerateSchema.parse(args);
// ... handler logic
},
);
此模式提供:
- 静态类型安全 — IDE 自动补全,并对所有输入字段进行编译时检查。
- 运行时验证 — Zod
.parse()会确保所有输入在处理前均符合 schema。 - MCP SDK 兼容性 —
inputSchema: schema.shape提供用于工具注册的 JSON Schema。
所有工具(openai-images-*、openai-videos-*、fetch-images、fetch-videos、fetch-document、test-images)都遵循此模式。
🧩 工具注解
此 MCP 服务公开了以下带注解提示的工具:
| 工具 | readOnlyHint | destructiveHint | idempotentHint | openWorldHint |
|---|---|---|---|---|
| openai-images-generate | true | false | false | true |
| openai-images-edit | true | false | false | true |
| openai-videos-create | true | false | false | true |
| openai-videos-remix | true | false | false | true |
| openai-videos-list | true | false | false | true |
| openai-videos-retrieve | true | false | false | true |
| openai-videos-delete | true | false | false | true |
| openai-videos-retrieve-content | true | false | false | true |
| fetch-images | true | false | false | false |
| fetch-videos | true | false | false | false |
| fetch-document | true | false | false | false |
| test-images | true | false | false | false |
这些提示有助于 MCP 客户端了解,这些工具:
- 可能会调用外部 API 或读取外部资源(开放世界),
- 不会修改现有项目文件或用户数据;它们只会在配置的输出目录中创建新的媒体文件(图片/视频/文档),
- 即使输入相同,每次调用也可能产生不同的输出。
由于大多数工具的 readOnlyHint 都设为 true,MCP 平台(包括 chatgpt.com)可以将此服务视为逻辑上只读,通常不会显示“此工具可以修改你的文件”警告。
📁 项目结构
media-gen-mcp/
├── src/
│ ├── index.ts # MCP server entry point
│ └── lib/
│ ├── compression.ts # Image compression (sharp)
│ ├── env.ts # Env parsing + allowlists (+ glob support)
│ ├── helpers.ts # URL/path validation, result building
│ ├── logger.ts # Structured logging + truncation helpers
│ └── schemas.ts # Zod schemas for all tools
├── test/
│ ├── compression.test.ts # 12 tests
│ ├── env.test.ts # 19 tests
│ ├── fetch-images.integration.test.ts# 2 tests
│ ├── fetch-videos.integration.test.ts# 2 tests
│ ├── helpers.test.ts # 31 tests
│ ├── logger.test.ts # 10 tests
│ └── schemas.test.ts # 64 tests
├── debug/ # Local debug helpers (MCP client scripts)
├── plan/ # Design notes / plans
├── dist/ # Compiled output
├── tsconfig.json
├── vitest.config.ts
├── package.json
├── CHANGELOG.md
├── README.md
└── AGENTS.md
📝 许可证
MIT
🩺 故障排除
- 确保你的
OPENAI_API_KEY有效且具有图像 API 访问权限。 - 你必须拥有已验证的 OpenAI 组织。验证后,图像 API 访问权限可能需要 15–20 分钟才能激活。
- 文件路径[可选参数]必须是绝对路径。
- Unix/macOS/Linux:以
/开头(例如,/path/to/image.png) - Windows:盘符后跟
:(例如,C:/path/to/image.png或C:\path\to\image.png)
- Unix/macOS/Linux:以
- 对于文件输出,请确保目标目录可写。
- 如果看到与文件类型有关的错误,请检查图像文件的扩展名和格式。
🙏 灵感
本服务最初受到 SureScaleAI/openai-gpt-image-mcp 的启发,但现在已是一个独立实现,专注于紧密遵循官方规范:
- 与 OpenAI Images API 保持一致——
openai-images-generate和openai-images-edit的参数与images.create/gpt-image-1.5一致:prompt、n、size、quality、background、output_format、output_compression、user,以及response_format(url/b64_json), 其语义与 OpenAI Images API 相同。 - 与 MCP 工具结果保持一致(image + resource_link)——当
result_placement = "content"时,服务遵循 MCP 5.2 工具结果 章节 (5.2.2 图像内容, 5.2.4 资源链接) 并输出强类型的content[]条目:- 对于
response_format = "b64_json",输出{ "type": "image", "data": "<base64>", "mimeType": "image/png" }; - 对于基于文件/URL 的输出,输出
{ "type": "resource_link", "uri": "file:///..." | "https://...", "name": "...", "mimeType": "image/..." }。
- 对于
- 原始 OpenAI 风格 API 输出——当
result_placement = "api"时,工具 结果本身就是一个 OpenAI Images 风格的对象:{ created, data: [...], background, output_format, size, quality, usage? }, 其中每个data[]条目包含b64_json(当response_format = "b64_json"时)或url(当response_format = "url"时)。此模式下不会添加 MCP 包装字段(content、structuredContent、files、urls)。
简而言之,这个库:
- 当
result_placement = "api"且response_format = "url" | "b64_json"时, 在参数和结果结构上遵循 OpenAI Images API;并且 - 当
result_placement = "content"时,在工具结果内容块(image、resource_link、text)上遵循 MCP 规范。
常见客户端的推荐预设
-
默认模式 / Claude Desktop / 严格遵循 MCP 规范的客户端
对于严格遵循 MCP 规范的客户端,推荐且自然的配置是:result_placement = contentresponse_format = b64_json
在此模式下,服务会返回:
content[],其中包含type: "image"(base64 图像数据)和type: "resource_link"(文件/URL 链接),符合 MCP 第 5.2 节(图像 内容和资源链接)。此输出非常适合与 Claude Desktop 及任何完整实现 2025‑11‑25 规范的客户端直接集成。
-
chatgpt.com Developer Mode
若要将此服务作为 MCP 后端接入 ChatGPT Developer Mode,最实用的配置是 尽可能贴近 OpenAI Images API 的配置:result_placement = apiresponse_format = url
在此模式下,工具结果与
images.create/gpt-image-1.5的格式 一致(包括data[].url),这让预期使用 OpenAI 架构的后端和库更容易 处理结果。但是,即使采用这种原生 OpenAI 格式,chatgpt.com 客户端目前仍无法 渲染图像。以下报告对此行为作了详细说明:
https://github.com/strato-space/report/issues/1
⚠️ 局限性与大型文件处理
- 可配置的负载保护: 默认情况下,此服务会为内联
content使用约 50MB(52,428,800 字节)的预算,以适应常见 MCP 客户端的限制。你可以通过设置MCP_MAX_CONTENT_BYTES环境变量来提高(或降低)此阈值。 - 自动切换为文件输出: 如果图像的 base64 总大小超过配置的阈值,工具会自动将图像保存到磁盘,并通过
resource_link返回文件路径,而不是内联 base64。这有助于避免客户端出现“负载过大”错误,同时仍能提供完整分辨率的图像。 - 默认文件位置: 如果未指定
file路径,输出会以output_<time_t>_media-gen__<tool>_<id>.<ext>这样的名称保存在MEDIA_GEN_DIRS[0]下(默认:/tmp/media-gen-mcp)。 - 环境变量:
MEDIA_GEN_DIRS:设置此变量以控制输出文件的保存位置。示例:export MEDIA_GEN_DIRS=/your/desired/dir。如果直接从该目录提供文件服务,此目录可以与公共静态文件目录相同。MEDIA_GEN_MCP_URL_PREFIXES:可选的、以逗号分隔的 HTTPS 前缀,按位置与MEDIA_GEN_DIRS条目对应。设置后,服务会构建公共 URL,格式为<prefix>/<relative_path_inside_root>,并与文件路径一同返回(例如通过resource_linkURI,以及response_format: "url"时的structuredContent.data[].url)。示例:export MEDIA_GEN_MCP_URL_PREFIXES=https://media-gen.example.com/media,https://media-gen.example.com/samples- 最佳实践: 对于大型图像或生产环境中的图像,始终使用文件输出,并确保客户端已配置为处理文件路径。配置
MEDIA_GEN_DIRS,并可选配置MEDIA_GEN_MCP_URL_PREFIXES,通过公共 Web 服务(例如 nginx)提供图像。
🌐 通过 HTTPS 提供生成的文件
如果你希望 ChatGPT(或任何 MCP 客户端)在文件路径旁一并提供可公开访问的 URL:
-
通过 HTTPS 公开你的图像目录。例如,使用 nginx:
server { # listen 443 ssl http2; # server_name <server_name>; # ssl_certificate <path>; # ssl_certificate_key <path>; location /media/ { alias /home/username/media-gen-mcp/media/; autoindex off; expires 7d; add_header Cache-Control "public, immutable"; } } -
确保
MEDIA_GEN_DIRS中的第一项指向同一目录(例如MEDIA_GEN_DIRS=/home/username/media-gen-mcp/media/,或者在项目根目录运行时使用MEDIA_GEN_DIRS=media/)。 -
设置
MEDIA_GEN_MCP_URL_PREFIXES=https://media-gen.example.com/media,使服务在顶层urls、resource_linkURI 和image_url字段中返回相应的 HTTPS URL(对于response_format: "url")。
现在,openai-images-generate 和 openai-images-edit 在 base64 和 文件响应模式下都会附带 files + urls,使客户端可以引用本地文件系统路径或公共 HTTPS 链接。这在 ChatGPT 尚无法内联渲染 MCP 图像块时尤其有用。
📚 参考资料
-
Model Context Protocol
-
OpenAI Images
-
OpenAI Videos
-
案例研究
- ChatGPT 中的 MCP 图像渲染(GitHub issue)
- 症状: ChatGPT 经常忽略或错误处理 MCP
image内容块:工具结果为空、将原始 base64 当作文本处理(消耗大量 token),或给出笼统的“我看不到图像”回复;而其他 MCP 客户端(Cursor、Claude)都能正确渲染相同的图像。 - 根本原因: 问题不在 MCP 规范本身,而在于 ChatGPT 处理/序列化 MCP
CallToolResult图像内容块和媒体对象的方式(尤其是 UI 渲染和嵌套容器相关部分)。 - 状态与变通方法: OpenAI 已开始为 Codex/ChatGPT 推出 MCP 图像支持修复,但行为仍不一致;此服务采用 file/resource_link + URL 模式和符合规范的
image块,确保工具在当前和未来的 MCP 客户端中均可使用。
- 症状: ChatGPT 经常忽略或错误处理 MCP
- ChatGPT 中的 MCP 图像渲染(GitHub issue)
🙏 致谢
- 使用 @modelcontextprotocol/sdk 构建
- 使用 openai Node.js SDK
- 在 Windsurf 和 GPT-5 High Reasoning 的协助下完成重构并与 MCP 规范保持一致
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。