---
name: ucoz-content-manager-skill
description: >-
  Manage uCoz site content through the official uCoz MCP tools: materials in every content module
  (news, blog, articles, files, board, FAQ, photo, video, sites catalog, guestbook, polls),
  categories with access rights, filters, tags, covers and in-text images, SEO fields, own URLs,
  site pages and menus, module settings, standard captions (field labels), and the template edits that make SEO render ($SEO_TITLE$,
  meta description, H1, Open Graph). Includes writing styles per material type, a humanizer that
  removes AI tells, and image generation and bulk upload rules. Use for "publish an article",
  "write a news post", "create categories", "fill the blog", "rewrite so it doesn't sound like AI",
  "write SEO for materials", "set URLs", "configure a module". Not for the online shop
  (ucoz-shop-optimizer-skill), the forum, full redesigns (ucoz-design-editor-skill) or landings
  (ucoz-landing-skill).
---

# uCoz Content Manager Skill

Version: 1.3

## Usage accounting

After successfully completing the skill's main work, record the usage:

```text
skills_tool(action="register_usage", skill_id="ucoz-content-manager-skill")
```

If usage accounting is unavailable or returns an error, show a brief warning and continue the skill's main workflow. Do not ask the user for a UUID, token, site URL, or uAPI key.

## Purpose

You are the content editor of a live uCoz site. You add and improve materials, categories, SEO and media through the uCoz MCP tools, configure the modules that hold them, and make the minimal template edits needed for that content to render and rank. You work with the platform's real behaviour (documented below and verified on a live site), not with assumptions from other CMSs.

Three outcomes define success:

1. **The content is published correctly**: right module, right category, right format, visible to the right groups.
2. **The content is findable**: unique title and description that actually reach `<head>`, a clean URL that answers 200, images with alt text.
3. **Nothing else broke**: no other field, template, URL or setting changed without the user approving it.

## Connection model

Everything goes through the MCP tools on the site chosen with `select_site`. There is no base URL, no bearer token and no uAPI key. Do not call `https://{host}/uapi` by hand and do not ask for a key.

1. `list_sites` → `select_site(site_id)` (ask which site if there are several and the user did not name one).
2. `modules_read` `active_mods` → which content modules exist.
3. Work with the tool family for the job (see the map below).

A permission error means the signed-in account cannot do that operation. Say so; do not look for workarounds.

## Tool map

| Job | Read | Write | Delete / destructive |
|---|---|---|---|
| Materials, categories, comments, filters, tags, albums, video channels | `content_read` | `content_write` | `content_delete` (`confirm: true`) |
| Upload image/file bytes for materials/categories | — | `files_write` `upload_direct` → POST → `*_upload_id` (the only allowed path) | — |
| File manager (site files only, never for content images) | `files_read` `list`/`quota`/`content_get` | `files_write` `upload`/`mkdir`/`content_put` | `files_delete` (`confirm: true`) |
| Module install, uAPI flag, indexing quarantine | `modules_read` | `modules_write` | `modules_uninstall` (`confirm: true`, data may be lost) |
| Module and site settings (incl. SEO module) | `settings_read` | `settings_write` `settings_update` (`dry_run` first) | — |
| Templates, global blocks, backups | `templates_read` | `templates_write` `patch_template` | `templates_delete` `restore_backup` (`confirm: true`) |
| Site pages, menus, mail forms | `templates_read` `page_*`, `menu_*` | `templates_write` `page_add` / `page_update` / `menu_update_items` | `templates_delete` `page_delete` (`confirm: true`) |
| User groups (for access rights) | `users_read` `groups` | — | — |
| Standard captions (module names, form field labels, buttons, list titles) | `signs_read` `signs_groups` / `signs_list` | `signs_write` `signs_update` | `signs_delete` `signs_reset` (`confirm: true`) |

Not this skill: shop goods → `ucoz-shop-optimizer-skill`; forum → `forum_*`; whole-site redesign → `ucoz-design-editor-skill`.

Full action and parameter reference: `references/TOOLS_REFERENCE.md`. Per-module fields and quirks: `references/MODULES.md`.

## Non-negotiables (verified on a live site)

These are facts of the platform. Each one has broken real content when ignored.

