Skip to main content
Glama
qwenImage.ts3.4 kB
import { z } from "zod"; import { appConfig } from "../config/index.js"; import { runQwenImageAnalysis } from "../providers/qwen.js"; import { prepareImage } from "../utils/file.js"; import { CommandError } from "../utils/cli.js"; import { registerTool } from "./registry.js"; const qwenSchema = z .object({ image: z .string() .min(1) .describe( "Local file path, http(s) URL, or base64-encoded image to analyze." ), prompt: z .string() .min(1) .optional() .describe("Instruction for Qwen. Defaults to config value."), model: z .string() .min(1) .optional() .describe("Qwen model identifier."), cliPath: z .string() .min(1) .optional() .describe("Override the Qwen CLI executable path."), sandbox: z .boolean() .optional() .describe("Whether to run the CLI with the sandbox flag (-s)."), extraFlags: z .array(z.string().min(1)) .optional() .describe("Additional CLI flags to append as-is."), timeoutMs: z .number() .int() .positive() .max(600_000) .optional() .describe("Maximum time (in milliseconds) to wait for CLI execution."), }) .describe("Invoke Qwen CLI to analyze an image."); type QwenArgs = z.infer<typeof qwenSchema>; registerTool({ name: "qwen_analyze_image", description: "Use Qwen CLI to describe or analyze an image with its multimodal capabilities.", schema: qwenSchema, async execute(args: QwenArgs) { const originalInput = args.image.trim(); const prepared = await prepareImage(originalInput, appConfig); const prompt = args.prompt?.trim() ?? appConfig.qwen.defaultPrompt ?? "请描述这张图片的内容。"; try { const result = await runQwenImageAnalysis({ prompt, model: args.model, sandbox: args.sandbox, extraFlags: args.extraFlags, timeoutMs: args.timeoutMs ?? appConfig.commandTimeoutMs, originalInput, preparedImage: prepared, commandOverride: args.cliPath, }); const cleaned = result.stdout || "(Qwen CLI returned no output)"; const metaLines = [ `model: ${result.model ?? "default"}`, `imageSource: ${prepared.source}`, `durationMs: ${result.durationMs}`, ]; if (prepared.source === "local") { metaLines.push(`imagePath: ${prepared.path}`); } return { content: [ { type: "text", text: [ "### Qwen Output", cleaned, "", metaLines.join("\n"), ].join("\n"), }, ], isError: false, } as const; } catch (error) { if (error instanceof CommandError) { const details = [ error.message, error.result.stderr.trim() && `stderr:\n${error.result.stderr.trim()}`, error.result.stdout.trim() && `stdout:\n${error.result.stdout.trim()}`, ] .filter(Boolean) .join("\n\n"); return { content: [ { type: "text", text: `Qwen CLI failed:\n${details}`, }, ], isError: true, }; } throw error; } finally { await prepared.cleanup(); } }, });

Implementation Reference

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/ah-wq/mcp-vision-relay'

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