Releases: TaherSayed/sayed-wp-conductor-for-claude
Release list
v1.9.1 - GitHub repo renamed to match wp.org slug
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"
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.php→sayed-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-botsystem username — renaming would break existing installs' audit trails.X-Commander-Signaturewebhook header — protocol contract; receivers depend on exact string match.CMCP_*PHP constants andCMCP\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
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 inassets/js/*.js, registered viawp_enqueue_script+wp_add_inline_scriptfor PHP→JS data. OAuth consent + error pages linkassets/css/oauth-consent.cssinstead of inlining CSS. uninstall.phpno longer includes core admin files directly. Bot user deletion is now conditional onwp_delete_useralready being loaded.
Still pending (decisions, not code)
The review also flagged:
- Name / slug — "Commander" and "Claude" in the name/slug imply false affiliation. New name + slug needed.
- 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.deor add a DNS TXT recordwordpressorg-tahersayed-verificationat the domain root.
v1.8.1 - DCR dedup + SSRF v6 + destructive gate on media_delete
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 IPv6 —
media_uploadpreviously usedgethostbynamel(), which is IPv4-only. An attacker host with an AAAA record pointing atfc00::…or::1could bypass the filter. Guard now resolves A+AAAA viadns_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_deletenow respects "Allow destructive operations" — it was an unconditional hard delete before. Matches the gate already enforced byposts_deleteandsettings_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)
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
- Update the plugin to v1.8.0.
- Visit wp-admin → Commander → Settings once to trigger the migration.
- 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
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)
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
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
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
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.