- emcp-page-building, emcp-content-ops, emcp-site-audit: EMCP Tools MCP workflows verified live (atomic/legacy interplay, apply-template overwrite risk, create-theme-template goes live immediately, false-positive malware pattern in scan-security, change ledger + rollback) - elementor-pro-widgets: 30+5 native Elementor Pro widgets (curated catalog) - elementskit-widgets / powerpack-widgets: 42 + 97 third-party widgets, widgetType extracted from plugin source (not guessed by convention) - plugin.json bumped 1.2.0 -> 1.3.0, keywords + description updated - commits pending wordpress skills already present as untracked files (emcp-tools, wordfence, wp-activity-log, seguranca-descomplicar, webp-express, wp-fastest-cache, wp-font-perf, wp-meteor, wp-activity-log, redis-object-cache, app-for-cloudflare) and pending edits (rank-math, wp-cli, wp-content-seo-gate)
562 lines
43 KiB
Markdown
562 lines
43 KiB
Markdown
---
|
||
name: emcp-tools
|
||
description: Auditoria e gestão de postura de segurança do EMCP Tools (extensão do WP MCP Adapter da Elementskit — expõe dados Elementor, widgets e ferramentas de operação como MCP tools para agentes de IA). Cobre inventário completo das ~162 abilities registadas por categoria (activas vs desligadas, verificado via wp_get_abilities()), os 9 módulos do plugin (prompts, brand-kits, templates, themer, redirects, agent-skills, cloud, image-optimization, svg-support) e o que cada um expõe, o mecanismo de deny-list incremental versionado (34 migrações), activação granular e segura de uma ferramenta individual (ex: só leitura Rank Math), avaliação de risco por categoria, e arquitectura de registo MCP multi-site. Usar quando "emcp tools", "emcp-tools", "mcp adapter wordpress", "ferramentas mcp elementor", "que tools o agente pode chamar", "activar tool emcp", "desligar tool mcp", "postura default-deny mcp", "agentes de ia no wordpress", "módulos emcp tools", "inventário completo mcp tools", "quantas tools estão activas".
|
||
---
|
||
|
||
# /emcp-tools — Auditoria e Postura de Segurança do EMCP Tools (MCP para Elementor/WP)
|
||
|
||
Plugin `emcp-tools` (Mian Shahzad Raza) — extensão do WP MCP Adapter que expõe
|
||
dados Elementor, widgets, page design tools e um conjunto amplo de
|
||
operações WordPress como **ferramentas MCP** chamáveis por agentes de IA.
|
||
Versão verificada `3.12.1`, instalado e activo em `emanuelalmeida.pt`,
|
||
`descomplicar.pt` (`public_html`) e `starter.descomplicar.pt`.
|
||
|
||
**Fonte:** `Hub/04-Stack/02.04-Sistemas/71.Seguranca/CONFIG-Plugins-Referencia.md`
|
||
§10 (EMCP Tools) + `BUNDLE-Excelencia-WP.md` + verificação SSH ao vivo nesta
|
||
sessão (16-08-2026) nos três sites do ecossistema.
|
||
|
||
---
|
||
|
||
## Arquitectura — como o agente chega às tools deste plugin
|
||
|
||
O plugin regista um servidor MCP próprio, `emcp-tools-server` (nome visível
|
||
"MCP Tools for Elementor Server"), lado a lado com outros servidores do
|
||
mesmo WP MCP Adapter (`elementskit-mcp-server`, `mcp-adapter-default-server`,
|
||
e nalguns sites `fluent-crm`). A ligação do agente ao site faz-se por SSH +
|
||
STDIO, uma entrada por site em `~/.omp/agent/mcp.json`:
|
||
|
||
```json
|
||
"emcp-emanuelalmeida": {
|
||
"type": "stdio",
|
||
"command": "ssh",
|
||
"args": ["-T", "-o", "BatchMode=yes", "server",
|
||
"sudo -u ealmeida /usr/local/bin/wp mcp-adapter serve --server=emcp-tools-server --user=ealmeida --path=/home/ealmeida/emanuelalmeida.pt"],
|
||
"timeout": 60000,
|
||
"enabled": true
|
||
}
|
||
```
|
||
|
||
**Três instâncias activas no ecossistema**, uma ligação MCP por site (cada
|
||
uma com o seu próprio `--path` e, portanto, a sua própria config
|
||
`emcp_tools_*` independente — **não presumir que a postura de um site se
|
||
aplica a outro**, ver §3):
|
||
|
||
| Ligação em `mcp.json` | Site | `--path` |
|
||
|---|---|---|
|
||
| `emcp-descomplicar` | descomplicar.pt | `/home/ealmeida/public_html` |
|
||
| `emcp-tools` | starter.descomplicar.pt | `/home/ealmeida/starter.descomplicar.pt` |
|
||
| `emcp-emanuelalmeida` | emanuelalmeida.pt | `/home/ealmeida/emanuelalmeida.pt` |
|
||
|
||
Comando nativo WP-CLI para inspecção do lado do servidor (sem passar pelo
|
||
protocolo MCP):
|
||
|
||
```bash
|
||
wp mcp-adapter list --path=$PATH --allow-root
|
||
wp mcp-adapter list --format=json --path=$PATH --allow-root
|
||
```
|
||
|
||
⚠️ **Achado desta sessão — a coluna `Tools` de `wp mcp-adapter list` NÃO é
|
||
um proxy fiável do nº de ferramentas realmente activas.** Verificado ao
|
||
vivo nos 3 sites (16-08-2026):
|
||
|
||
| Site | `emcp_tools_disabled_tools` (desligadas) | `wp mcp-adapter list` → coluna `Tools` do `emcp-tools-server` | Activas REAIS (`wp_get_abilities()`, §7) |
|
||
|---|---|---|---|
|
||
| descomplicar.pt | 78 | `3` | **165** (achado crítico — §8.2) |
|
||
| starter.descomplicar.pt | 131 | `3` | 114 |
|
||
| emanuelalmeida.pt | 131 | `115` | 115 |
|
||
|
||
Não há correlação directa (menos desligadas em `descomplicar.pt` devia
|
||
implicar mais activas, mas mostra o valor mais baixo). A contagem desta
|
||
coluna parece depender de estado de registo/cache do lado do WP-CLI, não do
|
||
filtro `emcp_tools_disabled_tools` aplicado em tempo de pedido MCP. **Não
|
||
usar esta coluna para avaliar postura de segurança** — usar sempre o
|
||
conteúdo real de `emcp_tools_disabled_tools` (§2) para saber o que está
|
||
fechado, e o protocolo MCP (`tools/list` via um cliente MCP ligado, ex. a
|
||
própria sessão do agente) para saber com exactidão o que está disponível
|
||
para chamada num momento dado. A 4ª coluna acima é a contagem definitiva,
|
||
obtida com o método de §7 (`wp eval` + `wp_get_abilities()` filtrado, cruzado
|
||
slug-a-slug contra `emcp_tools_disabled_tools`) — coincide exactamente com a
|
||
coluna `Tools` só em `emanuelalmeida.pt`; nos outros dois sites a coluna do
|
||
WP-CLI é enganadora nos dois sentidos (mostra `3` quando o real é 114 **e**
|
||
165).
|
||
|
||
---
|
||
|
||
## 1. Config verificada (`emanuelalmeida.pt`, `wp_options`)
|
||
|
||
```bash
|
||
wp option list --search='emcp_tools*' --path=$PATH --allow-root
|
||
```
|
||
|
||
| Opção | Valor real | Nota |
|
||
|---|---|---|
|
||
| `emcp_tools_sandbox_location` | `emcp-sandbox` | Directório isolado para operações de sandbox |
|
||
| `emcp_tools_active_modules` | `["prompts","brand-kits","templates","themer","redirects","agent-skills","cloud"]` (7 de 9 semeados) | `image-optimization` e `svg-support` estão **semeados mas não activos** — idêntico nos 3 sites verificados |
|
||
| `emcp_tools_disabled_tools` | array indexado com **131** ferramentas desligadas (formato `emcp-tools/<nome-tool>`) | Ver lista completa §2 |
|
||
| `emcp_tools_defaults_applied` | `34` | Contador interno de defaults aplicados na instalação |
|
||
| `emcp_tools_modules_seeded` / `emcp_tools_legacy_meta_migrated` / `emcp_tools_slug_namespace_migrated` | flags internas de migração | Sem acção |
|
||
| `emcp_tools_changelog_db_version` / `emcp_tools_oauth_db_version` / `emcp_tools_redirects_db_version` / `emcp_tools_search_index_db_version` | versões de schema interno | Sem acção |
|
||
| `emcp_tools_themer_index` / `emcp_tools_themer_index_healed` | índice interno do módulo Themer | Sem acção |
|
||
|
||
Outros dois sites (`descomplicar.pt`, `starter.descomplicar.pt`) partilham
|
||
o mesmo `emcp_tools_active_modules`; `starter.descomplicar.pt` partilha
|
||
exactamente os mesmos 131 nomes desligados que `emanuelalmeida.pt`;
|
||
`descomplicar.pt` tem apenas 78 desligados (config mais permissiva —
|
||
**verificar antes de assumir postura igual entre sites**). Note-se também
|
||
que `templates` e `agent-skills` são módulos **Pro** (`tier() === 'pro'`)
|
||
semeados como "activos" em todos os 3 sites por omissão do próprio plugin,
|
||
mas nenhum destes sites tem licença Pro (`emcp_tools_fs()->can_use_premium_code()
|
||
=== false`), logo `is_available()` devolve `false` e **nenhum dos dois
|
||
módulos corre de facto** — ver tabela completa dos 9 módulos em §6, e o
|
||
achado crítico específico de `descomplicar.pt` em §8.2 (78 desligados não
|
||
significa "mais permissivo apenas um pouco" — significa **zero** tools
|
||
nativas fechadas).
|
||
|
||
---
|
||
|
||
## 2. Lista completa das 131 ferramentas desligadas por omissão
|
||
|
||
Confirmada ao vivo (`emanuelalmeida.pt` e `starter.descomplicar.pt`,
|
||
formato idêntico): array indexado (não associativo) em
|
||
`emcp_tools_disabled_tools`, cada entrada `emcp-tools/<slug-da-tool>`.
|
||
|
||
```bash
|
||
wp option get emcp_tools_disabled_tools --format=json --path=$PATH --allow-root
|
||
```
|
||
|
||
### 2.1 Ficheiros, sistema e execução remota — risco máximo, nunca activar sem supervisão directa
|
||
```
|
||
write-file, edit-file, delete-file, run-wp-cli, dispatch-wp-cli,
|
||
get-wp-cli-job, list-wp-cli-jobs
|
||
```
|
||
|
||
### 2.2 Base de dados directa
|
||
```
|
||
insert-row, update-rows, delete-rows
|
||
```
|
||
|
||
### 2.3 Gestão de plugins e temas
|
||
```
|
||
install-plugin, activate-plugin, deactivate-plugin, update-plugin, delete-plugin,
|
||
install-theme, switch-theme, update-theme, delete-theme
|
||
```
|
||
|
||
### 2.4 Utilizadores
|
||
```
|
||
create-user, update-user
|
||
```
|
||
|
||
### 2.5 Redirecções e migração de site
|
||
```
|
||
create-redirect, update-redirect, delete-redirect,
|
||
migrate-site, sync-to-live, sync-content-item
|
||
```
|
||
|
||
### 2.6 Integrações de terceiros — leitura e escrita (granularidade por par read/write)
|
||
```
|
||
acf-write
|
||
woo-read, woo-write
|
||
metabox-write
|
||
essential-addons-read, premium-addons-read, uae-read, uae-write
|
||
cf7-write
|
||
wpforms-read, wpforms-write
|
||
gravityforms-read, gravityforms-write
|
||
fluentforms-read, fluentforms-write
|
||
ninjaforms-read, ninjaforms-write
|
||
formidable-read, formidable-write
|
||
metform-read, metform-write
|
||
sureforms-read, sureforms-write
|
||
forminator-read, forminator-write
|
||
```
|
||
|
||
### 2.7 SEO — TODOS os plugins, leitura E escrita fechadas (Rank Math dono único da superfície SEO neste bundle)
|
||
```
|
||
slimseo-write
|
||
yoast-read, yoast-write
|
||
rankmath-read, rankmath-write
|
||
aioseo-read, aioseo-write
|
||
seopress-read, seopress-write
|
||
seoframework-read, seoframework-write
|
||
surerank-read, surerank-write
|
||
```
|
||
|
||
### 2.8 Temas/frameworks de blocos
|
||
```
|
||
theme-write
|
||
astra-write
|
||
spectra-write
|
||
kadence-write, kadence-blocks-write
|
||
generatepress-read, generatepress-write
|
||
generateblocks-read, generateblocks-write
|
||
blocksy-blocks-read, blocksy-blocks-write, blocksy-extensions-read, blocksy-extensions-write
|
||
```
|
||
|
||
### 2.9 Elementor avançado (widgets Pro, templates de tema, popups, dynamic tags, CSS/classes globais)
|
||
```
|
||
add-pro-widget, create-elementor-theme-template, set-elementor-template-conditions,
|
||
list-dynamic-tags, set-dynamic-tag, create-popup, set-popup-settings,
|
||
delete-media, add-custom-css,
|
||
create-global-class, update-global-class, delete-global-class, reorder-global-classes
|
||
```
|
||
|
||
### 2.10 Snippets PHP — execução de código arbitrário, risco máximo absoluto
|
||
```
|
||
add-code-snippet, list-code-snippets,
|
||
validate-php-snippet, create-php-snippet, update-php-snippet, get-php-snippet,
|
||
list-php-snippets, delete-php-snippet
|
||
```
|
||
|
||
### 2.11 Memória do agente
|
||
```
|
||
recall, remember, save-session-summary
|
||
```
|
||
|
||
### 2.12 Templates PHP de tema
|
||
```
|
||
create-theme-php-template, list-theme-php-templates, get-theme-php-template,
|
||
update-theme-php-template, delete-theme-php-template
|
||
```
|
||
|
||
### 2.13 SEO/A11y automatizados (geração de conteúdo/schema/contraste)
|
||
```
|
||
audit-page-seo, extract-keywords-from-content, generate-meta-tags,
|
||
generate-schema-markup, set-social-image,
|
||
audit-page-a11y, fix-color-contrast, add-alt-text-from-context
|
||
```
|
||
|
||
### 2.14 Widgets e blocos custom (criação/edição/eliminação)
|
||
```
|
||
list-control-types, validate-widget-spec,
|
||
create-custom-widget, update-custom-widget, get-custom-widget, list-custom-widgets,
|
||
set-widget-status, delete-custom-widget,
|
||
list-block-control-types, validate-block-spec,
|
||
create-custom-block, update-custom-block, get-custom-block, list-custom-blocks,
|
||
set-block-status, delete-custom-block
|
||
```
|
||
|
||
---
|
||
|
||
## 3. Como listar ferramentas activas vs desligadas num site
|
||
|
||
```bash
|
||
PATH=/home/USER/SITE
|
||
|
||
# Quantas e quais estão desligadas
|
||
wp option get emcp_tools_disabled_tools --format=json --path=$PATH --allow-root
|
||
|
||
# Módulos activos (nível mais alto — prompts/brand-kits/templates/themer/redirects/agent-skills/cloud/image-optimization/svg-support)
|
||
wp option get emcp_tools_active_modules --format=json --path=$PATH --allow-root
|
||
|
||
# Servidores MCP registados neste site (não usar a coluna Tools como medida de activo — ver aviso acima)
|
||
wp mcp-adapter list --path=$PATH --allow-root
|
||
```
|
||
|
||
**Para saber com exactidão quais tools estão disponíveis para chamada num
|
||
dado momento** (a lista real, não a config): ligar via o protocolo MCP
|
||
(a própria ligação `emcp-*` em `mcp.json`) e pedir `tools/list` — a config
|
||
`emcp_tools_disabled_tools` é aplicada como filtro em tempo de pedido pelo
|
||
plugin, não é reflectida de forma fiável pelo WP-CLI.
|
||
|
||
---
|
||
|
||
## 4. Activar uma ferramenta específica com segurança (granularidade individual)
|
||
|
||
O array é **indexado** (não associativo), por isso `wp option patch` não
|
||
serve para remover/adicionar uma entrada isolada — usar `wp eval` com
|
||
`array_diff`/`array_values` para manter o array limpo e sem duplicados.
|
||
|
||
### Activar (remover do deny-list)
|
||
|
||
|
||
```bash
|
||
wp eval '
|
||
$tool = "emcp-tools/rankmath-read";
|
||
$disabled = get_option("emcp_tools_disabled_tools", []);
|
||
$before = count($disabled);
|
||
$disabled = array_values(array_diff($disabled, [$tool]));
|
||
update_option("emcp_tools_disabled_tools", $disabled);
|
||
printf("antes=%d depois=%d removida=%s\n", $before, count($disabled), $before !== count($disabled) ? "sim" : "nao (ja estava activa ou nome errado)");
|
||
' --allow-root --path=$PATH
|
||
```
|
||
|
||
**Exemplo do pedido típico — activar só leitura Rank Math sem abrir
|
||
escrita:** activar `emcp-tools/rankmath-read` e deixar
|
||
`emcp-tools/rankmath-write` no array (continua desligada). A granularidade
|
||
é sempre ao nível do slug individual — nunca existe um toggle "Rank Math
|
||
on/off" only por read/write, exactamente como aparece na lista §2.7.
|
||
|
||
### Reverter (voltar a fechar)
|
||
|
||
```bash
|
||
wp eval '
|
||
$tool = "emcp-tools/rankmath-read";
|
||
$disabled = get_option("emcp_tools_disabled_tools", []);
|
||
if (!in_array($tool, $disabled, true)) { $disabled[] = $tool; }
|
||
update_option("emcp_tools_disabled_tools", $disabled);
|
||
echo count($disabled) . " tools desligadas\n";
|
||
' --allow-root --path=$PATH
|
||
```
|
||
|
||
### Verificar sempre depois, de forma independente
|
||
|
||
```bash
|
||
wp option get emcp_tools_disabled_tools --format=json --path=$PATH --allow-root | grep -o 'rankmath-read' || echo "confirmado: activa (nao esta no deny-list)"
|
||
```
|
||
|
||
---
|
||
|
||
## 5. Avaliação de risco por categoria — o que activar e o que nunca activar sem supervisão
|
||
|
||
| Categoria | Postura recomendada | Justificação |
|
||
|---|---|---|
|
||
| Leitura de design Elementor (o que fica activo por omissão — não está no deny-list) | ✅ Seguro por omissão | Propósito central do plugin; só leitura/inspecção, sem mutação |
|
||
| SEO leitura isolada (ex.: só `rankmath-read`) | ✅ Seguro activar caso a caso | Não muta nada; útil para um agente auditar sem escrever — mas Rank Math continua a ser gerido preferencialmente via `/rank-math` (WP-CLI directo), não via MCP |
|
||
| SEO escrita (qualquer `*-write` de SEO) | 🔴 Nunca activar sem supervisão | Contorna o fluxo de auditoria/rollback do `/rank-math`; risco de meta/schema incoerente sem revisão humana |
|
||
| Redirecções/migração (`create-redirect`, `migrate-site`, `sync-to-live`) | 🔴 Nunca activar sem supervisão | Mutação estrutural com impacto em produção e SEO (redirects mal configurados = perda de ranking) |
|
||
| Gestão de plugins/temas (`install-plugin`, `activate-plugin`, …) | 🔴 Nunca activar sem supervisão | Um agente autónomo instalar/remover plugins é a superfície mais perigosa depois de execução de código |
|
||
| Snippets PHP (`create-php-snippet`, `validate-php-snippet`, `update-php-snippet`) | 🔴🔴 Nunca activar — risco máximo absoluto | **Execução de PHP arbitrário** persistido no site; equivalente a dar shell ao agente. Único candidato a "nunca, em circunstância nenhuma, sem revisão humana linha a linha antes de guardar" |
|
||
| Ficheiros/sistema (`write-file`, `edit-file`, `delete-file`, `run-wp-cli`, `dispatch-wp-cli`) | 🔴🔴 Nunca activar — risco máximo | Escrita directa no filesystem e execução WP-CLI arbitrária via MCP; contorna toda a auditoria de shell/SSH existente |
|
||
| Base de dados directa (`insert-row`, `update-rows`, `delete-rows`) | 🔴🔴 Nunca activar — risco máximo | SQL de escrita sem passar por validação da camada WP; risco de corrupção silenciosa |
|
||
| Widgets/blocos custom (`create-custom-widget`, `create-custom-block`, …) | 🟡 Só com supervisão activa | Cria código PHP/JS executado no frontend; menos grave que snippets PHP mas ainda superfície de execução |
|
||
| Utilizadores (`create-user`, `update-user`) | 🔴 Nunca activar sem supervisão | Escalada de privilégios / criação de contas fora do fluxo humano |
|
||
| Memória do agente (`recall`, `remember`, `save-session-summary`) | 🟡 Avaliar por site | Sem risco de segurança directo, mas cria estado persistente fora do controlo humano — activar só se o workflow do site precisar de continuidade entre sessões MCP |
|
||
| Integrações de terceiros — leitura (`woo-read`, `wpforms-read`, …) | 🟡 Seguro activar caso a caso, um a um | Só expõe dados existentes; activar apenas as integrações realmente instaladas no site, nunca em bloco |
|
||
| Integrações de terceiros — escrita (`woo-write`, `cf7-write`, …) | 🔴 Nunca activar sem supervisão | Mutação em dados de negócio (encomendas, submissões de formulário) sem revisão humana |
|
||
|
||
**Regra geral (revista após leitura completa do código-fonte, §6-§8):** a
|
||
**concepção** do plugin é default-deny bem desenhada — o deny-list incremental
|
||
descrito em §8.1 fecha metodicamente cada nova categoria de risco assim que é
|
||
lançada. Mas a **postura real, verificada ao vivo, NÃO é uniforme entre os 3
|
||
sites**: `emanuelalmeida.pt` e `starter.descomplicar.pt` reflectem essa
|
||
concepção (115/162 e 114/160 tools activas, respectivamente, com todas as
|
||
categorias 🔴/🔴🔴 de facto fechadas); `descomplicar.pt` diverge de forma
|
||
crítica — **165/165 tools registadas estão activas**, incluindo filesystem,
|
||
base de dados directa, WP-CLI, PHP snippets e gestão de plugins/utilizadores
|
||
(ver achado detalhado em §8.2). Qualquer activação deve ser: (1) ao nível de
|
||
uma única tool, nunca em bloco; (2) reversível e verificada de imediato (§4,
|
||
com o método correcto de §7/§8.3 — nunca por contagem de arrays); (3)
|
||
documentada aqui ou em nota do site, para não perder rasto de porque é que
|
||
uma excepção existe.
|
||
|
||
---
|
||
|
||
## 6. Módulos — os 9 blocos que a página *Modules* liga/desliga
|
||
|
||
Módulo ≠ ferramenta individual: é um interruptor de alto nível (`emcp_tools_active_modules`)
|
||
que liga/desliga uma funcionalidade inteira (CPT, hooks de front-end, tab de admin e, nalguns
|
||
casos, o próprio grupo de MCP tools). Cada módulo estende `EMCP_Tools_Module`
|
||
(`includes/modules/class-module.php`) e expõe `tier()` (`free`/`pro`), `default_active()`
|
||
(semeado uma única vez, via `EMCP_Tools_Modules_Registry::apply_defaults()`, marcador
|
||
`emcp_tools_modules_seeded`) e `is_available()` (gate adicional, ex. licença Pro).
|
||
**Um módulo `pro` pode estar "activo" no option e mesmo assim não fazer nada** — `is_available()`
|
||
exige `emcp_tools_fs()->can_use_premium_code()`; nos 3 sites verificados (build Free, sem licença),
|
||
`templates` e `agent-skills` estão semeados activos mas `is_available()` devolve `false`, logo não
|
||
correm.
|
||
|
||
| Módulo (`id`) | Tier | Activo por omissão | Disponível nesta sessão (build Free, sem licença) | O que liga quando activo+disponível |
|
||
|---|---|---|---|---|
|
||
| `prompts` | free | sim | sim | Mostra a tab de admin **Prompts** (blueprints de prompts prontos a usar para construir páginas; amostras grátis + biblioteca Pro). Não regista MCP tools — é só UI de admin (`register()` vazio). |
|
||
| `brand-kits` | free | sim | sim | Mostra a tab **Brand Kits** (kits de cor+tipografia de um clique; kits grátis + biblioteca Pro). Também só UI de admin, sem MCP tools próprias. |
|
||
| `cloud` | free | sim | sim | Arranca `EMCP_Tools_Cloud_Connect::init()` (fluxo OAuth de ligação à conta EMCP Cloud) e — só quando `EMCP_Tools_Cloud::is_connected()` for verdadeiro — regista as 7 ferramentas `cloud-*` (§5 tabela de categorias). Nos 3 sites: módulo activo mas nenhum ligado a uma conta Cloud, logo 0 tools `cloud-*` registadas. |
|
||
| `templates` | **pro** | sim (seeded) | **não** (sem licença) | Quando disponível: mostra a tab **Templates** (templates de página Elementor prontos a aplicar). Metadata-only (`register()` vazio) — vive na árvore free só como descrição, a lógica Pro real está fora deste build. |
|
||
| `themer` | free | sim | sim | O módulo mais substancial do bundle free: regista o CPT `EMCP_Tools_Themer_CPT`, o índice de condições, o controlador de render no front-end, a metabox de admin, blocos Gutenberg dinâmicos, widgets Elementor dinâmicos e templates PHP (Themer PHP, sub-toggle próprio). Desligar este módulo é kill-switch total — pára o CPT, o front-end takeover, a tab, **e** o registrador de abilities omite as 8 tools `*-theme-template*`/`*-template*` (§5). |
|
||
| `redirects` | free | sim | sim | Instala a tabela do Redirect Manager, liga o handler de 301/302 no front-end, o scan de links partidos e as sugestões de redirect ao apagar/renomear uma página. Desligar pára tudo isto **e** remove as 5 tools `*-redirect*`/`find-broken-links` do registo. |
|
||
| `agent-skills` | **pro** | sim (seeded) | **não** (sem licença) | Quando disponível: expõe `list-skills`/`get-skill` aos agentes ligados + injecta um catálogo `## Skills` (~900 tokens) no contexto de discovery. Metadata-only na árvore free. |
|
||
| `image-optimization` | free | **não** (opt-in) | depende (precisa de editor de imagem com suporte WebP) | Comprime uploads (`wp_generate_attachment_metadata`) e gera/serve WebP (rewriter de URL); regista `resize-media`. 5 opções próprias: `compress`, `webp`, `webp_serve`, `quality` (0-100, default 60), `max_dimension`, `keep_originals`. Um optimizador retomável trata a biblioteca já existente a partir do card do módulo. |
|
||
| `svg-support` | free | **não** (opt-in — superfície de segurança) | depende (precisa da lib `enshrined/svg-sanitize` bundled) | Permite upload de SVG (mime `svg`) para quem tiver a capability necessária, corrige `wp_check_filetype_and_ext()` para REST/sideload, e sanitiza cada SVG (fail-closed: um SVG que não possa ser limpo é rejeitado). Uma opção: `admin_only` (restringe upload a administradores). Nota: se o Elementor já permitir SVG (como normalmente acontece), este módulo é redundante excepto pela sanitização extra. |
|
||
|
||
---
|
||
|
||
## 7. Inventário verificado das ~162 abilities registadas (build Free, Elementor activo) — por categoria
|
||
|
||
**Correcção a uma hipótese de partida:** subtrair ingenuamente 162 − 131 = "~31 activas" está
|
||
**errado** — 84 dos 131 slugs em `emcp_tools_disabled_tools` são nomes de ferramentas **Pro**
|
||
(WooCommerce, 6 SEO plugins além do Slim SEO, 5 dos 6 plugins de formulários, frameworks de
|
||
tema além do Astra, memória do agente, Themer PHP, SEO/A11y automático, Widget/Block Builder —
|
||
ver lista completa em §2) que **nunca chegam a registar-se** neste build Free — estão pré-semeados
|
||
no option para o dia em que o site tiver licença Pro, mas `wp_get_abilities()` não os devolve porque
|
||
as classes Pro não existem na árvore free. Contá-los como "desligados" infla artificialmente a
|
||
contagem de fechadas e desinfla a de activas.
|
||
|
||
**Método de verificação usada** (a única fonte fiável — ver aviso sobre `wp mcp-adapter list` no
|
||
topo deste documento):
|
||
|
||
```bash
|
||
wp eval '
|
||
$abilities = wp_get_abilities();
|
||
$emcp = array_filter(array_keys($abilities), function($k){ return strpos($k, "emcp-tools/") === 0; });
|
||
$disabled = get_option("emcp_tools_disabled_tools", []);
|
||
$active = array_diff($emcp, $disabled);
|
||
echo "registadas=" . count($emcp) . " desligadas(option)=" . count($disabled) . " activas=" . count($active) . "\n";
|
||
' --path=$PATH --allow-root
|
||
```
|
||
|
||
**Resultado real, verificado ao vivo (16-08-2026):**
|
||
|
||
| Site | Abilities `emcp-tools/*` registadas | Entradas em `emcp_tools_disabled_tools` | … das quais correspondem a uma ability REALMENTE registada | Activas (registada E não desligada) |
|
||
|---|---|---|---|---|
|
||
| `emanuelalmeida.pt` | 162 | 131 | 47 | **115** |
|
||
| `starter.descomplicar.pt` | 160 | 131 | ~46 | **114** |
|
||
| `descomplicar.pt` | 165 | 78 | **0** | **165** (ver achado crítico, §8) |
|
||
|
||
A tabela abaixo usa `emanuelalmeida.pt` (162 registadas) como referência — é o site com a
|
||
config mais representativa da postura default-deny pretendida pelo plugin (`starter` é quase
|
||
idêntico; `descomplicar.pt` diverge de forma crítica, ver §8). Por categoria: ferramentas
|
||
**ACTIVAS** (chamáveis agora), **DESLIGADAS** (bloqueadas pelo deny-list, mas registadas — activáveis
|
||
via §4), e, quando aplicável, ferramentas do grupo que **nem chegam a registar-se** neste site
|
||
(dependem de um plugin/tema de terceiros ausente).
|
||
|
||
| Categoria | O que faz | Activas | Desligadas |
|
||
|---|---|---|---|
|
||
| **Compact tool mode (dispatcher)** | `list-tools`/`get-tool-schema`/`call-tool` — o modo de despacho compacto (3 ferramentas que expõem indirectamente todas as outras); descrito na arquitectura do servidor MCP no início deste documento. | `call-tool`, `get-tool-schema`, `list-tools` | — |
|
||
| **Elementor — descoberta/query (P0)** | Fundação de leitura: percorre containers/elementos, resolve schemas de widget/container, lista páginas Elementor e templates disponíveis. | `find-element`, `get-container-schema`, `get-element-settings`, `get-page-structure`, `get-widget-schema`, `list-pages`, `list-templates`, `list-widgets` | — |
|
||
| **Elementor — páginas (P1 CRUD)** | Cria/edita páginas Elementor, exporta o conteúdo de uma página, importa um template para uma página, e ajusta page settings (SEO básico, layout). | `create-page`, `delete-page-content`, `export-page`, `import-template`, `update-page-settings` | — |
|
||
| **Elementor — layout/container** | Manipula a árvore de containers/flexbox/elementos: adicionar, mover, duplicar, remover, reordenar, actualizar propriedades, edição em lote (`batch-update`). | `add-container`, `batch-update`, `duplicate-element`, `move-element`, `remove-element`, `reorder-elements`, `set-element-label`, `update-container`, `update-element` | — |
|
||
| **Elementor — widgets clássicos (catálogo)** | Coloca widgets Elementor gratuitos no layout e actualiza as suas definições; `add-pro-widget` (Elementor Pro) fica desligado por omissão. | `add-free-widget`, `update-widget` | `add-pro-widget` |
|
||
| **Elementor — templates/popups/dynamic tags** | `apply-template`/`save-as-template` activos (aplicar/gravar templates de página); criação de theme templates, popups, dynamic tags e condições de exibição ficam desligados (mutação estrutural). | `apply-template`, `save-as-template` | `create-elementor-theme-template`, `create-popup`, `list-dynamic-tags`, `set-dynamic-tag`, `set-elementor-template-conditions`, `set-popup-settings` |
|
||
| **Elementor — configurações globais (cores/tipografia)** | Lê e actualiza o kit global (cores e tipografia do site) — `get-global-settings` está agrupado na categoria Query (P0) mas afecta as mesmas definições. | `get-global-settings`, `update-global-colors`, `update-global-typography` | — |
|
||
| **Elementor — build-page composto** | `build-page` — ferramenta de alto nível que constrói uma página inteira a partir de uma especificação estruturada (composição de containers+widgets num único pedido). | `build-page` | — |
|
||
| **Elementor — SVG icons** | `upload-svg-icon` — envia um SVG para a biblioteca de ícones Elementor (sanitizado). | `upload-svg-icon` | — |
|
||
| **Elementor — custom code (CSS/JS/snippets)** | `add-custom-js` activo (injecta JS Elementor); `add-custom-css`, `add-code-snippet` e `list-code-snippets` ficam desligados (execução/injecção persistente). | `add-custom-js` | `add-code-snippet`, `add-custom-css`, `list-code-snippets` |
|
||
| **Elementor 4.0+ — atomic widgets** | Widgets atómicos do Elementor 4.0+ (heading, paragraph, button, image, svg, youtube, video, divider) e o genérico `add-atomic-widget`/`update-atomic-widget` — todos activos. | `add-atomic-button`, `add-atomic-divider`, `add-atomic-heading`, `add-atomic-image`, `add-atomic-paragraph`, `add-atomic-svg`, `add-atomic-video`, `add-atomic-widget`, `add-atomic-youtube`, `update-atomic-widget` | — |
|
||
| **Elementor 4.0+ — atomic layout (flexbox/div-block)** | `add-div-block`, `add-flexbox` (containers atómicos) e `detect-elementor-version` (detecta se o site suporta Elementor 4.0+ atomic). | `add-div-block`, `add-flexbox`, `detect-elementor-version` | — |
|
||
| **Elementor 4.0+ — global classes (leitura)** | `list-global-classes` — lista as classes CSS globais do Elementor 4.0+. | `list-global-classes` | — |
|
||
| **Elementor 4.0+ — global classes (escrita)** | Criar/actualizar/eliminar/reordenar classes globais — todas desligadas por omissão (mutação de CSS partilhado entre todas as páginas). | — | `create-global-class`, `delete-global-class`, `reorder-global-classes`, `update-global-class` |
|
||
| **Gutenberg (blocos nativos)** | Conjunto completo de leitura+escrita para blocos Gutenberg nativos (descoberta de blocos/patterns, inserir pattern, CRUD de blocos numa página) — todo activo por omissão (Gutenberg é considerado superfície de baixo risco face ao Elementor neste bundle). | `add-block`, `duplicate-block`, `get-block-schema`, `get-post-blocks`, `insert-pattern`, `list-blocks`, `list-patterns`, `move-block`, `remove-block`, `update-block` | — |
|
||
| **Page Snapshot** | `get-page-snapshot` — digest normalizado de uma página (base para outras ferramentas de leitura); sempre activo. | `get-page-snapshot` | — |
|
||
| **Transações/rollback (change ledger)** | `get-change`/`list-changes`/`rollback-change` — ledger de alterações feitas via MCP com possibilidade de reverter; sempre activo (é a rede de segurança das escritas). | `get-change`, `list-changes`, `rollback-change` | — |
|
||
| **Pesquisa de conteúdo (índice léxico)** | `search-content`/`reindex-search` — índice léxico sobre páginas/templates/widgets/globals. | `reindex-search`, `search-content` | — |
|
||
| **Content mirror (export/restore git-friendly)** | `export-content`/`list-content-exports`/`restore-content` — exporta conteúdo de página como ficheiros rastreáveis em git e permite restaurar. | `export-content`, `list-content-exports`, `restore-content` | — |
|
||
| **WordPress — conteúdo (posts/CPT/taxonomias)** | CRUD completo de posts/CPT (criar, ler, listar, actualizar, eliminar), listar post types/taxonomias, definir termos — activo por omissão. | `create-post`, `delete-post`, `get-post`, `list-post-types`, `list-posts`, `list-taxonomies`, `set-post-terms`, `update-post` | — |
|
||
| **WordPress — media library** | Ler/listar/actualizar/carregar media activos; `delete-media` desligado (eliminação permanente). | `get-media`, `list-media`, `update-media`, `upload-media` | `delete-media` |
|
||
| **WordPress — resize de imagem** | `resize-media` só regista quando o módulo Image Optimization está activo (reutiliza o motor de compressão/WebP) — não registado nesta sessão porque o módulo está desligado por omissão. | *(nenhuma — grupo não registado: `resize-media`)* | *(n/a — ver nota)* |
|
||
| **WordPress — settings** | `get-settings`/`update-settings` — leitura e escrita de um conjunto curado de definições do site (não é `wp_options` livre). | `get-settings`, `update-settings` | — |
|
||
| **WordPress — plugins** | Listar/pesquisar plugins fica activo; instalar/activar/desactivar/actualizar/eliminar plugin ficam desligados (superfície de maior risco depois de execução de código). | `list-plugins`, `search-plugins` | `activate-plugin`, `deactivate-plugin`, `delete-plugin`, `install-plugin`, `update-plugin` |
|
||
| **WordPress — temas (gestão)** | Listar/pesquisar temas activo; instalar/mudar/actualizar/eliminar tema desligados. | `list-themes`, `search-themes` | `delete-theme`, `install-theme`, `switch-theme`, `update-theme` |
|
||
| **WordPress — utilizadores** | Ler/listar utilizadores activo; criar/actualizar utilizador desligados (escalada de privilégios). | `get-user`, `list-users` | `create-user`, `update-user` |
|
||
| **WordPress — menus de navegação** | `menu-read`/`menu-write` — ambos activos por omissão (menus, itens, theme locations, render). | `menu-read`, `menu-write` | — |
|
||
| **Tema activo (framework-agnostic)** | `theme-read` activo (`get-theme-context`, `get-mods` — identidade do tema, theme_mods); `theme-write` desligado (`set-mods`, `create-child-theme`). | `theme-read` | `theme-write` |
|
||
| **Astra (tema)** | Só regista quando o Astra é o tema activo. `astra-read` activo (definições Astra Customizer); `astra-write` desligado. | `astra-read` | `astra-write` |
|
||
| **ACF (Advanced Custom Fields)** | Dispatcher `acf-read`/`acf-write` + 15 operações (field groups, post types, taxonomias, options pages) — só regista se ACF (free ou Pro) estiver activo no site; não registado nesta sessão (ACF ausente). | *(nenhuma — grupo não registado: `acf-read`, `acf-write`, `create-acf-field-group`, `create-acf-post-type`, `create-acf-taxonomy`, `get-acf-field-group`, `get-acf-fields`, `get-acf-post-type`, `get-acf-taxonomy`, `list-acf-field-groups`, `list-acf-options-pages`, `list-acf-post-types`, `list-acf-taxonomies`, `update-acf-field-group`, `update-acf-fields`, `update-acf-post-type`, `update-acf-taxonomy`)* | *(n/a — ver nota)* |
|
||
| **Meta Box** | Dispatcher `metabox-read`/`metabox-write` — só regista se o Meta Box estiver activo; não registado nesta sessão. | *(nenhuma — grupo não registado: `metabox-read`, `metabox-write`)* | *(n/a — ver nota)* |
|
||
| **Themer (free) — templates de header/footer/single/archive** | CPT + condições de exibição para header/footer/single/archive/search/404 com qualquer page builder. Todo o grupo activo por omissão: listar/obter/criar/actualizar/eliminar template, listar alvos de condição, definir condições, resolver qual template se aplica a um contexto. | `create-theme-template`, `delete-theme-template`, `get-theme-template`, `list-condition-targets`, `list-theme-templates`, `resolve-template`, `set-template-conditions`, `update-theme-template` | — |
|
||
| **Themer PHP templates (toggle próprio)** | Sub-funcionalidade do Themer para templates PHP brutos, atrás de um toggle independente (`EMCP_Tools_Themer_PHP::enabled()`) — não activo nesta sessão, por isso as 5 tools não estão sequer registadas. | *(nenhuma — grupo não registado: `create-theme-php-template`, `delete-theme-php-template`, `get-theme-php-template`, `list-theme-php-templates`, `update-theme-php-template`)* | *(n/a — ver nota)* |
|
||
| **Redirect Manager** | `list-redirects`/`find-broken-links` activos (leitura + scan de links partidos); `create/update/delete-redirect` desligados (mutação de routing com impacto directo em SEO). | `find-broken-links`, `list-redirects` | `create-redirect`, `delete-redirect`, `update-redirect` |
|
||
| **Stock images (busca + sideload + widget)** | `search-images`/`sideload-image`/`add-stock-image` — pesquisa num provider de stock, descarrega para a Media Library, e coloca como widget de imagem; todo activo (não muta nada fora da Media Library). | `add-stock-image`, `search-images`, `sideload-image` | — |
|
||
| **Performance Analyzer** | `analyze-performance` — auditoria de performance só de leitura. | `analyze-performance` | — |
|
||
| **Security & Malware Scanner** | `scan-security` — scanner de malware/postura de segurança, só leitura, sempre activo. | `scan-security` | — |
|
||
| **Filesystem** | `list-directory`/`read-file`/`search-files` activos; `write-file`/`edit-file`/`delete-file` desligados (escrita directa no filesystem). | `list-directory`, `read-file`, `search-files` | `delete-file`, `edit-file`, `write-file` |
|
||
| **Base de dados directa** | `describe-table`/`list-tables`/`query` (SELECT) activos; `insert-row`/`update-rows`/`delete-rows` desligados (escrita SQL directa). | `describe-table`, `list-tables`, `query` | `delete-rows`, `insert-row`, `update-rows` |
|
||
| **WP-CLI (run + jobs)** | `run-wp-cli`/`dispatch-wp-cli`/`get-wp-cli-job`/`list-wp-cli-jobs` — todo o grupo desligado por omissão (execução arbitrária de comandos WP-CLI). | — | `dispatch-wp-cli`, `get-wp-cli-job`, `list-wp-cli-jobs`, `run-wp-cli` |
|
||
| **PHP Snippets (Sandbox)** | `validate/create/update/get/list/delete-php-snippet` — todo o grupo desligado por omissão (execução de PHP arbitrário persistido). | — | `create-php-snippet`, `delete-php-snippet`, `get-php-snippet`, `list-php-snippets`, `update-php-snippet`, `validate-php-snippet` |
|
||
| **Sandbox — export/import cloud (bundle)** | `export-sandbox-artifact`/`import-sandbox-artifact` — exporta/importa um artefacto de sandbox (bloco/widget/snippet) como bundle; ambos activos (o bundle em si não executa nada, é só serialização). | `export-sandbox-artifact`, `import-sandbox-artifact` | — |
|
||
| **EMCP Cloud (sync remoto)** | `cloud-status`/`cloud-backup`/`cloud-list`/`cloud-pull`/`cloud-config-sync`/`cloud-marketplace-list`/`cloud-marketplace-install` — só registam quando o módulo Cloud está activo E o site está ligado a uma conta EMCP Cloud; não registadas nesta sessão porque nenhum dos 3 sites está ligado a uma conta Cloud (ver módulo `cloud`, §6). | *(nenhuma — grupo não registado: `cloud-backup`, `cloud-config-sync`, `cloud-list`, `cloud-marketplace-install`, `cloud-marketplace-list`, `cloud-pull`, `cloud-status`)* | *(n/a — ver nota)* |
|
||
|
||
---
|
||
|
||
## 8. Mecanismo do deny-list incremental — e um achado crítico ao vivo em `descomplicar.pt`
|
||
|
||
### 8.1 Como o plugin decide o que fecha por omissão
|
||
|
||
O deny-list não é estático: `includes/admin/class-admin.php`, método
|
||
`maybe_apply_default_disabled_tools()` (chamado no boot do admin), aplica **34 blocos de migração
|
||
incremental** (`DEFAULTS_VERSION = 34`, contador `emcp_tools_defaults_applied`), cada um
|
||
introduzido numa versão do plugin para fechar uma nova categoria de tool assim que ela é lançada
|
||
— ex.: v6 fecha escrita de plugins/temas, v9 fecha filesystem, v10 fecha base de dados, v18 fecha
|
||
WP-CLI, v28 fecha escrita de global classes, v33-34 fecham as tools de migração/sync. A função só
|
||
adiciona slugs (nunca remove uma escolha do utilizador) e só corre os blocos cujo número é maior
|
||
que o `$applied` já gravado:
|
||
|
||
```php
|
||
if ( $applied < N ) { $add = array_merge( $add, /* slugs da versão N */ ); }
|
||
// ...
|
||
update_option( self::OPTION_DISABLED_TOOLS, array_values( array_unique( array_merge( $existing, $add ) ) ) );
|
||
update_option( self::OPTION_DEFAULTS_APPLIED, (string) self::DEFAULTS_VERSION );
|
||
```
|
||
|
||
Consequência arquitectural importante: **um site cujo `emcp_tools_defaults_applied` já esteja em
|
||
34 nunca mais recebe fecho automático de tools novas**, mesmo que o plugin lance uma v35 no
|
||
futuro — nesse cenário a nova categoria nasceria **activa** nesse site até alguém a fechar à mão. E
|
||
mais relevante ainda para o presente: se o valor de `emcp_tools_disabled_tools` for alterado
|
||
manualmente (via `wp eval`/`array_diff`, como o método §4 deste documento ensina, ou por qualquer
|
||
outro caminho) **removendo** entradas em massa, o contador de versão não volta atrás — o site fica
|
||
com um deny-list mais pequeno do que o "de fábrica" para essa versão, sem qualquer aviso.
|
||
|
||
### 8.2 🔴 Achado crítico verificado ao vivo (16-08-2026) — `descomplicar.pt`
|
||
|
||
Ao aplicar o método de verificação do §7 aos 3 sites, `descomplicar.pt` destacou-se: `active=165`
|
||
= `registered=165` — **zero ferramentas efectivamente fechadas**, apesar de
|
||
`emcp_tools_disabled_tools` ter 78 entradas. Inspeccionando essas 78 entradas
|
||
(`wp option get emcp_tools_disabled_tools --format=json --path=/home/ealmeida/public_html`):
|
||
são **exclusivamente** slugs de integrações de terceiros que não estão instaladas neste site
|
||
(WooCommerce, Essential/Premium Addons, UAE, os 6 plugins de formulários, os 7 plugins de SEO,
|
||
Astra/Spectra/Kadence/GeneratePress/Blocksy, `recall`/`remember`/`save-session-summary`, os 4
|
||
achados SEO/A11y automáticos, e os 16 slugs do Widget/Block Builder Pro) — **nenhuma** das
|
||
categorias nativas mais perigosas (filesystem, base de dados, WP-CLI, PHP snippets, gestão de
|
||
plugins/temas, gestão de utilizadores) aparece nessa lista. Confirmado directamente, ferramenta a
|
||
ferramenta:
|
||
|
||
| Tool | Registada em `descomplicar.pt`? | Está no deny-list? | **Chamável agora via MCP?** |
|
||
|---|---|---|---|
|
||
| `emcp-tools/write-file` | sim | não | **🔴 SIM** |
|
||
| `emcp-tools/edit-file` | sim | não | **🔴 SIM** |
|
||
| `emcp-tools/delete-file` | sim | não | **🔴 SIM** |
|
||
| `emcp-tools/run-wp-cli` | sim | não | **🔴 SIM** |
|
||
| `emcp-tools/dispatch-wp-cli` | sim | não | **🔴 SIM** |
|
||
| `emcp-tools/insert-row` | sim | não | **🔴 SIM** |
|
||
| `emcp-tools/update-rows` | sim | não | **🔴 SIM** |
|
||
| `emcp-tools/delete-rows` | sim | não | **🔴 SIM** |
|
||
| `emcp-tools/create-php-snippet` | sim | não | **🔴 SIM** |
|
||
| `emcp-tools/update-php-snippet` | sim | não | **🔴 SIM** |
|
||
| `emcp-tools/install-plugin` | sim | não | **🔴 SIM** |
|
||
| `emcp-tools/activate-plugin` | sim | não | **🔴 SIM** |
|
||
| `emcp-tools/create-user` | sim | não | **🔴 SIM** |
|
||
| `emcp-tools/update-user` | sim | não | **🔴 SIM** |
|
||
|
||
Todas as 34 versões de migração já correram (`emcp_tools_defaults_applied = 34`, igual aos outros
|
||
2 sites), o que exclui "instalação nunca migrada" como explicação — a hipótese mais provável, dado
|
||
o padrão exacto de remoção (sobrevivem só integrações de terceiros; desaparecem só as categorias
|
||
nativas de risco máximo/alto de §5), é que o array foi reescrito manualmente nalgum momento — por
|
||
exemplo com uma variante do próprio comando de §4 aplicada de forma demasiado ampla (ex.:
|
||
`array_diff` contra uma lista de slugs "de terceiros" em vez de um único slug) — sem que a
|
||
subtracção tenha sido revertida depois.
|
||
|
||
**Isto não foi corrigido nesta tarefa** (o âmbito desta expansão de skill é só leitura — ver
|
||
constraints). **Requer decisão humana urgente**: ou (a) confirmar que a abertura destas 14+ tools
|
||
nativas em `descomplicar.pt` foi intencional e está devidamente supervisionada, ou (b) alinhar
|
||
`descomplicar.pt` com o deny-list dos outros 2 sites, repondo pelo menos as categorias 🔴🔴 de §5
|
||
(filesystem, base de dados, WP-CLI, snippets PHP) com o padrão do método §4, aplicado entrada a
|
||
entrada.
|
||
|
||
### 8.3 Regra de verificação a aplicar sempre, daqui em diante
|
||
|
||
**Nunca confiar na contagem de entradas em `emcp_tools_disabled_tools` isoladamente** — nem para
|
||
avaliar "quão fechado" está um site (v. `descomplicar.pt`, 78 entradas e 0 tools realmente
|
||
fechadas), nem para o inverso (a lista de 131 em `emanuelalmeida.pt`/`starter` também tem 84
|
||
entradas "mortas" que nunca vão fechar nada neste build). O único método correcto é o `wp eval` +
|
||
`wp_get_abilities()` do §7, comparado slug a slug contra `emcp_tools_disabled_tools` — nunca o
|
||
tamanho dos arrays, nunca a coluna `Tools` de `wp mcp-adapter list` (ver aviso na arquitectura, que
|
||
mostra `3` para `descomplicar.pt` quando o valor real é 165).
|
||
|
||
---
|
||
|
||
## Fonte
|
||
|
||
`Hub/04-Stack/02.04-Sistemas/71.Seguranca/CONFIG-Plugins-Referencia.md` §10
|
||
(EMCP Tools, mapeado 16-08-2026) + `BUNDLE-Excelencia-WP.md` (contexto do
|
||
bundle e registo dos 3 sites) + verificação SSH ao vivo nesta tarefa
|
||
(`wp option list/get`, `wp plugin get`, `wp mcp-adapter list`,
|
||
`~/.omp/agent/mcp.json`) em `descomplicar.pt`, `starter.descomplicar.pt` e
|
||
`emanuelalmeida.pt` **+ leitura completa do código-fonte do plugin
|
||
(build Free `emcp-tools` 3.12.1) em `emanuelalmeida.pt`**: todos os ficheiros
|
||
em `includes/abilities/` (46 classes de abilities + integrações
|
||
forms/seo), `includes/modules/` (9 módulos + sub-módulos Image Optimization
|
||
e SVG Support), `includes/admin/class-admin.php` (catálogo de tools,
|
||
`maybe_apply_default_disabled_tools()`, as 34 versões do deny-list
|
||
incremental), `includes/modules/class-modules-registry.php` +
|
||
`class-module.php` (ciclo de vida dos módulos), `includes/class-migration.php`
|
||
(migração `elementor-mcp` → `emcp-tools`), `emcp-tools.php` (bootstrap,
|
||
guarda Free⇄Pro) — e verificação ao vivo via `wp eval` + `wp_get_abilities()`
|
||
filtrado a `emcp-tools/*` cruzado slug-a-slug contra
|
||
`emcp_tools_disabled_tools`, nos 3 sites (método completo em §7).
|