PluginProbe
Fluent Support – Helpdesk & Customer Support Ticket System / 2.4.5
Fluent Support – Helpdesk & Customer Support Ticket System v2.4.5
2.4.5 2.4.0 2.3.2 2.3.1 2.3.0 2.2.1 2.2.0 trunk 1.10.0 1.10.1 1.10.2 1.10.3 1.10.4 1.10.5 1.4.0 1.4.1 1.4.2 1.4.5 1.4.6 1.4.7 1.5.0 1.5.1 1.5.2 1.5.3 1.5.4 All 69 releases
← All changes | app/Http/Controllers/McpSettingsController.php +31 -38 2.3.0 → 2.4.5 View file →
@@ -6,13 +6,10 @@
6 6 use FluentSupport\App\Modules\MCP\Support\PermissionGate;
7 7 use FluentSupport\Framework\Http\Request\Request;
8 8
9 9 /**
10 - * Backend for the Settings → MCP for AI Agents page.
11 - *
12 - * Covers: enable/disable toggle, one-click FluentHub install, and per-client
13 - * connection snippets. SLA and AI guidelines are intentionally not exposed here —
14 - * they are tool-layer concerns read by PermissionGate and live in _mcp_settings.
10 + * Settings → MCP for AI Agents: enable toggle, FluentHub install, client snippets.
11 + * SLA and AI guidelines live in _mcp_settings and are read by PermissionGate, not here.
15 12 */
16 13 class McpSettingsController extends Controller
17 14 {
18 15 const TOOLKIT_PLUGIN_FILE = 'fluent-toolkit/fluent-toolkit.php';
@@ -18,10 +15,9 @@
18 15 const TOOLKIT_PLUGIN_FILE = 'fluent-toolkit/fluent-toolkit.php';
19 16 const TOOLKIT_DOWNLOAD_URL = 'https://github.com/WPManageNinja/fluent-toolkit';
20 17
21 18 /**
22 - * GET fluent-support/v2/settings/mcp
23 - * Returns all data the settings page needs in one request.
19 + * GET settings/mcp. Everything the settings page needs.
24 20 */
25 21 public function getStatus(Request $request)
26 22 {
27 23 $user = wp_get_current_user();
@@ -43,10 +39,9 @@
43 39 ];
44 40 }
45 41
46 42 /**
47 - * POST fluent-support/v2/settings/mcp/toggle
48 - * Body: { mcp_enabled: true|'yes'|1|'on' }
43 + * POST settings/mcp/toggle with mcp_enabled: true|'yes'|1|'on'.
49 44 */
50 45 public function toggle(Request $request)
51 46 {
52 47 if (!current_user_can('manage_options')) {
@@ -62,9 +57,9 @@
62 57 : (bool) $value;
63 58
64 59 PermissionGate::setEnabled($enabled);
65 60
66 - // Re-read the persisted state so the UI can never show "enabled" for a write that didn't land.
61 + // Re-read so the UI never shows a state that failed to save.
67 62 $stored = PermissionGate::isEnabled();
68 63
69 64 return [
70 65 'mcp_enabled' => $stored,
@@ -74,11 +69,10 @@
74 69 ];
75 70 }
76 71
77 72 /**
78 - * POST fluent-support/v2/settings/mcp/install-adapter
79 - * One-click FluentHub install. Requires a Fluent Pro plugin to hook
80 - * fluent_toolkit/can_auto_install + fluent_toolkit/do_auto_install.
73 + * POST settings/mcp/install-adapter. Needs a Fluent Pro plugin hooked into
74 + * fluent_toolkit/can_auto_install and fluent_toolkit/do_auto_install.
81 75 */
82 76 public function installAdapter(Request $request)
83 77 {
84 78 if (!current_user_can('install_plugins')) {
@@ -94,11 +88,29 @@
94 88 'toolkit_download_url' => self::TOOLKIT_DOWNLOAD_URL,
95 89 ]);
96 90 }
97 91
92 + // The installer reports why it failed through this action.
93 + $failure = null;
94 + $onFailure = function ($error) use (&$failure) {
95 + $failure = $error;
96 + };
97 + add_action('fluent_toolkit/auto_install_failed', $onFailure);
98 +
98 99 do_action('fluent_toolkit/do_auto_install');
100 +
101 + remove_action('fluent_toolkit/auto_install_failed', $onFailure);
99 102 wp_clean_plugins_cache();
100 103
104 + if (!$this->isToolkitPresent()) {
105 + $reason = is_wp_error($failure) ? $failure->get_error_message() : '';
106 +
107 + return $this->sendError([
108 + 'message' => trim(__('FluentHub could not be installed automatically.', 'fluent-support') . ' ' . $reason . ' ' . __('Install it manually, then reload this page.', 'fluent-support')),
109 + 'toolkit_download_url' => self::TOOLKIT_DOWNLOAD_URL,
110 + ]);
111 + }
112 +
101 113 $adapterAvailable = MCPInit::adapterAvailable();
102 114
103 115 return $this->sendSuccess([
104 116 'adapter_available' => $adapterAvailable,
@@ -104,15 +116,16 @@
104 116 'adapter_available' => $adapterAvailable,
105 117 'toolkit_installed' => $this->isToolkitPresent(),
106 118 'message' => $adapterAvailable
107 119 ? __('FluentHub installed and activated. The MCP endpoint is ready.', 'fluent-support')
108 - : __('FluentHub was installed. Please reload this page to finish connecting the MCP endpoint.', 'fluent-support'),
120 + : (is_wp_error($failure)
121 + ? $failure->get_error_message()
122 + : __('FluentHub was installed. Please reload this page to finish connecting the MCP endpoint.', 'fluent-support')),
109 123 ]);
110 124 }
111 125
112 126 /**
113 - * GET fluent-support/v2/settings/mcp/config-snippets
114 - * Query param: local_dev=yes|no (falls back to auto-detected isLocalDev when omitted)
127 + * GET settings/mcp/config-snippets. local_dev=yes|no overrides isLocalDev().
115 128 */
116 129 public function getConfigSnippets(Request $request)
117 130 {
118 131 $endpoint = MCPInit::getEndpointUrl();
@@ -220,25 +233,18 @@
220 233 ];
221 234 }
222 235 }
223 236
224 - // -------------------------------------------------------------------------
225 - // Toolkit detection helpers — mirrors FluentCRM MCPSettingsController
226 - // -------------------------------------------------------------------------
227 -
228 - /** True when FluentHub is loaded in the current request (constant defined). */
229 237 private function isToolkitLoaded()
230 238 {
231 239 return defined('FLUENT_TOOLKIT_VERSION');
232 240 }
233 241
234 - /** True when FluentHub is loaded OR present in the plugin directory. */
235 242 private function isToolkitPresent()
236 243 {
237 244 return $this->isToolkitLoaded() || $this->isPluginPresent(self::TOOLKIT_PLUGIN_FILE);
238 245 }
239 246
240 - /** Version string from the loaded constant, or from the plugin header, or null. */
241 247 private function detectToolkitVersion()
242 248 {
243 249 if ($this->isToolkitLoaded()) {
244 250 return (string) FLUENT_TOOLKIT_VERSION;
@@ -266,24 +272,11 @@
266 272
267 273 return $plugins[$pluginFile]['Version'] ?? null;
268 274 }
269 275
270 - // -------------------------------------------------------------------------
271 - // Local-dev detection
272 - // -------------------------------------------------------------------------
273 -
274 276 /**
275 - * Heuristic: are we on a local/dev install?
276 - *
277 - * Checks (in order):
278 - * 1. Hostname ends in a dev TLD (.test, .local, .localhost, .lab, .docker)
279 - * 2. Hostname is a loopback literal (localhost, 127.0.0.1, ::1)
280 - * 3. Hostname is a private RFC 1918 IP address
281 - *
282 - * Note: .dev is intentionally excluded — it is a real HSTS-preloaded
283 - * public gTLD (owned by Google) and we must not disable TLS on those sites.
284 - *
285 - * Filterable via fluent_support/mcp_is_local_dev for edge cases.
277 + * Dev TLD, loopback host, or private/reserved IP. The snippet disables TLS
278 + * checks on local installs, so .dev is excluded: it's a real public gTLD.
286 279 */
287 280 private function isLocalDev()
288 281 {
289 282 $host = strtolower((string) wp_parse_url(home_url(), PHP_URL_HOST));