collect_input
Collect user input including text, images, or pixel art through an interactive interface for contextual data gathering and user submissions.
Instructions
get image, text, or pixel art input from user. This is used to get contextual input from the user of different kinds.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| gridHeight | No | Grid height for pixel art (default: 16) | |
| gridWidth | No | Grid width for pixel art (default: 16) | |
| height | No | Canvas height for image mode (default: 512) | |
| initialImage | No | Initial image to load for editing (file path) | |
| kind | No | ||
| message | No | Custom message to show to the user | |
| width | No | Canvas width for image mode (default: 512) |
Implementation Reference
- src/server.ts:30-75 (handler)Main handler for collect_input tool: normalizes spec, launches UI prompt, handles results (text or image/pixelart), caches images, returns MCP-formatted content.}, async ({ kind, initialImage, gridWidth, gridHeight, width, height, message }) => { const baseSpec = normalizeSpec(kind); // Apply custom parameters const spec = { ...baseSpec, ...(initialImage && { initialImage }), ...(message && { message }), ...(baseSpec.kind === 'pixelart' && gridWidth && { gridWidth }), ...(baseSpec.kind === 'pixelart' && gridHeight && { gridHeight }), ...(baseSpec.kind === 'image' && width && { width }), ...(baseSpec.kind === 'image' && height && { height }) }; try { const result = await launchInputPrompt({ spec }); if (result.kind === "text") { return { content: [{ type: "text", text: result.value }] }; } if (result.kind === "image" || result.kind === "pixelart") { // Save image to cache const cachedPath = await saveImageToCache(result.dataUrl); // Return the file path as text instead of base64 image data return { content: [{ type: "text", text: cachedPath }], isError: false }; } throw new Error(`Unsupported input result kind: ${(result as { kind?: string } | undefined)?.kind ?? "unknown"}`); } catch (error) { if (error instanceof InputCancelledError) { throw new Error("User cancelled the input"); } if (error instanceof InputFailedError) { throw error; // Re-throw with original message } throw error; // Re-throw any other errors } });
- src/server.ts:18-29 (registration)Registers the collect_input tool with MCP server, including title, description, and Zod input schema.server.registerTool("collect_input", { title: "Collect Input", description: "get image, text, or pixel art input from user. This is used to get contextual input from the user of different kinds. ", inputSchema: { kind: z.enum(["text", "image", "pixelart"]).optional(), initialImage: z.string().optional().describe("Initial image to load for editing (file path)"), gridWidth: z.number().int().min(4).max(128).optional().describe("Grid width for pixel art (default: 16)"), gridHeight: z.number().int().min(4).max(128).optional().describe("Grid height for pixel art (default: 16)"), width: z.number().int().min(32).max(4096).optional().describe("Canvas width for image mode (default: 512)"), height: z.number().int().min(32).max(4096).optional().describe("Canvas height for image mode (default: 512)"), message: z.string().optional().describe("Custom message to show to the user") },
- src/shared/types.ts:4-44 (schema)Zod schemas defining full InputSpec for text, image, pixelart used by normalizeSpec and tool.export const TextInputSpecSchema = z.object({ kind: z.literal('text'), ui: z.literal('text').default('text'), message: z.string().default('Enter your input:'), submitLabel: z.string().default('Send'), placeholder: z.string().default('Type something here...'), lines: z.number().int().min(1).max(20).default(1), format: z.enum(['text', 'json']).default('text') }); export const ImageInputSpecSchema = z.object({ kind: z.literal('image'), ui: z.literal('image').default('image'), message: z.string().default('Draw your input:'), submitLabel: z.string().default('Send'), width: z.number().int().min(32).max(4096).default(512), height: z.number().int().min(32).max(4096).default(512), mimeType: z.string().default('image/png'), backgroundColor: z.string().optional(), initialImage: z.string().optional() // Can be file path or base64 data URL }); export const PixelArtInputSpecSchema = z.object({ kind: z.literal('pixelart'), ui: z.literal('pixelart').default('pixelart'), message: z.string().default('Create your pixel art:'), submitLabel: z.string().default('Send'), gridWidth: z.number().int().min(4).max(128).default(16), gridHeight: z.number().int().min(4).max(128).default(16), cellSize: z.number().int().min(4).max(64).default(20), palette: z.array(z.string()).default(['#000000', '#FFFFFF', '#f28478', '#a8e6cf', '#80b7ff', '#ffd89b', '#dda0dd', '#b0e0e6']), backgroundColor: z.string().default('#FFFFFF'), mimeType: z.string().default('image/png'), initialImage: z.string().optional() // Can be file path or base64 data URL }); export const InputSpecSchema = z.discriminatedUnion('kind', [ TextInputSpecSchema, ImageInputSpecSchema, PixelArtInputSpecSchema ]);
- src/create.ts:58-70 (helper)normalizeSpec: Creates full InputSpec from minimal kind input using Zod schemas with defaults.export function normalizeSpec(kind: InputKind | undefined): InputSpec { const resolved = kind ?? "text"; if (resolved === "image") { return ImageInputSpecSchema.parse({ kind: "image" }); } if (resolved === "pixelart") { return PixelArtInputSpecSchema.parse({ kind: "pixelart" }); } return TextInputSpecSchema.parse({ kind: "text" }); }
- src/shared/cache.ts:50-67 (helper)saveImageToCache: Saves base64 dataUrl to PNG file in user cache dir, returns absolute file path.export async function saveImageToCache(dataUrl: string): Promise<string> { // Ensure cache directory exists const imagesDir = await ensureCacheDir(); // Extract base64 data from data URL const base64Data = dataUrl.replace(/^data:image\/\w+;base64,/, ''); const buffer = Buffer.from(base64Data, 'base64'); // Generate unique filename const filename = generateImageFilename(); const filepath = path.join(imagesDir, filename); // Write file await fs.writeFile(filepath, buffer); //console.error(`Image saved to cache: ${filepath}`); return filepath; }