Skip to content

Releases: TaherSayed/sayed-wp-conductor-for-claude

v1.9.1 - GitHub repo renamed to match wp.org slug

Choose a tag to compare

@TaherSayed TaherSayed released this 26 May 13:27

Renamed the GitHub repository from commander-secure-mcp-control to sayed-wp-conductor-for-claude to match the new WordPress.org slug. Updated every in-tree URL accordingly. GitHub auto-redirects the old URL so any existing clone / fork / release link continues to work.

Also: replaced the security@hbs-it-gmbh.de reporting mailbox with the GitHub private security advisory flow.

No code/behaviour changes.

v1.9.0 - Rename to "Sayed WP Conductor for Claude"

Choose a tag to compare

@TaherSayed TaherSayed released this 26 May 13:23

Final answer to the WordPress.org plugin review.

Rename + slug change

  • Display name: Sayed WP Conductor for Claude
  • Slug: sayed-wp-conductor-for-claude
  • Main file renamed: mcp-for-claude.phpsayed-wp-conductor-for-claude.php
  • Text domain updated everywhere

The previous name "Commander — Secure MCP Control" / slug mcp-for-claude was flagged: "Commander" is generic, and starting the slug with mcp-for-claude implies false affiliation with Anthropic. The new pattern follows the directory's recommended "distinctive prefix … for Trademark" structure.

Branding

All references to "HBS IT GmbH" and hbs-it-gmbh.de removed from the plugin. The plugin is now a personal project by Taher Sayed — which resolves the email-domain ownership flag from the review (a gmail.com account is fine to verify ownership of a personal project, just not of a company-branded one). The hbsitgmbh contributor was removed from readme.txt.

Preserved on purpose

  • wp-commander-bot system username — renaming would break existing installs' audit trails.
  • X-Commander-Signature webhook header — protocol contract; receivers depend on exact string match.
  • CMCP_* PHP constants and CMCP\ namespace — internal, not user-facing.

These are technical identifiers, not user-facing branding, and the review team's concerns don't apply to them.

Repo

The GitHub repo name is still commander-secure-mcp-control for URL continuity — only the WordPress.org slug changed. If you want the repo renamed too, say the word.

v1.8.2 - WP.org review fixes: revoke auth, attribution, enqueue

Choose a tag to compare

@TaherSayed TaherSayed released this 26 May 13:18

Addresses the four code issues flagged by the WordPress.org plugin review team. This release does NOT yet address the plugin name / slug / ownership-email items — those are administrative decisions and tracked separately.

Critical security fix

/oauth/revoke now authenticates the client (RFC 7009). The previous implementation had permission_callback => __return_true and looked up tokens purely by hash — no client auth, no token-ownership check. Anyone who knew (or guessed) a token value could revoke it remotely. The endpoint now requires Basic or POST client credentials and matches the token row's client_id to the authenticated client before revoking. RFC 7009 §2.2 200-response semantics preserved on no-match. Per-IP rate limit (20/min) added.

