UNPKG

@takashito/linode-mcp-server

Version:

MCP server for Linode API

156 lines 6.33 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.actionSchema = exports.statusSchema = exports.idSchema = exports.dateSchema = exports.cidrSchema = exports.ipAddressStringSchema = exports.imageSchema = exports.regionSchema = exports.tagSchema = exports.tagsSchema = exports.paginatedResponseSchema = exports.pagingParamsSchema = exports.paginationSchema = exports.coerceBoolean = exports.jsonArray = void 0; exports.mcpInput = mcpInput; const zod_1 = require("zod"); // MCP clients may serialize array/object parameters as JSON strings. // This helper wraps a zod array schema so it accepts either a native array // or a JSON-encoded string and parses the string before validation. const jsonArray = (schema) => zod_1.z.preprocess((v) => { if (typeof v === 'string') { try { return JSON.parse(v); } catch { return v; } } return v; }, schema); exports.jsonArray = jsonArray; // Safe boolean coercion: converts only the literal strings "true"/"false" // (and numeric 0/1) to booleans. Unlike z.coerce.boolean() which treats any // non-empty string as true, this preserves the intent when MCP clients // stringify boolean params. const coerceBoolean = () => zod_1.z.preprocess((v) => { if (typeof v === 'string') { if (v === 'true') return true; if (v === 'false') return false; } if (v === 1) return true; if (v === 0) return false; return v; }, zod_1.z.boolean()); exports.coerceBoolean = coerceBoolean; // Universal MCP input preprocessor. MCP clients frequently serialize ALL // parameters as strings — including arrays, objects, booleans, and numbers. // This wraps a zod object schema with a preprocessor that inspects each field // and JSON-parses string inputs whose target type is array/object/record/tuple, // coerces numeric strings to numbers, and converts "true"/"false"/0/1 to bool. // Wraps at registration time: `parameters: mcpInput(schemas.fooSchema)`. function mcpInput(schema) { const shape = schema.shape; return zod_1.z.preprocess((raw) => { if (typeof raw !== 'object' || raw === null) return raw; const result = { ...raw }; for (const key of Object.keys(shape)) { const value = raw[key]; if (value === undefined) continue; let inner = shape[key]; // Unwrap wrapping zod types to find the ultimate target. while (inner?._def) { const t = inner._def.typeName; if (t === 'ZodOptional' || t === 'ZodNullable' || t === 'ZodEffects' || t === 'ZodDefault') { inner = inner._def.innerType ?? inner._def.schema ?? inner; } else { break; } } const name = inner?._def?.typeName; if (typeof value === 'string') { if (name === 'ZodArray' || name === 'ZodObject' || name === 'ZodRecord' || name === 'ZodTuple') { try { result[key] = JSON.parse(value); } catch { /* leave as-is */ } } else if (name === 'ZodNumber') { const n = Number(value); if (!Number.isNaN(n) && value.trim() !== '') result[key] = n; } else if (name === 'ZodBoolean') { if (value === 'true') result[key] = true; else if (value === 'false') result[key] = false; } } } return result; }, schema); } // Common schema definitions used across multiple tools // Pagination schema for list endpoints exports.paginationSchema = zod_1.z.object({ page: zod_1.z.coerce.number().int().optional().describe('Page number to fetch (minimum: 1)'), page_size: zod_1.z.coerce.number().int().optional().describe('Number of items per page (minimum: 1, maximum: 500)') }); // For backward compatibility exports.pagingParamsSchema = exports.paginationSchema; // For paginated response const paginatedResponseSchema = (schema) => zod_1.z.object({ data: zod_1.z.array(schema), page: zod_1.z.coerce.number(), pages: zod_1.z.coerce.number(), results: zod_1.z.coerce.number() }); exports.paginatedResponseSchema = paginatedResponseSchema; // Tags schema used in many resources exports.tagsSchema = (0, exports.jsonArray)(zod_1.z.array(zod_1.z.string())).optional() .describe('Array of user-defined tags for organization. Each tag can be up to 50 characters'); // For backward compatibility exports.tagSchema = exports.tagsSchema; // Region schema used in many resources exports.regionSchema = zod_1.z.string() .describe('Region where the resource will be created (e.g. us-east, ap-south)'); // Image schema for instances exports.imageSchema = zod_1.z.string() .describe('The image to deploy the instance from (e.g. linode/debian11)'); // Simple IP address schema (string only, not the complex object) exports.ipAddressStringSchema = zod_1.z.string().ip() .describe('A valid IPv4 or IPv6 address'); // CIDR block schema exports.cidrSchema = zod_1.z.string() .describe('A CIDR block notation (e.g. 10.0.0.0/24 or 2001:db8::/64)'); // Date schema exports.dateSchema = zod_1.z.string().datetime() .describe('ISO-8601 formatted date-time string'); // ID schema - can be number or string depending on resource exports.idSchema = zod_1.z.union([zod_1.z.coerce.number().int(), zod_1.z.string()]) .describe('Unique identifier for the resource'); // Common status values exports.statusSchema = zod_1.z.enum([ 'active', 'creating', 'deleting', 'disabled', 'failed', 'pending', 'provisioning', 'rebooting', 'rebuilding', 'resizing', 'stopped', 'stopping' ]).describe('Current status of the resource'); // Common actions exports.actionSchema = zod_1.z.enum([ 'boot', 'reboot', 'shutdown', 'power_on', 'power_off', 'resize', 'rebuild', 'restore', 'migrate' ]).describe('Action to perform on the resource'); //# sourceMappingURL=schemas.js.map