PluginProbe
Kit (formerly ConvertKit) – Email Newsletter, Email Marketing, Membership, Subscribers and Landing Pages / 3.4.3
Kit (formerly ConvertKit) – Email Newsletter, Email Marketing, Membership, Subscribers and Landing Pages v3.4.3
3.4.3 3.4.2 3.4.1 3.4.0 3.3.9 3.3.8 3.3.7 3.3.6 3.3.5 3.3.4 3.3.3 3.3.2 3.3.1 2.2.0 2.2.1 2.2.2 2.2.3 2.2.4 2.2.5 2.2.6 2.2.7 2.2.8 2.2.9 2.3.0 2.3.1 All 196 releases
← All changes | admin/section/class-convertkit-admin-section-mcp.php +420 -113 3.4.03.4.3 View file →
@@ -23,8 +23,17 @@
23 23 */
24 24 private $authorization_header = false;
25 25
26 26 /**
27 + * Whether the Kit account is on a paid plan, once queried.
28 + *
29 + * @since 3.4.1
30 + *
31 + * @var bool|null
32 + */
33 + private $is_paid_plan = null;
34 +
35 + /**
27 36 * Constructor.
28 37 *
29 38 * @since 3.4.0
30 39 */
@@ -50,8 +59,13 @@
50 59 'title' => $this->title,
51 60 'callback' => array( $this, 'print_section_info' ),
52 61 'wrap' => true,
53 62 ),
63 + 'connect' => array(
64 + 'title' => __( 'Connect an AI client', 'convertkit' ),
65 + 'callback' => array( $this, 'print_section_info_connect' ),
66 + 'wrap' => true,
67 + ),
54 68 );
55 69
56 70 $this->maybe_generate_authentication_header();
57 71 $this->maybe_revoke_application_password();
@@ -157,9 +171,21 @@
157 171 }
158 172
159 173 // Enqueue JS.
160 174 wp_enqueue_script( 'convertkit-admin-settings-conditional-display', CONVERTKIT_PLUGIN_URL . 'resources/backend/js/settings-conditional-display.js', array( 'jquery' ), CONVERTKIT_PLUGIN_VERSION, true );
175 + wp_enqueue_script( 'convertkit-admin-ui', CONVERTKIT_PLUGIN_URL . 'resources/backend/js/ui.js', array(), CONVERTKIT_PLUGIN_VERSION, true );
161 176
177 + // Localize the strings displayed when copying a code block to the clipboard.
178 + wp_localize_script(
179 + 'convertkit-admin-ui',
180 + 'convertkit_ui',
181 + array(
182 + 'copy' => __( 'Copy', 'convertkit' ),
183 + 'copied' => __( 'Copied', 'convertkit' ),
184 + 'failed' => __( 'Press Ctrl/Cmd + C to copy', 'convertkit' ),
185 + )
186 + );
187 +
162 188 }
163 189
164 190 /**
165 191 * Registers settings fields for this section.
@@ -186,32 +212,8 @@
186 212 ),
187 213 )
188 214 );
189 215
190 - // Bail if MCP is not enabled — none of the connect UI applies.
191 - if ( ! $this->settings->enabled() ) {
192 - return;
193 - }
194 -
195 - // If an Application Password exists for this Plugin, display the instructions and revoke section.
196 - if ( $this->get_application_password_uuid() ) {
197 - add_settings_field(
198 - 'connect',
199 - __( 'Connection', 'convertkit' ),
200 - array( $this, 'instructions_disconnect_callback' ),
201 - $this->settings_key,
202 - $this->name
203 - );
204 - } else {
205 - add_settings_field(
206 - 'connect',
207 - __( 'Connection', 'convertkit' ),
208 - array( $this, 'connect_callback' ),
209 - $this->settings_key,
210 - $this->name
211 - );
212 - }
213 -
214 216 }
215 217
216 218 /**
217 219 * Prints help info for this section
@@ -226,9 +228,8 @@
226 228 <?php
227 229
228 230 }
229 231
230 -
231 232 /**
232 233 * Returns the URL for the ConvertKit documentation for this setting section.
233 234 *
234 235 * @since 3.4.0
@@ -236,9 +237,9 @@
236 237 * @return string Documentation URL.
237 238 */
238 239 public function documentation_url() {
239 240
240 - return '#';
241 + return 'https://help.kit.com/en/articles/16729038-using-the-kit-plugin-s-mcp-server-on-your-wordpress-website';
241 242
242 243 }
243 244
244 245 /**
@@ -271,10 +272,9 @@
271 272 */
272 273 public function enabled_callback( $args ) {
273 274
274 275 // If the user doesn't have a paid plan, show the upgrade required message.
275 - $account = new ConvertKit_Resource_Account();
276 - if ( ! $account->is_paid_plan() ) {
276 + if ( ! $this->is_paid_plan() ) {
277 277 // Disable saving settings.
278 278 $this->save_disabled = true;
279 279
280 280 $this->output_upgrade_required_message();
@@ -293,15 +293,131 @@
293 293
294 294 }
295 295
296 296 /**
297 - * Renders the Connect a client setting, to allow the user to generate an Application Password
298 - * for this Plugin which is used to connect AI clients to the MCP Server.
297 + * Renders the connection instructions, comprising of the steps the user needs
298 + * to complete to connect an AI client to this site's MCP server.
299 299 *
300 - * @since 3.4.0
300 + * @since 3.4.1
301 301 */
302 - public function connect_callback() {
302 + public function print_section_info_connect() {
303 303
304 + // Don't output anything if the Kit account isn't on a paid plan, as the
305 + // upgrade message is displayed in the section above.
306 + if ( ! $this->is_paid_plan() ) {
307 + return;
308 + }
309 +
310 + // The output is wrapped in its own container, so that the settings screen's
311 + // styles for a beta section's immediate children aren't applied to it.
312 + echo '<div class="convertkit-mcp">';
313 +
314 + if ( ! $this->settings->enabled() ) {
315 + // The MCP server isn't enabled; tell the user how to enable it.
316 + ?>
317 + <p class="description">
318 + <?php esc_html_e( 'Enable the MCP server above and click Save Changes, to then connect an AI client to this site.', 'convertkit' ); ?>
319 + </p>
320 + <?php
321 + } elseif ( $this->application_passwords_available() ) {
322 + // Get the Application Password for this Plugin, if one exists.
323 + $application_password = $this->get_application_password();
324 + ?>
325 +
326 + <ol class="kit-numbered-steps">
327 + <li>
328 + <h3><?php esc_html_e( 'Enable the MCP server', 'convertkit' ); ?></h3>
329 + <p class="description">
330 + <?php
331 + printf(
332 + /* translators: %s: MCP server URL. */
333 + esc_html__( 'Done. AI clients connect to %s', 'convertkit' ),
334 + '<code>' . esc_url( ConvertKit_MCP::get_server_url() ) . '</code>'
335 + );
336 + ?>
337 + </p>
338 + </li>
339 +
340 + <li>
341 + <h3><?php esc_html_e( 'Create an Application Password', 'convertkit' ); ?></h3>
342 + <?php
343 + if ( is_array( $application_password ) ) {
344 + $this->output_application_password( $application_password );
345 + } else {
346 + $this->output_create_application_password();
347 + }
348 + ?>
349 + </li>
350 +
351 + <li>
352 + <h3><?php esc_html_e( 'Connect your AI client', 'convertkit' ); ?></h3>
353 + <?php
354 + if ( ! is_array( $application_password ) ) {
355 + ?>
356 + <p class="description">
357 + <?php esc_html_e( 'Create an Application Password above to display the configuration for your AI client.', 'convertkit' ); ?>
358 + </p>
359 + <?php
360 + } else {
361 + $this->output_client_instructions();
362 + }
363 + ?>
364 + </li>
365 + </ol>
366 +
367 + <?php
368 + // Output a summary of what the AI client can do once connected.
369 + $this->output_capabilities_summary();
370 + }
371 +
372 + echo '</div>';
373 +
374 + }
375 +
376 + /**
377 + * Returns whether WordPress' Application Passwords feature is available for
378 + * the site and the current user, outputting an error message if it isn't.
379 + *
380 + * WordPress disables Application Passwords when the site isn't served over
381 + * HTTPS and isn't a local environment, meaning no AI client can authenticate.
382 + *
383 + * @since 3.4.1
384 + *
385 + * @return bool Application Passwords are available.
386 + */
387 + private function application_passwords_available() {
388 +
389 + // Application Passwords are disabled for the site.
390 + if ( ! wp_is_application_passwords_available() ) {
391 + $this->output_error(
392 + sprintf(
393 + /* translators: %1$s: Site URL, %2$s: WP_ENVIRONMENT_TYPE constant. */
394 + __( 'Application Passwords are disabled on this site, so AI clients cannot authenticate. WordPress disables Application Passwords when a site is not served over HTTPS. Serve %1$s over HTTPS, or set %2$s to local on a development site, and then reload this screen.', 'convertkit' ),
395 + home_url(),
396 + 'WP_ENVIRONMENT_TYPE'
397 + )
398 + );
399 + return false;
400 + }
401 +
402 + // Application Passwords are disabled for this user.
403 + if ( ! wp_is_application_passwords_available_for_user( get_current_user_id() ) ) {
404 + $this->output_error( __( 'Application Passwords are disabled for your WordPress user, so you cannot create the password an AI client needs. Ask an administrator to enable Application Passwords for your user.', 'convertkit' ) );
405 + return false;
406 + }
407 +
408 + return true;
409 +
410 + }
411 +
412 + /**
413 + * Renders the Create Application Password button, which sends the user to
414 + * WordPress' authorize-application.php screen.
415 + *
416 + * @since 3.4.1
417 + */
418 + private function output_create_application_password() {
419 +
304 420 // Build the WordPress authorize-application.php URL.
305 421 // See: https://developer.wordpress.org/advanced-administration/security/application-passwords/.
306 422 // We don't use add_query_arg(), as rawurlencode() is needed for authorize-application.php's JS to work correctly.
307 423 $authorize_url = admin_url( 'authorize-application.php' )
@@ -314,10 +430,16 @@
314 430 )
315 431 )
316 432 . '&reject_url=' . rawurlencode( $this->get_settings_url() );
317 433 ?>
318 - <p>
319 - <?php esc_html_e( 'Click Create Application Password to create a password that AI clients can use to connect to this site\'s MCP server.', 'convertkit' ); ?>
434 + <p class="description">
435 + <?php
436 + printf(
437 + /* translators: %s: WordPress user's display name. */
438 + esc_html__( 'An AI client signs in to this site using an Application Password. The client will act as %s, and can only do what that user can do.', 'convertkit' ),
439 + '<strong>' . esc_html( wp_get_current_user()->display_name ) . '</strong>'
440 + );
441 + ?>
320 442 </p>
321 443 <p>
322 444 <a href="<?php echo esc_attr( $authorize_url ); ?>" id="convertkit-settings-mcp-create-application-password" class="button button-primary">
323 445 <?php esc_html_e( 'Create Application Password', 'convertkit' ); ?>
@@ -327,58 +449,97 @@
327 449
328 450 }
329 451
330 452 /**
331 - * Renders the instructions and Disconnect section.
453 + * Renders the Application Password's details, the authorization header (if the
454 + * password was just created), and the Revoke Application Password button.
332 455 *
333 - * @since 3.4.0
456 + * @since 3.4.1
457 + *
458 + * @param array $application_password Application Password.
334 459 */
335 - public function instructions_disconnect_callback() {
460 + private function output_application_password( $application_password ) {
336 461
337 462 // Build disconnect URL.
338 463 $disconnect_url = $this->get_settings_url( array( '_convertkit_settings_mcp_revoke_application_password' => wp_create_nonce( 'convertkit-mcp-revoke-application-password' ) ) );
339 464
340 - // Fetch query parameters to build the Basic auth header.
465 + // Define the date and time format used for the Application Password's dates.
466 + $date_format = get_option( 'date_format' ) . ' ' . get_option( 'time_format' );
467 + ?>
468 + <p class="description">
469 + <?php
470 + printf(
471 + /* translators: %1$s: WordPress user's display name, %2$s: Date and time the Application Password was created. */
472 + esc_html__( 'AI clients using this Application Password act as %1$s, and can only do what that user can do. Created %2$s.', 'convertkit' ),
473 + '<strong>' . esc_html( wp_get_current_user()->display_name ) . '</strong>',
474 + esc_html( (string) wp_date( $date_format, $application_password['created'] ) )
475 + );
476 +
477 + if ( ! empty( $application_password['last_used'] ) ) {
478 + echo ' ';
479 + printf(
480 + /* translators: %s: Date and time the Application Password was last used. */
481 + esc_html__( 'Last used %s.', 'convertkit' ),
482 + esc_html( (string) wp_date( $date_format, $application_password['last_used'] ) )
483 + );
484 + } else {
485 + echo ' ';
486 + esc_html_e( 'Not yet used by an AI client.', 'convertkit' );
487 + }
488 + ?>
489 + </p>
490 +
491 + <?php
341 492 if ( $this->authorization_header ) {
342 493 ?>
343 494 <p>
344 - <strong><?php esc_html_e( 'Authorization Header:', 'convertkit' ); ?></strong>
345 - <code id="kit-authorization-header">Basic <?php echo esc_html( $this->authorization_header ); ?></code>
495 + <strong><?php esc_html_e( 'Authorization header:', 'convertkit' ); ?></strong>
346 496 </p>
347 - <p>
348 - <?php esc_html_e( 'Copy the above. It won\'t be displayed again. If you lose this, you\'ll need to revoke the Application Password and create a new one.', 'convertkit' ); ?>
497 + <?php
498 + $this->output_code_block( 'Basic ' . $this->authorization_header, 'kit-authorization-header' );
499 + ?>
500 + <p class="description">
501 + <?php esc_html_e( 'Copy the above now. It won\'t be displayed again. If you lose it, revoke the Application Password and create a new one.', 'convertkit' ); ?>
349 502 </p>
350 503 <?php
351 504 } else {
352 505 ?>
353 - <p>
354 - <?php esc_html_e( 'An Application Password was previously created for this Plugin. It is not displayed here for security.', 'convertkit' ); ?>
355 - <br />
356 - <?php esc_html_e( 'If you forgot your Application Password, you can revoke it using the Revoke Application Password button below, and then create a new one.', 'convertkit' ); ?>
506 + <p class="description">
507 + <?php
508 + printf(
509 + /* translators: %s: Placeholder text displayed in the configuration snippets in place of the authorization header. */
510 + esc_html__( 'For security, WordPress only displays an Application Password once, at the point it is created. The configuration below therefore shows %s in place of your Application Password. If you no longer have it, revoke the Application Password and create a new one.', 'convertkit' ),
511 + '<code>BASE64_ENCODED_USERNAME_AND_APPLICATION_PASSWORD</code>'
512 + );
513 + ?>
357 514 </p>
358 515 <?php
359 516 }
360 517 ?>
518 +
361 519 <p>
362 520 <a href="<?php echo esc_url( $disconnect_url ); ?>" id="convertkit-settings-mcp-revoke-application-password" class="button button-secondary"><?php esc_html_e( 'Revoke Application Password', 'convertkit' ); ?></a>
363 521 </p>
522 + <?php
364 523
365 - <?php
366 - // Build server URL and pre-encoded Basic auth header for use in the
367 - // per-client configuration snippets below.
524 + }
525 +
526 + /**
527 + * Renders the configuration for each supported AI client, in a tabbed interface.
528 + *
529 + * @since 3.4.1
530 + */
531 + private function output_client_instructions() {
532 +
533 + // Build the server URL and authorization header used in each client's configuration.
534 + // When the Application Password isn't available to display, a placeholder is used, so
535 + // that the configuration is still valid and shows where the header value belongs.
368 536 $server_url = ConvertKit_MCP::get_server_url();
369 - $auth_header = $this->authorization_header
370 - ? 'Basic ' . $this->authorization_header
371 - : __( 'Your base64 encoded username and application password', 'convertkit' );
537 + $auth_header = 'Basic ' . ( $this->authorization_header ? $this->authorization_header : 'BASE64_ENCODED_USERNAME_AND_APPLICATION_PASSWORD' );
372 538
373 - // Claude desktop / Cline JSON.
374 - //
375 - // The Authorization header value is inlined (not passed via the
376 - // `env` block + `${VAR}` substitution as the mcp-remote docs
377 - // suggest), because mcp-remote's variable substitution is unreliable
378 - // with Basic auth values that contain `$` characters in their
379 - // base64 payload — the substitution silently leaves the literal
380 - // `${KIT_AUTH}` string in place, producing 401s.
539 + // Claude Desktop JSON.
540 + // Claude Desktop only supports remote MCP servers that authenticate using OAuth, so
541 + // mcp-remote is used to proxy requests to the MCP server, adding the authorization header.
381 542 $claude_desktop_config = wp_json_encode(
382 543 array(
383 544 'mcpServers' => array(
384 545 'kit-wordpress' => array(
@@ -395,8 +556,15 @@
395 556 ),
396 557 JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES
397 558 );
398 559
560 + // Claude Code command.
561 + $claude_code_command = sprintf(
562 + 'claude mcp add --transport http kit-wordpress %s --header "Authorization: %s"',
563 + $server_url,
564 + $auth_header
565 + );
566 +
399 567 // Cursor JSON.
400 568 $cursor_config = wp_json_encode(
401 569 array(
402 570 'mcpServers' => array(
@@ -409,64 +577,160 @@
409 577 ),
410 578 ),
411 579 JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES
412 580 );
413 - ?>
414 581
415 - <h3><?php esc_html_e( 'Claude', 'convertkit' ); ?></h3>
416 - <p>
417 - <?php
418 - printf(
419 - /* translators: %s: Path to Claude desktop config file. */
420 - esc_html__( 'Add the following to your %s file, then restart Claude desktop:', 'convertkit' ),
421 - '<code>claude_desktop_config.json</code>'
422 - );
423 - ?>
424 - <br />
425 - macOS: <code>~/Library/Application Support/Claude/claude_desktop_config.json</code>
426 - <br />
427 - Windows: <code>%APPDATA%\Claude\claude_desktop_config.json</code>
428 - </p>
429 - <pre><code><?php echo esc_html( $claude_desktop_config ); ?></code></pre>
582 + // Codex TOML.
583 + $codex_config = '[mcp_servers.kit_wordpress]' . "\n"
584 + . 'url = "' . $server_url . '"' . "\n"
585 + . 'http_headers = { "Authorization" = "' . $auth_header . '" }';
430 586
431 - <h3><?php esc_html_e( 'Claude Code', 'convertkit' ); ?></h3>
432 - <p>
433 - <?php esc_html_e( 'Run the following command in your terminal.', 'convertkit' ); ?>
434 - <br />
435 - <code>
587 + // Define the clients to display, in the order they should be displayed.
588 + $clients = array(
589 + 'claude-desktop' => __( 'Claude Desktop', 'convertkit' ),
590 + 'claude-code' => __( 'Claude Code', 'convertkit' ),
591 + 'cursor' => __( 'Cursor', 'convertkit' ),
592 + 'codex' => __( 'Codex', 'convertkit' ),
593 + 'other' => __( 'Other clients', 'convertkit' ),
594 + );
595 + ?>
596 + <div class="kit-inline-tabs">
597 + <ul class="kit-inline-tabs-nav">
436 598 <?php
437 - printf(
438 - 'claude mcp add --transport http kit-wordpress %s --header "Authorization: %s"',
439 - esc_html( $server_url ),
440 - esc_html( $auth_header )
441 - );
599 + $first_client = true;
600 + foreach ( $clients as $client => $label ) {
601 + ?>
602 + <li>
603 + <button type="button" class="kit-inline-tab<?php echo ( $first_client ? ' is-active' : '' ); ?>" data-tab="<?php echo esc_attr( $client ); ?>">
604 + <?php echo esc_html( $label ); ?>
605 + </button>
606 + </li>
607 + <?php
608 + $first_client = false;
609 + }
442 610 ?>
443 - </code>
444 - </p>
611 + </ul>
445 612
446 - <h3><?php esc_html_e( 'Cursor', 'convertkit' ); ?></h3>
447 - <p>
448 - <?php
449 - printf(
450 - /* translators: %s: Path to Cursor MCP config file. */
451 - esc_html__( 'Add the following to your %s file, then restart Cursor:', 'convertkit' ),
452 - '<code>~/.cursor/mcp.json</code>'
453 - );
454 - ?>
455 - </p>
456 - <pre><code><?php echo esc_html( $cursor_config ); ?></code></pre>
613 + <div class="kit-inline-tab-panel is-active" data-tab="claude-desktop">
614 + <p>
615 + <?php
616 + printf(
617 + /* translators: %s: Claude Desktop configuration file name. */
618 + esc_html__( 'Add the following to your %s file, then restart Claude Desktop:', 'convertkit' ),
619 + '<code>claude_desktop_config.json</code>'
620 + );
621 + ?>
622 + <br />
623 + macOS: <code>~/Library/Application Support/Claude/claude_desktop_config.json</code>
624 + <br />
625 + Windows: <code>%APPDATA%\Claude\claude_desktop_config.json</code>
626 + </p>
627 + <?php $this->output_code_block( (string) $claude_desktop_config ); ?>
628 + <p class="description">
629 + <?php
630 + printf(
631 + /* translators: %1$s: mcp-remote, %2$s: Node.js. */
632 + esc_html__( 'Claude Desktop only connects to remote MCP servers that use OAuth, so %1$s is used to connect to this site. This requires %2$s to be installed on your computer.', 'convertkit' ),
633 + '<code>mcp-remote</code>',
634 + '<a href="https://nodejs.org/" target="_blank">Node.js</a>'
635 + );
636 + ?>
637 + </p>
638 + </div>
457 639
458 - <h3><?php esc_html_e( 'Other clients', 'convertkit' ); ?></h3>
459 - <p>
460 - <?php esc_html_e( 'For any other MCP client, provide it with the following:', 'convertkit' ); ?>
640 + <div class="kit-inline-tab-panel" data-tab="claude-code">
641 + <p>
642 + <?php esc_html_e( 'Run the following command in your terminal:', 'convertkit' ); ?>
643 + </p>
644 + <?php $this->output_code_block( $claude_code_command ); ?>
645 + </div>
646 +
647 + <div class="kit-inline-tab-panel" data-tab="cursor">
648 + <p>
649 + <?php
650 + printf(
651 + /* translators: %s: Cursor configuration file name. */
652 + esc_html__( 'Add the following to your %s file, then restart Cursor:', 'convertkit' ),
653 + '<code>~/.cursor/mcp.json</code>'
654 + );
655 + ?>
656 + </p>
657 + <?php $this->output_code_block( (string) $cursor_config ); ?>
658 + </div>
659 +
660 + <div class="kit-inline-tab-panel" data-tab="codex">
661 + <p>
662 + <?php
663 + printf(
664 + /* translators: %s: Codex configuration file name. */
665 + esc_html__( 'Add the following to your %s file, then restart Codex:', 'convertkit' ),
666 + '<code>~/.codex/config.toml</code>'
667 + );
668 + ?>
669 + </p>
670 + <?php $this->output_code_block( $codex_config ); ?>
671 + <p class="description">
672 + <?php
673 + printf(
674 + /* translators: %s: Codex configuration option. */
675 + esc_html__( 'Older versions of Codex require %s at the top of the configuration file to connect to remote MCP servers.', 'convertkit' ),
676 + '<code>experimental_use_rmcp_client = true</code>'
677 + );
678 + ?>
679 + </p>
680 + </div>
681 +
682 + <div class="kit-inline-tab-panel" data-tab="other">
683 + <p>
684 + <?php esc_html_e( 'For any other MCP client, use the following. The server uses the streamable HTTP transport, and authenticates using HTTP Basic authentication.', 'convertkit' ); ?>
685 + </p>
686 + <p>
687 + <strong><?php esc_html_e( 'Server URL:', 'convertkit' ); ?></strong>
688 + </p>
689 + <?php $this->output_code_block( $server_url ); ?>
690 + <p>
691 + <strong><?php esc_html_e( 'Authorization header:', 'convertkit' ); ?></strong>
692 + </p>
693 + <?php $this->output_code_block( $auth_header ); ?>
694 + </div>
695 + </div>
696 + <?php
697 +
698 + }
699 +
700 + /**
701 + * Renders a summary of what an AI client can do once connected.
702 + *
703 + * @since 3.4.1
704 + */
705 + private function output_capabilities_summary() {
706 +
707 + ?>
708 + <h3><?php esc_html_e( 'What your AI client can do', 'convertkit' ); ?></h3>
709 + <p class="description">
710 + <?php esc_html_e( 'Describe what you want in your own words; your AI client works out which tools to use.', 'convertkit' ); ?>
461 711 </p>
462 - <p>
463 - <strong><?php esc_html_e( 'Server URL:', 'convertkit' ); ?></strong>
464 - <code><?php echo esc_html( $server_url ); ?></code>
712 + <ul class="convertkit-mcp-capabilities">
713 + <li><?php esc_html_e( 'Look up the Forms, Landing Pages, Products and Tags in your Kit account.', 'convertkit' ); ?></li>
714 + <li><?php esc_html_e( 'Add, list, change and remove Kit Forms, Form Triggers, Products and Broadcasts within a post or page\'s content.', 'convertkit' ); ?></li>
715 + <li><?php esc_html_e( 'Read and change a post or page\'s Kit settings, such as its Form, Landing Page, Tag and Member Content.', 'convertkit' ); ?></li>
716 + <li><?php esc_html_e( 'Read and change a category\'s Kit Form and Form Position.', 'convertkit' ); ?></li>
717 + <li><?php esc_html_e( 'Read and change this Plugin\'s General, Broadcasts and Member Content settings.', 'convertkit' ); ?></li>
718 + </ul>
719 + <p class="description">
720 + <?php esc_html_e( 'Your Kit account credentials, and your Form Entries, are never exposed to AI clients.', 'convertkit' ); ?>
465 721 </p>
722 + <?php
723 +
724 + // Output a link to the documentation, if it's defined.
725 + if ( $this->documentation_url() === '#' ) {
726 + return;
727 + }
728 + ?>
466 729 <p>
467 - <strong><?php esc_html_e( 'Authorization header:', 'convertkit' ); ?></strong>
468 - <code><?php echo esc_html( $auth_header ); ?></code>
730 + <a href="<?php echo esc_url( $this->documentation_url() ); ?>" target="_blank">
731 + <?php esc_html_e( 'Read the MCP documentation', 'convertkit' ); ?>
732 + </a>
469 733 </p>
470 734 <?php
471 735
472 736 }
@@ -494,17 +758,38 @@
494 758
495 759 }
496 760
497 761 /**
498 - * Finds the UUID of the most recently-created Application Password for the
499 - * currently logged in user
762 + * Returns whether the Kit account is on a paid plan.
500 763 *
501 - * @since 3.4.0
764 + * @since 3.4.1
502 765 *
503 - * @return bool|string
766 + * @return bool
504 767 */
505 - private function get_application_password_uuid() {
768 + private function is_paid_plan() {
506 769
770 + // If the result has already been fetched for this request, return it.
771 + if ( ! is_null( $this->is_paid_plan ) ) {
772 + return $this->is_paid_plan;
773 + }
774 +
775 + // Fetch the account resource and return the result.
776 + $account = new ConvertKit_Resource_Account();
777 + $this->is_paid_plan = $account->is_paid_plan();
778 + return $this->is_paid_plan;
779 +
780 + }
781 +
782 + /**
783 + * Finds the most recently-created Application Password for this Plugin, belonging
784 + * to the currently logged in user.
785 + *
786 + * @since 3.4.1
787 + *
788 + * @return bool|array
789 + */
790 + private function get_application_password() {
791 +
507 792 // Get the user's Application Passwords.
508 793 $passwords = WP_Application_Passwords::get_user_application_passwords( get_current_user_id() );
509 794
510 795 // Return false if no Application Passwords exist.
@@ -514,13 +799,35 @@
514 799
515 800 // Iterate through the Application Passwords and return the password that matches the app name.
516 801 foreach ( $passwords as $password ) {
517 802 if ( $password['name'] === CONVERTKIT_MCP_APP_NAME ) {
518 - return $password['uuid'];
803 + return $password;
519 804 }
520 805 }
521 806
522 807 return false;
808 +
809 + }
810 +
811 + /**
812 + * Finds the UUID of the most recently-created Application Password for the
813 + * currently logged in user
814 + *
815 + * @since 3.4.0
816 + *
817 + * @return bool|string
818 + */
819 + private function get_application_password_uuid() {
820 +
821 + // Get the Application Password for this Plugin.
822 + $password = $this->get_application_password();
823 +
824 + // Return false if no Application Password exists.
825 + if ( ! is_array( $password ) ) {
826 + return false;
827 + }
828 +
829 + return $password['uuid'];
523 830
524 831 }
525 832
526 833 }