$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. // Same values the site publishes at /.well-known/oauth-authorization-server. // Rendered literally rather than named, because an operator filling in // console.x.ai has no other way to discover them — omitting them is // what left Business/Enterprise accounts stuck with credentials that // could not be used. $issuer = \AcrossAI_MCP_Manager\Includes\OAuth\DiscoveryController::issuer(); $authorize_url = $issuer . '/authorize'; $token_url = $issuer . '/token'; ob_start(); ?>

  1. ' . esc_html( $client_id ) . '' ); ?>
  2. ' . esc_html( $authorize_url ) . '' ); ?>
  3. ' . esc_html( $token_url ) . '' ); ?>
  4. mcp' ); ?>
  5. client_secret_post' ); ?>
__( 'Grok wants to connect to your site', 'acrossai-mcp-manager' ), 'subtitle' => __( 'This will let Grok 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 a * Grok / xAI-owned host. Prefer host-based matching over substring * name matching so short brand words don't false-positive against * unrelated clients ("xai" is a two-letter root that could appear in * random client names or paths). * * @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 — whole-word `grok` match. No `xai` fallback // since the two-letter root is too fragile. return (bool) preg_match( '/\bgrok\b/i', $client_name ); } /** * Grok-branded "How to connect" panel. Covers the two Grok surfaces * that accept a custom MCP server today — Grok on the web (grok.com) * and the Grok mobile / X app — and links to * acrossai.co/grok-connectors/ for the fuller walkthrough. Grok uses * Dynamic Client Registration, so no credentials need to be pasted. * * @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' => 'Grok', 'lead' => __( 'Grok reaches your site over OAuth. You approve once on a WordPress consent screen.', 'acrossai-mcp-manager' ), 'open_label' => __( 'Open Grok connectors', 'acrossai-mcp-manager' ), 'open_url' => 'https://grok.com/connectors', 'steps' => array( array( 'text' => __( 'In Grok, open Settings > Connectors', 'acrossai-mcp-manager' ) ), array( 'text' => __( 'Click New Connector, then choose Custom to open the "Custom Connector" dialog', '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 connector in your list. This one matches the site.', 'acrossai-mcp-manager' ), ), array( 'text' => __( 'Paste the MCP endpoint URL into Server URL', 'acrossai-mcp-manager' ), 'url' => true, ), array( 'text' => __( 'Click Add Connector, then Connect, and approve the consent screen', 'acrossai-mcp-manager' ), 'note' => __( 'There is nothing else to fill in — Grok registers itself and signs in through your browser.', 'acrossai-mcp-manager' ), 'open' => true, ), ), 'plan' => __( 'Availability depends on your xAI plan. On Business and Enterprise an admin adds the connector from the console.x.ai admin surface instead — that one is different: it does not register itself, so the OAuth credentials must be filled in by hand.', 'acrossai-mcp-manager' ), 'docs_url' => 'https://acrossai.co/docs/connect-grok-troubleshooting/', ); return $spec; } /** * Render the Grok "How to connect" panel below the standard card. * * @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. }