Digital Sovereignty for everyone

Notes

Rationale and cross-ability notes behind the generated ability reference.

Permission gates

Most abilities are gated to edit_posts by a single plugin-wide permission check. Two differ: search-users requires list_users, because it returns email addresses, and get-site-info requires nothing at all. That gate is deliberately coarse: it establishes that the caller edits content on this site and nothing more, so any ability touching a specific object does its own per-object check on top of it (read_post in get-post, edit_post in update-post, the target resource’s own permission callback in read-mcp-resource).

get-site-info is open on purpose

It is a trivial ability anyone can use as a connection test. Everything it can return already appears in the markup of every front-end page. What keeps that safe is a fixed, deliberately non-filterable allowlist: requested fields are intersected against it before anything reaches get_bloginfo(), which would otherwise hand back admin_email, the WordPress version and the template paths. audit-abilities flags its __return_true permission callback; that warning is accepted.

Reading content

get-post is constrained to the readable post-type allowlist (post and page by default). content_raw is always complete; content_markdown is the part that can be absent. markdown_source takes one of five values. lh-content-converter means the conversion ran (before 1.11.0 this value was lh-mcp-block-transformer). empty means the post has no content, so content_markdown is an empty string. classic means the post has no block markup to convert (classic-editor content, a bare shortcode or embed URL); it is expected rather than an error, and content_raw should be read and edited in whatever form it was saved. unavailable means LH Content Converter is not active, and failed means it ran and reported an error; both are genuine problems, and notice carries what to tell the user.

list-posts is deliberately not narrowed to the readable allowlist, since it returns titles, slugs, links and dates rather than content. Whether it should be narrowed is a real question, and an open one.

Authoring content

Neither write ability can publish a post or page. Which statuses each may write is set per post type (see Menus, template parts and synced patterns): for posts, pages and other content it is draft or pending, so publishing stays a human act. Only block-theme menus, template parts and synced patterns may be published here, behind edit_theme_options and guards that refuse a publish that would change the live site by itself.

create-post is restricted to post types with a write rule (post, page and the three design types by default, filterable, and deliberately separate from the readable allowlist) and checks the type’s own create_posts capability. Everything is validated before the insert runs, so a failure on meta or terms leaves no empty draft behind. It is annotated non-idempotent: repeating a call creates a second post.

update-post has patch semantics: a field is written only if it was supplied, so the natural way to retitle a post is to send a title alone. Which posts may be touched is decided per type by an allowlist of current statuses (for posts and pages draft, pending and auto-draft) rather than by excluding publish, so a status nobody anticipated is refused by default. A live post or page is refused with a pointer to lh-agora/propose-changes. It is annotated destructive, because supplied fields replace what was there and the post’s revisions are the only way back, and idempotent, because repeating the same call leaves the post in the same state.

Users

search-users ranks across nine priorities: exact beats partial, and last name beats first name. Multi-word input runs an AND pass first and falls back to OR if that yields nothing. Each result reports which field and match type determined its rank.

MCP resources

list-mcp-resources and read-mcp-resource let a caller discover and read abilities registered as MCP resources rather than tools, instead of a human attaching them by hand. read-mcp-resource invokes the target exactly as the MCP resources/read handler does, and its content is whatever the target returns, typed as any JSON value. audit-abilities asks for an items schema on it because the type list includes array; that warning is accepted.

If you like this plugin please consider making a donation to further development

Install LHero.org

lhero.org

Open it straight from your home screen, full screen and quicker to load.

  1. Tap the Share button . If you cannot see it, tap ••• first.
  2. Scroll down and tap Add to Home Screen.
  3. Tap Add.
  1. Tap the browser menu â‹®.
  2. Tap Install app or Add to Home screen.
  1. In the menu bar, choose File, then Add to Dock.

Use your browser's menu to install this site or add it to your home screen.