Skip to main content
Glama

asset_upscale_refine

Read-only

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

TableJSON Schema
NameRequiredDescriptionDefault
imageYes
asset_typeNo
target_sizeNo
modeNoauto
output_dirNo

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()
    });
  • 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 }
    },
  • Case branch in the tool dispatch switch: calls upscaleRefine(UpscaleRefineInput.parse(args)).
    case "asset_upscale_refine":
      result = await upscaleRefine(UpscaleRefineInput.parse(args ?? {}));
      break;
Behavior1/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description claims a write operation ('upscale / refine') but annotations set readOnlyHint=true, creating a direct contradiction. No additional behavioral context (e.g., permissions, side effects) is disclosed.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is three concise sentences, front-loaded with the core purpose, and every sentence adds meaningful information without extra fluff.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given 5 parameters, no output schema, and an annotation contradiction, the description is insufficient. It does not clarify return values, explain all parameters, or resolve the readOnly inconsistency.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 0% schema description coverage, the description adds value by explaining the mode enum's algorithms (DAT2, Real-ESRGAN, etc.) and ties asset_type to algorithm selection. However, it does not explain target_size, output_dir, or image format.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool upscales/refines images with asset-type awareness, listing specific algorithms for different types. This verb+resource combination distinguishes it from sibling tools like asset_generate_logo or asset_remove_background.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies the tool is for upscaling/refinement but does not explicitly state when to use it over alternatives or when not to use it. No exclusions or sibling comparisons are provided.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/MohamedAbdallah-14/prompt-to-asset'

If you have feedback or need assistance with the MCP directory API, please join our Discord server