Surface license status visually on the AI Credits tab #67 (e0d0e2)
Surface the real balance-check error instead of a generic retry #52. (c087a5)
Trim message guard + same passthrough for credit packages #52. (be459c)
Align preview error code and widen drift guard to traits (7ddac4)
Finish safe-error allow-list and stop preview/PII leaks (14d109)
Match update_member field gate to the service isset contract (450565)
Stop update_member clobbering or rejecting on absent fields (6e8fbf)
Surface validation error messages to MCP clients (577c6d)
Align the Cursor OAuth step with the Authorize Application flow (e3584c)
Gate the corporate sub-accounts copy on the Corporate add-on too (be84b2)
Only mention gifts in Manage members copy when Gifting is active #57 (e05628)
Update Claude Desktop setup steps to the current connection flow #59 (3d9b26)
Versão 1.4.3
7 melhorias
Melhoria
Discount_mode now allows trial-override (in CouponService::create, the create_coupon tool, and the create-coupon ability).
Two new optional fields, trial_days and trial_amount, are stored as _mepr_coupons_trial_days / _mepr_coupons_trial_amount when the mode is trial-override.
Write abilities now require mpai_use_mcp_write (and mpai_use_mcp, so write implies read), not the read capability alone.
Application Password sessions are denied write on the Abilities surface, mirroring the read-only cap enforced on /mcp.
Breaking change for Abilities clients: write and destructive abilities now preview by default. The dry_run schema default flips from false to true, so a call that omits the flag previews. Pass dry_run: false to execute live. Affects refund-transaction, manage-subscription, create-member, update-member, create-coupon, and create-rule.
The admin "pause destructive writes" kill switch is now honored on the Abilities surface for refund-transaction and manage-subscription.
Residual divergences from the /mcp Tools path (per-tool requires_cap parity and the two-step confirmation token) are tracked as follow-ups; the write-capability requirement plus preview-by-default is the safety net in the meantime.
Versão 1.4.2
7 melhorias
Melhoria
Schema enums updated to MemberPress's canonical vocabulary: discount_mode: ['standard', 'first-payment'], discount_type: ['percent', 'dollar']. Pre-launch breaking change, legacy 'first' / 'all' / 'flat' values are now rejected at every layer (Tools schema, Abilities API schema, service validation, formatter output).
When discount_mode is 'first-payment', the service now also writes the per-mode _mepr_coupons_first_payment_discount_* meta keys. Without this, MemberPress core would have read the standard meta keys (which it ignores for first-payment mode) and applied a $0 first-payment discount despite the mode being right.
CouponFormatter::detail canonicalizes its output on read, legacy 'first'/'all' stored values and any other unrecognized mode coerce to 'standard' (matching MemberPress's runtime fallback). Legacy 'flat' discount_type coerces to 'dollar'. The formatter's output schema now always matches the public enum regardless of what's in the DB.
Discount_mode === 'first-payment' reads from the _mepr_coupons_first_payment_discount_* meta keys when present so coupons that originated in the WP admin (where the form has separate fields for first-payment discount amount/type) surface the right values via the MCP read API.
Switched isset →! empty for membership_ids so a wrapper layer defaulting to 0 doesn't end up storing [0] as a valid_products filter (which would silently break the coupon).
Copy button hover-reveal. The button next to the MCP Server URL on the Setup Wizard's "Existing Setup" panel now collapses to zero width when hidden and expands to its content width on hover, focus, or post-click success state. Uses an inline-flex layout (no fixed pixel padding to mismatch the button's actual width across locales), bounded by a max-width: 160px ceiling so a long localized label can't blow out the URL field. @media (hover: none) keeps the button visible by default on touch…
Memberpress_refund_transaction now flags a MemberPress-core listing side effect. When the refunded transaction has an associated subscription AND the caller did NOT pass cancel_subscription: true, the response (preview and live) includes a new subscription_listing_may_show_inactive: true flag plus a localized subscription_listing_note explaining that the WP admin Subscriptions list will show the subscription as Active: No (because MemberPress core's "Active" column on that list is computed…
Versão 1.4.1
2 melhorias
Melhoria
Reload the AI Settings page after the MCP Settings form is saved. Sibling sub-tabs (Setup Wizard, Connected Clients) are server-rendered once per page load, AJAX-saving an option like the access-level ceiling didn't refresh them, so the wizard kept the stale write-checkbox HTML it had at page-load time even though the new ceiling would have hidden it. Adds a short delay so the "Settings saved" notice registers before the navigation, and closes the whole class of cross-tab stale-state bugs (any…
Route the "Settings saved. Refreshing..." status message through wp_localize_script. Pre-existing pattern in admin.js is that user-facing strings are hardcoded English; this one new string is properly localized via the mpMcpAdmin global. Issue #27 tracks the broader sweep for the other hardcoded strings in that file.
Versão 1.4.0
2 novidades14 melhorias
Novidade
New "sentinel" token row is upserted on first App Password auth, keyed by user_id. Auth-method chip in the Connected Clients table distinguishes Wizard / OAuth / Application Password sessions.
New Settings::get_scope_ceiling getter normalizes the stored option through Auth::normalize_scope_csv so the wizard UI and the server enforcement see the same canonical tokens, closes a parity bug where a legacy whitespace-padded saved value could desync them.
Melhoria
App Password sessions are always issued read-only scope at the server, regardless of the user's mpai_use_mcp_write capability. Granular write scopes must go through the wizard, which carries an explicit per-scope grant on the token.
Revoking an App Password row deletes every WP Application Password for that user via WP_Application_Passwords::delete_all_application_passwords. Revoke confirmation surfaces this with a louder warning because the action affects other REST integrations the user may have running.
Activity Log entries for App Password calls now show "Application Password: " instead of "Unknown".
Setting renamed to "Maximum access level for new connections" with help text that makes the ceiling semantics explicit ("Caps the access any new client connection can be issued. Read Only here disables write scopes in the setup wizard and for OAuth client registrations.").
Wizard step 2 hides write checkboxes entirely when the ceiling is Read Only and shows an explanatory notice.
Server-side cap via new Auth::cap_scope_to_ceiling applied at four issuance paths: wizard token creation, OAuth /authorize, OAuth /token exchange (re-cap closes a TOCTOU window if the ceiling tightens between authorize and exchange), and OAuth root redirect. A hand-crafted POST that bypasses the hidden wizard UI is still capped down to read.
The cap delegates to ScopeMatcher::has for the intersection so it respects the existing scope hierarchy and would Just Work if a future UI exposes a granular ceiling (e.g. read + write:members but not write:billing).
Existing already-issued tokens are NOT retroactively narrowed. The ceiling applies at issuance time only.
Dry_run parameter removed from every write-tool schema. The polarity flip in Server::handle_tool_call already derived dry_run from execute on every call (client-supplied dry_run was ignored), so the schema entry was a documented-but-non-functional parameter. Non-destructive write tools now advertise only execute (default false = preview); destructive tools advertise neither, they use the two-step confirm token flow as their execute mechanism. delete_member's pattern (no execute, no dry_run…
Default Access Level radios bind to derived state. Fixes a display bug where the canonical CSV 'read,full' (emitted by Auth::normalize_scope_csv for full-access defaults) left both radios unchecked because the template used direct string equality. Same root cause affected the wizard's write-checkbox pre-state.
Test_AppPasswordSession (15 tests), sentinel insert/race/revoke contract, scope-pin invariant against legacy DB drift.
Test_CapScopeToCeiling (16 tests), full / read-only / granular ceilings, whitespace-bypass regression, TOCTOU re-cap on token exchange.
Test_GetScopeCeiling (6 tests), pins the normalization contract for the canonical getter.
Suite is now 371 tests / 814 assertions, all green.
Versão 1.3.1
1 correção
Correção
Fix setup wizard's Claude Code CLI snippet: use --header="..." form and wrap the server URL in double quotes so the command works regardless of the Claude Code arg parser's handling of spaces and regardless of WordPress permalink settings.
Versão 1.3.0
3 novidades30 melhorias
Novidade
New admin toggle on the Connected Clients page (gated on mpai_manage_mcp) that pauses every destructive tool call sitewide. Read tools and non-destructive writes keep working.
New ConfirmationTokens class. First call to a destructive tool returns a preview plus a one-time confirmation token (60s TTL). Second call with confirm: executes for real.
New scope vocabulary: read, write:content, write:members, write:billing, write:imports, write:webhooks, write:courses. The legacy read/full pair is preserved for back-compat, existing tokens keep working unchanged.
Melhoria
AJAX endpoint mp_mcp_toggle_writes_paused flips the state with audit-log entries (admin.writes_paused / admin.writes_resumed).
Server-side check in Server::handle_tool_call returns WRITES_PAUSED for any tool whose annotations.destructiveHint is true while the toggle is on.
Token is bound to (tool_name, canonicalized_args, user_id), any change invalidates. Single-use: deleted on first verify.
Special-cased: manage_subscription/resume and manage_sub_account/add are non-destructive variants of destructive-annotated tools, so they skip the gate. Unknown actions fail safe (still gated).
Atomic-when-possible: prefers wp_cache_* over transients when a persistent object cache is available, shrinking the consume-race window.
Every write tool now defaults to preview unless the call sets execute: true. The polarity flip is server-level, adding a future write tool inherits the safe default automatically.
Old dry_run=true parameter still respected (back-compat). Schemas updated to advertise execute as the canonical control.
ScopeMatcher is the single source of truth for scope vocabulary. Token storage is a CSV string; the matcher handles parsing, the meta-scope expansion (full → all writes), and the implicit-read rule.
14 write tools migrated from requires_full_access to requires_scope: 'write: '.
Wizard step 2 rewritten as a scope-checkbox panel. Read is shown disabled+checked (always granted). Write rows are gated on mpai_use_mcp_write capability. The write:courses checkbox only renders when MemberPress Courses is active.
Wizard step 2 now honors the Default Access Level setting from MCP Settings, when admin has set the default to "Full Access," all write checkboxes start pre-checked (still gated on mpai_use_mcp_write). Previously the new checkbox panel ignored the setting and always opened with everything unchecked, so every new connection was issued read-only regardless of the configured default.
Wizard step 4 ("You're All Set!") now displays the actual scope CSV in human-readable form, Read Only, Full Access, or e.g. Read + Manage members, Billing operations, instead of the legacy two-state label that always collapsed granular scopes to "Read Only".
Connected Clients table renders multi-scope tokens as colored chips (read neutral, write:* blue, write:billing/imports amber for high-impact buckets).
Test_Scopes (11 tests), drives the real ScopeMatcher, locks down vocabulary constants and meta-scope semantics. Earlier mirror-test pattern caught and replaced.
Test_RequiresConfirmation (9 tests), locks down the destructive-tool exception list, including fail-safe behavior when the action arg is missing.
Existing tokens (read or full) keep working without migration. New tokens issued by the wizard will carry granular CSV scopes.
For best confirmation-token atomicity under concurrent load, run with a persistent object cache (Redis or Memcached). Transient backend works on basic installs but the single-use property is best-effort there.
Validates member + product, refuses duplicate enrollment
Branches on one-time vs. recurring products (creates MeprSubscription only when needed)
Always uses gateway='manual', admin-granted access, not a billing event
Inherits Measure B (preview by default; execute: true to run live)
Fires mpai_before_create_subscription filter and mpai_subscription_created action for extension
Welcome fires last in the import row, after wp_insert_user + MeprUser->store + optional auto-subscribe, so the user lands in their inbox to a fully-provisioned account.
Skipped on dry_run previews and on rows that fail validation.
Existing users matched by email aren't re-created, so no duplicate notifications.
Calls wp_delete_user($member_id) and lets MemberPress's deleted_user hook chain cascade-clean the mepr_members row, transactions, subscriptions, and events.
Refuses to delete the calling user (self_delete_refused, would terminate their session) or any user holding manage_options (admin_delete_refused). Both checks fire before any state mutation.
Required scope: write:members. Required capability: delete_users. destructiveHint: true so Measure A's confirmation gate is automatic.
Versão 1.2.4
1 correção
Correção
AI Credits "Purchase Credits" modal now centers on the screen. The opener was setting display: block on the modal element, which overrode the CSS display: flex rule that owned the centering. The white card sat anchored at the top-left of the overlay instead of centered. Switched to display: flex to match the chart modal's opener (which already worked correctly).
Versão 1.2.3
2 correções
Correção
OAuth /register rate limit raised from 5/hour to 60/hour per IP. AI clients (Claude.ai, ChatGPT) often register a new OAuth client on every connection attempt, and a single Claude.ai region can have many user sessions sharing one origin IP. The 5/hour limit was rate-limiting legitimate users out of the integration, surfacing as step=start_error in Claude Desktop's connector flow with no clear cause. New limit (1/min average) is still abuse-resistant.
Retry-After: 3600 header added to the 429 response so clients know how long to wait, instead of just "try again later."
Versão 1.2.2
1 melhoria
Melhoria
OAuth redirect URI allowlist now uses prefix matching for claude.ai/claude.com hosts. Previously v1.2.1 added a second hard-coded path (/api/mcp/oauth-redirect) to fix the cloud connector flow, but pinning to specific paths is brittle, any future Claude.ai redirect path change would break the integration again. Now any path under /api/mcp/* is accepted for claude.ai/claude.com hosts. Future-proofs against path changes; the host check is the security boundary.
Versão 1.2.1
1 correção
Correção
Claude.ai cloud connector connection failure, the OAuth dynamic client registration endpoint (POST /wp-json/mp-mcp/v1/register) was rejecting Claude.ai's current redirect URI as invalid_redirect_uri. The plugin's allowlist only accepted the older /api/mcp/auth_callback path. Now accepts both paths, so both the desktop flow (older auth_callback) and the cloud connector flow (current oauth-redirect) work.
Versão 1.2.0
1 novidade1 melhoria
Novidade
/.well-known/mcp.json discovery, when the public catalog endpoint is enabled, AI agents can auto-discover the public MCP URL by fetching Returns site name, description, public endpoint URL, protocol version, and auth_required: false. Returns nothing (404) when the public catalog is disabled, so it never leaks the existence of the endpoint when off.
Melhoria
Settings save form refactored to use new FormData(form), the admin JS now submits the entire form element instead of hand-collecting individual field values. Adding new settings to the page only requires updating PHP and the template, no JS changes needed. Prevents the bug class that caused v1.1.3 (silently dropping new fields).
Versão 1.1.4
1 correção
Correção
Copy buttons in the wizard's Existing Setup panel now actually copy. They were using data-clipboard-text (raw text), but the existing handler expects data-copy-target pointing to an element ID. Fixed both the MCP Server URL and Public Catalog URL copy buttons.
Versão 1.1.3
1 correção
Correção
Settings save form now actually submits the Public AI Catalog checkbox value. The admin JS was building a FormData body with only 5 fields and never appending mp_mcp_public_catalog_enabled, so the toggle silently reverted to OFF on every save. Same bug also caused the Allowed Roles checkboxes to never persist via the Update Settings button, both are fixed in the same patch.
Versão 1.1.2
1 novidade
Novidade
The Public Catalog URL now appears in the "Existing Setup" panel on the wizard Welcome step (when the public endpoint is enabled), with its own Copy button and a description distinguishing it from the authenticated MCP endpoint. Site owners no longer need to dig into Settings to find the URL to share.
Versão 1.1.1
1 correção
Correção
Fatal error on activation/load: v1.1.0 introduced Admin\Settings::get_settings in Plugin.php, but Settings was already imported via use, so the partial qualifier resolved to the non-existent MemberPressAI\MCP\Admin\Admin\Settings. Changed to the imported Settings::get_settings. Also removed an unused Foundation import in PublicTools.php.
Versão 1.1.0
1 novidade4 melhorias
Novidade
New endpoint: /wp-json/mp-mcp/v1/public-mcp, JSON-RPC 2.0, no auth, per-IP rate limited (60 req/min), Cache-Control: public, max-age=300 headers
Melhoria
Curated public tools:: memberpress_list_memberships, publicly-available plans with pricing and signup URLs; memberpress_get_membership, single plan details; memberpress_list_courses, public courses (when MP Courses is active); memberpress_get_course, single course preview
Admin opt-in toggle in MemberPress → AI Settings → MCP Settings: "Enable public AI catalog endpoint". Default OFF, when off, the route returns 404.
Per-product opt-out meta box on memberpressproduct and mpcs-course edit screens: "Show in public AI catalog". Default checked.
MembershipFormatter::public_detail and CourseFormatter::public_detail, public-safe formatters that strip internal fields (member counts, access rules, custom meta) and add public signup URLs.
Versão 1.0.6
5 melhorias
Melhoria
Tools/list now filters by capability, users only see tools they can actually call. AI clients no longer suggest tools that fail mid-conversation. The visible toolset varies per user based on their scope and WP capabilities.
A Subscriber with mpai_use_mcp now sees only public catalog tools (memberships, courses, lessons, rules, protected_urls). They can no longer enumerate members, view financials, or run reports.
An Editor sees PII-related tools they can already access in WP admin (member info, course students) but no financial data.
An Admin sees everything.
Versão 1.0.5
1 reforço de segurança
Segurança
Each write tool now declares the WordPress capability it requires (create_users, edit_users, or manage_options), and the MCP server enforces it before dispatch. Previously, a full scope token could call any write tool regardless of the user's actual WP role, e.g., an Author with mpai_use_mcp_write could create users despite lacking create_users. Now the tool returns CAPABILITY_INSUFFICIENT if the token owner doesn't hold the required cap.
Versão 1.0.4
1 reforço de segurança
Segurança
Application Password auth no longer hardcodes scope = 'full'. Scope now follows the user's mpai_use_mcp_write capability, users without that cap get read-only access even with a valid App Password. Closes a bypass where a user could pick read-only in the wizard but still get full access via an App Password.
Versão 1.0.3
1 novidade1 correção
Novidade
"Existing Setup" panel on the Welcome step shows the MCP server URL and active connection count, so users don't need to re-run the wizard to see their config. "Get Started" button text changes to "Add Another Connection" when at least one token already exists.
Correção
Wizard "Done" button no longer leaves non-admin users on a blank page. Now returns to the Welcome step (which always exists), instead of trying to navigate to the Connected Clients tab that only admins can see.
Versão 1.0.2
2 novidades2 melhorias
Novidade
New capability mpai_use_mcp_write, gates whether a user can create full scope tokens, separate from mpai_manage_mcp (settings admin)
MCP requests now run as the token owner via wp_set_current_user, so capability checks inside tools and Foundation services reflect the token user's role
Melhoria
Wizard's "Full Access" option is now gated on mpai_use_mcp_write instead of mpai_manage_mcp, admins still get it by default, and site owners can grant write-via-MCP without granting full settings-admin rights
Token creation downgrades full → read for users without mpai_use_mcp_write
Versão 1.0.1
1 correção
Correção
Suppress third-party admin notices on the AI Settings / MCP Setup Wizard page so the wizard UI stays clean
Versão 1.0.0
14 novidades13 reforços de segurança
Novidade
Service Layer, 17 domain services (members, memberships, subscriptions, transactions, rules, coupons, content, reports, webhooks, reminders, system, import, credits, courses, corporate, downloads, gifting) with typed accessors via mpai global and Foundation static facade
MCP Server, JSON-RPC 2.0 protocol server with ~48 tools across 17 tool classes, Bearer token + OAuth 2.1 PKCE authentication, scope enforcement (read/write), and admin UI (Setup Wizard, Connected Clients, Settings)
WordPress Abilities API, ~30 abilities under memberpress/ namespace for WP 6.9+ native AI integration, with typed JSON schemas and manage_options permission callbacks
AI Credits Dashboard, Credit balance display (admin bar + dashboard widget), usage statistics, operation cost reference, credit package purchase via Stripe, AJAX refresh
AI Services, Revenue analysis, churn prediction, and smart query tools powered by Mastermind AI orchestrator
LLM Client, Generic AI client with prompt validation, credit checking, retry logic, and SSE streaming support
Mastermind Integration, Centralized API client for the Mastermind orchestrator with license key auth, environment switching (production/staging), structured error mapping, and retry with exponential backoff
PSR-4 Namespaces, All classes under MemberPressAI\ namespace with Composer autoloading
7 Data Formatters, Consistent data shaping for members, memberships, subscriptions, transactions, rules, coupons, and courses with apply_filters extensibility
3 Shared Traits, Pagination, Validation, and DateValidation reused across all services
Dry Run Support, All write operations support dry_run: true for safe preview before execution
Hook System, mpai_before_{action} filters and mpai_{action} actions on all write operations; mpai_{entity}_{type} filters on all formatters
Self-Hosted Updates, MeprAddonUpdates integration for automatic updates via Caseproof Mothership
Uninstall Cleanup, Database tables and options removed on plugin deletion
Segurança
Credit checks enforced before all AI orchestration calls (revenue analysis, churn prediction, smart query)
SSRF protection on Mastermind URL override, https-only, private IP ranges blocked
Atomic rate limiter using wp_cache_incr (Redis/Memcached compatible), enabled by default at 120 req/min
Brute-force auth rate limiting, 20 failed token attempts per 15 minutes per IP
OAuth client registration capped at 50 total clients
Tool name sanitized in error responses to prevent input reflection
JSON-RPC id field validated to spec-compliant types (string, number, null)
Error messages mapped to safe allowlist, internal details never forwarded to clients
RestProxy restricted to GET, POST, DELETE, OPTIONS, HEAD (was ALLMETHODS)
UsageTracking PII stripping changed to allowlist approach