orientation
Extract image orientation values (1-8) from various input formats (path, URL, base64, buffer) using metadata analysis to ensure correct display and processing.
Instructions
Get image orientation value (1-8)
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| image | Yes |
Implementation Reference
- src/tools/index.ts:181-195 (handler)The core handler function for the 'orientation' tool. Loads the image buffer using loadImage, extracts the orientation value using exifr.orientation(buf), and returns it or an error response.async (args, extra) => { try { const { image } = args; const buf = await loadImage(image); const orientation = await exifr.orientation(buf); if (orientation === undefined) { return createErrorResponse('No orientation metadata found in image'); } return createSuccessResponse({ orientation }); } catch (error) { return createErrorResponse(`Error reading orientation: ${error instanceof Error ? error.message : String(error)}`); } }
- src/tools/index.ts:54-60 (schema)Zod schema defining the input structure for the image source parameter used by the 'orientation' tool.const ImageSourceSchema = z.object({ kind: z.enum(['path', 'url', 'base64', 'buffer']), path: z.string().optional(), url: z.string().optional(), data: z.string().optional(), buffer: z.string().optional() });
- src/tools/index.ts:176-197 (registration)Registers the 'orientation' tool with the MCP server, specifying name, description, input schema, and handler function. Also stores reference in tools object.const orientationTool = server.tool('orientation', "Get image orientation value (1-8)", { image: ImageSourceSchema }, async (args, extra) => { try { const { image } = args; const buf = await loadImage(image); const orientation = await exifr.orientation(buf); if (orientation === undefined) { return createErrorResponse('No orientation metadata found in image'); } return createSuccessResponse({ orientation }); } catch (error) { return createErrorResponse(`Error reading orientation: ${error instanceof Error ? error.message : String(error)}`); } } ); tools['orientation'] = orientationTool;
- src/tools/loaders.ts:11-72 (helper)Supporting helper that loads image data from path, URL, base64, or buffer into a Buffer/Uint8Array, used by the orientation handler.export async function loadImage(src: ImageSourceType): Promise<Buffer | Uint8Array> { try { switch (src.kind) { case 'path': if (!src.path) { throw new Error('Path is required for kind="path"'); } return await fs.promises.readFile(src.path); case 'url': if (!src.url) { throw new Error('URL is required for kind="url"'); } if (src.url.startsWith('file://')) { // Handle file:// URLs by converting to filesystem path const filePath = fileURLToPath(src.url); return await fs.promises.readFile(filePath); } else { // Handle HTTP/HTTPS URLs const response = await fetch(src.url); if (!response.ok) { throw new Error(`Failed to fetch URL: ${response.status} ${response.statusText}`); } return new Uint8Array(await response.arrayBuffer()); } case 'base64': if (!src.data) { throw new Error('Data is required for kind="base64"'); } // Check for potential oversized base64 string (>30MB) if (src.data.length > 40000000) { // ~30MB in base64 throw new Error('PayloadTooLarge: Base64 data exceeds 30MB limit'); } // Handle data URIs or raw base64 if (src.data.startsWith('data:')) { const base64Data = src.data.split(',')[1]; return Buffer.from(base64Data, 'base64'); } else { return Buffer.from(src.data, 'base64'); } case 'buffer': if (!src.buffer) { throw new Error('Buffer is required for kind="buffer"'); } return Buffer.from(src.buffer, 'base64'); default: // This should never happen due to type constraints, but TypeScript needs it throw new Error(`Unsupported image source kind: ${(src as any).kind}`); } } catch (error) { if (error instanceof Error) { throw new Error(`Failed to load image: ${error.message}`); } throw error; } }
- src/tools/index.ts:18-27 (helper)Helper function used by the orientation handler to format successful MCP tool responses.function createSuccessResponse(data: any) { return { content: [ { type: "text" as const, text: typeof data === 'string' ? data : JSON.stringify(data, null, 2) } ] }; }