gpt-image-mcp 0.2.1 → 0.3.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 +9 -92
- package/dist/config.js +22 -1
- package/dist/images.js +8 -4
- package/dist/index.js +1 -1
- package/dist/server.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -6,58 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
需要 Node.js 22 或更高版本,以及具有所选模型调用权限和可用额度的 OpenAI 或兼容服务商 API 密钥。支持 Linux、macOS 和 Windows。无需手动安装,通过 `npx` 自动下载运行。
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
一条命令完成配置(仅当前项目生效):
|
|
12
|
-
|
|
13
|
-
```sh
|
|
14
|
-
claude mcp add image-gen -- npx -y gpt-image-mcp
|
|
15
|
-
```
|
|
16
|
-
|
|
17
|
-
不同作用域:
|
|
18
|
-
|
|
19
|
-
| 命令 | 作用域 |
|
|
20
|
-
| --- | --- |
|
|
21
|
-
| `claude mcp add image-gen -- npx -y gpt-image-mcp` | 当前项目,仅自己可见 |
|
|
22
|
-
| `claude mcp add --scope project image-gen -- npx -y gpt-image-mcp` | 写入 `.mcp.json`,团队共享 |
|
|
23
|
-
| `claude mcp add --scope user image-gen -- npx -y gpt-image-mcp` | 全局,跨项目生效 |
|
|
24
|
-
|
|
25
|
-
添加后需要设置环境变量。编辑对应配置文件,在 `image-gen` 下添加 `env` 字段:
|
|
26
|
-
|
|
27
|
-
```json
|
|
28
|
-
{
|
|
29
|
-
"env": {
|
|
30
|
-
"OPENAI_API_KEY": "你的 API 密钥",
|
|
31
|
-
"OPENAI_BASE_URL": "https://你的服务商/v1",
|
|
32
|
-
"IMAGE_GEN_MODEL": "服务商提供的图片模型名称",
|
|
33
|
-
"IMAGE_GEN_OUTPUT_DIR": "~/pictures"
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
```
|
|
37
|
-
|
|
38
|
-
仅 `OPENAI_API_KEY` 必填,其余按需配置。详见下方[配置](#配置)章节。
|
|
39
|
-
|
|
40
|
-
### Claude Desktop
|
|
41
|
-
|
|
42
|
-
编辑 `claude_desktop_config.json`(macOS 路径 `~/Library/Application Support/Claude/claude_desktop_config.json`):
|
|
43
|
-
|
|
44
|
-
```json
|
|
45
|
-
{
|
|
46
|
-
"mcpServers": {
|
|
47
|
-
"image-gen": {
|
|
48
|
-
"command": "npx",
|
|
49
|
-
"args": ["-y", "gpt-image-mcp"],
|
|
50
|
-
"env": {
|
|
51
|
-
"OPENAI_API_KEY": "你的 API 密钥"
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
```
|
|
57
|
-
|
|
58
|
-
### Cursor
|
|
59
|
-
|
|
60
|
-
在项目根目录创建 `.cursor/mcp.json`:
|
|
9
|
+
MCP 配置(适用于 Claude Code、Claude Desktop、Cursor 等支持 MCP 的客户端):
|
|
61
10
|
|
|
62
11
|
```json
|
|
63
12
|
{
|
|
@@ -66,53 +15,19 @@ claude mcp add image-gen -- npx -y gpt-image-mcp
|
|
|
66
15
|
"command": "npx",
|
|
67
16
|
"args": ["-y", "gpt-image-mcp"],
|
|
68
17
|
"env": {
|
|
69
|
-
"OPENAI_API_KEY": "你的 API 密钥"
|
|
18
|
+
"OPENAI_API_KEY": "你的 API 密钥",
|
|
19
|
+
"OPENAI_BASE_URL": "https://你的服务商/v1",
|
|
20
|
+
"IMAGE_GEN_MODEL": "服务商提供的图片模型名称",
|
|
21
|
+
"IMAGE_GEN_OUTPUT_DIR": "~/pictures"
|
|
70
22
|
}
|
|
71
23
|
}
|
|
72
24
|
}
|
|
73
25
|
}
|
|
74
26
|
```
|
|
75
27
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
在 `.codex/config.toml` 中配置,需要写全 `npx` 的绝对路径(运行 `which npx` 获取):
|
|
79
|
-
|
|
80
|
-
```toml
|
|
81
|
-
[mcp_servers.image-gen]
|
|
82
|
-
command = "/你的npx路径/bin/npx"
|
|
83
|
-
args = ["-y", "gpt-image-mcp"]
|
|
84
|
-
|
|
85
|
-
[mcp_servers.image-gen.env]
|
|
86
|
-
OPENAI_API_KEY = "你的 API 密钥"
|
|
87
|
-
```
|
|
88
|
-
|
|
89
|
-
### Windows 补充
|
|
90
|
-
|
|
91
|
-
Windows 上如果客户端无法直接启动 npx,可将 `command` 和 `args` 改为:
|
|
92
|
-
|
|
93
|
-
```json
|
|
94
|
-
{
|
|
95
|
-
"command": "cmd",
|
|
96
|
-
"args": ["/d", "/c", "npx", "-y", "gpt-image-mcp"]
|
|
97
|
-
}
|
|
98
|
-
```
|
|
99
|
-
|
|
100
|
-
### 全局安装(可选)
|
|
101
|
-
|
|
102
|
-
如果希望避免首次启动的下载等待,也可以全局安装后直接使用命令名:
|
|
103
|
-
|
|
104
|
-
```sh
|
|
105
|
-
npm install --global gpt-image-mcp
|
|
106
|
-
```
|
|
107
|
-
|
|
108
|
-
安装后将配置中的 `"command"` 改为 `"gpt-image-mcp"`,去掉 `"args"`。
|
|
109
|
-
|
|
110
|
-
### 通用说明
|
|
28
|
+
仅 `OPENAI_API_KEY` 必填,其余按需配置。详见下方[配置](#配置)章节。
|
|
111
29
|
|
|
112
|
-
|
|
113
|
-
- 工具执行超时建议设为至少 360 秒,具体配置字段由客户端决定;服务自身的 API 超时默认为 300 秒
|
|
114
|
-
- 服务启动后会等待 MCP 输入,直接在终端运行时没有欢迎输出属于正常行为
|
|
115
|
-
- 日志只写入 stderr,stdout 保留给 MCP 协议
|
|
30
|
+
首次启动会自动下载依赖,之后使用缓存。工具执行超时建议设为至少 360 秒;服务自身的 API 超时默认为 300 秒。
|
|
116
31
|
|
|
117
32
|
## 配置
|
|
118
33
|
|
|
@@ -124,6 +39,8 @@ npm install --global gpt-image-mcp
|
|
|
124
39
|
| `IMAGE_GEN_OUTPUT_DIR` | 用户主目录下的 `gpt-image-mcp/images` | 输出根目录,支持本机绝对路径或 `~/`;自动按本地日期创建 `yyyy/MM/dd` 子目录 |
|
|
125
40
|
| `IMAGE_GEN_TIMEOUT_MS` | `300000` | API 请求超时,单位毫秒,必须为不小于 1000 的整数 |
|
|
126
41
|
| `IMAGE_GEN_RESPONSE_FORMAT` | `b64_json` | API 返回图片的方式:`b64_json`(返回 Base64 数据)或 `url`(返回下载地址,服务自动下载保存)。默认 `b64_json` 时不向 API 发送此参数,仅配置 `url` 时才显式发送。部分代理对新模型(如 `gpt-image-2.5-sunburst`)可能不支持此参数,遇到 `unknown_parameter` 错误时请保持默认值 |
|
|
42
|
+
| `IMAGE_GEN_DEFAULT_SIZE` | `auto` | 全局默认分辨率,格式为 `WIDTHxHEIGHT`(如 `1024x1024`)。不填或留空时使用 `auto`,由 API 自行决定。宽高需为 16 的倍数,比例不超过 3:1,总像素 655360~8294400。单次调用仍可通过 `size` 参数覆盖 |
|
|
43
|
+
| `IMAGE_GEN_DEFAULT_QUALITY` | `auto` | 全局默认质量:`auto`、`low`、`medium`、`high`、`xhigh`、`max`。不填或留空时使用 `auto`,由 API 自行决定。单次调用仍可通过 `quality` 参数覆盖 |
|
|
127
44
|
|
|
128
45
|
`OPENAI_BASE_URL` 填写 API 根地址;未配置、空字符串或纯空格均使用官方端点。只有地址不包含路径时自动补 `/v1`,已有路径则按用户配置保留,避免破坏代理前缀或其他版本。尾部斜杠会去除,不会重复追加 `/v1`。
|
|
129
46
|
|
package/dist/config.js
CHANGED
|
@@ -36,11 +36,32 @@ export function readConfig(env = process.env) {
|
|
|
36
36
|
if (responseFormat !== "b64_json" && responseFormat !== "url") {
|
|
37
37
|
throw new Error("IMAGE_GEN_RESPONSE_FORMAT 仅支持 b64_json 或 url。");
|
|
38
38
|
}
|
|
39
|
+
const defaultSize = parseDefaultSize(env.IMAGE_GEN_DEFAULT_SIZE?.trim());
|
|
40
|
+
const validQualities = ["auto", "low", "medium", "high", "xhigh", "max"];
|
|
41
|
+
const defaultQuality = (env.IMAGE_GEN_DEFAULT_QUALITY?.trim() || "auto");
|
|
42
|
+
if (!validQualities.includes(defaultQuality)) {
|
|
43
|
+
throw new Error(`IMAGE_GEN_DEFAULT_QUALITY 仅支持 ${validQualities.join("、")}。`);
|
|
44
|
+
}
|
|
39
45
|
return {
|
|
40
|
-
apiKey, baseURL, model, timeout, responseFormat,
|
|
46
|
+
apiKey, baseURL, model, timeout, responseFormat, defaultSize, defaultQuality,
|
|
41
47
|
outputDir: outputDir ? localPath(outputDir) : path.join(homedir(), "gpt-image-mcp", "images"),
|
|
42
48
|
};
|
|
43
49
|
}
|
|
50
|
+
/** 校验 IMAGE_GEN_DEFAULT_SIZE:空值返回 "auto",否则必须满足 WIDTHxHEIGHT 约束。 */
|
|
51
|
+
function parseDefaultSize(value) {
|
|
52
|
+
if (!value)
|
|
53
|
+
return "auto";
|
|
54
|
+
const match = /^(\d+)x(\d+)$/.exec(value);
|
|
55
|
+
if (!match)
|
|
56
|
+
throw new Error("IMAGE_GEN_DEFAULT_SIZE 格式必须为 WIDTHxHEIGHT(如 1024x1024)。");
|
|
57
|
+
const w = Number(match[1]), h = Number(match[2]);
|
|
58
|
+
if (w % 16 !== 0 || h % 16 !== 0 || w <= 0 || h <= 0
|
|
59
|
+
|| Math.max(w, h) / Math.min(w, h) > 3
|
|
60
|
+
|| w * h < 655_360 || w * h > 8_294_400) {
|
|
61
|
+
throw new Error("IMAGE_GEN_DEFAULT_SIZE 宽高需为 16 的倍数,比例不超过 3:1,总像素 655360~8294400。");
|
|
62
|
+
}
|
|
63
|
+
return value;
|
|
64
|
+
}
|
|
44
65
|
/** 仅为无路径地址补 /v1;显式路径代表用户选择,不能猜测并改写。 */
|
|
45
66
|
function normalizeBaseURL(value) {
|
|
46
67
|
let url;
|
package/dist/images.js
CHANGED
|
@@ -56,9 +56,11 @@ export class ImageService {
|
|
|
56
56
|
* @throws 上游请求失败、结果不可解析或本地保存失败时抛出错误。
|
|
57
57
|
*/
|
|
58
58
|
async generate(input, signal) {
|
|
59
|
+
const size = input.size === "auto" ? this.config.defaultSize : input.size;
|
|
60
|
+
const quality = input.quality === "auto" ? this.config.defaultQuality : input.quality;
|
|
59
61
|
const response = await this.client.images.generate({
|
|
60
|
-
model: this.config.model, prompt: input.prompt, size
|
|
61
|
-
quality
|
|
62
|
+
model: this.config.model, prompt: input.prompt, size,
|
|
63
|
+
quality, output_format: input.format, n: 1,
|
|
62
64
|
background: input.background,
|
|
63
65
|
moderation: input.moderation,
|
|
64
66
|
...(this.config.responseFormat === "url" && { response_format: "url" }),
|
|
@@ -94,9 +96,11 @@ export class ImageService {
|
|
|
94
96
|
throw new Error("遮罩必须是带透明通道的 PNG,且尺寸与第一张原图一致。");
|
|
95
97
|
}
|
|
96
98
|
}
|
|
99
|
+
const size = input.size === "auto" ? this.config.defaultSize : input.size;
|
|
100
|
+
const quality = input.quality === "auto" ? this.config.defaultQuality : input.quality;
|
|
97
101
|
const response = await this.client.images.edit({
|
|
98
|
-
model: this.config.model, prompt: input.prompt, size
|
|
99
|
-
quality
|
|
102
|
+
model: this.config.model, prompt: input.prompt, size,
|
|
103
|
+
quality, output_format: input.format, n: 1,
|
|
100
104
|
background: input.background,
|
|
101
105
|
image: images.map((image) => image.upload), mask: mask?.upload,
|
|
102
106
|
...(this.config.responseFormat === "url" && { response_format: "url" }),
|
package/dist/index.js
CHANGED
|
@@ -8,7 +8,7 @@ import { createServer } from "./server.js";
|
|
|
8
8
|
try {
|
|
9
9
|
const args = process.argv.slice(2);
|
|
10
10
|
if (args.length === 1 && args[0] === "--help") {
|
|
11
|
-
process.stdout.write("gpt-image-mcp\n\n用法:\n gpt-image-mcp 启动本地 stdio MCP 服务\n gpt-image-mcp --check 检查模型列表接口,不发送生图请求\n gpt-image-mcp --help 显示帮助\n\n配置:OPENAI_API_KEY、OPENAI_BASE_URL、IMAGE_GEN_MODEL、IMAGE_GEN_OUTPUT_DIR、IMAGE_GEN_TIMEOUT_MS、IMAGE_GEN_RESPONSE_FORMAT\n");
|
|
11
|
+
process.stdout.write("gpt-image-mcp\n\n用法:\n gpt-image-mcp 启动本地 stdio MCP 服务\n gpt-image-mcp --check 检查模型列表接口,不发送生图请求\n gpt-image-mcp --help 显示帮助\n\n配置:OPENAI_API_KEY、OPENAI_BASE_URL、IMAGE_GEN_MODEL、IMAGE_GEN_OUTPUT_DIR、IMAGE_GEN_TIMEOUT_MS、IMAGE_GEN_RESPONSE_FORMAT、IMAGE_GEN_DEFAULT_SIZE、IMAGE_GEN_DEFAULT_QUALITY\n");
|
|
12
12
|
}
|
|
13
13
|
else if (args.length === 1 && args[0] === "--check") {
|
|
14
14
|
const config = readConfig();
|
package/dist/server.js
CHANGED
|
@@ -50,7 +50,7 @@ async function toolResult(operation) {
|
|
|
50
50
|
*/
|
|
51
51
|
export function createServer(config, client = createApiClient(config)) {
|
|
52
52
|
const service = new ImageService(client, config);
|
|
53
|
-
const server = new McpServer({ name: "gpt-image-mcp", version: "0.
|
|
53
|
+
const server = new McpServer({ name: "gpt-image-mcp", version: "0.3.0" });
|
|
54
54
|
const annotations = { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true };
|
|
55
55
|
server.registerTool("check_endpoint", {
|
|
56
56
|
title: "端点检查",
|