mcp-duojie-image 0.5.4 → 0.5.5

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.
Files changed (2) hide show
  1. package/dist/provider.js +23 -5
  2. package/package.json +1 -1
package/dist/provider.js CHANGED
@@ -46,8 +46,21 @@ function mapSize(size) {
46
46
  function isOpenAIImageModel(model) {
47
47
  return model === "gpt-image-2";
48
48
  }
49
+ function normalizeAspectRatio(aspectRatio) {
50
+ const normalized = aspectRatio?.trim().replace(":", ":").replace(/\s+/g, "");
51
+ const match = normalized?.match(/^(\d+(?:\.\d+)?):(\d+(?:\.\d+)?)$/);
52
+ if (!match)
53
+ return undefined;
54
+ const width = Number(match[1]);
55
+ const height = Number(match[2]);
56
+ if (!Number.isFinite(width) || !Number.isFinite(height) || width <= 0 || height <= 0) {
57
+ return undefined;
58
+ }
59
+ return `${match[1]}:${match[2]}`;
60
+ }
49
61
  function parseAspectRatio(aspectRatio) {
50
- const match = aspectRatio?.match(/^(\d+):(\d+)$/);
62
+ const normalized = normalizeAspectRatio(aspectRatio);
63
+ const match = normalized?.match(/^(\d+(?:\.\d+)?):(\d+(?:\.\d+)?)$/);
51
64
  if (!match)
52
65
  return [1, 1];
53
66
  return [Number(match[1]), Number(match[2])];
@@ -78,10 +91,11 @@ function mapOpenAISize(size, aspectRatio) {
78
91
  };
79
92
  if (size === "4K")
80
93
  return mapOpenAI4KSize(aspectRatio);
81
- if (aspectRatio === "16:9" || aspectRatio === "3:2" || aspectRatio === "4:3") {
94
+ const [ratioWidth, ratioHeight] = parseAspectRatio(aspectRatio);
95
+ if (ratioWidth > ratioHeight) {
82
96
  return size === "2K" ? "2048x1536" : "1536x1024";
83
97
  }
84
- if (aspectRatio === "9:16" || aspectRatio === "2:3" || aspectRatio === "3:4") {
98
+ if (ratioHeight > ratioWidth) {
85
99
  return size === "2K" ? "1536x2048" : "1024x1536";
86
100
  }
87
101
  return squareBySize[size] ?? "1024x1024";
@@ -149,7 +163,8 @@ async function generateGeminiImage(config, opts) {
149
163
  async function generateOpenAIImage(config, opts) {
150
164
  const model = opts.model ?? config.model;
151
165
  const prompt = opts.negativePrompt ? `${opts.prompt}\n\nAvoid: ${opts.negativePrompt}` : opts.prompt;
152
- const size = mapOpenAISize(opts.size ?? "1K", opts.aspectRatio);
166
+ const aspectRatio = normalizeAspectRatio(opts.aspectRatio);
167
+ const size = mapOpenAISize(opts.size ?? "1K", aspectRatio);
153
168
  const hasReferenceImages = Boolean(opts.referenceImages?.length);
154
169
  const url = `${config.baseUrl}${hasReferenceImages ? "/v1/images/edits" : "/v1/images/generations"}`;
155
170
  let body;
@@ -161,6 +176,9 @@ async function generateOpenAIImage(config, opts) {
161
176
  form.set("model", model);
162
177
  form.set("prompt", prompt);
163
178
  form.set("size", size);
179
+ if (aspectRatio) {
180
+ form.set("aspect_ratio", aspectRatio);
181
+ }
164
182
  for (const [index, imgPath] of opts.referenceImages.entries()) {
165
183
  const data = await resizeIfNeeded(imgPath);
166
184
  const bytes = data.buffer.slice(data.byteOffset, data.byteOffset + data.byteLength);
@@ -170,7 +188,7 @@ async function generateOpenAIImage(config, opts) {
170
188
  }
171
189
  else {
172
190
  headers = { ...headers, "Content-Type": "application/json" };
173
- body = JSON.stringify({ model, prompt, size });
191
+ body = JSON.stringify({ model, prompt, size, ...(aspectRatio ? { aspect_ratio: aspectRatio } : {}) });
174
192
  }
175
193
  const res = await fetchWithRetry(url, {
176
194
  method: "POST",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mcp-duojie-image",
3
- "version": "0.5.4",
3
+ "version": "0.5.5",
4
4
  "description": "MCP server for image generation via duojie.games",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",