$server Server row from the base plugin's * MCP Servers table. * @param string $client_id The freshly-generated OAuth client_id. * @param string $client_secret The freshly-generated OAuth client_secret. * @return string HTML block, escaped where necessary. * @since 0.1.0 */ public function get_setup_instructions( array $server, string $client_id, string $client_secret ): string { unset( $server, $client_secret ); // Server-context + secret are shown separately in render_tab_section. ob_start(); ?>

  1. ' . esc_html( $client_id ) . '' ); ?>

__( 'ChatGPT wants to connect to your site', 'acrossai-mcp-manager' ), 'subtitle' => __( 'This will let ChatGPT access the MCP tools this server exposes, acting as your WordPress user.', 'acrossai-mcp-manager' ), 'permissions_bullets' => array( __( 'Read and act on the tools exposed on this MCP server', 'acrossai-mcp-manager' ), __( 'Access the WordPress data your user account has permission to see', 'acrossai-mcp-manager' ), __( 'Connect until you revoke access from the Connectors/Integrations tab', 'acrossai-mcp-manager' ), ), ); } /** * Claim DCR-registered clients whose redirect URIs point at an * OpenAI-owned host. Prefer host-based matching over substring name * matching — "OpenAI" and "ChatGPT" appear in third-party client names * frequently enough that name-only matching risked false positives * (e.g., "OpenAI Community Bot" for an unrelated tool). * * @param string $client_name DCR-submitted client_name. * @param array $redirect_uris DCR-submitted redirect_uris. * @return bool */ public function matches_dcr_client( string $client_name, array $redirect_uris ): bool { if ( self::dcr_matches_by_host( $redirect_uris, self::DCR_HOSTS ) ) { return true; } // Name-only fallback — narrow, whole-word `chatgpt` match. No // `openai` fallback because that string is too common in // unrelated third-party client names. return (bool) preg_match( '/\bchatgpt\b/i', $client_name ); } /** * ChatGPT-branded "How to connect" panel. Verified against * help.openai.com's Plugins + Developer Mode docs (2026): the surface * ChatGPT surfaces custom MCP servers under is now called Plugins (the * old "Connectors" label was retired in July 2026), Developer Mode has * to be flipped on first, and the feature is limited to paid workspaces. * * @param string $mcp_url MCP endpoint URL. * @return array Spec for the shared panel renderer. */ protected function get_setup_spec( string $mcp_url ): array { $spec = array( 'name' => 'ChatGPT', 'lead' => __( 'ChatGPT lists custom MCP servers under Plugins once Developer Mode is on.', 'acrossai-mcp-manager' ), 'open_label' => __( 'Open ChatGPT settings', 'acrossai-mcp-manager' ), 'open_url' => 'https://chatgpt.com/', 'steps' => array( array( 'text' => __( 'In ChatGPT, open Settings > Plugins', 'acrossai-mcp-manager' ), 'note' => __( 'Custom MCP servers need Developer Mode on — enable it under Settings > Security and login. On Business and Enterprise an admin turns it on for the workspace first.', 'acrossai-mcp-manager' ), ), array( 'text' => __( 'Click Add, then choose Add custom MCP server', 'acrossai-mcp-manager' ) ), array( 'text' => __( 'Fill in Name', 'acrossai-mcp-manager' ), 'copy' => $this->get_connector_name(), 'note' => __( 'Anything works — the name is only so you recognise this server in your list. Icon and Description are optional.', 'acrossai-mcp-manager' ), ), array( 'text' => __( 'Leave Connection set to Server URL, not Tunnel, and paste the MCP endpoint URL', 'acrossai-mcp-manager' ), 'url' => true, ), array( 'text' => __( 'Set Authentication to OAuth and leave Advanced OAuth settings alone', 'acrossai-mcp-manager' ), 'note' => __( 'ChatGPT discovers the settings and registers itself — no client ID or secret to enter.', 'acrossai-mcp-manager' ), ), array( 'text' => __( 'Tick "I understand and want to continue", click Create as a plugin, then approve the consent screen', 'acrossai-mcp-manager' ), 'open' => true, ), ), 'plan' => __( 'Available on paid ChatGPT plans.', 'acrossai-mcp-manager' ), 'docs_url' => 'https://acrossai.co/docs/connect-chatgpt-troubleshooting/', ); return $spec; } /** * Override the shared card body so the ChatGPT "How to connect" panel * renders on the tab immediately, without requiring the operator to * click Generate first. * * @param array $server Server row. * @return void */ // F021 Phase 9 (2026-07-11): render_tab_section is now inherited from // AbstractConnectorProfile::render_default_card. The base plugin's shared // CSS + JS bundle (enqueued via Admin\Main::maybe_enqueue_ai_connectors_app) // handles all card layout, Generate/Regenerate buttons, and copy behavior. // This class is now pure metadata: get_slug + get_name + get_icon_url + // get_redirect_uri_whitelist + get_setup_instructions + get_consent_branding + // (F024) matches_dcr_client + get_mcp_url_setup_html. }