io.github.jonradoff/lightcms
AI-native CMS with 41 MCP tools for managing websites through natural language.
Versions
1.1.0latestTools 125
update_collection Update a collection's settings.
list_asset_folders List all unique folder paths in the asset library.
delete_collection Delete a collection. This does not delete the content in the collection.
regenerate_all_content Regenerate all published static HTML pages. Use after major theme or template changes.
list_assets List all assets in the asset library. Assets are files like images, documents, CSS, JS, etc.
start_link_check Start an asynchronous broken-link check across all published content. Returns a job_id immediately. Poll get_link_check_results(job_id) until status is "done". Example workflow: start_link_check() → {job_id: "abc123"} get_link_check_results("abc123") → if status=="running", wait and retry; if "done", review broken_links
get_link_check_results Get the status and results of a link check job. Status is "running", "done", or "failed".
get_theme Get current theme settings including colors, fonts, and custom HTML for header/footer.
update_theme Update theme settings. Only the fields you provide are changed — all other settings are preserved (partial update, safe to call without get_theme first). Changing header_html or footer_html triggers background regeneration of all published pages. Changing colors, fonts, or custom_css does NOT require content regeneration. Use pin_theme_version to protect important milestones before making major changes.
get_theme_versions Get the version history for theme settings. Returns list of versions with timestamps.
get_theme_version Get a specific version of theme settings with full data.
revert_theme_to_version Revert theme to a previous version. Creates a new version with the old data.
pin_theme_version Lock a theme version so it is protected from automatic pruning or accidental overwrite. Pinned versions are marked with locked=true in get_theme_versions. Use this to preserve milestone theme states (e.g., after a major redesign) before making further changes. Example: {"version": 5}
unpin_theme_version Remove the lock from a previously pinned theme version. Example: {"version": 5}
get_site_config Get site configuration including title templates.
update_site_config Update site configuration. Title templates support {{title}} and {{site_name}} placeholders.
list_redirects List all URL redirects configured for the site.
create_redirect Create a new URL redirect. Use 301 for permanent redirects, 302 for temporary.
update_redirect Update an existing redirect.
delete_redirect Delete a redirect.
list_folders List all content folders. Folders organize content into URL path segments.
create_folder Create a new content folder. Folders create URL path segments for organizing content.
get_folder Get a folder by ID.
delete_folder Delete an empty folder. Cannot delete folders that contain content or subfolders.
list_collections List all content collections. Collections group and display content by category.
create_collection Create a new content collection. Collections display grouped content with custom templates.
get_collection Get a collection by ID.
get_asset Get asset metadata by ID or path. Does not return file content (use the serve path to access the file).
upload_asset Upload or replace an asset in the asset library. Re-uploading to the same serve_path replaces the existing file in place — no need to delete first. Provide file content via one of: - file_path: Absolute local path to the file (preferred for files >100KB — avoids MCP transport size limits) - data_base64: Base64-encoded file content (fine for small files) Validates file type and MIME type for security.
upload_asset_from_url Fetch a public URL and store it as a LightCMS asset. Useful for importing images or files from the web without downloading them locally first. Example: {"url": "https://example.com/logo.png", "serve_path": "/assets/logo.png", "description": "Site logo"} If serve_path is omitted, the filename is derived from the URL. Returns id, serve_path, mime_type, and size.
delete_asset Delete an asset from the library. Removes both the file and database record.
list_import_sources List all configured RSS/Atom import sources
create_import_source Create a new RSS/Atom import source that automatically pulls content from a feed
update_import_source Update an RSS import source configuration
delete_import_source Delete an RSS import source
trigger_import_source Manually trigger an RSS import source to run immediately
import_markdown Import one or more Markdown pages into LightCMS. Each page can include YAML frontmatter (title, slug, folder, template, published, publish_at). Ideal for bulk content creation by AI agents — generate markdown with frontmatter and import directly. Example frontmatter: --- title: My Page slug: my-page folder: /blog template: Blog Post published: false --- Page body content here.
import_csv Import content from CSV data. Each row becomes a content page. Specify which column is the title; all columns become content fields.
list_import_jobs List recent import jobs with their status and results
get_import_job Get the status, results, and log of a specific import job
cancel_import_job Cancel a running import job
list_comments List all discussion comments on a content item.
create_comment Post a discussion comment on a content item. Requires discussion.post permission.
delete_comment Delete a discussion comment. Requires comment.delete permission (admin only).
start_agent_sandbox Start a sandboxed editing session backed by a content fork ("pull request for content"). While the sandbox is active: - update_content / update_content_by_path transparently copy pages into the fork and edit the copies (copy-on-write). Live content is never modified. - create_content creates new pages inside the fork. - Publishing, deleting, bulk operations, and search/replace-execute are blocked. - The site is unaffected until a human reviews the fork at /cm/forks and merges it. Recommended for any multi-page or risky editing task. End with end_agent_sandbox.
get_agent_sandbox Show whether an agent sandbox is active, and if so its fork ID, name, and the pages changed so far (with per-field diffs against live).
end_agent_sandbox End the sandbox session. action='submit' keeps the fork for human review and merge (at /cm/forks/{id}); action='discard' permanently deletes the fork and all its changes. Agents cannot merge their own sandbox — merging is a human decision.
get_fork_diff Per-field differences between each page in a fork and its live counterpart — the review surface for merging a fork. Status 'added' means the page exists only in the fork.
get_agent_session_changes The audit ledger for an agent session: every content item it changed, with actions and timestamps. Defaults to the current MCP session. Requires audit permissions.
rollback_agent_session Undo every content change made by an agent session as a unit: content the session created is soft-deleted, deleted content is restored, and updated content reverts to its latest pre-session version. Defaults to the current MCP session ("undo everything I did"). Non-content changes (templates, settings) are listed for manual review but not auto-reverted.
get_maintenance_report The latest site-health scan: stale pages (no update in ~6 months), published pages missing meta descriptions, and lingering drafts. Use it as a work queue — fix issues via the sandbox workflow.
run_maintenance_scan Run a site-health scan now and return the fresh report. Scans also run automatically once a day.
get_site_info Name, tagline, and base URL of this site, plus pointers to llms.txt and the sitemap.
list_pages All published pages on this site: title, path, and meta description.
search_site Full-text search across the published site. Returns matching pages with snippets.
get_page Full plain-text content of one published page by URL path, with title, description, and publish date.
list_approval_workflows List all configured approval workflows. Requires approval.manage_workflows permission.
get_approval_workflow Get a single approval workflow by ID.
create_approval_workflow Create a new approval workflow. Trigger types: all_contributor, folder_path, template_id, tag. Mode: sequential or concurrent.
update_approval_workflow Update an existing approval workflow.
delete_approval_workflow Delete an approval workflow.
list_approval_requests List pending approval requests. Use filter=mine to see only requests in your queue.
get_approval_request Get details of a single approval request including decisions so far.
submit_for_approval Explicitly submit a content item for editorial approval. Contributors must submit content for approval before it can be published.
approve_request Approve an approval request. When all required approvals are collected the content is automatically published.
reject_request Reject an approval request. A comment explaining the rejection is required and will be posted to the content's discussion thread.
cancel_approval_request Cancel a pending approval request.
list_templates List all available templates. Templates define content structure with fields and HTML layout.
get_template Get a single template by ID or slug. Returns full template including fields and HTML layout.
create_template Create a new template. Define fields with name, label, type (text, textarea, richtext, date, image, select), and options.
update_template Update an existing template. Changing the HTML layout will regenerate all content using this template.
delete_template Delete a template. Cannot delete system templates or templates that have content using them.
list_snippets List all snippets. Snippets are reusable Go-template HTML fragments used in lc:query index page directives.
get_snippet Get a snippet by ID.
create_snippet Create a new snippet. Snippets are Go templates that render one content item in an lc:query index page. Reference by name: <!-- lc:query filter=\"tag:MyTag\" snippet=\"your-snippet-name\" -->
update_snippet Update an existing snippet's name and/or HTML template.
delete_snippet Delete a snippet by ID.
search_content Search across all content items by title or full text. Returns matching content with paths and match context.
search_replace_preview Preview a site-wide search-and-replace without making any changes. ALWAYS run this before search_replace_execute. Returns: affected page count, total match count, and per-page field breakdown. For targeted replacements (a folder, template, or category), use scoped_search_replace_preview instead.
search_replace_execute Execute a site-wide search-and-replace across all content. Modifies every matching page permanently. MANDATORY workflow: 1. Run search_replace_preview and show the user which pages will be affected. 2. Get explicit user confirmation before executing. 3. Run search_replace_execute with a clear version_comment. Set auto_republish: true to immediately re-publish all previously-published pages after updating them, collapsing the execute + publish_multiple flow into one call. For targeted replacements, use scoped_search_replace_execute instead.
end_user_search Search published content using full-text exact match, semantic (AI) similarity, or hybrid mode. Returns page titles, paths, and snippets.
reindex_embeddings Regenerate vector embeddings for all published content. Required after initial setup or if embeddings become stale.
list_forks List all content fork workspaces. Forks let you stage changes to multiple pages as a batch before merging them live. Each fork shows its status (active/merged/archived), page count, and who created it. Use get_fork to see the specific pages in a fork.
create_fork Create a new named fork workspace for staging content changes. A fork is an isolated workspace where you can edit copies of live pages without affecting the public site. When ready, an admin can merge the fork to push all changes live at once. Typical workflow: 1. create_fork — create the workspace 2. fork_page — copy pages you want to edit into the fork (returns a fork page ID) 3. update_content (with the fork page ID) — make your edits 4. merge_fork — merge all changes to the live site (admin only) Returns the fork ID needed for subsequent fork operations.
get_fork Get details of a fork workspace including its status and list of pages. Returns: fork metadata + array of pages (id, title, full_path, updated_at). Use the page id with get_content or update_content to read/edit fork pages.
fork_page Copy a live page into a fork workspace so you can edit it without affecting the public site. Provide either: - path: the URL path of the page (e.g. "/about", "/blog/my-post") — preferred when you know the URL - content_id: the MongoDB ObjectID of the content item Returns the fork page ID. Use this ID with update_content to make edits: 1. fork_page → get fork_page_id 2. update_content with id=fork_page_id to edit 3. get_content with id=fork_page_id to verify 4. merge_fork when all edits are ready (admin only) If the page is already in this fork, returns the existing fork copy.
remove_fork_page Remove a page from a fork workspace (discards the fork copy, does not affect the live page).
merge_fork Merge all pages in a fork workspace into live content. Requires admin role. For each page in the fork: - If a matching live page exists (same URL): updates it with the fork content (fork wins). If the live page was edited after the fork was created, records a conflict but still merges. - If no live page exists at that URL: creates a new live page. After merging, the fork status changes to "merged". Published live pages are regenerated immediately. Returns: updated count, created count, any conflicts detected. ALWAYS confirm with the user before merging, as this pushes changes to the live site.
archive_fork Archive a fork without merging it. The fork and its pages are preserved but the fork becomes read-only. Requires admin role.
delete_fork Permanently delete a fork and all its pages. Cannot delete a merged fork. Requires admin role.
schedule_content_publish Set a future publish date/time for a content item. The scheduler automatically publishes it when the time arrives.
cancel_scheduled_publish Clear the scheduled publish time for a content item.
list_scheduled_content List all unpublished content items that have a scheduled publish time set.
list_content List all content items with optional filters. Returns content metadata including title, path, publish status, and timestamps. Add include_data: true to get full field data for all items in one call, or include_fields: ["field1", "field2"] to fetch only specific fields — both avoid per-item get_content calls for bulk workflows. Up to 20 concurrent update_content calls are safe. For larger batches, prefer bulk_update_content (up to 100 items per call).
get_content Get a single content item by ID or path. Returns full content including all field data (title, slug, full_path, data fields, published state). Prefer path when you know the URL: {"path": "/about"} Use id when you have the MongoDB ObjectID: {"id": "abc123"} Set include_rendered=true to also receive the fully rendered HTML output (template + theme header/footer applied). Useful for verifying what visitors see without publishing. Tip: to preview unsaved edits before publishing, use preview_content instead.
create_content Create a new content item. Requires a template_id, title, slug, and the data fields defined by the template. Workflow: 1. Call list_templates to find the right template and its field names. 2. Create the content with data matching those fields. 3. Call publish_content to make it live (or set published=true here to do both in one step). Set use_header=true, use_footer=true, use_theme=true for pages that should use the site layout. Always include version_comment to make history readable. Content data fields support rich markup features: - [[Wikilinks]] and [[Page Title|display text]] — link to other pages by title or path; auto-update when paths change - [[include:snippet-name]] — embed a named snippet inline (reusable callouts, CTAs, disclaimers) - #hashtags — mention #tagname anywhere to automatically tag the page - Markdown fields (type "markdown") — GitHub Flavored Markdown converted to HTML at publish time Templates can use {{.lc_toc}} in their HTML layout to inject an auto-generated table of contents.
update_content Update an existing content item by ID. Creates a new version automatically. Only send fields you want to change. For partial data updates, only the keys you include in "data" are changed — existing keys are preserved (merge semantics). Use clear_fields: ["field1", "field2"] to explicitly set fields to empty string. Set dry_run: true to validate the update without saving. To update by URL path instead of ID, use update_content_by_path. Always include version_comment so the version history is useful. Up to 20 concurrent update_content calls are safe. For larger batches (>20 items), prefer bulk_update_content instead. Example: {"id": "abc123", "data": {"body": "<p>Updated text</p>"}, "version_comment": "Revised intro paragraph"} Content data fields support rich markup features: - [[Wikilinks]] and [[Page Title|display text]] — link to other pages by title or path; auto-update when paths change - [[include:snippet-name]] — embed a named snippet inline (reusable callouts, CTAs, disclaimers) - #hashtags — mention #tagname anywhere to automatically tag the page - Markdown fields (type "markdown") — GitHub Flavored Markdown converted to HTML at publish time Templates can use {{.lc_toc}} in their HTML layout to inject an auto-generated table of contents.
publish_content Publish a content item, making it visible on the public site. Generates the static HTML page.
unpublish_content Unpublish a content item, removing it from the public site. Removes the static HTML page.
delete_content Soft-delete a content item. The content can be restored later. Removes the static HTML page.
restore_content Restore a soft-deleted content item. Regenerates static page if content was published.
get_content_versions Get the version history for a content item. Returns list of versions with timestamps.
get_content_version Get a specific version of a content item with full field data.
revert_to_version Revert content to a previous version. Creates a new version with the old data.
publish_multiple Publish multiple content items in a single call. Use this instead of calling publish_content in a loop. Examples: - Publish specific pages: {"ids": ["abc123", "def456"]} - Publish all drafts at once: {"publish_all_drafts": true} Returns a list of published IDs and any failures.
preview_content Render a content item's HTML without saving or publishing. Use this to verify what a page will look like before publishing. Also accepts optional title/data overrides to preview unsaved edits: {"id": "abc123", "data": {"body": "<p>New text</p>"}} Returns rendered_html and any warnings (missing required fields, unclosed tags, unresolved placeholders).
update_content_by_path Update content identified by its URL path instead of its ID. Useful when you know the page URL but not the MongoDB ID. Example: {"path": "/about", "title": "About Us", "data": {"body": "<p>Updated content</p>"}} Only the fields you provide are changed. Always include a version_comment describing what changed.
scoped_search_replace_preview Preview a search-and-replace limited to a subset of pages. Safer than site-wide replacement. Scope options (all optional — leave blank to match all pages): - content_ids: specific page IDs - folder_path: pages under /blog, /docs, etc. - template_name: pages using "Concept Page", "Blog Post", etc. - category: pages with a matching category Example: {"search": "old text", "replace": "new text", "folder_path": "/blog"} Always run preview before execute.
get_backlinks Find all published pages that link to the given URL path. Links are tracked automatically whenever a page is published — both [[Wikilinks]] and ordinary <a href="..."> links in content fields are indexed. Use this to discover which pages reference a given page (wiki-style backlink graph), assess the impact of deleting or renaming a page, or find orphaned pages with no inbound links. Example: {"path": "/about"} returns every published page whose content contains a link to /about.
scoped_search_replace_execute Execute a search-and-replace limited to a subset of pages. ALWAYS run scoped_search_replace_preview first and show results to the user before executing. Scope options (all optional): - content_ids, folder_path, template_name, category Set auto_republish: true to immediately re-publish all previously-published pages after updating them, collapsing the execute + publish_multiple flow into one call. Example: {"search": "old text", "replace": "new text", "folder_path": "/blog", "auto_republish": true, "version_comment": "Updated old references"}
bulk_create_content Create up to 100 content items in a single call using efficient batch insert. Items are inserted via MongoDB InsertMany for maximum throughput. If one item fails (e.g., duplicate path), the rest continue. Published items get their static HTML generated in parallel (up to 10 concurrent). Set upsert: true to update existing pages at the same path instead of failing on duplicates. Returns: total attempted, succeeded, failed counts, and per-item {id, full_path, success, error} details.
bulk_update_content Update up to 100 content items in a single call. Use instead of calling update_content in a loop. Each update in the array specifies the content ID and only the fields you want to change (merge semantics on data). Use clear_fields to explicitly clear field values to empty string. Set dry_run: true to validate all IDs exist without committing changes. Returns: total attempted, succeeded, failed counts, and per-item success/error details. Tip: call list_content with include_data: true first to get IDs + current field values, transform as needed, then submit here. Recommended batch size: up to 50 per call for optimal performance.
bulk_field_operation Apply a single field operation to all matching content pages in one call. Operations: - clear: set field to empty string - set: replace field value with a fixed string - prepend: add text before existing field value - append: add text after existing field value - wrap: surround existing value with before/after strings Use scope filters to limit which pages are affected (content_ids, folder_path, template_name, category). Set dry_run: true to preview which pages would be changed without saving. Example: {"operation": "prepend", "field": "disclaimer", "value": "<p>Note: </p>", "template_name": "Blog Post"}
export_content Export content items with their full field data as a structured JSON array. Use for batch transformations: export → transform externally → re-import via bulk_update_content. Scope filters (all optional): - template_name: most useful for bulk workflows, e.g. "Concept Page" or "Blog Post" - category, folder_path, content_ids: narrower scoping options Use fields: ["field1", "field2"] to include only specific data fields instead of all fields. Returns: total count and array of items with id, title, slug, full_path, template_name, published, and data.
list_audit_logs List recent audit log entries. Admin only. Supports filtering by action and resource type.
get_content_lock Get the current advisory lock status for a content item. Returns lock holder and expiry, or {locked: false} if unlocked.
acquire_content_lock Acquire an advisory lock on a content item for the current API user. Returns conflict if another user holds the lock.
release_content_lock Release the advisory lock on a content item held by the current API user.
force_unlock_content Admin only: force-release any lock on a content item regardless of who holds it.
list_webhooks List all registered webhooks. Secrets are never returned.
create_webhook Create a new webhook. Returns the generated HMAC-SHA256 secret ONCE — save it immediately. Valid event types: content.create, content.update, content.publish, content.unpublish, content.delete, comment.created, content.pending_approval, asset.pending_review
update_webhook Update an existing webhook (name, URL, events, active). Partial update — only provided fields change.
delete_webhook Permanently delete a webhook.
regenerate_webhook_secret Generate a new HMAC-SHA256 signing secret for a webhook. The old secret stops working immediately. The new secret is returned ONCE — save it.
list_webhook_deliveries List recent delivery attempts for a webhook.
Permissions 1
network medium