=== Rectus Content Access for MCP ===
Contributors: rectuswp
Tags: mcp, ai, content, custom post types, media
Requires at least: 6.9
Tested up to: 7.1
Requires PHP: 7.4
Stable tag: 1.6.0
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

Connect MCP clients to WordPress posts, pages, custom post types, taxonomies, and media with configurable access.

== Description ==

Rectus Content Access for MCP lets authenticated MCP clients manage WordPress content, classic navigation menus, and media files.

For a Japanese overview and setup guide, visit the [Rectus Content Access for MCP introduction page](https://www.rectus.co.jp/tool/rectuscontentaccessformcp.html).

The plugin provides:

* Listing, creation, and updating of posts, pages, and selected custom post types, including exact slug lookup and conflict-checked slug changes.
* Targeted string edits with full-field SHA-256 conflict detection, so small corrections do not require resending an entire title, excerpt, or content field.
* Confirmation-protected movement of posts to the WordPress trash with post type and modified-time conflict checks.
* Listing, reading, and conflict-checked restoring of post revisions, with the text a post had before each change through MCP kept as a revision.
* Preview links for unpublished posts in post lists, reads, and write results.
* Exact text search across the posts the user can edit, and batch edits and updates of up to 50 posts in one call, so an old URL or a category can be changed across many posts after the list has been checked.
* Page order on creation and update, and duplication of a post into a new draft.
* An optional publication date on creation and update, so back-dated entries such as a release history can be filed under the day they happened.
* Reading of a single post's stored title, content, excerpt, and assigned terms, available to any account WordPress allows to read the post.
* Listing of enabled post types with labels, supported fields, and taxonomies.
* Searching, creation, conflict-checked updating, and confirmation-protected permanent deletion of categories, tags, and custom taxonomy terms.
* Paginated content lists with status, search, taxonomy term, and ordering filters.
* Featured image assignment from uploaded media when creating or updating posts.
* Classic navigation menu, menu item, hierarchy, order, and theme-location management with checksum conflict protection, including batch edits of up to 100 menu items in one call.
* Media library listing, physical filename changes, and confirmation-protected permanent attachment deletion.
* Conflict-checked updates of the title, alternative text, caption, and description of up to 100 media items in one call.
* A settings screen where administrators choose which post types MCP clients may access, and which protected custom fields, such as SEO plugin fields, MCP may read and write.
* An activity log of successful changes and partially completed batches under Tools > MCP Activity.
* Site information, including the front page, permalink structure, and whether the active theme is a block theme.
* Listing of classic widget areas and conflict-checked changes to a widget's settings.
* Comment listing without email or IP addresses, and approving, holding, spamming, or trashing up to 100 comments in one call.
* Support for standard content fields, public custom fields, and taxonomies assigned to the selected post type.
* Listing, reading, creation, update, and confirmation-protected deletion of managed fixed-page templates in the active theme.
* Reading, replacing, partly editing, and clearing Additional CSS with checksum conflict protection, and restoring it from its revisions.
* Fixed-page template assignment through post creation and update operations.
* Direct multipart image uploads for Codex and Claude Code using short-lived, one-time tickets.
* Base64-encoded image uploads as a fallback for MCP clients that cannot perform direct uploads.
* Browser-based OAuth 2.1 authorization with PKCE and automatic token refresh.
* Copy-ready setup commands for Codex and Claude Code.
* Site-specific MCP server names derived from the WordPress domain and path to prevent client configuration collisions.
* Support for MCP protocol revisions 2025-11-25, 2025-06-18, and 2024-11-05, negotiated with the connecting client.
* Server identity reported on connection, including the site title, description, website URL, and icons, so a client registered against several sites can tell them apart.
* Translation-ready administration, OAuth, MCP ability, and error strings.

Posts and pages are enabled by default. Custom post types must be enabled by an administrator before MCP clients can use them.

Rectus Content Access for MCP checks the authorized WordPress user's native capabilities for every operation, including each post type's create, edit, publish, and taxonomy permissions.

Reading follows the read capability rather than the edit capability. An account that may read but not edit, a subscriber by default, can therefore list and read published content, its public custom fields, and the terms assigned to it, while every write operation stays refused. Drafts and private posts remain limited to the users WordPress already allows to see them.

Saved content is filtered by the same capability WordPress itself uses, so an edit made through an MCP client is stored exactly as the block or classic editor would have stored it. Markup that the editors keep, such as JSON-LD structured data and schema.org microdata, survives the round trip instead of being silently rewritten.

For targeted corrections, post-get returns SHA-256 checksums of the exact stored title, content, and excerpt. Post-edit requires the selected field checksum, re-reads the database immediately before saving, and returns a conflict without saving if the field changed. WordPress save filters still run normally, and the stored value is verified before success is reported.

OAuth access tokens, refresh tokens, authorization codes, and direct media upload tickets are stored only as SHA-256 hashes. Access tokens expire after one hour, refresh tokens are rotated automatically, and connections can be revoked from the settings screen. Uninstalling Rectus Content Access for MCP removes its settings and OAuth data.

A client that shares one credential between several processes can present a refresh token that another process already rotated away. For supported retry behavior, Rectus Content Access for MCP can replay the already-issued token pair instead of issuing a parallel credential, so the client converges on the single active credential. Replay material is encrypted with a key derived from the presented refresh token itself, so it is never recoverable from the database alone. Replay requests are bounded by the rotation history and a time safety limit; requests outside those bounds are treated as reuse of an invalid credential and revoke the connection family.

The official WordPress MCP Adapter library is bundled with Rectus Content Access for MCP. A separate MCP Adapter plugin or Node.js process is not required on the WordPress server.

== Installation ==

1. Install and activate Rectus Content Access for MCP.
2. Open Settings, Rectus Content Access for MCP.
3. Select the post types that MCP clients may list, create, or update.
4. Copy and run the setup command for your client.
5. Follow the client-specific authentication instructions shown on the settings screen.

HTTPS is required for OAuth connections. The connection has the same effective permissions as the WordPress user who approved it.

== Screenshots ==

1. Configure connection readiness, allowed post types, and MCP client setup commands.

== Frequently Asked Questions ==

= Does Rectus Content Access for MCP require an external service? =

No service operated by the plugin author is required. MCP requests are handled by WordPress through the bundled official MCP Adapter library. When an OAuth client uses an HTTPS URL as its client ID, Rectus Content Access for MCP retrieves public client metadata from that client-provided URL as described below.

= What data is sent when URL-based OAuth client metadata is retrieved? =

During OAuth authorization, a connecting client may provide an HTTPS metadata URL as its client ID. Rectus Content Access for MCP then sends a server-side GET request to that exact URL with an `Accept: application/json` header. The response is limited to 64 KB and valid metadata is cached for one hour. No WordPress content, passwords, OAuth codes, or tokens are sent. The destination is selected and operated by the connecting MCP client, not by the plugin author, so the destination operator's terms and privacy policy apply.

= Does the WordPress server need Node.js? =

No. The server-side plugin runs in PHP. An MCP client may have its own local runtime requirements, depending on the client.

= Does Rectus Content Access for MCP send my WordPress password to the MCP client? =

No. The user signs in on the WordPress site and approves the connection in the browser. The MCP client receives short-lived OAuth tokens instead of the WordPress password.

= How do I revoke a connection? =

Open Settings, Rectus Content Access for MCP and revoke the connection in the OAuth connections table. MCP clients may also clear or revoke their saved authorization.

= Can I connect an account that reads content but never changes it? =

Yes. Authorize the connection as a user without editing rights, a subscriber by default. That account can list posts, read a post with its content and public custom fields, read the terms assigned to it, list the enabled post types, and read the site information. Every create, update, edit, delete, media, menu, template, and CSS operation is refused, as is reading a draft or a private post, because WordPress itself limits those to the users allowed to see them. The media library cannot be listed either, since that needs the upload capability.

On WordPress 7.1 or later the connection is offered only those five read abilities. The rest are hidden from ability discovery rather than listed and refused on use.

= How are local images uploaded without Base64? =

Codex and Claude Code should call the media upload ticket tool with the local image filename, byte size, MIME type, and attachment metadata. The tool returns a plugin REST endpoint and a short-lived, one-time token. The client then sends the image bytes directly as multipart form data. The image does not enter the model context, and no Application Password or second WordPress login is required.

The ticket is valid for five minutes, is bound to the authorized WordPress user and expected file metadata, and is stored only as a SHA-256 hash. Repeating a completed request with the same ticket returns the existing attachment instead of creating a duplicate.

MCP clients that cannot perform the direct HTTP upload may continue to use the Base64 media upload tool. Files already present in the WordPress uploads/mcp-inbox directory may use the media import tool without transferring image bytes through MCP.

= How do I rename or delete media? =

Use the media list tool to search the WordPress media library and obtain the exact attachment ID, filename, and file-state SHA-256. To change the physical filename, call media rename with those values, a new filename, and `confirm` set to true. The extension and upload directory stay unchanged. Local original files, generated sizes, edit backups, and attachment metadata are renamed together.

To delete media, call the media delete tool with the selected ID, matching filename, and `confirm` set to true. WordPress checks the authorized user's delete permission for the selected attachment.

Renaming changes the public media URL. Deletion is permanent and removes the attachment and its generated files. Existing links to that media in post content are not rewritten, so clients should show the selected ID and filename to the user before confirming either operation.

= Can MCP manage Appearance > Menus? =

Yes. Navigation menu abilities list and read classic menus, create and update menu metadata, add and edit ordered hierarchical items, delete childless items or whole menus with confirmation, and assign or clear registered theme locations. Mutations require the SHA-256 returned by the latest menu read, and all operations require the authorized user's edit_theme_options capability.

To build or rework a large menu, navigation-menu-item-batch creates, updates, and deletes up to 100 items in one call. Every operation is checked before sequential saving starts. A later WordPress or reorder failure can leave earlier operations applied and returns their results with a new checksum, so read the menu again before retrying. Items created in the batch can be parents of later ones, and the response does not repeat every item unless requested.

= Can a change made through MCP be undone? =

Yes, for post text and Additional CSS. post-revision-list lists the revisions of a post, post-revision-get reads one, and post-revision-restore brings back its title, content, and excerpt. Other data a revision holds is not restored, so a revision whose revisioned custom fields, such as footnotes, differ from the post is refused; restore that one in WordPress. Before post-update, post-edit, or a restore replaces the text of a post, the current text is saved as a revision, so even the text a post was created with can be restored.

Revisions require the right to edit the post, and restoring a published post also requires publishing rights. A restore requires the current field checksums from post-get, so a post changed after it was read is not overwritten. When the site keeps no revisions, post-revision-list reports `revisions_enabled` as false. Additional CSS has its own revisions, described under the CSS question.

= How do I change the alternative text of images? =

media-list returns the title, alternative text, caption, description, and `meta_sha256` of each item. Pass up to 100 items with their `meta_sha256` to media-update to change any of those four fields. Every item is checked before sequential saving starts. A later conflict or WordPress failure can leave earlier items changed and returns them in a partial error, so list the media again before retrying. Text the user may not save is refused rather than altered. Files and existing links in content are not changed.

= Can MCP set SEO titles and meta descriptions? =

Yes, when the SEO plugin keeps them in custom fields and an administrator allows their keys. Fields whose keys begin with an underscore are hidden from MCP. List the keys one per line under Protected custom fields in the settings, such as `_yoast_wpseo_title` and `_yoast_wpseo_metadesc` for Yoast SEO. Only users who can edit a post can then read or change those fields through post-get, post-create, and post-update.

Keys that WordPress uses itself, such as those beginning with `_wp_` or `_edit_`, are never opened. Rank Math fields have no leading underscore and are available already. All in One SEO keeps its data in its own database tables and is not supported.

WordPress treats custom field keys without a leading underscore as public metadata, and readable posts return them through MCP. Do not store secrets or personal data in a public custom field; use a protected key and grant access only when it is intended.

= What does Tools > MCP Activity show? =

Every successful change made through MCP, every partially completed batch, and every direct media upload: the time, WordPress user, client, operation, target, and the names of the fields given. Values such as post content are never stored. Only administrators can view the log. A failed database write fires the `rectus_mcp_content_log_write_failed` action. Entries older than 90 days are removed daily, and the `rectus_mcp_content_log_retention_days` filter changes the period. Uninstalling the plugin removes the log.

= Can MCP change many posts at once? =

Yes. post-text-search finds exact, case-sensitive text, such as an old URL, in the posts the user can edit, and returns where and how often it occurs with the field checksums, without the full text. After the list has been shown to the user, post-edit-batch applies post-edit to up to 50 posts in one call, and post-update-batch applies post-update, for example to add a category. Each post-update item also requires the latest `modified_gmt`. Every item is checked before sequential saving starts. A later conflict or WordPress failure can leave earlier posts changed and returns them in a partial error, so read the posts again before retrying. The text each post had is kept as a revision.

= Can MCP copy a page or change the page order? =

post-duplicate copies one post into a new draft with its content, excerpt, parent, order, page template, terms, featured image, and the custom fields MCP can read. Custom fields hidden from MCP, including hidden ACF field references, are not copied. post-create and post-update accept `menu_order` for post types with page attributes, such as page, and post-get and post-list return it.

= Can MCP manage widgets and comments? =

On a classic theme with widget areas, widget-list lists every area, including inactive widgets, with each widget's settings, and widget-update changes settings of one widget after matching its checksum. The widget sanitizes the values as Appearance > Widgets does, and a value it would alter is refused. Widgets are not added, moved, or removed. This requires the edit_theme_options capability.

comment-list lists comments by status without email or IP addresses, and comment-moderate approves, holds, marks as spam, or trashes up to 100 comments after checking each comment's current status. Comments are never deleted permanently. This requires the moderate_comments capability.

= How are posts deleted? =

Post delete moves an enabled post, page, or custom post type entry to the WordPress trash. It requires the exact ID, post type, modified time from a prior read, and `confirm` set to true. It never permanently deletes content and refuses the operation on sites where the trash is disabled.

= How are post slugs found and changed? =

Pass `slug` to post-list for an exact slug lookup. The separate `search` field uses WordPress content search. Post-create accepts an optional slug and returns the actual stored value.

To change a slug, first call post-get, then pass its current `slug` as `expected_slug` and the new value as `slug` to post-update. A stale current value is rejected. A value that WordPress would silently suffix, such as adding `-2` because another post already uses it, is also rejected with the suggested value in the error data.

WordPress does not keep a published post without a slug. Passing an empty slug to post-update resets the manual value: published content regenerates the slug from its current title, while a draft may remain empty until publication. To delete the post itself and release its active slug, use post-delete. Its response reports the slug before trashing and the stored trashed slug.

= Can MCP manage categories, tags, and custom taxonomy terms? =

Yes. The term list tool searches existing terms and returns their IDs, names, slugs, descriptions, parents, usage counts, and an editable-state SHA-256. Term create can add a category, tag, or custom taxonomy term, including an optional slug, description, and parent for hierarchical taxonomies. Term update can change those fields after matching the latest state checksum.

Term delete permanently removes the selected term and may remove or reassign existing post relationships according to WordPress rules. It therefore requires the exact ID, taxonomy, latest state checksum, and `confirm` set to true. WordPress-protected default terms cannot be deleted. Every operation remains limited to taxonomies attached to an enabled post type and to the authorized user's native taxonomy capabilities.

= How is the MCP server name chosen? =

Rectus Content Access for MCP derives the client configuration name from the site's domain and subdirectory path. For example, `rectus.co.jp` becomes `wordpress-rectus-co-jp`, while `example.com/site-a` becomes `wordpress-example-com-site-a`. This prevents different WordPress sites from overwriting each other's MCP client configuration.

= Why should I run the Codex login command only when needed? =

Codex App and Codex CLI share MCP configuration. After the add command saves the server, Codex App may open the authorization screen automatically. Approve that screen once. Run `codex mcp login` only when authorization does not start; running both flows at the same time can create a duplicate OAuth connection.

= How do I authenticate Claude Code? =

Run the displayed `claude mcp add` command, then run `claude mcp login`. The login command opens the browser authorization screen directly, so there is no need to start Claude Code and run `/mcp` manually.

= Why do new MCP clients fail to connect while existing clients keep working? =

The OAuth discovery URLs under `/.well-known/` are served through WordPress. Server rules that handle `/.well-known/` before WordPress break new authorizations while issued tokens keep refreshing. Rectus Content Access for MCP reports this state in Site Health and in the Discovery metadata row on the settings screen.

= Does OAuth support random localhost callback ports? =

Yes. Native MCP clients may select an available loopback port when authorization starts. Rectus Content Access for MCP follows RFC 8252 by allowing the port to differ for `localhost`, `127.0.0.1`, and `::1` redirect URIs while still requiring the scheme, host, path, and query to match. All other redirect URIs require an exact match.

= Is post content sanitized before it is saved? =

Yes, by the same rule WordPress applies to the block and classic editors. Content from a user who holds the unfiltered_html capability, which on a single site means an administrator, is stored as written and left to the content_save_pre filters that wp_insert_post() applies, so nothing is removed that the editors would have kept. Content from every other user is filtered with wp_kses_post(), which strips script elements, event handler attributes, and anything else outside the allowed list. Rectus Content Access for MCP additionally allows schema.org microdata attributes there, because WordPress core omits them and structured data lives in the post content.

An MCP connection therefore never grants more reach than the approving WordPress user already had in the editor.

= Which custom post types are available? =

Rectus Content Access for MCP lists non-built-in post types that have a WordPress editing screen and support a title, editor, or excerpt. Administrators must explicitly enable each post type.

= Are ACF and other custom fields supported? =

Yes. The post-get, post-create, and post-update tools expose public custom fields through the custom_fields object. Values may be strings, numbers, booleans, arrays, or objects; pass null during create or update to delete a field.

When post-get returns a stored custom field, custom_field_definitions returns its label, type, description, required setting, available choices, and whether the definition came from registered WordPress meta, ACF, or unregistered post meta. Fields without a stored value are omitted.

For safety, WordPress-protected meta keys, including keys beginning with an underscore, are not exposed or writable unless an administrator lists them as protected custom fields in the settings. Existing public ACF value rows are therefore available, but hidden ACF field-reference metadata is not created or changed. Plugin-specific validation, new field-reference setup, or side effects that only run through a plugin's own form or API are not emulated.

= Can MCP edit individual blocks? =

Yes. post-block-list parses stored content into a flat list with zero-based nested paths, a content SHA-256, and one SHA-256 per block. post-block-edit performs one replace_text, replace, insert_before, insert_after, or delete action. Both fingerprints must match, and the database is read again immediately before saving.

To avoid silently restructuring content, edits are refused for non-canonical or freeform content, unregistered blocks, synchronized patterns, and locked blocks or post type templates. Replacement and insertion markup must contain exactly one canonical registered block. Text replacement is limited to one exact match in a leaf block. Nested insertion and deletion preserve the parent's inner block map, and the stored content is verified after saving.

= Can MCP manage fixed-page templates? =

Yes. The page-template-list, page-template-get, page-template-create, page-template-update, and page-template-delete tools manage only root-level `page-*.php` files with a `Template Name` header in the active theme. They cannot read or modify arbitrary theme PHP files such as functions.php.

Only users with WordPress theme-editing permission can use these tools. Updates and deletions require the SHA-256 returned by a prior read or list, so a changed template is never overwritten or deleted silently. Deletion also requires `confirm: true` and is refused while the template remains assigned to a non-trashed page.

The post-get result includes `page_template`. Pass a managed template filename to the page_template field of post-create or post-update to assign it to a page, or pass `default` to clear the assignment.

= Can MCP edit the site's CSS? =

Yes, through Additional CSS under Appearance > Customize. custom-css-get reads it with its SHA-256, custom-css-update replaces it, custom-css-edit replaces exact strings the way post-edit does, and custom-css-delete empties it when `confirm: true` is supplied. Theme files are never changed, and CSS containing a closing style tag is refused.

The CSS that a change replaces stays in the WordPress revisions, which custom-css-revision-list, custom-css-revision-get, and custom-css-revision-restore list, read, and bring back. When the site keeps no revisions, custom-css-get reports `revisions_enabled` as false and replaced CSS cannot be restored. Changes require the SHA-256 from the latest read, and every CSS operation requires both edit_theme_options and edit_css, which on a single site only administrators hold.

On a block theme WordPress still prints this CSS, but the Site Editor edits separate CSS in the global styles, so CSS saved through MCP does not appear there. custom-css-get and site-info-get report `is_block_theme` so a client can tell the user.

= Which languages are supported? =

English source strings are included. After publication on WordPress.org, community translations are provided through translate.wordpress.org and delivered as WordPress language packs.

== Third-Party Libraries ==

Rectus Content Access for MCP includes the following GPL-compatible Composer packages:

* WordPress MCP Adapter, copyright WordPress.org Contributors, GPL-2.0-or-later.
* WordPress PHP MCP Schema, copyright WordPress.org Contributors, GPL-2.0-or-later.
* Jetpack Autoloader, copyright Automattic, GPL-2.0-or-later.

License files are included with each package under the `vendor` directory.

== Changelog ==

= 1.6.0 =

* Added post-block-list and post-block-edit for SHA-256-guarded block text replacement, whole-block replacement, insertion before or after a block, and deletion through WordPress's native block parser.
* Refused block edits that would cross freeform, unregistered, synchronized, non-canonical, or locked content, and verified that nested and unrelated blocks were preserved before reporting a save as successful.
* Added navigation-menu-item-batch, which preflight-checks and then sequentially creates, updates, and deletes up to 100 classic navigation menu items. A later write or reorder failure returns the already applied results and new checksum, and items created in the batch can be parents of later ones through ref and parent_ref.
* Limited the batch response to the menu summary, the new checksum, and one result per operation, returning every item only on request, so building a large menu no longer repeats the whole menu after each item.
* Pointed navigation-menu-item-create to the batch ability for adding or changing several items.
* Added custom-css-get, custom-css-update, custom-css-edit, and custom-css-delete for the Additional CSS of the active theme. Every change requires the checksum from the latest read, CSS containing a closing style tag is refused, and theme files are never changed.
* Added custom-css-revision-list, custom-css-revision-get, and custom-css-revision-restore, so CSS replaced or cleared through MCP can be brought back from the WordPress revisions.
* Required both edit_theme_options and edit_css for every CSS operation, as Appearance > Customize does, so on a single site only administrators can use them.
* Added post-revision-list, post-revision-get, and post-revision-restore. A restore requires the current field checksums, refuses a revision whose markup the user may not save or whose revisioned custom fields, such as footnotes, differ from the post, and verifies the stored post afterwards.
* Saved the current text of a post as a revision before post-update, post-edit, or a restore replaces it, so the text a post was created with is no longer lost to its first change.
* Added media-update for the title, alternative text, caption, and description of up to 100 media items in one call, checked against the meta_sha256 now returned by media-list. media-list also returns the description and whether the user can edit each item.
* Added a Protected custom fields setting that opens listed protected meta keys, such as SEO plugin fields, to users who can edit a post. Keys WordPress uses itself are never opened.
* Added Tools > MCP Activity, a 90-day log of successful changes and partially completed batches with their time, user, client, operation, target, and the names of the fields given.
* Added preview_link to post-list, post-get, post-create, post-update, post-edit, and post-revision-restore results for unpublished posts.
* Added post-text-search, post-edit-batch, and post-update-batch, so text such as an old URL can be found across the posts the user can edit, shown for confirmation, and changed sequentially in up to 50 posts with conflict checks and explicit partial-failure results.
* Added post-duplicate, which verifies a new draft's terms, featured image, page template, and readable custom fields and removes an incomplete copy instead of reporting it as successful.
* Added menu_order to post-create, post-update, post-get, and post-list for post types with page attributes.
* Added site-info-get for the site title, tagline, front page, permalink structure, and active theme, including whether it is a block theme.
* Added widget-list and widget-update for the classic widget areas of the active theme.
* Added comment-list and comment-moderate for approving, holding, spamming, and trashing comments without returning email or IP addresses.
* Noted in custom-css-get, which now returns is_block_theme, that the Site Editor does not show Additional CSS saved through MCP on a block theme.

= 1.5.0 =

* Widened the connection readiness table and gave its label column a fixed width, so a long value beside a label no longer breaks that label across two lines.
* Named the MCP endpoint as the MCP server URL as well, since a client set up through a settings screen rather than a command asks for the address under that name.
* Described the setup commands as the same on macOS and Windows, and as commands that run on a computer where the client is already installed. Only the way the client itself is installed differs.
* Linked separately from the settings screen to the plugin overview and the MCP client installation guide.
* Added a section for clients that have no command line, offering the MCP server URL on its own with a button to copy it.
* Added a parent post ID to post-create, post-update, and post-get, accepted only for a hierarchical post type and rejected when the parent is negative, missing, of another post type, unreadable, the post itself, or one of its descendants. A move that would silently suffix the current slug is rejected before saving.

= 1.4.1 =

* Fixed Claude OAuth connections being rejected when its client metadata also advertises the JWT bearer grant. Only authorization_code and refresh_token are enabled by the plugin.
* Accepted additional response types in client metadata while enabling only code responses. Malformed metadata and clients without authorization_code or code support remain rejected.

= 1.4.0 =

* Checked the read abilities against the WordPress read capability instead of the edit capability, so an account that may read but not edit can list and read content through MCP.
* Returned public custom fields to any user allowed to read the post, matching what WordPress exposes through the REST API and the_meta().
* Required only the read capability to list taxonomy terms, which previously asked for the capability to assign them.
* Listed a post status only when the authorized user may see posts in it, so post-list no longer reports a total it will not return and no longer leaves short pages.
* Reported that a status cannot be listed instead of returning an empty list for it.
* Hid the abilities the authorized user could not use whatever the input from ability discovery, so an MCP client is offered what it may call instead of learning the difference one refusal at a time. WordPress 7.1 or later is needed for this; on 6.9 and 7.0 every ability stays listed and each call is refused as before.
* Described post-list and post-get as reading what the user may read rather than what the user may edit.

= 1.3.0 =

* Added searchable category, tag, and custom taxonomy term creation, update, and permanent deletion abilities.
* Added editable-state SHA-256 values to term-list and required a matching value for term updates and deletions.
* Required explicit confirmation for permanent term deletion and verified that WordPress removed the selected term before reporting success.
* Added parent-term validation for hierarchical taxonomies, including missing-parent and ancestry-cycle protection.

= 1.2.0 =

* Added exact post slug lookup to post-list.
* Added conflict-checked post slug updates to post-update. The current slug returned by post-get must be supplied, so a changed slug is never overwritten silently.
* Made post-create and post-update return the stored slug, and reject a requested slug that WordPress would otherwise silently suffix for a conflict.
* Defined an empty slug update as resetting a manual slug: published content regenerates it from the current title, while drafts may remain empty until publication.
* Added the slug before and after post-delete moves an entry to the WordPress trash.

= 1.1.1 =

* Hardened refresh-token retry handling so incomplete or out-of-bounds replay data cannot create a parallel token family.
* Made normal refresh-token rotation atomic and kept replay responses bounded for compatible retrying clients.
* Replayed the rotation that already happened when a client presents a refresh token another of its processes rotated away, instead of revoking the connection or issuing a parallel credential.
* Measured how far behind such a token is in rotations rather than in elapsed time, so that the allowance follows the client's own refresh interval instead of a fixed clock.
* Encrypted rotation replay material with a key derived from the presented refresh token so that it cannot be recovered from the database alone.
* Fixed a revoked connection being resurrected by a refresh token presented within a minute of the revocation.
* Restored the presented refresh token when the pair it was exchanged for could not be issued, instead of leaving the connection unusable.

= 1.1.0 =

* Added confirmation-protected post trashing with post type and modified-time conflict checks.
* Added classic navigation menu, item hierarchy and order, and theme-location management with SHA-256 conflict protection.
* Added physical media filename changes for local uploads, including generated image sizes and edit backups, with rollback and verification.
* Added file-state SHA-256 values to media listing and stricter schemas for media rename and deletion.

= 1.0.1 =

* Added an optional date to post-create and post-update, read in the site time zone, so an entry can carry a past date instead of the time of the request.
* Scheduled the post when that date is in the future, reporting the resulting future status instead of the requested publish.
* Verified the stored date after saving, like the other post fields.

= 1.0.0 =

* Reported the plugin and site identity to MCP clients instead of the bundled adapter's default server name, version, and instructions.
* Added the server title, description, website URL, and icons defined by MCP 2025-11-25, sent only to clients that negotiated a protocol version which defines them.
* Added openWorldHint to every ability annotation, stating that operations stay within this WordPress site.
* Fixed the OAuth discovery metadata check reporting a failure with the message "1" on sites without a persistent object cache, which made the settings screen and Site Health report broken discovery while authorization worked normally.
* Brought the plugin source to a clean WordPress Coding Standards run.
* Removed unused parameters from the internal taxonomy helpers.

= 0.6.0 =

* Added post-edit, which replaces exact strings inside a stored post title, excerpt, or content instead of resending the whole field.
* Added field_sha256 checksums to post-get and required the selected checksum as expected_field_sha256 when calling post-edit.
* Required each edit to match exactly once unless replace_all is set, and rejected the whole request without saving when an edit does not match or is ambiguous.
* Re-read the database immediately before saving, rejected stale field checksums, refreshed the post cache, and verified the stored value before reporting success.
* Kept WordPress save filters active and returned an explicit re-read error when a filter stored a different value.

= 0.5.5 =

* Added permission-checked fixed-page template listing, reading, creation, update, and deletion for active-theme root-level page-*.php files with Template Name headers.
* Added SHA-256 concurrency checks, explicit deletion confirmation, and an assigned-page safeguard for template deletion.
* Added fixed-page template reporting and assignment through post-get, post-create, and post-update.

= 0.5.4 =

* Made post updates determine the post type from the post ID; an optional post_type input now acts only as a checked assertion.
* Verified submitted post fields directly against the database and refreshed the post cache before reporting success.
* Added permission-checked reading, writing, and deletion of public custom fields for posts, pages, and enabled custom post types.
* Added per-field definitions to post reads for stored custom fields, including registered WordPress meta and ACF metadata when available.
* Rejected protected custom field keys and returned explicit errors for mismatched post types, empty updates, or values that were not preserved.

= 0.5.3 =

* Fixed MCP sessions being rejected as invalid on sites with a persistent object cache, which stopped Claude Code and other clients from loading the tool list right after connecting.

= 0.5.2 =

* Verified post content after create and update operations so silently changed content is no longer reported as a successful save.
* Preserved backslashes and escaped JSON values when creating posts, pages, and custom post type entries.
* Allowed a short refresh-token rotation overlap for concurrent processes using the same MCP client credentials without revoking the active connection family.
* Stored MCP HTTP sessions independently so Codex, Claude Code, and other clients can connect concurrently as the same WordPress user without overwriting one another.
* Added media listing and permission-checked permanent deletion with exact ID, filename, and confirmation safeguards.

= 0.5.1 =

* Stopped running post content through wp_kses_post() for users who hold unfiltered_html, so an edit made through MCP keeps the markup that the block and classic editors would have stored.
* Fixed JSON-LD structured data being dropped, and its raw JSON left behind as visible body text, when those users saved content through the create and update tools.

= 0.5.0 =

* Added a preferred direct multipart image upload flow for Codex and Claude Code.
* Added short-lived, one-time media upload tickets exposed through an MCP ability.
* Added a plugin REST endpoint that validates the ticket, WordPress user permissions, filename, byte size, MIME type, and image contents.
* Added idempotent retry behavior that returns an existing attachment instead of creating a duplicate.
* Kept Base64 media upload and server-side inbox import as compatible fallbacks.
* Renamed PHP symbols, internal hooks, settings, OAuth storage, and credential prefixes to match Rectus Content Access for MCP.

= 0.4.1 =

* Preserved schema.org microdata attributes in post content saved through the create and update tools.

= 0.4.0 =

* Renamed the plugin to Rectus Content Access for MCP and updated its pre-approval slug.
* Internationalized MCP ability names, descriptions, and error messages.
* Standardized English source strings for WordPress.org translation workflows.
* Removed bundled translation files in favor of WordPress.org language packs.
* Generated site-specific MCP client server names from the WordPress domain and path.
* Documented URL-based OAuth client metadata retrieval and the data it sends.
* Separated Codex server setup from the fallback login command to prevent duplicate OAuth authorization flows.
* Updated Claude Code setup to open browser authorization directly via `claude mcp login`.
* Added a Site Health test and a settings screen check for OAuth discovery metadata reachability.
* Added a post read tool that returns the stored content and terms for AI editing workflows.
* Added a taxonomy term listing tool so clients assign existing terms instead of creating variants.
* Added featured image support to the post create, update, and read tools.
* Added taxonomy term filtering to the post list tool.
* Allowed RFC 8252 ephemeral ports for native client loopback OAuth redirects.

= 0.3.0 =

* Added read-only paginated listing for posts, pages, and enabled custom post types.
* Added read-only discovery of enabled post types, supported fields, and taxonomies.

= 0.2.0 =

* Added MCP OAuth 2.1 authorization with PKCE, resource indicators, and discovery metadata.
* Added automatic access token refresh, refresh token rotation, and connection revocation.
* Replaced Application Password setup with one-copy Codex and Claude Code commands.
* Added an OAuth connection management table to the settings screen.

= 0.1.0 =

* Initial release.
* Added configurable post, page, and custom post type access.
* Added standard content, taxonomy, and media abilities.
* Bundled the official WordPress MCP Adapter with conflict-safe autoloading.
* Added initial Application Password and MCP client setup tools.
