Summit of SummitsReturn to the Source
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.
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.
Two credential shapes, same capability + ACL enforcement:
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.
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 the webdav grant; 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 (the site_backup / site_apply tools; the domain-*
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 MCP analyse_visitors tool AND as the control-API
analyse_visitors action (?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-API
audit action). A separate capability from analytics; 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.
The connector deliberately cannot reach operator-only surfaces. Attempts return a
machine-readable kind:
lazysite/forms/*.conf and other config - blocked-config (delivery settings +
SMTP credentials are operator-only; use bind_form to reference a handler, never
to set one).lazysite/auth/*, .pl scripts, the manager - blocked.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.
tools manifest,
and the auth block (method + expiry). No capability required. Call it first.
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.
{ path }/) with size, mtime, ext
and generated. Brief presence left the listing with SM245 - ask list_briefs.
{ path }kind: binary) and files over 512 KB
(kind: too-large).
{ path }{ path }{ query, path }{ path }{ path | content }{ window }analytics
capability). Returns per-day totals, a people/AI-assistant/bot/noise breakdown,
top pages, referrers, status codes, and a capped recent event stream over the
last window days (1-365, default 30). Never the raw log, any filesystem path,
or a visitor IP. Read /docs/ai-briefing-stats for how to interpret it and what
may/may not be reported.
{ path }set_permissions.
manage_themes.
install_layout can pull without downloading anything. Needs manage_layouts.
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.
{ path, limit }{ path, version }{ path, version }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.
{ path, content }created (1 new / 0 overwrite) and runs
validate_page on the content, returning any warnings/issues. Audited as
create or edit.
{ slug, title, subtitle, body, register }{ slug }still_referenced_in (nav, other pages) for cleanup; generated indexes
refresh automatically.
{ old, new, update_links }update_links, rewrites
internal links to the old path across pages (nav.conf is not rewritten).
{ path, old, new }old is absent (no silent clobber); reports the replacement count.
{ from, to }{ from, to }{ path }delete.
{ path, read, write, draft }@groups), and the draft flag. A partial update: omitted fields keep their
current value. Setting a read list on a draft section leaves it draft -
still a 404 - so the API equivalent of the Publish button is
{"draft": false} alongside your grants. A field agent replicated the UI
flow, granted access, and the section kept 404ing; least surprise says the
trap gets named where the tool is learned.
{ form, handler }list_form_handlers. The connector never sets a destination or credential.
{ items }items is an ordered list of { label, url }
(a children list becomes a sub-menu; an item with no url is a section header).
Writes nav.conf and rebuilds the cache.
{ theme }manage_themes.
{ layout, theme }manage_layouts.
{ layout, theme, all, update, activate }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. Use
list_layout_catalogue first to see names.
{ layout }list_layout_catalogue -> install_layout -> (optionally) delete_layout.
A recovery snapshot is kept. Needs manage_layouts.
{ summary, good, bad, rating, context }{ path }"*" for all). A normal write
already clears its own page; use this for pages that embed another.
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.
{ host }lazysite-site-<host>-<stamp>.tar.gz in the backups area (fetch it with the
backup download if you need to move it to another instance). Returns the
package name.
{ name, host, clean }host to apply to the default site; clean: true clears
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-add on 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.
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).
whoami - confirm identity, capabilities, and that tools are loaded.list_files / list_pages / read_page - orient; read before you edit.validate_page (with content) - catch front-matter / form / public-data
issues before writing.write_file or replace_text - make one change at a time.preview_page - confirm the render in-channel (not a web fetch). page_status
confirms it will reach visitors.audit_site after 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]).