mcp-duojie-image 0.8.0 → 0.9.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 +2 -4
- package/dist/index.js +1 -4
- package/dist/provider.js +4 -20
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -5,9 +5,7 @@ MCP server for image generation via duojie.games GPT image API.
|
|
|
5
5
|
## Features
|
|
6
6
|
|
|
7
7
|
- Text-to-image generation with `gpt-image-2`
|
|
8
|
-
- Reference image support with
|
|
9
|
-
- `reference` / `style_reference` / `composition_reference` / `insert_source` → `/v1/images/generations` (JSON body + base64 data URIs; stable endpoint)
|
|
10
|
-
- `edit_target` → `/v1/images/edits` (multipart form; for modifying an existing image)
|
|
8
|
+
- Reference image support: requests with reference images route through `/v1/images/edits` (multipart form); text-only requests route through `/v1/images/generations` (JSON body)
|
|
11
9
|
- Prompt structuring helpers for use case, asset type, constraints, and effective prompt echo
|
|
12
10
|
- Optional chroma-key transparent background post-processing
|
|
13
11
|
- Async submission with task status lookup
|
|
@@ -63,7 +61,7 @@ Supported `input_images.role` values:
|
|
|
63
61
|
- `composition_reference`
|
|
64
62
|
- `insert_source`
|
|
65
63
|
|
|
66
|
-
**Endpoint routing:**
|
|
64
|
+
**Endpoint routing:** Any request with reference images is sent to `/v1/images/edits` as a multipart form, which correctly handles both reference images and the `size`/`aspect_ratio` parameters. Text-only requests (no reference images) are sent to `/v1/images/generations` as a JSON body. The `role` field on `input_images` is used only for prompt structuring, not for endpoint selection.
|
|
67
65
|
|
|
68
66
|
When both `input_images` and `reference_images` are provided, `input_images` takes precedence. `generate_image` returns `effective_prompt` so callers can diagnose the exact prompt sent upstream.
|
|
69
67
|
|
package/dist/index.js
CHANGED
|
@@ -34,7 +34,7 @@ const server = new McpServer({
|
|
|
34
34
|
version: "0.1.0",
|
|
35
35
|
});
|
|
36
36
|
server.registerTool("generate_image", {
|
|
37
|
-
description: "Generate image async with gpt-image-2. Reference
|
|
37
|
+
description: "Generate image async with gpt-image-2. Reference images route through /v1/images/edits (multipart form); text-only requests route through /v1/images/generations. Return after tool call; don't wait/check.",
|
|
38
38
|
inputSchema: z.object({
|
|
39
39
|
prompt: z.string().min(1).describe("Prompt"),
|
|
40
40
|
output_dir: z.string().describe("Absolute output dir"),
|
|
@@ -105,8 +105,6 @@ server.registerTool("generate_image", {
|
|
|
105
105
|
}
|
|
106
106
|
const task = createTask();
|
|
107
107
|
updateTask(task.id, { effectivePrompt: preparedPrompt.prompt });
|
|
108
|
-
// 只有 edit_target 角色才走 edits 端点;reference/style/composition 走 generations
|
|
109
|
-
const hasEditTarget = preparedPrompt.imageInputs?.some((img) => img.role === "edit_target") ?? false;
|
|
110
108
|
// Start background generation (don't await)
|
|
111
109
|
(async () => {
|
|
112
110
|
try {
|
|
@@ -114,7 +112,6 @@ server.registerTool("generate_image", {
|
|
|
114
112
|
let imageBuffer = await generateImage(config, {
|
|
115
113
|
prompt: preparedPrompt.prompt,
|
|
116
114
|
referenceImages: preparedPrompt.imagePaths,
|
|
117
|
-
useEditsEndpoint: hasEditTarget,
|
|
118
115
|
size: args.size ?? "1K",
|
|
119
116
|
aspectRatio: args.aspect_ratio,
|
|
120
117
|
referenceMaxSide: args.preserve_reference_detail ? false : args.reference_max_side,
|
package/dist/provider.js
CHANGED
|
@@ -105,16 +105,16 @@ async function generateOpenAIImage(config, opts) {
|
|
|
105
105
|
const prompt = opts.prompt;
|
|
106
106
|
const size = mapOpenAISize(opts.size, opts.aspectRatio);
|
|
107
107
|
const hasReferenceImages = Boolean(opts.referenceImages?.length);
|
|
108
|
-
//
|
|
109
|
-
//
|
|
110
|
-
const useEdits = hasReferenceImages
|
|
108
|
+
// 有参考图 → /v1/images/edits(multipart form)
|
|
109
|
+
// 无参考图 → /v1/images/generations(JSON body,纯文本)
|
|
110
|
+
const useEdits = hasReferenceImages;
|
|
111
111
|
const url = `${config.baseUrl}${useEdits ? "/v1/images/edits" : "/v1/images/generations"}`;
|
|
112
112
|
let body;
|
|
113
113
|
let headers = {
|
|
114
114
|
Authorization: `Bearer ${config.apiKey}`,
|
|
115
115
|
};
|
|
116
116
|
if (useEdits) {
|
|
117
|
-
//
|
|
117
|
+
// 有参考图:multipart form
|
|
118
118
|
const form = new FormData();
|
|
119
119
|
form.set("model", GPT_IMAGE_MODEL);
|
|
120
120
|
form.set("prompt", prompt);
|
|
@@ -129,22 +129,6 @@ async function generateOpenAIImage(config, opts) {
|
|
|
129
129
|
}
|
|
130
130
|
body = form;
|
|
131
131
|
}
|
|
132
|
-
else if (hasReferenceImages) {
|
|
133
|
-
// reference/style/composition: generations + base64 data URIs in JSON body
|
|
134
|
-
const imageUrls = [];
|
|
135
|
-
for (const imgPath of opts.referenceImages) {
|
|
136
|
-
const data = await resizeIfNeeded(imgPath, opts.referenceMaxSide);
|
|
137
|
-
imageUrls.push(`data:image/webp;base64,${data.toString("base64")}`);
|
|
138
|
-
}
|
|
139
|
-
headers = { ...headers, "Content-Type": "application/json" };
|
|
140
|
-
body = JSON.stringify({
|
|
141
|
-
model: GPT_IMAGE_MODEL,
|
|
142
|
-
prompt,
|
|
143
|
-
size,
|
|
144
|
-
image: imageUrls,
|
|
145
|
-
...(opts.aspectRatio ? { aspect_ratio: opts.aspectRatio } : {}),
|
|
146
|
-
});
|
|
147
|
-
}
|
|
148
132
|
else {
|
|
149
133
|
// 纯文本生成
|
|
150
134
|
headers = { ...headers, "Content-Type": "application/json" };
|