asset_upscale_refine
Upscale and refine images with asset-type-aware processing: DAT2 for flat logos/icons, Real-ESRGAN/SUPIR for photoreal, img2img for diffusion polish, and Lanczos fallback.
Instructions
Upscale / refine an image, asset-type-aware. DAT2 for flat logos/icons, Real-ESRGAN/SUPIR for photoreal, img2img for diffusion polish. Lanczos fallback.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| image | Yes | ||
| asset_type | No | ||
| target_size | No | ||
| mode | No | auto | |
| output_dir | No |
Implementation Reference
- Handler function for asset_upscale_refine: reads input image buffer, calls the upscale pipeline, writes the result to disk, and returns output_path/method_used/target_size/warnings.
export async function upscaleRefine(input: UpscaleRefineInputT): Promise<{ output_path: string; method_used: string; target_size: number; warnings: string[]; }> { const imagePath = safeReadPath(input.image); const buf = readFileSync(imagePath); const result = await upscale({ image: buf, ...(input.asset_type && { asset_type: input.asset_type }), target_size: input.target_size, mode: input.mode }); const out = safeWritePath( resolve(input.output_dir ?? ".", `${basename(input.image)}.upscaled.png`) ); writeFileSync(out, result.image); return { output_path: out, method_used: result.method_used, target_size: result.target_size, warnings: result.warnings }; } - Core upscale pipeline: tries remote upscaler (PROMPT_TO_BUNDLE_UPSCALER_URL) with mode resolution based on asset_type, falls back to local sharp Lanczos resize. resolveMode maps asset types to upscale modes (DAT2 for flat assets, SUPIR for photoreal, lanczos for og_image, real-esrgan default).
export async function upscale(input: UpscaleInput): Promise<UpscaleResult> { const sharp = await loadSharp(); if (!sharp) { return { image: input.image, method_used: "passthrough", target_size: input.target_size, warnings: ["sharp not installed; upscale returned input unchanged"] }; } const mode = input.mode ?? "auto"; // Remote upscaler hook const upscalerUrl = process.env["PROMPT_TO_BUNDLE_UPSCALER_URL"]; if (upscalerUrl && mode !== "lanczos") { try { const resp = await fetch(upscalerUrl, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ image_b64: input.image.toString("base64"), target_size: input.target_size, mode: resolveMode(mode, input.asset_type) }) }); if (resp.ok) { const json = (await resp.json()) as { image_b64?: string; method?: string }; if (json.image_b64) { return { image: Buffer.from(json.image_b64, "base64"), method_used: json.method ?? "remote", target_size: input.target_size, warnings: [] }; } } } catch { /* fall through to local */ } } // Local Lanczos fallback — fine for logos and vector-like content up to 4x; // for photoreal upscales beyond 2x, a neural upscaler is required for production quality. const meta = await sharp(input.image).metadata(); const w = meta.width ?? input.target_size; const h = meta.height ?? input.target_size; const longest = Math.max(w, h); if (longest >= input.target_size) { return { image: input.image, method_used: "no-op (already at or above target size)", target_size: input.target_size, warnings: [] }; } const scale = input.target_size / longest; const newW = Math.round(w * scale); const newH = Math.round(h * scale); const resized = await sharp(input.image) .resize(newW, newH, { kernel: "lanczos3", fit: "inside" }) .toBuffer(); return { image: resized, method_used: "lanczos3", target_size: input.target_size, warnings: mode !== "lanczos" && mode !== "auto" ? [ `requested mode "${mode}" unavailable locally; used Lanczos fallback. Configure PROMPT_TO_BUNDLE_UPSCALER_URL for DAT2/ESRGAN/SUPIR.` ] : [] }; } function resolveMode(mode: string, assetType?: AssetType): string { if (mode !== "auto") return mode; switch (assetType) { case "logo": case "favicon": case "app_icon": case "icon_pack": case "transparent_mark": case "sticker": return "dat2"; // flat assets case "illustration": return "dat2"; case "hero": return "supir"; // photoreal hero case "og_image": return "lanczos"; // template-rendered, lossless default: return "real-esrgan"; } } - Zod input schema for UpscaleRefineInput: image (string), asset_type (optional enum), target_size (int 64-8192, default 2048), mode (auto/dat2/real-esrgan/supir/img2img, default auto), output_dir (optional string).
export const UpscaleRefineInput = z.object({ image: z.string(), asset_type: AssetTypeSchema.optional(), target_size: z.number().int().min(64).max(8192).default(2048), mode: z.enum(["auto", "dat2", "real-esrgan", "supir", "img2img"]).default("auto"), output_dir: z.string().optional() }); - packages/mcp-server/src/server.ts:348-368 (registration)Tool registration in the tools array: defines name 'asset_upscale_refine', description, inputSchema, and annotations for the MCP server.
{ name: "asset_upscale_refine", description: "Upscale / refine an image, asset-type-aware. DAT2 for flat logos/icons, Real-ESRGAN/SUPIR for photoreal, img2img for diffusion polish. Lanczos fallback.", inputSchema: { type: "object", properties: { image: { type: "string" }, asset_type: { type: "string" }, target_size: { type: "integer", default: 2048 }, mode: { type: "string", enum: ["auto", "dat2", "real-esrgan", "supir", "img2img", "lanczos"], default: "auto" }, output_dir: { type: "string" } }, required: ["image"] }, annotations: { readOnlyHint: true } }, - packages/mcp-server/src/server.ts:816-818 (registration)Case branch in the tool dispatch switch: calls upscaleRefine(UpscaleRefineInput.parse(args)).
case "asset_upscale_refine": result = await upscaleRefine(UpscaleRefineInput.parse(args ?? {})); break;