MCP custom pages: show_in_sidebar + постоянная ссылка для закладок

- create_custom_page: параметр show_in_sidebar (default true); результат содержит
  url (/pages/<slug>) и bookmark_url (полный URL) — страницу можно сразу добавить в закладки
- update_custom_page: параметр show_in_sidebar — скрыть/показать в боковом меню без удаления;
  результат также отдаёт url/bookmark_url
- В UI (Боты → JS Страницы) переключатель «Показывать в боковом меню» и ссылка /pages/<slug>
  уже были; сайдбар фильтрует по showInSidebar
This commit is contained in:
2026-09-30 00:04:10 +03:00
parent 59bd802bf7
commit 98499ca9d4

View File

@@ -1904,7 +1904,7 @@ RULES for tab component code:
"create_custom_page",
{
title: "Create Custom Page",
description: `Create a new custom JS page that appears in the sidebar.
description: `Create a new custom JS page (accessible by a permanent link, optionally in the sidebar).
MANDATORY: Call get_js_coding_reference BEFORE writing any code. Critical rules:
- Only use ctx.libs.ui shadcn components. Ant Design (ui.Tag/Row/Col/Statistic/Spin) does NOT exist.
- ctx.libs.charts — recharts для графиков (BarChart, Line, ComposedChart, ReferenceArea, ResponsiveContainer и т.д.).
@@ -1919,9 +1919,10 @@ MANDATORY: Call get_js_coding_reference BEFORE writing any code. Critical rules:
description: z.string().optional().describe("Short description"),
icon: z.string().optional().describe("Lucide icon name, default: FileCode"),
form_ids: z.array(z.number().int()).optional().describe("IDs of associated forms (used in ctx.forms)"),
show_in_sidebar: z.boolean().optional().describe("Show in the app sidebar (default true). The page is ALWAYS reachable by its permanent URL /pages/<slug> — bookmarkable regardless of this flag."),
},
},
async ({ name, slug, code, description, icon, form_ids }) => {
async ({ name, slug, code, description, icon, form_ids, show_in_sidebar }) => {
const existing = await storage.getCustomPageBySlug(slug, organizationId);
if (existing) {
return { content: [{ type: "text" as const, text: `A page with slug "${slug}" already exists` }], isError: true };
@@ -1939,8 +1940,14 @@ MANDATORY: Call get_js_coding_reference BEFORE writing any code. Critical rules:
formIds: form_ids ?? [],
organizationId,
createdBy,
showInSidebar: show_in_sidebar ?? true,
});
const createResult: Record<string, unknown> = { success: true, page };
const createResult: Record<string, unknown> = {
success: true,
page,
url: `/pages/${page.slug}`,
bookmark_url: `${process.env.APP_BASE_URL || "https://iistwin.ru"}/pages/${page.slug}`,
};
if (createWarnings.length > 0) {
createResult.warnings = createWarnings;
createResult.action_required = "The page was saved but contains potential bugs listed in 'warnings'. Fix them before considering the task complete.";
@@ -1972,9 +1979,10 @@ MANDATORY: Call get_js_coding_reference BEFORE writing any code. Critical rules:
icon: z.string().optional().describe("New Lucide icon name"),
form_ids: z.array(z.number().int()).optional().describe("New list of associated form IDs"),
is_active: z.boolean().optional().describe("Enable or disable the page"),
show_in_sidebar: z.boolean().optional().describe("Show/hide in the app sidebar. The page is always reachable by its permanent URL /pages/<slug>."),
},
},
async ({ page_id, name, code, description, icon, form_ids, is_active }) => {
async ({ page_id, name, code, description, icon, form_ids, is_active, show_in_sidebar }) => {
const existing = await storage.getCustomPage(page_id, organizationId);
if (!existing) return { content: [{ type: "text" as const, text: "Custom page not found" }], isError: true };
@@ -1988,9 +1996,15 @@ MANDATORY: Call get_js_coding_reference BEFORE writing any code. Critical rules:
if (icon !== undefined) updates.icon = icon;
if (form_ids !== undefined) updates.formIds = form_ids;
if (is_active !== undefined) updates.isActive = is_active;
if (show_in_sidebar !== undefined) updates.showInSidebar = show_in_sidebar;
const page = await storage.updateCustomPage(page_id, organizationId, updates as any);
const result: Record<string, unknown> = { success: true, page };
const result: Record<string, unknown> = {
success: true,
page,
url: `/pages/${page.slug}`,
bookmark_url: `${process.env.APP_BASE_URL || "https://iistwin.ru"}/pages/${page.slug}`,
};
if (warnings.length > 0) {
result.warnings = warnings;
result.action_required = "The page was saved but contains potential bugs listed in 'warnings'. Fix them before considering the task complete.";