{"id":333805,"date":"2026-06-30T09:51:00","date_gmt":"2026-06-30T09:51:00","guid":{"rendered":"https:\/\/wordpress.org\/plugins\/closehub-connector\/"},"modified":"2026-10-18T15:00:14","modified_gmt":"2026-10-18T15:00:14","slug":"closehub-connector","status":"publish","type":"plugin","link":"https:\/\/os.wordpress.org\/plugins\/closehub-connector\/","author":20355766,"comment_status":"closed","ping_status":"closed","template":"","meta":{"version":"1.3.0","stable_tag":"1.3.0","tested":"7.1.3","requires":"6.4","requires_php":"8.1","requires_plugins":null,"header_name":"CloseHub Connector","header_author":"Close Marketing","header_description":"Connect your WordPress site to CloseHub with a single API key. Exposes secure endpoints for posts, WooCommerce, and Gravity Forms.","assets_banners_color":"3c57af","last_updated":"2026-10-18 15:00:14","external_support_url":"","external_repository_url":"","donate_link":"","header_plugin_uri":"https:\/\/github.com\/closemarketing\/closehub-connector","header_author_uri":"https:\/\/close.marketing","rating":0,"author_block_rating":0,"active_installs":30,"downloads":1181,"num_ratings":0,"support_threads":0,"support_threads_resolved":0,"author_block_count":0,"sections":["description","installation","faq","changelog"],"tags":{"1.0.0":{"tag":"1.0.0","author":"closetechnology","date":"2026-06-30 09:50:44","revision":3591217},"1.0.1":{"tag":"1.0.1","author":"closetechnology","date":"2026-07-01 06:44:34","revision":3592190},"1.0.2":{"tag":"1.0.2","author":"closetechnology","date":"2026-07-07 06:44:50","revision":3598556},"1.0.3":{"tag":"1.0.3","author":"closetechnology","date":"2026-07-07 06:59:50","revision":3598564},"1.0.4":{"tag":"1.0.4","author":"closetechnology","date":"2026-08-27 08:53:20","revision":3668388},"1.0.5":{"tag":"1.0.5","author":"closetechnology","date":"2026-09-03 11:47:55","revision":3679667},"1.1.0":{"tag":"1.1.0","author":"closetechnology","date":"2026-09-08 11:12:18","revision":3686458},"1.1.1":{"tag":"1.1.1","author":"closetechnology","date":"2026-09-15 07:19:39","revision":3696364},"1.1.2":{"tag":"1.1.2","author":"closetechnology","date":"2026-09-18 08:05:37","revision":3701557},"1.2.0":{"tag":"1.2.0","author":"closetechnology","date":"2026-09-30 08:56:45","revision":3720756},"1.2.1":{"tag":"1.2.1","author":"closetechnology","date":"2026-10-17 17:27:00","revision":3752205},"1.3.0":{"tag":"1.3.0","author":"closetechnology","date":"2026-10-18 15:00:14","revision":3753202}},"upgrade_notice":{"1.0.0":"<p>Initial release \u2014 no upgrade steps required.<\/p>"},"ratings":[],"assets_icons":{"icon-158x158.png":{"filename":"icon-158x158.png","revision":3592190,"resolution":"158x158","location":"assets","locale":"","width":158,"height":158},"icon-256x256.gif":{"filename":"icon-256x256.gif","revision":3592190,"resolution":"256x256","location":"assets","locale":"","width":256,"height":256},"icon-256x256.png":{"filename":"icon-256x256.png","revision":3592190,"resolution":"256x256","location":"assets","locale":"","width":256,"height":256}},"assets_banners":{"banner-1544x500.png":{"filename":"banner-1544x500.png","revision":3592190,"resolution":"1544x500","location":"assets","locale":"","width":1544,"height":500},"banner-772x250.png":{"filename":"banner-772x250.png","revision":3592190,"resolution":"772x250","location":"assets","locale":"","width":772,"height":250}},"assets_blueprints":{},"all_blocks":[],"tagged_versions":["1.0.0","1.0.1","1.0.2","1.0.3","1.0.4","1.0.5","1.1.0","1.1.1","1.1.2","1.2.0","1.2.1","1.3.0"],"block_files":[],"assets_screenshots":[],"screenshots":{"1":"Settings page showing the Site URL, API key, and available endpoints.","2":"Regenerate Key button with confirmation notice."}},"plugin_section":[],"plugin_tags":[1556,269564,1655,597,286],"plugin_category":[42,45],"plugin_contributors":[210094,131625],"plugin_business_model":[],"class_list":["post-333805","plugin","type-plugin","status-publish","hentry","plugin_tags-api","plugin_tags-closehub","plugin_tags-gravity-forms","plugin_tags-integration","plugin_tags-woocommerce","plugin_category-contact-forms","plugin_category-ecommerce","plugin_contributors-closetechnology","plugin_contributors-davidperez","plugin_committers-closetechnology"],"banners":{"banner":"https:\/\/ps.w.org\/closehub-connector\/assets\/banner-772x250.png?rev=3592190","banner_2x":"https:\/\/ps.w.org\/closehub-connector\/assets\/banner-1544x500.png?rev=3592190","banner_rtl":false,"banner_2x_rtl":false},"icons":{"svg":false,"icon":"https:\/\/ps.w.org\/closehub-connector\/assets\/icon-256x256.png?rev=3592190","icon_2x":"https:\/\/ps.w.org\/closehub-connector\/assets\/icon-256x256.png?rev=3592190","generated":false},"screenshots":[],"raw_content":"<!--section=description-->\n<p>CloseHub Connector replaces the multiple credentials previously required to link a WordPress site with <a href=\"https:\/\/close.marketing\/closehub\/\">CloseHub<\/a> \u2014 a marketing project management platform.<\/p>\n\n<p>Once the plugin is activated, it generates a secure API key and exposes a dedicated REST API namespace (<code>\/wp-json\/closehub\/v1\/<\/code>) that CloseHub uses to interact with your site.<\/p>\n\n<p>It also exposes content abilities through the WordPress MCP Adapter. MCP clients can discover, list, read, create, update, upload an image, update a post slug, replace one exact Gutenberg block, and send posts to the trash using the server at <code>\/wp-json\/mcp\/mcp-adapter-default-server<\/code>. <code>closehub\/upload-media<\/code> accepts an image as <code>data_base64<\/code>, returns its Media Library URL, and requires the user's <code>upload_files<\/code> capability; pass that URL as <code>featured_image_url<\/code> to create or update content without uploading a duplicate. <code>closehub\/update-post-slug<\/code> accepts a post ID and slug, then returns the normalized unique slug and resulting URL. <code>closehub\/get-post<\/code> returns a <code>content_hash<\/code>; use it with <code>closehub\/replace-gutenberg-block<\/code>, a zero-based <code>block_path<\/code>, the current block name, and one replacement serialized block so a stale read cannot overwrite newer content. These abilities default to the <code>post<\/code> type but accept a <code>post_type<\/code> input for any other post type registered with an admin UI \u2014 pages, WooCommerce products (including product types WooCommerce's own MCP abilities don't support, such as subscriptions), or custom post types. Authenticate with OAuth as a WordPress user, or use the same CloseHub API key as a Bearer token for a shared Claude Team connector. The API key acts with the capabilities of the WordPress user who last generated it.<\/p>\n\n<p><strong>Settings:<\/strong> One page under Settings \u2192 CloseHub (Network Admin \u2192 Settings \u2192 CloseHub on multisite) shows the API key, the CloseHub endpoint, the MCP server URL, and the user the key acts as. The same API key connects CloseHub and Claude.<\/p>\n\n<p><strong>Claude Team:<\/strong> In Claude, add a custom connector with the <strong>MCP server URL<\/strong> from Settings \u2192 CloseHub, choose <strong>No sign-in<\/strong>, and add a request header named <code>authorization<\/code> with the value <code>Bearer &lt;your API key&gt;<\/code>. The URL uses a <code>?rest_route=<\/code> query to help preserve the header when a server rewrite strips it from <code>\/wp-json\/<\/code> requests. Everyone sharing this connector has the WordPress permissions of the user who last generated the key. Regenerating the key disconnects CloseHub and every Claude user until updated. OAuth per-user sign-in remains available under <strong>Advanced<\/strong>.<\/p>\n\n<p>When WPML is active, create-post and <code>POST \/closehub\/v1\/posts<\/code> also accept <code>language<\/code> and an optional <code>translation_of<\/code> source post ID. The connector assigns the new post to the requested language and joins it to the source post's translation group. List\/get\/create responses include the language and translation-group details. Existing posts retain their language on update.<\/p>\n\n<p>For WooCommerce, MCP clients with the <code>manage_woocommerce<\/code> capability can retrieve an order summary for a date range, including order count, total sales, average order value, and matching orders.<\/p>\n\n<p>It also exposes a set of \"site\" abilities for the CLOSE web go-live checklist \u2014 configuration steps that used to be manual or wp-cli only. Each requires the WordPress capability noted below.<\/p>\n\n<p><strong>Available MCP site abilities:<\/strong><\/p>\n\n<ul>\n<li><code>closehub\/search-replace-domain<\/code> (<code>manage_options<\/code>) \u2014 Replace <code>old_domain<\/code> with <code>new_domain<\/code> across post content, options, comments, and meta tables, re-serializing serialized values safely. Skips <code>wp_posts.guid<\/code>. Pass <code>dry_run: true<\/code> to preview the number of rows that would change per table without writing anything. Example: <code>{ \"old_domain\": \"staging.example.com\", \"new_domain\": \"example.com\" }<\/code>.<\/li>\n<li><code>closehub\/set-robots-txt<\/code> (<code>manage_options<\/code>) \u2014 Write <code>content<\/code> to <code>robots.txt<\/code>, physically if the site root is writable, otherwise served virtually through the <code>robots_txt<\/code> filter. Example: <code>{ \"content\": \"User-agent: *\\nDisallow:\\nSitemap: https:\/\/example.com\/sitemap.xml\" }<\/code>.<\/li>\n<li><code>closehub\/set-post-noindex<\/code> (<code>edit_post<\/code> on the target <code>post_id<\/code>) \u2014 Set or clear the noindex robots meta for one post\/page using whichever SEO plugin (Rank Math or Yoast) is active. Example: <code>{ \"post_id\": 42, \"noindex\": true }<\/code>.<\/li>\n<li><code>closehub\/flush-permalinks<\/code> (<code>manage_options<\/code>) \u2014 Regenerate rewrite rules, equivalent to <code>wp rewrite flush<\/code>. Takes no parameters.<\/li>\n<li><code>closehub\/get-htaccess<\/code> (<code>manage_options<\/code>, read-only) \u2014 Return whether <code>.htaccess<\/code> exists and its current content. Takes no parameters.<\/li>\n<li><code>closehub\/set-site-settings<\/code> (<code>manage_options<\/code>) \u2014 Update the site timezone and\/or admin email; at least one is required. Example: <code>{ \"timezone\": \"Europe\/Madrid\", \"admin_email\": \"client@example.com\" }<\/code>.<\/li>\n<li><code>closehub\/reassign-posts-author<\/code> (<code>edit_others_posts<\/code>) \u2014 Reassign every post of <code>post_type<\/code> (default <code>post<\/code>) from <code>from_author_id<\/code> to <code>to_author_id<\/code>, with a per-post success result. Example: <code>{ \"from_author_id\": 3, \"to_author_id\": 1 }<\/code>.<\/li>\n<li><code>closehub\/install-wp-org-plugin<\/code> (<code>install_plugins<\/code>) \u2014 Install (without activating) a plugin from the WordPress.org plugin directory by <code>slug<\/code>. Example: <code>{ \"slug\": \"two-factor\" }<\/code>.<\/li>\n<li><code>closehub\/list-unused-plugins<\/code> (<code>activate_plugins<\/code>, read-only) \u2014 List installed plugins that are not currently active, as removal candidates. Takes no parameters.<\/li>\n<li><code>closehub\/update-plugins-and-core<\/code> (<code>update_plugins<\/code> and <code>update_core<\/code>) \u2014 Update every plugin with an available update and WordPress core to the latest version, with a per-plugin success result. Takes no parameters.<\/li>\n<li><code>closehub\/create-site-user<\/code> (<code>create_users<\/code>, plus <code>promote_users<\/code> when <code>role<\/code> is <code>administrator<\/code>) \u2014 Create a WordPress user for the site's client. <code>role<\/code> defaults to <code>editor<\/code>; <code>username<\/code> defaults to the local part of <code>email<\/code> when omitted. Example: <code>{ \"email\": \"client@example.com\", \"role\": \"editor\" }<\/code>.<\/li>\n<li><code>closehub\/clear-cache<\/code> (<code>rocket_purge_cache<\/code> or <code>manage_options<\/code>) \u2014 Purge the page cache of the active caching plugin (currently WP Rocket). <code>scope<\/code> is <code>all<\/code> (default, whole site) or <code>posts<\/code> (only the given <code>post_ids<\/code>; IDs that don't match a post are reported back in <code>invalid_post_ids<\/code>). Pass <code>minify: true<\/code> to also clear minified CSS\/JS files. Returns <code>503<\/code> when no supported cache plugin is active. On multisite it purges only the site the MCP request is made against; on a subdirectory network, purging the main site with WP Rocket also clears the subsites' cached pages, since they live inside the main site's cache folder. Example: <code>{ \"scope\": \"posts\", \"post_ids\": [ 42, 57 ] }<\/code>.<\/li>\n<\/ul>\n\n<p><strong>What it replaces:<\/strong><\/p>\n\n<ul>\n<li>WordPress Application Password (username + password)<\/li>\n<li>WooCommerce REST API consumer key and consumer secret<\/li>\n<li>Gravity Forms API key<\/li>\n<\/ul>\n\n<p><strong>You only need to share two things with CloseHub:<\/strong><\/p>\n\n<ol>\n<li>Your site URL<\/li>\n<li>The generated API key (found at Settings \u2192 CloseHub)<\/li>\n<\/ol>\n\n<p><strong>Available endpoints:<\/strong><\/p>\n\n<ul>\n<li><code>GET \/closehub\/v1\/ping<\/code> \u2014 verify the connection<\/li>\n<li><code>POST \/closehub\/v1\/posts<\/code> \u2014 publish or draft a post (or another post type via <code>post_type<\/code>), including optional SEO metadata (Rank Math or Yoast), featured image, categories, and WPML <code>language<\/code>\/<code>translation_of<\/code> when WPML is active<\/li>\n<li><code>PUT \/closehub\/v1\/posts\/{id}<\/code> \u2014 update a post's (or other post type's) title, content, excerpt, status, SEO metadata, featured image, or categories<\/li>\n<li><code>GET \/closehub\/v1\/woocommerce\/orders<\/code> \u2014 fetch order data (requires WooCommerce)<\/li>\n<li><code>GET \/closehub\/v1\/gravity-forms\/forms<\/code> \u2014 list forms (requires Gravity Forms)<\/li>\n<li><code>GET \/closehub\/v1\/gravity-forms\/forms\/{id}<\/code> \u2014 get form details<\/li>\n<li><code>GET \/closehub\/v1\/gravity-forms\/forms\/{id}\/entries<\/code> \u2014 count form entries by date range<\/li>\n<li><code>POST \/closehub\/v1\/elm-releases<\/code> \u2014 create an Easy License Manager release for a product (by <code>product_id<\/code> or <code>product_sku<\/code>) and update its WooCommerce download file to the given <code>zip_url<\/code> in one call; optional <code>tested<\/code>, <code>requires<\/code>, <code>requires_php<\/code>, <code>upgrade_notice<\/code><\/li>\n<li><code>PUT \/closehub\/v1\/elm-releases\/{id}<\/code> \u2014 update fields on an existing release (all optional) and, if <code>zip_url<\/code> is given, its product's download file<\/li>\n<\/ul>\n\n<p>WooCommerce, Gravity Forms, and Easy License Manager endpoints return a clear error if those plugins are not active \u2014 they are not required.<\/p>\n\n<p><strong>Multisite networks:<\/strong><\/p>\n\n<p>On a WordPress Multisite network, the same endpoints listed above are shared by every site in the network \u2014 there is no separate namespace or key to manage. Activate the plugin network-wide and go to <strong>Network Admin \u2192 Settings \u2192 CloseHub<\/strong> to find one API key shared by the whole network. Every request to those endpoints automatically returns a <code>sites<\/code> array with one entry per site in the network (<code>site_id<\/code>, <code>url<\/code>, and that site's data or an <code>error<\/code> message), instead of a single site's result \u2014 handy when a network is used to run the same company in multiple languages.<\/p>\n\n<!--section=installation-->\n<ol>\n<li>Upload the <code>closehub-connector<\/code> folder to <code>\/wp-content\/plugins\/<\/code>.<\/li>\n<li>Activate the plugin through the <strong>Plugins<\/strong> screen in WordPress admin.<\/li>\n<li>Go to <strong>Settings \u2192 CloseHub<\/strong>.<\/li>\n<li>Copy the <strong>Site URL<\/strong> and <strong>API Key<\/strong> shown on that page.<\/li>\n<li>Paste both values into CloseHub under your project's WordPress connection settings.<\/li>\n<\/ol>\n\n<!--section=faq-->\n<dl>\n<dt id=\"where%20do%20i%20find%20my%20api%20key%3F\"><h3>Where do I find my API key?<\/h3><\/dt>\n<dd><p>Go to <strong>Settings \u2192 CloseHub<\/strong> in your WordPress admin. The key is displayed there along with a copy button.<\/p><\/dd>\n<dt id=\"can%20i%20regenerate%20the%20api%20key%3F\"><h3>Can I regenerate the API key?<\/h3><\/dt>\n<dd><p>Yes. Click <strong>Regenerate Key<\/strong> on the Settings \u2192 CloseHub page. The old key stops working immediately \u2014 update CloseHub with the new key right away.<\/p><\/dd>\n<dt id=\"how%20do%20i%20connect%20claude%20team%20when%20oauth%20discovery%20is%20blocked%3F\"><h3>How do I connect Claude Team when OAuth discovery is blocked?<\/h3><\/dt>\n<dd><p>Go to <strong>Settings \u2192 CloseHub<\/strong>, copy the <strong>MCP server URL<\/strong>, choose <strong>No sign-in<\/strong> authentication in Claude Team, and add a request header named <code>authorization<\/code> with the value <code>Bearer &lt;your API key&gt;<\/code> (use the Copy button next to the header). Everyone using that connector shares the WordPress permissions of the user shown under <strong>Acts as user<\/strong>.<\/p><\/dd>\n<dt id=\"do%20i%20need%20woocommerce%20or%20gravity%20forms%20installed%3F\"><h3>Do I need WooCommerce or Gravity Forms installed?<\/h3><\/dt>\n<dd><p>No. Both are optional. If they are not active, those endpoints return a <code>503<\/code> response with a clear message instead of crashing.<\/p><\/dd>\n<dt id=\"how%20is%20the%20api%20key%20secured%3F\"><h3>How is the API key secured?<\/h3><\/dt>\n<dd><p>The key is stored in <code>wp_options<\/code> (or network-wide in <code>wp_sitemeta<\/code> on multisite), never exposed on the frontend, transmitted only via HTTPS, and verified using constant-time comparison (<code>hash_equals<\/code>) to prevent timing attacks. It is never logged or included in REST responses.<\/p><\/dd>\n<dt id=\"can%20i%20use%20this%20plugin%20on%20a%20multisite%20network%3F\"><h3>Can I use this plugin on a multisite network?<\/h3><\/dt>\n<dd><p>Yes. When network-activated, the plugin generates one API key shared by every site in the network (managed from <strong>Network Admin \u2192 Settings \u2192 CloseHub<\/strong> instead of a per-site Settings page), and the same REST endpoints automatically query every site and return combined, per-site results. On a regular, non-multisite install, everything works exactly as a single site as described above.<\/p><\/dd>\n<dt id=\"is%20this%20plugin%20affiliated%20with%20woocommerce%20or%20gravity%20forms%3F\"><h3>Is this plugin affiliated with WooCommerce or Gravity Forms?<\/h3><\/dt>\n<dd><p>No. It integrates with those plugins using their public PHP APIs but is not developed, endorsed, or supported by WooCommerce or Gravity Forms.<\/p><\/dd>\n\n<\/dl>\n\n<!--section=changelog-->\n<h4>1.3.0<\/h4>\n\n<ul>\n<li>Simplified settings into a single page: the CloseHub API key now also authenticates MCP (Claude Team) as a Bearer token, acting as the user who last generated it. The separate <code>chm_<\/code> shared token and the API\/MCP tabs were removed; Claude Team connectors using a <code>chm_<\/code> token must be updated to use the API key.<\/li>\n<\/ul>\n\n<h4>1.2.1<\/h4>\n\n<ul>\n<li>Added a revocable shared MCP Bearer token for Claude Team connections when OAuth discovery is blocked by the web server. The token uses the permissions of its WordPress creator and can be rotated or revoked from the MCP settings tab. (#47)<\/li>\n<li>Added a query-routed MCP server URL for hosts where the <code>\/wp-json\/<\/code> rewrite drops the <code>authorization<\/code> header, and made the complete <code>Bearer chm_...<\/code> value copyable for Claude Team setup. (#47)<\/li>\n<li>Split CloseHub settings into API and MCP tabs on single sites and multisite networks. (#47)<\/li>\n<\/ul>\n\n<h4>1.2.0<\/h4>\n\n<ul>\n<li>Added WordPress Multilingual Plugin (WPML) support to MCP and REST content creation, including optional language assignment and translation-group linking. (#30)<\/li>\n<li>Added MCP image uploads from base64 to the Media Library, with validation, quota checks, attachment metadata safeguards, and reuse as a post's featured image. (#40)<\/li>\n<li>Added a branded OAuth consent screen that clearly discloses the public CloseHub MCP abilities being authorized. (#41)<\/li>\n<li>Added the <code>closehub\/clear-cache<\/code> MCP ability for supported caching plugins, starting with WP Rocket. (#35)<\/li>\n<li>Fixed CloseHub content and site abilities not being exposed as direct tools by the default MCP server.<\/li>\n<li>Fixed Claude and other hosted MCP clients that identify themselves with a Client ID Metadata Document: OAuth authorization now validates that document directly when no prior dynamic registration exists, and advertises that capability in the authorization-server metadata. Re-registering the same verified client is idempotent and refreshes its stored metadata instead of failing on a duplicate client ID. (#34)<\/li>\n<li>Added <code>POST \/closehub\/v1\/elm-releases<\/code> to create an Easy License Manager release and update the product's WooCommerce download file in one call, unblocking automated premium-plugin releases. Accepts optional <code>tested<\/code>, <code>requires<\/code>, <code>requires_php<\/code>, and <code>upgrade_notice<\/code>. Preserves any other downloadable files already on the product instead of replacing them. Returns <code>503<\/code> if Easy License Manager is not active. (#19)<\/li>\n<li>Added <code>PUT \/closehub\/v1\/elm-releases\/{id}<\/code> to update fields on an existing release (and its product's download file) without creating a duplicate release for the same version.<\/li>\n<li>Fixed a crash on PHP 8+ when a route's numeric <code>id<\/code>\/<code>product_id<\/code> argument was validated: <code>is_numeric<\/code> was registered directly as <code>validate_callback<\/code>, but WordPress calls it with 3 arguments and the internal function only accepts 1. Affected <code>\/posts\/{id}<\/code>, <code>\/gravity-forms\/forms\/{id}<\/code>, and both new <code>elm-releases<\/code> routes.<\/li>\n<\/ul>\n\n<h4>1.1.2<\/h4>\n\n<ul>\n<li>Fixed MCP OAuth discovery on Apache-managed sites, including reliable handling of the protected-resource and authorization-server metadata routes after activation, URL changes, or regeneration. (#27)<\/li>\n<li>Added precise Gutenberg block replacement through MCP, with content-hash concurrency protection and block-path\/type validation, plus an MCP ability to update a post slug and return its normalized URL. (#29)<\/li>\n<\/ul>\n\n<h4>1.1.1<\/h4>\n\n<ul>\n<li>Added 11 MCP \"site\" abilities covering the CLOSE web go-live checklist: domain search-replace, robots.txt content, per-page noindex, permalink flush, <code>.htaccess<\/code> read, timezone\/admin email, bulk post-author reassignment, WordPress.org plugin install, unused-plugin listing, plugin\/core updates, and client user creation. See the Description section for the full list and required capabilities.<\/li>\n<li>Added <code>post_type<\/code> support to all <code>closehub\/*-post<\/code> MCP abilities (list-posts, get-post, create-post, update-post, trash-post) and to the <code>\/closehub\/v1\/posts<\/code> REST endpoints. They still default to <code>post<\/code>, but can now read and write pages and WooCommerce products (including product types WooCommerce's own MCP abilities don't support, such as subscriptions) instead of only plain blog posts. Allowed post types are limited to ones registered as public and admin-manageable, so internal WooCommerce records such as orders and coupons, and Media Library attachments, are not exposed as generic content.<\/li>\n<li>Fixed: creating a post now checks that post type's own <code>create_posts<\/code> capability, and publishing through <code>create-post<\/code>\/<code>update-post<\/code> checks its <code>publish_*<\/code> capability (e.g. <code>publish_products<\/code>), instead of always assuming <code>post<\/code>'s <code>edit_posts<\/code>\/<code>publish_posts<\/code>.<\/li>\n<li>Fixed: MCP post creation and updates now recheck those capabilities independently on every site in a multisite network before writing, so a denied site reports a per-site error without changing its content.<\/li>\n<li>Fixed: setting <code>categories<\/code> on a post type that doesn't support that taxonomy is now rejected before any other change is saved, instead of possibly after the title, content, or other fields were already updated.<\/li>\n<\/ul>\n\n<h4>1.1.0<\/h4>\n\n<ul>\n<li>Added an MCP server (OAuth 2.1 + PKCE) so AI clients such as Claude can list, read, create, update, and trash posts and read WooCommerce order summaries with the permissions of a real WordPress user.<\/li>\n<li>Added a <code>PUT \/closehub\/v1\/posts\/{id}<\/code> endpoint to update a post's title, content, excerpt, status, SEO metadata, featured image, or categories.<\/li>\n<li>Fixed: MCP post creation\/update no longer lets a user without the <code>manage_categories<\/code> capability create new categories by naming one that doesn't exist yet.<\/li>\n<li>Fixed: MCP get-post\/list-posts now include the same featured image and SEO metadata create-post and update-post accept.<\/li>\n<li>Fixed: a dynamic OAuth client registration using a real client_id metadata URL could no longer have its verified name and redirect URI overridden by the request body \u2014 closing an impersonation path where a code could be redirected to an attacker-controlled URI while the consent screen showed a trusted name.<\/li>\n<li>Fixed: the OAuth consent page now sends <code>X-Frame-Options<\/code>\/CSP headers to prevent it from being framed (clickjacking the Authorize button).<\/li>\n<li>Fixed: an MCP access token could previously authenticate as its user for any WordPress REST route whose query string happened to contain the MCP endpoint path, not just the MCP endpoint itself.<\/li>\n<li>Fixed: OAuth token responses now send <code>Cache-Control: no-store<\/code>; the dynamic client registration endpoint is now rate-limited per IP.<\/li>\n<\/ul>\n\n<h4>1.0.5<\/h4>\n\n<ul>\n<li>Fixed: featured images from URLs without a filename extension, including Google Drive download URLs, can now be attached when CloseHub creates a WordPress draft.<\/li>\n<\/ul>\n\n<h4>1.0.4<\/h4>\n\n<ul>\n<li>Added support for optional SEO titles, meta descriptions, focus keywords, categories, and featured images when creating posts from CloseHub.<\/li>\n<li>Added support for saving SEO metadata in Rank Math and Yoast SEO when either plugin is active.<\/li>\n<li>Improved post creation reliability by completing metadata before publishing and removing incomplete posts when metadata processing fails.<\/li>\n<\/ul>\n\n<h4>1.0.3<\/h4>\n\n<ul>\n<li>Fixed: sites that already had an API key configured on a subsite before multisite support was added (&lt;=1.0.1) now keep working after upgrading \u2014 the existing key is migrated to the network-wide setting instead of a new one being generated, which previously caused CloseHub requests to fail with 401.<\/li>\n<\/ul>\n\n<h4>1.0.2<\/h4>\n\n<ul>\n<li>Added WordPress Multisite network support: one API key shared across the whole network, managed from Network Admin \u2192 Settings \u2192 CloseHub.<\/li>\n<li>On multisite, existing endpoints (ping, posts, woocommerce\/orders, gravity-forms\/*) now return combined results for every site in the network instead of a single site.<\/li>\n<\/ul>\n\n<h4>1.0.1<\/h4>\n\n<ul>\n<li>Updated assets.<\/li>\n<\/ul>\n\n<h4>1.0.0<\/h4>\n\n<ul>\n<li>Initial release.<\/li>\n<li>Single API key replaces WordPress Application Password, WooCommerce REST credentials, and Gravity Forms API key.<\/li>\n<li>Endpoints: ping, posts, woocommerce\/orders, gravity-forms\/forms.<\/li>\n<li>Admin settings page at Settings \u2192 CloseHub with copy buttons and regenerate key action.<\/li>\n<\/ul>","raw_excerpt":"Connect WordPress to CloseHub with one API key and expose content and site tools to MCP clients such as Claude.","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/os.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin\/333805","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/os.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin"}],"about":[{"href":"https:\/\/os.wordpress.org\/plugins\/wp-json\/wp\/v2\/types\/plugin"}],"replies":[{"embeddable":true,"href":"https:\/\/os.wordpress.org\/plugins\/wp-json\/wp\/v2\/comments?post=333805"}],"author":[{"embeddable":true,"href":"https:\/\/os.wordpress.org\/plugins\/wp-json\/wporg\/v1\/users\/closetechnology"}],"wp:attachment":[{"href":"https:\/\/os.wordpress.org\/plugins\/wp-json\/wp\/v2\/media?parent=333805"}],"wp:term":[{"taxonomy":"plugin_section","embeddable":true,"href":"https:\/\/os.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_section?post=333805"},{"taxonomy":"plugin_tags","embeddable":true,"href":"https:\/\/os.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_tags?post=333805"},{"taxonomy":"plugin_category","embeddable":true,"href":"https:\/\/os.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_category?post=333805"},{"taxonomy":"plugin_contributors","embeddable":true,"href":"https:\/\/os.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_contributors?post=333805"},{"taxonomy":"plugin_business_model","embeddable":true,"href":"https:\/\/os.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_business_model?post=333805"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}