import { z } from "zod"; import { withAuth, getSessionCredentials } from "../../auth/index.js"; import { SAAS_URL } from "../../config/index.js"; import { handleToolError, validateRequired, handleApiResponse } from "../helpers/errorHandler.js"; import { AcaiHttpClient, FormParamsBuilder } from "../helpers/acaiHttpClient.js"; import { withAuthParams } from "../helpers/authSchema.js"; export function registerCreateTableTool(server) { server.tool( "create_table", "Create a new database table/schema in the system. This creates the table structure with basic configuration. After creation, you can use update_table_schema to add custom fields and modify the schema. Table types: 'multi' (multiple records like news, contacts), 'single' (single record like homepage), 'category' (category menu), 'separador' (menu separator/container). Table names are WITHOUT the 'cms_' prefix.", withAuthParams({ menuName: z.string().describe("Display name for the menu (e.g., 'Noticias', 'Productos')"), tableName: z.string().describe("Technical table name, lowercase with underscores (e.g., 'noticias', 'productos'). Will be auto-generated from menuName if not provided."), type: z.enum(["multi", "single", "category", "separador"]).describe("Table type: 'multi' for multiple records, 'single' for single record, 'category' for category menu, 'separador' for menu separator"), enlace: z.boolean().describe("Whether this table should include the 'enlace' field (true = generates general section URLs, false = no enlace). Ask the user before running this tool."), seo_metas: z.boolean().optional().describe("Whether this table has SEO meta fields. Default: false"), menuOrder: z.number().optional().describe("Order in the menu. If not provided, will be added at the end."), }), { readOnlyHint: false, destructiveHint: false }, withAuth(async ({ menuName, tableName, type, enlace, seo_metas = false, menuOrder }, extra) => { try { // Validate required parameters const validationError = validateRequired( { menuName, tableName, type, enlace }, ['menuName', 'tableName', 'type', 'enlace'], 'create_table' ); if (validationError) return validationError; if (typeof enlace !== "boolean") { return { content: [{ type: "text", text: "Error: 'enlace' must be explicitly set to true or false before calling this tool." }], isError: true, }; } // If menuOrder not provided, get max order from existing tables let order = menuOrder; if (!order) { try { const credentials = await getSessionCredentials(extra.sessionId); const tablesResponse = await AcaiHttpClient.saasPostRequest( { action: "getSchemaTables", type: "acai" }, credentials.token ); if (tablesResponse.data.result && tablesResponse.data.data) { const orders = tablesResponse.data.data.map(t => t.menuOrder || 0); order = Math.max(...orders, 0) + 1; } else { order = 1; } } catch (e) { order = 1; } } // Create table via Acai CMS admin using centralized HTTP client const params = FormParamsBuilder.buildTableCreateParams(menuName, tableName, type, enlace, seo_metas, order); const credentials = await getSessionCredentials(extra.sessionId); const createResponse = await AcaiHttpClient.postAdminForm( credentials.website, params, credentials.token ); // Check for API errors const apiError = handleApiResponse(createResponse.data, 'create_table'); if (apiError) return apiError; // Log response for debugging (stderr to avoid corrupting MCP stream) console.error("CMS Response:", createResponse.data); return { content: [{ type: "text", text: JSON.stringify({ success: true, message: "Table created successfully", tableName: tableName, menuName: menuName, type: type, menuOrder: order, note: "Table created. You can now use get_table_schema to view it or update_table_schema to add custom fields." }, null, 2) }], }; } catch (error) { return handleToolError(error, 'create_table', { menuName, tableName, type }); } }) ); }