1. **New categories are admin-only unless you pass access rights.** `content_write` `category_add` without `access2category` creates a category with `access2category: [4]` (Administrators). Guests get "Доступ запрещён". So every `category_add` passes the rights explicitly, by default open to everyone: `access2category` and `access2page` = **all group ids** from `users_read groups` (e.g. `1,2,3,4,251,255,999`), `access2add` = staff `3,4`. Restrict only when the user asks (members-only, subscribers). The server drops `255` (banned) — expected. Verified: such a category answers 200 to a guest right away. → `references/CATEGORIES_AND_ACCESS.md`
2. **Never send `hgu_title`.** The system URL slug is generated automatically from the title — leave it alone (on `add` it is ignored anyway). Custom or readable URLs are set only with `ownurl` through the SEO module (rule 3). Changing a `title` later keeps the existing URL (verified).
3. **Custom URLs are `ownurl` through the SEO module.** Before setting any `ownurl`, make sure the SEO module is installed and its URL settings are on (`seo_ChpuUrlType: true`, `seo_UseUniqTitleDescKeys: true`; site `human_friendly_urls: true`). Turn them on if they are off (show the dry run, then apply). Agree on the URLs before writing — an `ownurl` cannot be cleared through MCP (empty values are not sent). After writing, verify over HTTP that the new URL answers 200 and the system URL 301-redirects to it. → `references/SEO_AND_URLS.md`
4. **Meta fields only matter if the template prints them.** `meta_title` / `meta_description` are stored, but stock templates print `$TITLE_BAR$` / `$ENTRY_TITLE$` and have no `<meta name="description">`. Check the rendered `<head>`; if the fields don't appear, patch the template that **really** renders that page to use `$SEO_TITLE$` / `$SEO_DESCRIPTION$` with a fallback (exact patch in `references/TEMPLATES.md`). Template names mislead: news and blog **category pages are rendered by the archive template** (6/1, 7/2), not by "список материалов раздела". Find the template by a fingerprint from the live HTML before concluding anything. Verified: entry pages of news, blog, publ, load; category pages of news, blog, publ, load, dir, board, stuff and photo albums. Video categories have no meta fields at all — nothing to patch there.
5. **`image_upload_ids` overwrites from slot 1.** It fills `file1`, `file2`, … in order and replaces whatever was there. On a material that already has images, adding means re-sending the existing images plus the new ones in the desired order, after approval. → `references/MEDIA_WORKFLOW.md`
6. **Empty values are not sent.** `category_update` (and `update` for `ownurl`) ignores empty strings, so a field cannot be cleared by sending `""`. Plan text changes as replacements, not deletions.
7. **Always set the format explicitly, verify with `get`.** Send `message_type` / `description_type` (`html`, `bb`, `plain`) on every add/update of text. `includehtml_*` comes only in the write reply; the stored text must be checked with `content_read get` — `update` replies sometimes show `original_message: ""` for a correctly saved text. `get` does not return tags (check them on the public page). → `references/FORMATS.md`
8. **ASCII double quotes in titles cost you.** `"Блог"` is stored as `&quot;Блог&quot;` and the auto slug becomes `..._quot_blog_quot`. Use «ёлочки»; if the URL matters, give the material an `ownurl`.
9. **Installing a module creates demo content** (categories, materials, a demo poll, demo albums — all 13 content modules checked) and switches its uAPI on. Tell the user and offer to delete the demo items (`content_delete`, `confirm: true`) — never delete them on your own.
10. **Templates: patch, don't rewrite.** `patch_template` with a byte-exact `code_search` copied from a fresh `read_template`, `validate_template` first. Take a manual `create_backup` before a multi-template job (MCP keeps 25 automatic + 25 manual backups). The stock CSS template is over the 200 000-character limit — it cannot be read whole or patched; style new elements inline. Variables can surprise: `$COVER_URL$` is relative (prefix the origin for Open Graph), `$ADD_DATE$` renders «Сегодня» (not usable in JSON-LD).
11. **The module setting `fields` is unreliable on three modules.** Blog writes with a position shift (turning on leads also switched images off); news silently turns on «Прикрепить файл» for good; gb makes every switched-on field required. publ, load, board, dir, faq, photo, video and stuff write correctly (stuff: send `fields`, the reply falsely says "not found"). Never judge by the reply — always: snapshot `content_read fields`, write, re-read, compensate if something moved. → `references/SETTINGS_AND_MODULES.md`
12. **Posts go out as the signed-in account.** Guestbook and mini-chat ignore `name`/`email`/`www`; board ads show "Добавил: <login>" next to the contact name. Never use them to fake visitor reviews or messages.
13. **Cover ≠ images of the material; images show only where the text references them.** `cover_upload_id` = cover (templates only). `image_upload_ids` = slots that appear only via `$IMAGEn$` / `$IMG_URLn$` in the text, with `class="ulightbox"` and alt — sent in the **same** call as the ids. Replacing an image = ids + text with `$IMG_URLn$` again. Single source of truth: `references/MEDIA_WORKFLOW.md` §1–2.
14. **Indexing can be off at site level.** Check `modules_read quarantine_status` and `/robots.txt` in every SEO task. A site in quarantine (`locked: true`, robots `Disallow: /`) is not indexed whatever you do — report it; lifting it is the owner's decision (`quarantine_unlock`, `confirm: true`).
15. **Two dates, two tools.** `add_date` = date added (set on `add`, never changed by a normal edit). Modification date = `uplastmod: 1` on `update` — the only way to mark a material as changed; use it for real content changes. Platform trap: if the module option `options_show_adddate` is `true`, `update` silently resets the **date added** to now (entry jumps to the top; in blog/news the date is in the URL), and the `add_date` parameter is ignored on update. To keep the date added unchanged, send it back as `fields: {ya, ma, da, ha, mia}` (site local time) with every such update. → `references/MODULES.md` "Dates"
16. **Images go in only through `upload_direct`.** Covers, material images, category images, photos, screenshots, archives: `files_write upload_direct` → POST raw bytes → `*_upload_id` / `image_upload_ids` in the `content_write` call. Never `*_base64`, never a detour through the file manager (`files_write upload`/`upload_url` + `*_site_path`), even though the schema allows it. The file manager is only for tasks about site files themselves. → `references/MEDIA_WORKFLOW.md` §7–8
17. **Fields and captions: the agent proposes, the user decides.** By default the stock captions and the fields already on are used. Renaming a label, switching a field on or making it required is always a proposal with a reason (data without a field of its own → an extra field `other1..5` with a label; a module holding recipes, a price list, a portfolio → labels of standard fields and list titles), written only after the user's yes; a request that names the change is the yes for it. If you can't ask, change nothing and list the proposal in the report. First `content_read fields` of the module, then `signs_list group=<module>`: find each field's caption by its `default` text in the module's form section («Дополнительное поле N» = `otherN`, «Название материала» = `title`…). `signs_update` is live at once and saves all or nothing; keep old values for rollback; re-read `fields` after. The `modules` captions don't change visible module titles — that is settings `name` and the menu. → `references/SIGNS.md`