Compliance fixes

  • Attribution removed from OAuth consent + error pages. The "powered by HBS IT GmbH" footer is gone (WP.org Guideline 10 forbids user-facing credit without opt-in). Admin attribution is unchanged.
  • Inline <script> / <style> extracted to enqueued files. Token + Settings page JS now in assets/js/*.js, registered via wp_enqueue_script + wp_add_inline_script for PHP→JS data. OAuth consent + error pages link assets/css/oauth-consent.css instead of inlining CSS.
  • uninstall.php no longer includes core admin files directly. Bot user deletion is now conditional on wp_delete_user already being loaded.

Still pending (decisions, not code)

The review also flagged:

  1. Name / slug — "Commander" and "Claude" in the name/slug imply false affiliation. New name + slug needed.
  2. Email / identity — submitted from a gmail.com address while plugin claims HBS IT GmbH ownership. Either change WP.org account email to @hbs-it-gmbh.de or add a DNS TXT record wordpressorg-tahersayed-verification at the domain root.

v1.8.1 - DCR dedup + SSRF v6 + destructive gate on media_delete

Choose a tag to compare

@TaherSayed TaherSayed released this 26 May 12:47

Highlights

  • DCR client dedup — fixes the "4 duplicate Claude clients" admin UI clutter that appears when a remote app (Claude.ai) re-registers because it dropped its credentials. The OAuth register endpoint now sweeps any existing DCR client rows that share the incoming metadata and have no active tokens before inserting the new row. Daily cron also reaps DCR clients older than 7 days with zero active tokens.
  • SSRF guard now covers IPv6media_upload previously used gethostbynamel(), which is IPv4-only. An attacker host with an AAAA record pointing at fc00::… or ::1 could bypass the filter. Guard now resolves A+AAAA via dns_get_record(), validates literal-IP hosts directly, and explicitly rejects IPv6 ULA (fc00::/7), link-local (fe80::/10), IPv4-mapped IPv6, and cloud metadata endpoints (169.254.169.254, fd00:ec2::254).
  • media_delete now respects "Allow destructive operations" — it was an unconditional hard delete before. Matches the gate already enforced by posts_delete and settings_update.
  • UX: Renamed the OAuth Clients page buttons. "Revoke tokens" → Sign out (keep registration, drop tokens). "Delete client" → Disconnect (revoke + remove). Tooltips and confirm prompts spell out the difference.
  • Internal: Fixed UTF-8 mojibake of em-dashes in 24 tool source files introduced by 1.8.0. No runtime impact.

Upgrade notes

  • Update the plugin, then visit wp-admin → Commander → OAuth Clients. The next time Claude.ai (or any DCR client) reconnects, the orphan rows for its app name will be cleaned up automatically before the new row is inserted. You can also manually click Disconnect on the duplicates right now to clear them.
  • The daily cron sweep runs at the next scheduled cleanup tick — no action needed.

v1.8.0 - Tool names: dots → underscores (Claude.ai compat)

Choose a tag to compare

@TaherSayed TaherSayed released this 26 May 12:26

Breaking-compatible: tool names changed to satisfy Claude.ai

Claude.ai's remote-MCP UI enforces ^[a-zA-Z0-9_-]{1,64}$ on tool names and was rejecting every tool the plugin advertised:

tools.36.FrontendRemoteMcpToolDefinition.name:
String should match pattern '^[a-zA-Z0-9_-]{1,64}$'

All 24 built-in tools are renamed from dotted (site.info, posts.list, media.upload, …) to underscored (site_info, posts_list, media_upload, …). The new names work in Claude.ai, Claude Desktop, and Claude Code.

Auto-migration on upgrade

Plugin::get_settings() now rewrites any legacy dotted ids in the stored enabled_tools option to underscored equivalents on first load and persists the result — so admins keep their existing tool selection without re-checking boxes after upgrade.

What to do after upgrade

  1. Update the plugin to v1.8.0.
  2. Visit wp-admin → Commander → Settings once to trigger the migration.
  3. In Claude.ai → Settings → Integrations, remove and re-add the connector so the tool list refreshes.

Compatibility note for external callers

If you have scripts that hard-code tools/call with name: "site.info", switch them to site_info. Legacy dotted names are not aliased on the wire — they're gone.

Full tool list (new names)

Read: site_info, site_health, posts_list, posts_get, posts_search, media_list, comments_list, terms_list, settings_get
Write: posts_create, posts_update, posts_delete, media_upload, media_delete, comments_moderate, terms_create
Admin: users_list, users_create, users_update, plugins_list, plugins_toggle, themes_list, themes_activate, settings_update

v1.7.2 - Generic OAuth metadata URLs

Choose a tag to compare

@TaherSayed TaherSayed released this 24 May 15:21

Fixes the only two hardcoded URLs that pointed to the author site. RFC 8414 service_documentation and RFC 9728 resource_documentation now default to the GitHub project URL and are overridable per-site via cmcp_oauth_service_documentation and cmcp_oauth_resource_documentation filters. Every other endpoint already used home_url() / rest_url() dynamically.

v1.7.1 - Bot user banner (rollup)

Choose a tag to compare

@TaherSayed TaherSayed released this 24 May 15:18

Adds the bot user banner that was supposed to ship with 1.7.0 but was lost from that commit. Otherwise identical to 1.7.0.

v1.7.0 - OAuth sessions, audit log filters, bot user UI

Choose a tag to compare

@TaherSayed TaherSayed released this 24 May 15:17

First release in the v1.7 line — closes the visibility gaps that emerged once OAuth went live.

New

  • Active OAuth sessions table on the OAuth Clients page. Lists every access token issued via the OAuth flow, with client, bound WP user, scopes, issued / last-used / access-expires / refresh-expires timestamps. Per-row Revoke action kills one session without nuking the parent client.

  • Audit log filters + pagination + CSV export. Filter by status (ok/fail), method, tool, IP, date range. Free-text search across method / tool / note / ip. Paginated at 50 per page. "Export CSV" button streams up to the last 50 000 rows.

  • Bot user banner on the Tokens page surfacing the wp-commander-bot service account (if the wizard created it) with role + Edit-user link, and the reasoning for binding tokens to it.

  • Audit log noise dedup. The post-OAuth-refresh "(pre-auth) cmcp_invalid_token" cascade (SDK retrying with a now-revoked stale token between refresh + cached use) is now deduplicated to one row per IP per minute when there is a successful OAuth token issuance from the same IP in the same window.

No schema change

Pure additive release. The new OAuth sessions view reads from the existing wp_cmcp_oauth_tokens table.

v1.6.3 - Fix OAuth consent rendering

Choose a tag to compare

@TaherSayed TaherSayed released this 24 May 15:04

Fixes the OAuth consent screen rendering as blank or garbled in the browser.

The bug

The OAuth authorize endpoint lives at /wp-json/claude-mcp/v1/oauth/authorize — a REST API route. WordPress REST always pipes the response body through wp_json_encode before sending it, even when you set Content-Type: text/html. So my consent-screen HTML was being delivered as a quoted, escaped JSON string. Browsers couldn't render it and the page came up empty (or showed just stray newline characters).

Fix

html_response() and raw_redirect() now call status_header() + header() + echo + exit directly. This bypasses the REST serializer entirely — same pattern already used by the well-known endpoints. The exit terminates the request before WP_REST_Server::serve_request gets a chance to wrap the body.

After updating

The auto-heal routine from 1.6.2 will detect 1.6.3 on next admin pageload. Try the OAuth flow — you'll see the proper consent screen (white card titled "Authorize access") with Approve/Deny buttons.

v1.6.2 - Self-heal missing tables

Choose a tag to compare

@TaherSayed TaherSayed released this 24 May 14:55

Fixes a silent token-creation failure on installs upgraded via "Replace current with uploaded".

The bug

WordPress fires register_activation_hook on initial activation only, NOT on the in-place upgrade flow. If the cmcp_tokens table was missing for any reason (e.g. the previous version had been Deleted via admin, triggering uninstall.php, then the new version installed via Replace), wpdb->insert failed silently and the token never appeared in the Existing tokens list.

Fix

Plugin::maybe_upgrade() now runs on every load (hooked from Plugin::init). It compares the stored cmcp_version option against CMCP_VERSION. If they differ OR the primary wp_cmcp_tokens table is missing, it re-runs Plugin::activate() (which calls dbDelta). dbDelta is idempotent — existing tables with matching schema are untouched.

Upgrade

Install over the existing 1.6.1. On the next admin pageload, missing tables get created. Try creating a token — it should appear in the list immediately.