diff --git a/scripts/patch-dynamic-tools-grid.php b/scripts/patch-dynamic-tools-grid.php new file mode 100644 index 0000000..9f96fdb --- /dev/null +++ b/scripts/patch-dynamic-tools-grid.php @@ -0,0 +1,104 @@ +tools));', + '}, array_filter($this->tools, function($t){ static $d=null; if($d===null)$d=(array)get_option(\'asktam_mcp_disabled_tools\',[]); return !in_array($t[\'name\'],$d,true); })));', + $r); + $r=str_replace( + "if (!isset(\$this->tools[\$name])) return null;\n \$h = \$this->tools[\$name]['handler'];", + "if (!isset(\$this->tools[\$name])) return null;\n { static \$d=null; if(\$d===null)\$d=(array)get_option('asktam_mcp_disabled_tools',[]); if(in_array(\$name,\$d,true)) return null; }\n \$h = \$this->tools[\$name]['handler'];", + $r); +} +if (strpos($r,'getAllToolsRaw')===false){ + $r=str_replace( + " public function getTool(string \$name): ?array {\n return \$this->tools[\$name] ?? null;\n }\n", + " public function getTool(string \$name): ?array {\n return \$this->tools[\$name] ?? null;\n }\n\n public function getAllToolsRaw(): array {\n return array_values(\$this->tools);\n }\n", + $r); +} +file_put_contents($reg,$r); +echo "REG disabled=".(strpos($r,'asktam_mcp_disabled_tools')!==false?1:0)." raw=".(strpos($r,'getAllToolsRaw')!==false?1:0)."\n"; + +/* ---------- AdminMenu.php: build the Tools grid from the live registry ---------- */ +$a=file_get_contents($adm); +if (strpos($a,'amp-dynamic-grid')===false){ + $start=strpos($a,'public function getAllToolsGrouped(): array {'); + $end=strpos($a,'public function getAllToolSlugs(): array {'); + if ($start!==false && $end!==false && $end>$start){ +$new = <<<'PHP' +public function getAllToolsGrouped(): array { /* amp-dynamic-grid */ + $registry = new \AskTamMCP\MCP\Registry(); + $cats = []; + foreach ($registry->getAllToolsRaw() as $t) { + $n = $t['name']; $scope = $t['scope'] ?? 'read'; $desc = $t['description'] ?? ''; + [$cid, $clabel] = $this->catFor($n); + $badges = [$scope]; + if (strpos($n, 'wc_') === 0) $badges[] = 'woocommerce'; + if (strpos($n, 'elementor') !== false) $badges[] = 'elementor'; + if (stripos($n, 'delete') !== false || stripos($n, 'remove') !== false || stripos($desc, 'permanently') !== false) $badges[] = 'destructive'; + if (!isset($cats[$cid])) $cats[$cid] = ['label' => $clabel, 'tools' => []]; + $cats[$cid]['tools'][$n] = ['label' => $this->prettyLabel($n), 'description' => $desc, 'badges' => array_values(array_unique($badges))]; + } + foreach ($cats as &$c) { ksort($c['tools']); } unset($c); + $order = ['posts','pages','media','blocks','taxonomy','users','options','plugins','themes','menus','comments','widgets','site','skills','seo','seo_yoast','seo_rm','seo_aio','seo_sp','woocommerce','elementor','woodmart','motion','memory','caching','cache_ls','cache_rocket','wpml','remote','a11y','file_manager','email','transients','cli','raw_sql','theme_discovery']; + $ordered = []; + foreach ($order as $cid) { if (isset($cats[$cid])) { $ordered[$cid] = $cats[$cid]; unset($cats[$cid]); } } + uasort($cats, fn($x, $y) => strcmp($x['label'], $y['label'])); + foreach ($cats as $cid => $c) { $ordered[$cid] = $c; } + return $ordered; + } + + private function prettyLabel(string $n): string { + return ucwords(str_replace('_', ' ', $n)); + } + + private function catFor(string $n): array { + $pref = [ + ['wc_','woocommerce','WooCommerce'],['elementor_','elementor','Elementor'],['woodmart_','woodmart','Woodmart'], + ['wordfence_','security','Security — Wordfence'],['litespeed_','cache_ls','Caching — LiteSpeed'],['rocket_','cache_rocket','Caching — WP Rocket'], + ['cache_','caching','Caching'],['motion_','motion','Motion & Animation'],['memory_','memory','Memory Store'],['wpml_','wpml','WPML'], + ['rankmath_','seo_rm','SEO — Rank Math'],['aioseo_','seo_aio','SEO — All in One SEO'],['seopress_','seo_sp','SEO — SEOPress'],['yoast_','seo_yoast','SEO — Yoast'],['seo_','seo','SEO'], + ['remote_','remote','Remote Data'],['a11y_','a11y','Accessibility'],['fs_','file_manager','File Manager'],['email_','email','Email'], + ['transient_','transients','Transients'],['widget_','widgets','Widget Areas'],['cli_','cli','WP-CLI'],['sql_','raw_sql','Raw SQL'],['theme_','theme_discovery','Theme Discovery'], + ['pexels_','media','Media'],['gf_','forms_gravity','Forms — Gravity Forms'],['fluentform_','forms_fluent','Forms — Fluent Forms'],['nf_','forms_ninja','Forms — Ninja Forms'], + ['frm_','forms_formidable','Forms — Formidable'],['forminator_','forms_forminator','Forms — Forminator'],['metform_','forms_metform','Forms — MetForm'],['sureforms_','forms_sureforms','Forms — SureForms'],['cf7_','forms_cf7','Forms — Contact Form 7'], + ['mc4wp_','mc4wp','Mailchimp for WP'],['fluentcrm_','crm_fluent','CRM — FluentCRM'],['mailpoet_','email_mailpoet','Email — MailPoet'],['funnelkit_','funnelkit','Funnels — FunnelKit'], + ['tutor_','lms_tutor','LMS — Tutor'],['llms_','lms_lifter','LMS — LifterLMS'],['tec_','events_tec','Events — The Events Calendar'],['amelia_','booking_amelia','Booking — Amelia'], + ['polylang_','tr_polylang','Translation — Polylang'],['trp_','tr_translatepress','Translation — TranslatePress'],['tablepress_','tablepress','Tables — TablePress'],['acf_','acf','Custom Fields — ACF'], + ['divi_','builder_divi','Builder — Divi'],['bricks_','builder_bricks','Builder — Bricks'],['oxygen_','builder_oxygen','Builder — Oxygen'],['bb_','builder_beaver','Builder — Beaver Builder'], + ['breakdance_','builder_breakdance','Builder — Breakdance'],['thrive_','builder_thrive','Builder — Thrive'],['vcv_','builder_vc','Builder — Visual Composer'],['wpbakery_','builder_wpbakery','Builder — WPBakery'], + ['generateblocks_','generateblocks','GenerateBlocks'],['blocksy_','blocksy','Blocksy'],['kirki_','kirki','Kirki'],['otter_','otter','Otter Blocks'],['moyasar_','moyasar','Payments — Moyasar'], + ['list_block_types','blocks','Blocks'],['insert_blocks','blocks','Blocks'],['create_reusable_block','blocks','Blocks'],['list_reusable_blocks','blocks','Blocks'],['render_shortcode','blocks','Blocks'], + ['export_elementor_page','elementor','Elementor'],['import_elementor_page','elementor','Elementor'],['export_global_styles','elementor','Elementor'],['import_global_styles','elementor','Elementor'],['duplicate_elementor_page','elementor','Elementor'], + ['get_skill','skills','Skills'],['list_skills','skills','Skills'],['get_page_context','skills','Skills'], + ['set_image_alt','media','Media'],['bulk_set_alt_from_title','media','Media'],['list_large_images','media','Media'],['duplicate_title_finder','media','Media'],['generate_gpt_image','media','Media'],['generate_gemini_image','media','Media'],['ai_media_status','media','Media'], + ['extract_page_text','site','Site'],['find_broken_internal_links','site','Site'], + ]; + foreach ($pref as $p) { if (strpos($n, $p[0]) === 0) return [$p[1], $p[2]]; } + $kw = [ + ['media','media','Media'],['post','posts','Posts'],['page','pages','Pages'],['user','users','Users'], + ['categor','taxonomy','Taxonomy & Terms'],['taxonom','taxonomy','Taxonomy & Terms'],['term','taxonomy','Taxonomy & Terms'],['tag','taxonomy','Taxonomy & Terms'], + ['option','options','Options'],['plugin','plugins','Plugins'],['theme','themes','Themes'],['menu','menus','Menus'],['comment','comments','Comments'], + ['cron','site','Site'],['health','site','Site'],['permalink','site','Site'],['search_content','site','Site'],['site_info','site','Site'],['custom_css','site','Site'],['get_option','options','Options'], + ]; + foreach ($kw as $k) { if (strpos($n, $k[0]) !== false) return [$k[1], $k[2]]; } + return ['other', 'Other Tools']; + } + + +PHP; + $a = substr($a,0,$start) . $new . substr($a,$end); + file_put_contents($adm,$a); + } +} +echo "ADM dynamic=".(strpos($a,'amp-dynamic-grid')!==false?1:0)."\n";