mcp tablas
This commit is contained in:
@@ -1,99 +1,51 @@
|
||||
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 { withAuth } from "../../auth/index.js";
|
||||
import { withAuthParams } from "../helpers/authSchema.js";
|
||||
import { handleToolError } from "../helpers/errorHandler.js";
|
||||
import { callSchemaEndpoint } from "./_schemaEndpoint.js";
|
||||
|
||||
// Tool: create_table
|
||||
// Crea una tabla nueva delegando en /api/schema/create-table. Enviamos solo
|
||||
// "intencion" (menuType + flags) — el server Python construye el schemaPreset
|
||||
// por defecto. Los tableNames viajan SIN el prefijo `cms_`; la PK siempre es `num`.
|
||||
|
||||
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.",
|
||||
`Create a new database table/module for the current Acai project.
|
||||
|
||||
Menu types:
|
||||
- 'multi': regular table with many records (news, products, contacts...)
|
||||
- 'single': single-record page (homepage, about us...)
|
||||
- 'category': category container — groups other tables under a menu node
|
||||
- 'separador': visual separator in the admin menu
|
||||
|
||||
Parameters:
|
||||
- tableName: technical name, lowercase + underscores, WITHOUT 'cms_' prefix. Primary key is always 'num'.
|
||||
- menuName: display name in the admin sidebar.
|
||||
- enlace: REQUIRED. Whether the table participates in public URLs (generates the 'enlace' field + slug). This is an architectural decision — ALWAYS ask the user before calling this tool.
|
||||
- seoMetas: adds SEO meta fields (title, description, og:image). Default false.
|
||||
- menuOrder: optional integer for sidebar order. Backend assigns one if omitted.`,
|
||||
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."),
|
||||
tableName: z.string().describe("Technical table name, lowercase + underscores, without 'cms_' prefix"),
|
||||
menuName: z.string().describe("Display name shown in the admin sidebar"),
|
||||
menuType: z.enum(["multi", "single", "category", "separador"]).describe("'multi' | 'single' | 'category' | 'separador'"),
|
||||
enlace: z.boolean().describe("Whether the table has public URLs (generates 'enlace' field). REQUIRED — ask the user first."),
|
||||
seoMetas: z.boolean().optional().describe("Include SEO meta fields. Default false."),
|
||||
menuOrder: z.number().int().optional().describe("Order in the admin sidebar. Backend picks one if omitted."),
|
||||
}),
|
||||
{ readOnlyHint: false, destructiveHint: false },
|
||||
withAuth(async ({ menuName, tableName, type, enlace, seo_metas = false, menuOrder }, extra) => {
|
||||
withAuth(async ({ tableName, menuName, menuType, enlace, seoMetas, menuOrder }, _extra) => {
|
||||
try {
|
||||
// Validate required parameters
|
||||
const validationError = validateRequired(
|
||||
{ menuName, tableName, type, enlace },
|
||||
['menuName', 'tableName', 'type', 'enlace'],
|
||||
'create_table'
|
||||
);
|
||||
if (validationError) return validationError;
|
||||
const body = { tableName, menuName, menuType, enlace };
|
||||
if (typeof seoMetas === "boolean") body.seoMetas = seoMetas;
|
||||
if (typeof menuOrder === "number") body.menuOrder = menuOrder;
|
||||
|
||||
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)
|
||||
}],
|
||||
};
|
||||
const { mcp } = await callSchemaEndpoint("/api/schema/create-table", body);
|
||||
return mcp;
|
||||
} catch (error) {
|
||||
return handleToolError(error, 'create_table', { menuName, tableName, type });
|
||||
return handleToolError(error, "create_table", { tableName, menuType });
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user