AI connector - tools reference
capability model, and every tool it exposes. For *setting up* a connector (adding
it in Claude.ai / ChatGPT / Claude Code) see Connect an AI assistant.
The connector is supervised, not autonomous: an AI drafts and edits through these tools, but it is bound by the partner's capabilities and per-file ACLs, the deny-list (it can never read or write delivery secrets), and - for write actions - the AI client's own per-call approval. Reads are not audited; writes are recorded as material events.
Endpoint and protocol
The connector is a single MCP endpoint, Streamable HTTP / JSON-RPC:
https://YOUR-SITE/cgi-bin/lazysite-mcp.pl
initialize and tools/list are open (discovery); a tools/call requires
authentication. An unauthenticated tool call returns HTTP 401 with a
WWW-Authenticate challenge so an OAuth client starts the sign-in flow.
Authentication
Two credential shapes, same capability + ACL enforcement:
- OAuth (Claude.ai, ChatGPT web)
- The client registers itself, the operator's one-time connect code is entered at the consent screen, and an opaque access token is issued (expires hourly, refreshed transparently).
- Static bearer (Claude Code, Desktop, scripts)
-
Authorization: Bearer <partner-id>:<lzs_ token>- the token comes from Generate credential on the Users page.
whoami returns an auth block - { method: "oauth"|"bearer", expires_at } - so
the agent can see how the session is authenticated and when it lapses.
Capabilities
A partner's grant (visible in whoami.capabilities) gates the tools:
manage_content- read/write content pages and use the file tools (most tools). Defaults to thewebdavgrant; set off for a theme-only partner.manage_themes- activate themes.manage_layouts- activate layouts.manage_domains- manage the domains this instance serves, and move whole sites between them (thesite_backup/site_applytools; thedomain-*control-API actions).webdav- the WebDAV transport / file-API mechanism flag.manage_config- site configuration (control API, not exposed as MCP tools).analytics- read the visitor-log analysis. Off by default; an explicit grant, since it exposes (aggregated, IP-anonymised, path-free) log data. Visitor analysis is available both as the MCPanalyse_visitorstool AND as the control-APIanalyse_visitorsaction (?action=analyse_visitors&window=N), so an API-channel client gets it too.audit- read the audit trail (the in-page Audit view plus the control-APIauditaction). A separate capability fromanalytics; off by default.
Per-file ACLs (owner + read/write lists, with @groups) bind a token client
exactly as over WebDAV - a tool call is refused if the partner lacks access to the
target, regardless of capability.
What is walled off
The connector deliberately cannot reach operator-only surfaces. Attempts return a
machine-readable kind:
lazysite/forms/*.confand other config -blocked-config(delivery settings + SMTP credentials are operator-only; usebind_formto reference a handler, never to set one).lazysite/auth/*,.plscripts, the manager -blocked.- User administration, secrets, credential minting - not exposed at all.
Tools
37 tools. Reads are not audited; writes are recorded in the audit log as
material events and may trigger the AI client's per-call approval. All file tools
need manage_content unless noted.
Identity
- whoami
-
Partner identity, capabilities, active layout/theme, the full
toolsmanifest, and theauthblock (method + expiry). No capability required. Call it first. - describe_capabilities
-
The full capability map: every capability and what it unlocks (MCP tools,
control-API actions, WebDAV paths), task recipes for common jobs, the
engine-owned paths you must not write, and - under
holds- what THIS account currently has. No capability required. The task recipes are the sanctioned sequences: follow them (e.g.switch-layout,restore-from-history) rather than improvising an order.
Reading and inspecting (reads - not audited)
- list_files
{ path } -
Files and folders under a directory (default
/) with size, mtime, ext, has_brief, generated, is_brief. - read_file
{ path } -
A text file's contents. Refuses binary (
kind: binary) and files over 512 KB (kind: too-large). - read_page
{ path } - A page as structured data - parsed front matter, Markdown body, has_brief, public_url.
- list_pages
- Every page with title, registries (sitemap/llms/feed) and public URL.
- page_status
{ path } - Whether the source exists + last-modified, whether the render is pending (cache dropped after an edit, re-renders next visit), and the public URL. Confirm an edit will reach visitors without a web fetch.
- search_files
{ query, path } - Case-insensitive content grep across text files, returning path + line snippets. Excludes the lazysite/ infra; file- and match-capped.
- preview_page
{ path } - Render a page server-side, fresh (no cache), and return its HTML + status - in-channel verification of layout / nav / form output. Public view; a protected page shows the auth gate.
- validate_page
{ path | content } - Pre-publish checks: unterminated front matter, missing title, invalid form-field rules, and a public-data warning (Wi-Fi passwords, postcodes/addresses, phone numbers).
- audit_site
- Whole-site audit: broken internal links, orphan pages, missing titles, stale generated HTML, duplicate content blocks.
- analyse_visitors
{ window } -
Sanitised visitor-log analysis for trend reporting (needs the
analyticscapability). Returns per-day totals, a people/AI-assistant/bot/noise breakdown, top pages, referrers, status codes, and a capped recent event stream over the lastwindowdays (1-365, default 30). Never the raw log, any filesystem path, or a visitor IP. Read/docs/ai-briefing-statsfor how to interpret it and what may/may not be reported. - get_permissions
{ path } -
The ACL for a path (owner + read/write grants) - call before
set_permissions. - list_form_handlers
- The configured form delivery handlers (id, type, name). No destinations or credentials are returned.
- read_nav
- The site navigation as a structured list (items + children) plus the raw nav.conf. Read before set_nav.
- list_themes
-
The themes installed across all layouts, with which is active. Needs
manage_themes. - list_layout_catalogue
-
The layouts available in the configured layouts repo (name, version, default
theme, themes), annotated with what is already installed - discover what
install_layoutcan pull without downloading anything. Needsmanage_layouts.
Version history (needs the site's Content history plugin)
When the operator has enabled the Content history plugin, every save
(manager, WebDAV, or this connector) is recorded as a version, and these tools
let you inspect and undo content changes. If list_versions returns
enabled: false, versions are not being recorded - ask the operator to enable
the plugin; do not try to build your own history. All three need
manage_content.
- list_versions
{ path, limit } - A file's recorded versions, newest first: version id, author, date, message. Not audited (a read).
- view_version
{ path, version } - One version's full content plus a unified diff against the current file. Not audited (a read).
- restore_version
{ path, version } - Restore the file to that version. The historic content is written back through the normal save path (page cache refreshed) and the restore itself becomes the newest recorded version - nothing is lost by restoring. Audited.
Remote sync of the history (push/pull to a git host) is operator-only by design - it is configured and driven from the manager UI (Remote sync plugin) and is not exposed over the connector or the control API.
Writing and editing (writes - audited)
- write_file
{ path, content } -
Create or overwrite a text file. Returns
created(1 new / 0 overwrite) and runsvalidate_pageon the content, returning anywarnings/issues. Audited ascreateoredit. - create_page
{ slug, title, subtitle, body, register } - Create a new page from front-matter fields + body; errors if it already exists.
- delete_page
{ slug } -
Delete a page and its
.brief, and reportstill_referenced_in(nav, other pages) for cleanup; generated indexes refresh automatically. - rename_page
{ old, new, update_links } -
Rename / move a page (carries
.brief+ ACL); withupdate_links, rewrites internal links to the old path across pages (nav.conf is not rewritten). - replace_text
{ path, old, new } -
Replace exact text without rewriting the whole file - safer for a small change.
Errors if
oldis absent (no silent clobber); reports the replacement count. - copy_file
{ from, to } - Copy a text file to a new path (templating). Destination starts with a fresh ACL.
- move_file
{ from, to } -
Rename / move a file; carries its
.briefand re-keys its ACL. - delete_file
{ path } -
Delete a file. Audited as
delete. - set_permissions
{ path, read, write } -
Set the per-file ACL - owner plus comma-separated read/write lists (users or
@groups). - bind_form
{ form, handler } -
Wire a form to delivery by referencing an existing handler from
list_form_handlers. The connector never sets a destination or credential. - set_nav
{ items } -
Replace the site navigation -
itemsis an ordered list of{ label, url }(achildrenlist becomes a sub-menu; an item with no url is a section header). Writes nav.conf and rebuilds the cache.
Site operations
- activate_theme
{ theme } -
Activate a theme for the current layout (clears the HTML cache).
Needs
manage_themes. - activate_layout
{ layout, theme } -
Activate a layout, optionally naming a compatible theme. Needs
manage_layouts. - install_layout
{ layout, theme, all, update, activate } -
Install a layout and its theme(s) from the configured repo and activate it
(default). Needs
manage_layouts. To switch the site to a different layout, this one call is the whole switch - it installs AND activates. Only delete the old layout afterwards, if at all. Uselist_layout_cataloguefirst to see names. - delete_layout
{ layout } -
Delete an installed layout and its themes. The ACTIVE layout is always
refused - when switching, install/activate the replacement first, then
delete the old one. Never delete first: the right order is
list_layout_catalogue->install_layout-> (optionally)delete_layout. A recovery snapshot is kept. Needsmanage_layouts. - submit_feedback
{ summary, good, bad, rating, context } - Report what worked and what got in the way while building through the connector - this is how the operators improve the tools. Use it freely; your identity and context are recorded automatically. No capability required.
- invalidate_cache
{ path } -
Drop a page's cached HTML so it re-renders (
"*"for all). A normal write already clears its own page; use this for pages that embed another.
Site migration (move a whole site between domains or instances)
A site package is a portable snapshot of ONE domain's site: its content, its
navigation, the theme and layout it uses, and its presentation settings. It
deliberately excludes plugins, instance settings and any secrets, so it is safe
to hand to another instance. Use it to turn an agency demo into a client's live
site, or to copy a site to another domain. Both tools need manage_domains and
access to the domain.
- site_backup
{ host } -
Package the named registered domain's site into
lazysite-site-<host>-<stamp>.tar.gzin the backups area (fetch it with the backup download if you need to move it to another instance). Returns the packagename. - site_apply
{ name, host, clean } -
Apply a package (already in this instance's backups area) onto a target: copies
its content into the target domain's content root, installs the bundled
theme/layout if the target lacks it, places the nav, and sets the domain's
presentation. Omit
hostto apply to the default site;clean: trueclears the target content first. Apply overwrites the target - take a backup first if you want a rollback point. The target domain must already be registered (domain-addon the control API) unless you are applying to the default site.
The end-to-end recipe (migrate-site) is in describe_capabilities under
tasks: site_backup on the source -> (download + site-backup-upload if a
different instance) -> site_apply on the target -> verify.
Error model
A failed tool result is { ok: 0, error, kind }. The kind lets an agent tell
causes apart: blocked, blocked-config, not-found, permission, binary,
too-large, invalid-path. A 401 carries error.data.reason -
sign-in-incomplete (no credential reached the server - re-authorise the
connector) vs credential-invalid (expired/revoked - reconnect).
A reliable edit loop
whoami- confirm identity, capabilities, and that tools are loaded.list_files/list_pages/read_page- orient; read before you edit.validate_page(withcontent) - catch front-matter / form / public-data issues before writing.write_fileorreplace_text- make one change at a time.preview_page- confirm the render in-channel (not a web fetch).page_statusconfirms it will reach visitors.audit_siteafter a set of changes - catch broken links / orphans / duplicates.
Pages are Markdown files served at their path (about.md → /about); a page that
registers in a feed lists it in front matter (register: [sitemap, llms]).