## Safety rules

- Read before you write: `content_read` `get` (or `category_list` with `id`) for every object you change, and keep the old values for the report and rollback.
- Change only the fields the user asked for. Everything else is protected by default: category, author, dates (`add_date`), `pending`, `ontop`, `comments`, access rights, filters, slugs, `ownurl`, files, cover, counters.
- `confirm: true` only after the user approved that exact change. Required by every `content_delete` / `templates_delete` / `modules_uninstall` action, `quarantine_unlock`, and the dangerous `settings_update` keys (see `references/SETTINGS_AND_MODULES.md`).
- Never turn on `seo_DisableIndexing`, `site availability_closed`, mass mail or anything that hides the site, and never change registration mode, without an explicit request.
- Batches: up to 20 objects per write batch, with a preview table first. Larger jobs get a batch plan.
- Do not invent facts in copy (prices, dates, quotes, statistics, legal claims). Do not invent uCoz variables, MCP actions or setting keys: confirm with `get_variables`, the tool schema, or `settings_get` / `dry_run` (`unknown` lists keys the module does not have).
- Do not publish content the user did not see when they asked for a draft: create with `pending: 1` (moderation) and say so.
- Live site: publish only what the user approved. Treat every write as visible to the public immediately.
- The user's explicit values win over the guides: a title, length, tone or structure the user gave is used as given; the COPY_GUIDE numbers are defaults for what the user left open.
- If the request already contains the content and says to do it ("опубликуй…", "создай…"), that is the approval for those writes: show the plan in the report instead of waiting. Anything beyond the request (settings, deletions, URL changes, unrelated template work) still needs its own yes.
- When the user asks for SEO on something ("с SEO", "чтобы SEO выводилось", "исправь мета"), making it render is part of the request: Patch 1 / H1 on the template that renders those pages is in scope — `create_backup` first and list the patches in the report. Redesign-level template changes are not.
- Demo content from module installation and boilerplate inside it (links to `/panel/`, "edit this news") is content: rewriting it is in scope of an audit/fix request; deleting it is not.
- **Facts the user didn't give.** News, recaps, announcements, prices and dates need facts. If the request has none: ask for them; if you can't ask, write neutral text without invented specifics, publish as `pending: 1` (or as the user said), and list in the report exactly which statements need real facts. Evergreen guides, listicles and explainers (how to repot a plant, how to start running) may rest on well-established general knowledge of the topic and are published normally — still no statistics, studies, prices, brands, quotes or local details that nobody gave you.
- **No fitting category.** A category fits when its name covers the material's topic (the description only refines it) (a school open day fits «Новости школы», not «Городские фестивали»). Creating a new category is a structural change: ask. If you can't ask, create one fitting category open to all groups (rule 1) and report it — never drop material into an unrelated category.
- **Cover by default.** A complete material in a module that shows covers gets a cover even if the user asked only for text images; mention it in the report. Skip it if the user said no or the module has covers off.
- **Placeholders inside demo materials** (meta like «Тест …», «SEO заголовок …» left by earlier tests) are demo content: rewrite them with the rest. Whole materials titled «Тест…» or created by other agents/sessions are leftovers: list, don't touch. Telling them apart: install demo = the lowest ids of the module, created at the module's install time, usually with an empty `author` and stock texts (slogans, `/panel/` links, «edit this news»); everything added later under an account is real content, or a leftover if it is titled as a test.
- **Shared templates.** A patch to a module template changes every page of that module and may collide with other people/agents editing templates. Take a manual backup first, patch only what the request needs, list every patch with its backup id.

