gpteam 0.1.23 → 0.1.26
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 +3 -3
- package/lib/config.js +2 -3
- package/lib/help.js +1 -1
- package/lib/image-mcp/image.js +3 -2
- package/lib/image-mcp/server.js +7 -8
- package/lib/models.js +8 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -16,14 +16,14 @@ Client config writing follows the same safety pattern as cc-switch: keep Codex t
|
|
|
16
16
|
|
|
17
17
|
The Image MCP config uses cc-switch-style per-client env blocks. Codex writes `[mcp_servers.gpteam_image.env]`, OpenCode writes `mcp.gpteam_image.environment`, and Claude Code writes `mcpServers.gpteam_image.env` in `~/.claude.json`. The MCP receives `GPTEAM_API_KEY` and `GPTEAM_BASE_URL` from that MCP config, so it does not depend on Codex `auth.json` or inherited `OPENAI_API_KEY`.
|
|
18
18
|
|
|
19
|
-
The Image MCP exposes
|
|
19
|
+
The Image MCP exposes an async-first local job flow plus a legacy compatibility alias:
|
|
20
20
|
|
|
21
21
|
- `create_image_job`: recommended for normal use. It starts a local background image job and returns `job_id` quickly, which avoids losing the whole generation when a VPN, proxy, or client has a 60-second idle timeout.
|
|
22
22
|
- `get_image_job_status`: checks whether the local job is queued, running, succeeded, failed, canceled, or expired.
|
|
23
23
|
- `cancel_image_job`: cancels a queued/running local job.
|
|
24
|
-
- `download_image_result`: returns the completed file metadata and
|
|
24
|
+
- `download_image_result`: returns the completed file metadata and local file path by default. Pass `include_image: true` only when the client must receive MCP image content, because large images can trigger context compaction.
|
|
25
25
|
- `get_capabilities`: returns supported sizes, formats, quality values, async support, cancellation semantics, queue limits, and image-to-image support.
|
|
26
|
-
- `generate_image`:
|
|
26
|
+
- `generate_image`: legacy compatibility alias. It now creates the same async job and returns `job_id` immediately instead of blocking until the image is complete.
|
|
27
27
|
|
|
28
28
|
Image MCP results are returned as stable JSON text and MCP `structuredContent`. Successful results include final file path, model, action, size, format, quality, byte size, SHA-256, MIME type, image dimensions, duration, retry count, `job_id`, `trace_id`, and optional `idempotency_key`. Error results use stable `error.code`, `error.message`, `error.retryable`, `error.stage`, `error.upstream_status`, and `error.trace_id` fields while keeping compatibility fields such as `category` and `http_status`.
|
|
29
29
|
|
package/lib/config.js
CHANGED
|
@@ -13,8 +13,7 @@ const IMAGE_MCP_ENABLED_TOOLS = [
|
|
|
13
13
|
'get_image_job_status',
|
|
14
14
|
'download_image_result',
|
|
15
15
|
'cancel_image_job',
|
|
16
|
-
'get_capabilities'
|
|
17
|
-
'generate_image'
|
|
16
|
+
'get_capabilities'
|
|
18
17
|
];
|
|
19
18
|
|
|
20
19
|
export const CLIENTS = [
|
|
@@ -63,7 +62,7 @@ export function writeCodexConfig(settings) {
|
|
|
63
62
|
`command = ${tomlString(mcpCommand.command)}`,
|
|
64
63
|
`args = [${mcpCommand.args.map((arg) => tomlString(arg)).join(', ')}]`,
|
|
65
64
|
'startup_timeout_sec = 20',
|
|
66
|
-
'tool_timeout_sec =
|
|
65
|
+
'tool_timeout_sec = 900',
|
|
67
66
|
`enabled_tools = [${IMAGE_MCP_ENABLED_TOOLS.map((name) => tomlString(name)).join(', ')}]`,
|
|
68
67
|
'default_tools_approval_mode = "prompt"',
|
|
69
68
|
'',
|
package/lib/help.js
CHANGED
package/lib/image-mcp/image.js
CHANGED
|
@@ -39,7 +39,7 @@ export const IMAGE_SIZE_CONSTRAINTS = {
|
|
|
39
39
|
|
|
40
40
|
const defaultMaxAttempts = 3;
|
|
41
41
|
const defaultRetryDelayMs = 800;
|
|
42
|
-
const defaultRequestTimeoutMs =
|
|
42
|
+
const defaultRequestTimeoutMs = 15 * 60 * 1000;
|
|
43
43
|
const defaultMaxConcurrentJobs = 2;
|
|
44
44
|
const defaultMaxQueuedJobs = 20;
|
|
45
45
|
const defaultJobTTLMS = 30 * 60 * 1000;
|
|
@@ -301,6 +301,7 @@ export function getCapabilities(options = {}) {
|
|
|
301
301
|
ok: true,
|
|
302
302
|
model: DEFAULT_IMAGE_MODEL,
|
|
303
303
|
default_model: DEFAULT_IMAGE_MODEL,
|
|
304
|
+
preferred_tool: 'create_image_job',
|
|
304
305
|
supports_async: true,
|
|
305
306
|
supports_cancel: true,
|
|
306
307
|
cancel_semantics: 'best_effort',
|
|
@@ -650,7 +651,7 @@ function normalizeIdempotencyKey(value) {
|
|
|
650
651
|
}
|
|
651
652
|
|
|
652
653
|
function shapeDownloadResult(result, input = {}) {
|
|
653
|
-
const includeImage =
|
|
654
|
+
const includeImage = input.include_image === true && !input.metadata_only;
|
|
654
655
|
const includeRevisedPrompt = input.include_revised_prompt !== false;
|
|
655
656
|
const output = {
|
|
656
657
|
...result,
|
package/lib/image-mcp/server.js
CHANGED
|
@@ -6,7 +6,6 @@ import {
|
|
|
6
6
|
cancelImageJob,
|
|
7
7
|
createImageJob,
|
|
8
8
|
downloadImageResult,
|
|
9
|
-
generateImage,
|
|
10
9
|
getCapabilities,
|
|
11
10
|
IMAGE_BACKGROUND_OPTIONS,
|
|
12
11
|
IMAGE_FORMATS,
|
|
@@ -19,7 +18,7 @@ import {
|
|
|
19
18
|
toolResultContent
|
|
20
19
|
} from './image.js';
|
|
21
20
|
|
|
22
|
-
const imageToolPromptingInstruction = '
|
|
21
|
+
const imageToolPromptingInstruction = '调用前请先确认用户真实需求:尺寸或比例、质量、输出格式、保存目录或文件名。缺少这些关键信息时应先追问,不要直接默认生成。常规生图请优先用 create_image_job,避免长任务占住 MCP 连接。';
|
|
23
22
|
|
|
24
23
|
const imageInputProperties = {
|
|
25
24
|
prompt: {
|
|
@@ -161,7 +160,7 @@ const tools = [
|
|
|
161
160
|
},
|
|
162
161
|
{
|
|
163
162
|
name: 'generate_image',
|
|
164
|
-
description:
|
|
163
|
+
description: `兼容旧调用的异步别名。为避免长图或高质量任务导致 MCP 连接断开,它不会等待图片完成,而是创建任务并立即返回 job_id;之后必须用 get_image_job_status 和 download_image_result 获取结果。${imageToolPromptingInstruction}`,
|
|
165
164
|
inputSchema: {
|
|
166
165
|
type: 'object',
|
|
167
166
|
properties: imageInputProperties,
|
|
@@ -225,7 +224,7 @@ export async function callImageTool(toolName, args = {}, deps = {}) {
|
|
|
225
224
|
case 'get_capabilities':
|
|
226
225
|
return getCapabilities(deps);
|
|
227
226
|
case 'generate_image':
|
|
228
|
-
return
|
|
227
|
+
return createImageJob(args || {}, deps);
|
|
229
228
|
default:
|
|
230
229
|
throw new McpError(ErrorCode.InvalidParams, `未知工具:${toolName}`);
|
|
231
230
|
}
|
|
@@ -239,13 +238,13 @@ function downloadSchema() {
|
|
|
239
238
|
const schema = jobIDSchema();
|
|
240
239
|
schema.properties.metadata_only = {
|
|
241
240
|
type: 'boolean',
|
|
242
|
-
description: '
|
|
243
|
-
default:
|
|
241
|
+
description: '只返回文件路径和元数据,不返回 MCP 图片内容。默认 true,避免大图进入上下文触发频繁 compact。',
|
|
242
|
+
default: true
|
|
244
243
|
};
|
|
245
244
|
schema.properties.include_image = {
|
|
246
245
|
type: 'boolean',
|
|
247
|
-
description: '
|
|
248
|
-
default:
|
|
246
|
+
description: '显式返回 MCP 图片内容。大图会显著增加上下文,通常保持 false,只使用本地文件路径。',
|
|
247
|
+
default: false
|
|
249
248
|
};
|
|
250
249
|
schema.properties.include_revised_prompt = {
|
|
251
250
|
type: 'boolean',
|
package/lib/models.js
CHANGED
|
@@ -45,8 +45,7 @@ export function normalizeModels(payload) {
|
|
|
45
45
|
|
|
46
46
|
for (const item of items) {
|
|
47
47
|
const id = String(item.id || item.name || '').trim();
|
|
48
|
-
if (!id
|
|
49
|
-
if (id.includes('image')) continue;
|
|
48
|
+
if (!isConfigurableCodexModel(id, item)) continue;
|
|
50
49
|
const fallback = FALLBACK_MODELS[id] || {};
|
|
51
50
|
const thinking = item.thinking && typeof item.thinking === 'object' ? item.thinking : {};
|
|
52
51
|
const levels = Array.isArray(thinking.levels) ? thinking.levels : fallback.efforts;
|
|
@@ -74,6 +73,13 @@ export function normalizeModels(payload) {
|
|
|
74
73
|
return Array.from(result.values()).sort((a, b) => a.id.localeCompare(b.id));
|
|
75
74
|
}
|
|
76
75
|
|
|
76
|
+
function isConfigurableCodexModel(id, item) {
|
|
77
|
+
if (!id || !id.startsWith('gpt-') || id.includes('image')) return false;
|
|
78
|
+
const owner = String(item?.owned_by || item?.provider || item?.type || '').trim().toLowerCase();
|
|
79
|
+
if (!owner) return Object.prototype.hasOwnProperty.call(FALLBACK_MODELS, id);
|
|
80
|
+
return owner === 'openai' || owner === 'codex' || owner === 'openai-compatible';
|
|
81
|
+
}
|
|
82
|
+
|
|
77
83
|
export async function fetchModels(baseUrl, apiKey, options = {}) {
|
|
78
84
|
let response;
|
|
79
85
|
try {
|