create-template
Create reusable templates for GPU instances or serverless deployments on the Novita AI platform by defining Docker images, ports, environment variables, and configuration settings.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| template | Yes |
Implementation Reference
- src/tools.ts:409-419 (handler)The inline async handler function for the 'create-template' tool. It calls novitaRequest to POST the parameters to the /template/create endpoint and formats the result as a text content response.}, async (params) => { const result = await novitaRequest("/template/create", "POST", params); return { content: [ { type: "text", text: JSON.stringify(result, null, 2), }, ], }; });
- src/tools.ts:350-408 (schema)Zod input schema defining the structure of the 'template' object parameter, including fields like name, readme, type, channel, image, ports, env, etc., with descriptions and validations.template: z.object({ name: z .string() .min(2) .nonempty() .trim() .describe("Name for the template, must be unique."), readme: z .string() .max(20480) .optional() .describe("Template README content (in Markdown format)"), type: z .enum(["instance", "serverless"]) .default("instance") .describe("Type of template"), channel: z .enum(["private", "community"]) .default("private") .describe("Channel for the template"), image: z .string() .nonempty() .max(500) .trim() .describe("Docker image address for instance startup"), imageAuth: z .string() .trim() .optional() .describe("ID of the container registry auth. Required only when the channel is private, or else keep it empty. You can use the `list-container-registry-auths` tool to check the ID if you're not sure."), startCommand: z .string() .max(2047) .optional() .describe("Command to run when the instance starts"), rootfsSize: z .number() .min(10) .describe("Root filesystem size (/Container disk size) in GB"), ports: z .array(z.object({ type: z.enum(["http", "udp", "tcp"]).describe("Type of exposed port"), ports: z.array( z.number() .min(1) .max(65535) .describe("Exposed port numbers, maximum of 10") ).max(10).describe("Exposed port numbers, maximum of 10"), })) .describe("Ports to expose"), env: z .array(z.object({ key: z.string().nonempty().describe("Environment variable key").max(2048), value: z.string().describe("Environment variable value").max(2048), })) .optional() .describe("Environment variables"), }),
- src/tools.ts:349-419 (registration)The server.tool() call within registerTemplateTools() that registers the 'create-template' tool, specifying its name, input schema, and handler function.server.tool("create-template", { template: z.object({ name: z .string() .min(2) .nonempty() .trim() .describe("Name for the template, must be unique."), readme: z .string() .max(20480) .optional() .describe("Template README content (in Markdown format)"), type: z .enum(["instance", "serverless"]) .default("instance") .describe("Type of template"), channel: z .enum(["private", "community"]) .default("private") .describe("Channel for the template"), image: z .string() .nonempty() .max(500) .trim() .describe("Docker image address for instance startup"), imageAuth: z .string() .trim() .optional() .describe("ID of the container registry auth. Required only when the channel is private, or else keep it empty. You can use the `list-container-registry-auths` tool to check the ID if you're not sure."), startCommand: z .string() .max(2047) .optional() .describe("Command to run when the instance starts"), rootfsSize: z .number() .min(10) .describe("Root filesystem size (/Container disk size) in GB"), ports: z .array(z.object({ type: z.enum(["http", "udp", "tcp"]).describe("Type of exposed port"), ports: z.array( z.number() .min(1) .max(65535) .describe("Exposed port numbers, maximum of 10") ).max(10).describe("Exposed port numbers, maximum of 10"), })) .describe("Ports to expose"), env: z .array(z.object({ key: z.string().nonempty().describe("Environment variable key").max(2048), value: z.string().describe("Environment variable value").max(2048), })) .optional() .describe("Environment variables"), }), }, async (params) => { const result = await novitaRequest("/template/create", "POST", params); return { content: [ { type: "text", text: JSON.stringify(result, null, 2), }, ], }; });
- src/utils.ts:15-55 (helper)Utility function novitaRequest used by the tool handler to perform authenticated HTTP requests to the Novita AI GPU instance API endpoints.export async function novitaRequest( endpoint: string, method: string = "GET", body: any = null ) { // Base URL for Novita AI API const API_BASE_URL = "https://api.novita.ai/gpu-instance/openapi/v1"; // Get API key from environment variable const API_KEY = process.env.NOVITA_API_KEY; const url = `${API_BASE_URL}${endpoint}`; const headers = { Authorization: `Bearer ${API_KEY}`, "Content-Type": "application/json", }; const options: any = { method, headers, }; if (body && (method === "POST" || method === "PATCH")) { options.body = JSON.stringify(body); } try { const response = await fetch(url, options); if (!response.ok) { const errorText = await response.text(); throw new Error(`Novita AI API Error: ${response.status} - ${errorText}`); } // Some endpoints might not return JSON const contentType = response.headers.get("content-type"); if (contentType && contentType.includes("application/json")) { return await response.json(); } return { success: true, status: response.status }; } catch (error) { console.error("Error calling Novita AI API:", error); throw error; } }