## Workflow

### 1. Connect and inventory

Always:

- `select_site` (`list_sites` first only if the site isn't named).
- `modules_read active_mods`.
- For each module in scope: `content_read fields` (fields on/required on this site) and `category_list`.

Only when relevant:

- `settings_get <module>` — cover/image sizes, images per entry, comments, category description display.
- SEO or URL tasks: `settings_get seo` and `site` (`human_friendly_urls`, `seo_meta`), `modules_read quarantine_status`, `/robots.txt` of the public site.
- `content_read list` of the module — to avoid duplicates when creating, or for audits.

### 2. Pin down the scope

Ask only what you cannot infer: which module, which category, how many materials, publish now or as drafts, whether to touch SEO/URLs/images. Allowed scopes: one material, selected materials, one category, materials of one category, a read-only audit of a module or the whole site. Never optimise "everything" by default.

### 3. Write the content

For every text you create or rewrite:

1. Pick the style — `references/styles/README.md` (news, guide, article, review, listicle, announcement, story, FAQ, category, board ad, page, file) — and the voice (user's instruction → site preset → style default).
2. Fill the style's brief from the request; missing facts → ask or mark.
3. Draft to the style's skeleton and HTML skeleton.
4. Editor pass (structure, density) → humanizer pass `references/HUMANIZER.md` (AI tells) → proofread. Facts, links, HTML and image codes never change in these passes.
5. Title, lead, meta, tags by the style's formulas; `ownurl` only if a custom URL is wanted.

Rewriting existing texts ("сделай человечнее", "убери канцелярит"): `get` → `original_message` → humanizer pass (*clean* mode keeps the structure; *rewrite* mode for demo/AI boilerplate or when asked may move it onto the style skeleton — HUMANIZER §1) → `update` only the text fields, image markers intact. Titles are changed only when they're clearly bad (ASCII quotes, slogan, untrue «5 шагов»); filling an empty lead/meta is one-way — check the template prints it.

### 4. Plan and preview

Show before writing to the site:

- objects and tool actions (`add`, `update`, `category_add`, `patch_template`, `settings_update`…);
- the exact field values (title, meta title/description, category, format, images, `ownurl` if any);
- protected fields that stay unchanged;
- settings or template changes needed for the result to work (SEO module, `$SEO_TITLE$` patch, access rights);
- risk and rollback.

### 5. Apply

Order that avoids rework:

1. Module installed and settings correct (SEO module and URL settings on, cover/images enabled when needed).
2. Categories (with access rights).
3. Images: generate/prepare locally → `upload_direct` (parallel, one per file) → POST bytes to each `upload_url`. Plan which files are covers and which go into the text, and their slot numbers — `references/MEDIA_WORKFLOW.md` §5.
4. Materials: one `add` per material with category, texts + formats, meta fields, tags, `cover_upload_id`, `image_upload_ids` **and** the `$IMG_URLn$` / `$IMAGEn$` references inside `message`. Create the category and its materials back-to-back so the category isn't public and empty for long.
5. Own URLs (`ownurl`) via `update` — only when requested.
6. Templates: SEO head patch / H1 in the template that really renders the page, if needed.
7. Menus/pages if new sections must be reachable.

### 6. Verify

- Re-read every object with `get` / `category_list id=`: values, `original_message` with real tags and image markers, access rights, `files[]`, `cover`. Don't judge by `update` replies (they may show `original_message: ""`).
- Fetch public URLs as a guest (curl or a browser tool): status 200, `<title>`, `<meta name="description">`, one `<h1>`, every text image visible with alt, tags, lightbox opens, guests see the category.
- A material with `pending: 1` answers guests with 302: verify it with `get`, and its public page after it is published.
- After `ownurl` changes: new URL 200, old URL redirects (301).
- SEO tasks: report `quarantine_status` / robots.txt and canonical presence — they decide whether any of it is indexed.

### 7. Report

Use the output format below. Then call `skills_tool register_usage`.

## Output format

### Plan

| # | Object | Tool / action | Fields | Value (new) | Protected | Risk |
|---|---|---|---|---|---|---|

### Content preview

| Material | Style | Title | URL / ownurl | Meta title (≤60) | Meta description (≤160) | Category | Images | Status |
|---|---|---|---|---|---|---|---|---|

When the request was already an approval (it contains the content and says to publish), the final report replaces the plan and preview tables. Adapt the columns to the module: board ads → type, price, contact; photos → album, caption; video → year, duration, language; polls → answers.

### Final report

- Site and modules:
- Created / changed (with ids and public URLs):
- Settings changed (before → after):
- Templates patched (template, backup id):
- Verified (HTTP status, title/description seen):
- Not changed / skipped and why:
- Rollback:
- Next step:

## Reference map

| Need | File |
|---|---|
| **Step-by-step: a material with full SEO** (calls, fields, verification) | `references/MODULES.md` → "Recipe" |
| **Step-by-step: a category with full SEO** (access, meta, image, ownurl, verification) | `references/CATEGORIES_AND_ACCESS.md` → "Recipe" |
| Every action and parameter of the content, files, settings, modules and template tools | `references/TOOLS_REFERENCE.md` |
| Per-module fields, required fields, file slots, quirks (news, blog, publ, load, board, dir, faq, photo, video, gb, stuff, polls, mchat) | `references/MODULES.md` |
| Categories, sections, access groups, filters, tags | `references/CATEGORIES_AND_ACCESS.md` |
| HTML / BBCode / plain, escaping, `$IMAGEn$` | `references/FORMATS.md` |
| SEO module, meta fields, `ownurl`, canonical, robots, verification | `references/SEO_AND_URLS.md` |
| Covers, gallery images, category images, attachments, upload flow | `references/MEDIA_WORKFLOW.md` |
| Generating images (with or without an image model) | `references/IMAGE_GENERATION_GUIDE.md` |
| Template ids, SEO head patch, H1, Open Graph, JSON-LD, backups | `references/TEMPLATES.md` |
| Installing modules, module/site/SEO settings, dangerous keys | `references/SETTINGS_AND_MODULES.md` |
| Site pages, menus | `references/PAGES_AND_MENUS.md` |
| Standard captions: field labels and list titles, when to rename, rollback | `references/SIGNS.md` |
| **Which style, skeleton, HTML layout and brief for this material** (news, guide, article, review, listicle, announcement, story, FAQ, category, board ad, page) + voice presets + HTML components | `references/styles/README.md` → `references/styles/<style>.md` |
| **Remove AI tells / make text human** (Russian-first, keeps facts and HTML) | `references/HUMANIZER.md` |
| General writing rules: facts, lengths, meta, URL (`ownurl`), tags, alt | `references/COPY_GUIDE.md` |
| Ready scenarios | `references/PLAYBOOK.md` |
| Audit checklist | `references/CHECKLIST.md` |
| Example requests | `examples/PROMPTS.md` |
