feat(wordpress): v2.0.0 adiciona skills mcp-loco-translate, mcp-ifthenpay, mcp-google-site-kit, mcp-complianz, mcp-tablepress

This commit is contained in:
2026-08-19 08:30:10 +01:00
parent 7035eae927
commit 4e33c1d697
277 changed files with 2022 additions and 227 deletions
+29 -123
View File
@@ -1,136 +1,42 @@
---
name: mcp-complianz
description: MCP dedicado (node stdio, ligação `complianz` em ~/.omp/agent/mcp.json) para gerir o Complianz GDPR/CMP (Cookie Consent Management) via WP-CLI/SSH — estado/versão, jurisdição e modo de consentimento (opt-in/opt-out por região), configuração principal (`cmplz_options`), banners de cookies (listar/ler/editar texto), cookies e serviços de terceiros detectados pelo scanner. NUNCA expõe pedidos DSAR (PII de titulares de dados). Usar quando "complianz", "cookie consent", "banner de cookies", "GDPR wordpress", "cmplz_options", "cookiebanner", "consenttype opt-in opt-out", "cookie scanner wordpress", "cmplz_dnsmpd".
layer: wiki
description: MCP dedicado ao Complianz GDPR para auditoria e gestão de cookies, consentimento, banner e serviços de terceiros na frota CWP
version: 1.0.0
author: Descomplicar®
---
# /mcp-complianz — MCP dedicado ao Complianz GDPR/CMP
# MCP Complianz GDPR (`mcp-complianz`)
Projecto em `/media/ealmeida/Dados/Dev/mcp-complianz/` (TypeScript, SDK MCP oficial, stdio). Sem
código PHP novo no WordPress — cada tool corre um snippet PHP ESTÁTICO (nunca interpolado com
dados externos) via `wp eval` sobre o WP-CLI já instalado em `server.descomplicar.pt`. Todo o
input/output variável viaja em JSON dentro de um envelope base64 por stdin/stdout — nunca
interpolado na linha de comando remota nem no código-fonte PHP.
> Servidor MCP StreamableHTTP (porta 3208) para auditoria e gestão de privacidade, consentimento de cookies e políticas legais (**Complianz GDPR** v7.5+) nos sites da frota WordPress no CWP.
Não há skill de conhecimento separada para o Complianz — esta skill é a única documentação,
incluindo o mapeamento completo de armazenamento (abaixo).
---
## Âmbito
## 1. Ferramentas Disponíveis
Ler o estado/jurisdição/modo de consentimento, ler e actualizar a configuração principal
(`cmplz_options`), ler e listar banners de cookies (e editar texto/copy), listar cookies e
serviços de terceiros detectados pelo scanner. **Fora do âmbito, deliberadamente**: qualquer
registo individual de consentimento de visitante (a tabela `cmplz_dnsmpd` guarda pedidos DSAR com
nome/email reais de titulares de dados — PII genuína, excluída estruturalmente, nenhum tool deste
MCP a toca, nem sequer agregada); apagar/criar banners; editar cores/CSS/flags do banner (só
texto/copy); scan activo de novos cookies (o Complianz corre isto via cron/admin, não há WP-CLI
para o disparar).
## Sites conhecidos
Confirmado por `wp plugin list` nos 8 sites reais do bundle (19-08-2026): **só
`starter.descomplicar.pt` (staging, v7.5.2) e `ccv.descomplicar.pt` (v7.5.3.1) têm o Complianz GDPR
activo**. Os outros 6 não o têm:
- `descomplicar.pt` (produção): Complianz GDPR **NÃO instalado** — tem `real-cookie-banner`
(inactive) e `wp-consent-api` (inactive), nenhum CMP activo neste site.
- `emanuelalmeida.pt`: Complianz GDPR não instalado — tem `cookie-notice` (plugin distinto,
inactive).
- `care.descomplicar.pt`, `ecommerce-demo.descomplicar.pt`, `ecommerce.descomplicar.pt`: nenhum
plugin de cookies/GDPR detectado.
- `e-commerce.descomplicar.pt`: Complianz GDPR não instalado — tem `cookie-notice` (plugin
distinto) ACTIVE.
`complianz_list_sites` devolve a lista completa com notas por site; qualquer tool aceita também um
path absoluto directo para uma instalação futura noutro site. Todos os tools de leitura/escrita
lidam com sites sem Complianz de forma graciosa (`complianz_get_jurisdiction` devolve
`{"active": false}`; tools de tabela custom devolvem erro claro "tabela ausente" em vez de crash).
## Mapeamento de armazenamento (confirmado por leitura do código-fonte e da base de dados)
| Onde | O quê | Formato | Gotcha |
|---|---|---|---|
| Option `cmplz_options` (wp_options) | Config principal: jurisdição (`regions`, `other_region_behaviour`), modo de consentimento (`consent-mode`), `records_of_consent`, `datarequest`, `respect_dnt`, `cookie_banner_required`, `enable_cookie_banner`, `region_redirect`, integrações de estatísticas (GA4/GTM/Matomo — só IDs de tracking públicos, sem chaves privadas), textos legais (`cookie-statement`, `privacy-statement`) | **Array PHP nativo** (confirmado: `wp option get cmplz_options` sem `--format` devolve `array(...)` var_export-style, `--format=json` produz JSON limpo sem dupla codificação) | Lido/escrito via `get_option()`/`update_option()` no lado PHP (não `wp option get/update --format=json` directo) para disparar os hooks nativos do plugin (`update_option_cmplz_options`) |
| Tabela custom `{$wpdb->prefix}cmplz_cookiebanners` | 1 linha por banner (normalmente 1, "Banner A"). ~53 colunas: texto/copy, cores (`colorpalette_*`), flags inteiras, `custom_css` | Colunas `text` com **serialização PHP nativa** (não JSON) — cada campo é OU uma string simples (`title`, `accept`, `message_optin`, `category_functional`, `save_preferences`, `view_preferences`) OU um array serializado `{text, show}` (`header`, `dismiss`, `category_stats`/`category_all`/`category_prefs`, `functional_text`, `statistics_text`, `statistics_text_anonymous`, `preferences_text`, `marketing_text`) OU cores/settings estruturados (`colorpalette_*`) | Ler/escrever via `maybe_unserialize()`/`maybe_serialize()` por campo — a forma (string vs array) varia por campo, confirmado empiricamente por leitura directa dos dados em produção/staging |
| Tabela custom `{$wpdb->prefix}cmplz_cookies` | Cookies/scripts detectados pelo cookie scanner: nome, slug, tipo, retenção, domínio, função/propósito, idioma, `ignored`/`showOnPolicy`/`deleted` | Colunas simples (int/text), sem serialização | Metadados técnicos do próprio site — **sem PII de visitantes** |
| Tabela custom `{$wpdb->prefix}cmplz_services` | Serviços de terceiros detectados: nome, tipo, categoria, `thirdParty`/`sharesData` | Colunas simples | Sem PII |
| Tabela custom `{$wpdb->prefix}cmplz_dnsmpd` | Pedidos DSAR ("Do Not Sell My Personal Data" / direito ao esquecimento / acesso) — colunas `name`, `email`, `region` de **pessoas reais** que submeteram um pedido GDPR | Colunas simples | **PII genuína — EXCLUÍDA estruturalmente de qualquer tool deste MCP**, mesmo agregada. 0 registos confirmados em ambos os sites testados (19-08-2026), mas a exclusão não depende disso |
Não existe comando WP-CLI custom (`wp help complianz`/`wp help cmplz` confirmam "not a registered
command" na v7.5.x) — todo o acesso é via `wp eval`.
O modo de consentimento (opt-in vs opt-out) **não** é uma chave directa em `cmplz_options` — é
computado em runtime por `cmplz_get_consenttype_for_region($regiao)` a partir da(s) região(ões)
configurada(s) em `regions`. `complianz_get_jurisdiction` chama esta função real do plugin (não
reimplementa a lógica), garantindo que o valor devolvido é exactamente o que o plugin usa para
decidir se o banner bloqueia scripts até aceitação.
## Tools (10)
| Tool | Read-only | Uso |
| Ferramenta | Descrição | Parâmetros |
|---|---|---|
| `complianz_list_sites` | sim | Aliases conhecidos, path WP, nota de estado do Complianz por site |
| `complianz_get_status` | sim | `wp plugin list` filtrado ao complianz-gdpr — instalado/activo/versão/update pendente |
| `complianz_get_jurisdiction` | sim | Regiões configuradas, `consenttype` computado por região (opt-in/opt-out real), flags de política (`records_of_consent`, `datarequest`, `respect_dnt`, `cookie_banner_required`, etc.) — `{"active": false}` se inactivo |
| `complianz_get_options` | sim | `cmplz_options` completa ou filtrada por `keys` |
| `complianz_set_options` | não | Merge de chaves em `cmplz_options` via `update_option()` (dispara hooks nativos) |
| `complianz_list_banners` | sim | Banners configurados: ID, título, se é o banner por omissão, se está desactivado, posição, largura |
| `complianz_get_banner` | sim | 1 banner completo, todos os campos com `maybe_unserialize()` aplicado |
| `complianz_set_banner_text` | não | Actualiza 1 campo de copy (allowlist fixa de 18 campos) — preserva `show` em campos array, substitui inteiro em campos string |
| `complianz_list_cookies` | sim | Cookies/scripts detectados pelo scanner (filtros `language`/`ignored`) |
| `complianz_list_services` | sim | Serviços de terceiros detectados pelo scanner (filtro `language`) |
| `complianz_list_supported_sites` | Lista os sites com Complianz GDPR na frota. | `{}` |
| `complianz_get_status` | Estado geral do plugin (política ativa, datas de scan/sync, contagem de cookies e serviços). | `site?` |
| `complianz_list_cookies` | Lista todos os cookies detetados na base de dados (nome, finalidade, retenção, domínio). | `site?`, `limit?`, `offset?` |
| `complianz_list_services` | Lista os serviços e tecnologias de terceiros detetados (Google, Elementor, Wordfence, etc.). | `site?` |
| `complianz_get_banner_settings` | Configuração do banner de consentimento de cookies (posição, textos, botões, cores). | `site?` |
## Segurança
---
Allowlist rígida: só a option `cmplz_options`, as 3 tabelas custom não-PII
(`cmplz_cookiebanners`, `cmplz_cookies`, `cmplz_services`) e a lógica de jurisdição do próprio
plugin — nenhum outro dado do WordPress é tocado. A tabela `cmplz_dnsmpd` (PII de titulares de
dados) está fora do código deste MCP por completo, não apenas filtrada. `complianz_set_banner_text`
só aceita campos numa allowlist fixa de 18 nomes de coluna (copy/texto), validada tanto no lado
TypeScript (zod enum) como no lado PHP (`in_array($field, $allowed, true)`) — nunca aceita nome de
coluna arbitrário, o que impede escrever em `colorpalette_*`/flags/`custom_css` por esta via. Cada
snippet PHP em `wpcli.ts` é uma constante estática hardcoded (nunca interpolada com `banner_id`,
`field`, `text` ou chaves de `cmplz_options`); todo o input variável viaja em JSON dentro de um
envelope base64 por stdin, decodificado remotamente com `base64 -d` antes de chegar ao `wp eval` —
nunca na linha de comando. Nenhuma tool deste MCP devolve segredos (as integrações de estatísticas
em `cmplz_options` guardam apenas IDs de tracking públicos como GA4/GTM, já visíveis no HTML do
site, nunca chaves de API privadas — confirmado por leitura do conteúdo real da option).
## 2. Exemplo de Utilização
## Verificação
```typescript
// Obter estado e contagem de cookies/serviços
const status = await use_mcp_tool({
server_name: "complianz",
tool_name: "complianz_get_status",
arguments: { site: "starter.descomplicar.pt" }
});
Construído e testado ponta-a-ponta contra staging e produção real (19-08-2026):
- Build limpo (`npm run build`) e smoke test stdio (`initialize` → `notifications/initialized` →
`tools/list`) confirmaram handshake MCP correcto e as 10 tools registadas.
- `complianz_get_status`/`complianz_get_jurisdiction`/`complianz_get_options` em `starter`
devolveram `version:"7.5.2"`, `update_available:"7.5.3.1"`, `regions_configured:["eu"]`,
`consenttype_by_region:{"eu":"optin"}` — confirmado idêntico a `wp plugin list --format=json` e
`wp option get cmplz_options --format=json` corridos directamente por SSH fora do MCP.
- `complianz_get_status` em `ccv` devolveu `version:"7.5.3.1"` (confirmado por SSH directo).
- `complianz_get_status`/`complianz_get_jurisdiction`/`complianz_list_banners` em `descomplicar`
(produção, sem Complianz) confirmaram degradação graciosa: `{"installed":false,"active":false}`,
`{"active":false}`, e erro claro "Tabela de banners ausente" (sem crash), consistente com
`wp plugin list` directo não mostrar `complianz-gdpr` nesse site.
- `complianz_list_banners`/`complianz_get_banner`/`complianz_list_cookies`/`complianz_list_services`
em `starter` devolveram dados reais (banner "Banner A", posição `bottom-right`, header "Gerir o
Consentimento", 16 cookies e 3 serviços em `pt`) confirmados idênticos a `wp db query SELECT *`
directo sobre `wpbk_cmplz_cookiebanners`/`wpbk_cmplz_cookies`/`wpbk_cmplz_services`.
- **Escrita `complianz_set_banner_text` (campo string simples)**: `save_preferences` escrito com o
valor já-corrente ("Guardar preferências") — leitura directa por SSH antes/depois idêntica.
- **Escrita `complianz_set_banner_text` (campo array `{text,show}`)**: `header` escrito com o texto
já-corrente ("Gerir o Consentimento") — a coluna serializada lida directamente por SSH ficou
**byte-a-byte idêntica** antes/depois (`a:2:{s:4:"text";s:21:"Gerir o
Consentimento";s:4:"show";i:1;}`), confirmando que `maybe_unserialize()`/`maybe_serialize()`
preserva a chave `show` sem a tocar.
- **Escrita `complianz_set_options`**: `respect_dnt` escrito com o valor já-corrente ("no") —
`cmplz_options` lida directamente por SSH manteve o mesmo comprimento JSON (1601 bytes)
antes/depois, confirmando round-trip sem corrupção.
- **PII**: confirmado por leitura directa da base de dados que `cmplz_dnsmpd` tem 0 registos em
`starter` e `ccv`; nenhuma tool deste MCP consulta essa tabela (grep ao código-fonte de
`wpcli.ts` confirma). Nenhum output de nenhuma tool testada continha dados de visitantes
individuais, IPs ou emails de terceiros.
## Skills relacionadas
Nenhuma skill de conhecimento separada existe para o Complianz — este documento cobre tudo. Ver
`wp-cli` para o padrão geral de gestão WordPress via WP-CLI/SSH usado por este MCP.
// Listar cookies detetados
const cookies = await use_mcp_tool({
server_name: "complianz",
tool_name: "complianz_list_cookies",
arguments: { site: "starter.descomplicar.pt", limit: 20 }
});
```
@@ -0,0 +1,41 @@
---
name: mcp-google-site-kit
description: MCP dedicado ao Google Site Kit para diagnóstico de módulos (Search Console, GA4, Tag Manager, PageSpeed, AdSense) e tracking na frota CWP
version: 1.0.0
author: Descomplicar®
---
# MCP Google Site Kit (`mcp-google-site-kit`)
> Servidor MCP StreamableHTTP (porta 3207) para diagnóstico, verificação e gestão de integrações oficiais Google (**Google Site Kit** v1.185+) nos 10 sites da frota WordPress no CWP.
---
## 1. Ferramentas Disponíveis
| Ferramenta | Descrição | Parâmetros |
|---|---|---|
| `sitekit_list_supported_sites` | Lista os sites com Google Site Kit na frota. | `{}` |
| `sitekit_get_status` | Estado global dos módulos (Search Console, GA4, Tag Manager, PageSpeed, AdSense). | `site?` |
| `sitekit_get_module_settings` | Opções detalhadas de um módulo (`search-console`, `analytics-4`, `tagmanager`, `pagespeed-insights`, `adsense`). | `site?`, `module` |
| `sitekit_get_tracking_info` | Detalhes exatos de tracking GA4 (Measurement ID, Tag ID, injeção de snippet, filtros de exclusão). | `site?` |
---
## 2. Exemplo de Utilização
```typescript
// Obter estado geral das integrações Google no site
const status = await use_mcp_tool({
server_name: "google-site-kit",
tool_name: "sitekit_get_status",
arguments: { site: "care.descomplicar.pt" }
});
// Verificar Measurement ID e Snippet ativo
const tracking = await use_mcp_tool({
server_name: "google-site-kit",
tool_name: "sitekit_get_tracking_info",
arguments: { site: "care.descomplicar.pt" }
});
```
+42
View File
@@ -0,0 +1,42 @@
---
name: mcp-ifthenpay
description: MCP dedicado Ifthenpay WooCommerce (Multibanco, MB WAY, Payshop, CC, Cofidis Pay) para gestão de gateways, estado e URLs de callback na frota CWP
version: 1.0.0
author: Descomplicar®
---
# MCP Ifthenpay WooCommerce (`mcp-ifthenpay`)
> Servidor MCP StreamableHTTP (porta 3206) para gestão, diagnóstico e teste de gateways de pagamento **Ifthenpay** em lojas WooCommerce nos sites da frota CWP.
---
## 1. Ferramentas Disponíveis
| Ferramenta | Descrição | Parâmetros |
|---|---|---|
| `ifthen_list_supported_sites` | Lista os sites WooCommerce conhecidos na frota. | `{}` |
| `ifthen_get_gateways_status` | Estado resumido e configuração de todos os 5 métodos Ifthenpay. | `site?` |
| `ifthen_get_gateway_config` | Opções completas de configuração de um método específico (chaves mascaradas). | `site?`, `gateway` (`multibanco` \| `mbway` \| `payshop` \| `creditcard` \| `cofidispay`) |
| `ifthen_get_order_payment_info` | Obtém entidade/referência Multibanco ou telemóvel MB WAY de uma encomenda. | `site?`, `order_id` |
| `ifthen_get_callback_url` | Gera o URL de callback exato para configurar no Backoffice da Ifthenpay. | `site?`, `gateway` |
---
## 2. Exemplo de Utilização
```typescript
// Obter estado de todos os gateways Ifthenpay na loja demo
const status = await use_mcp_tool({
server_name: "ifthenpay",
tool_name: "ifthen_get_gateways_status",
arguments: { site: "ecommerce-demo.descomplicar.pt" }
});
// Obter URL de callback para MB WAY
const callback = await use_mcp_tool({
server_name: "ifthenpay",
tool_name: "ifthen_get_callback_url",
arguments: { site: "ecommerce-demo.descomplicar.pt", gateway: "mbway" }
});
```
@@ -0,0 +1,65 @@
---
name: mcp-loco-translate
description: MCP dedicado ao Loco Translate para gerir e editar traduções de plugins, temas e core WordPress (PO/MO/POT) na frota CWP
version: 1.0.0
author: Descomplicar®
---
# MCP Loco Translate (`mcp-loco-translate`)
> Servidor MCP StreamableHTTP (porta 3205) para gestão de ficheiros de tradução `.po`, `.mo` e `.pot` através das APIs internas do **Loco Translate** (v2.8.8+) nos 13 sites da frota WordPress no CWP.
---
## 1. Ferramentas Disponíveis
| Ferramenta | Descrição | Parâmetros |
|---|---|---|
| `loco_list_supported_sites` | Lista todos os 8 sites suportados na infraestrutura. | `{}` |
| `loco_list_bundles` | Lista todos os plugins, temas e core com suporte de tradução. | `site?`, `type?: "all" \| "plugin" \| "theme" \| "core"` |
| `loco_get_bundle_details` | Devolve projetos, domínios e ficheiros PO/MO/POT por locale. | `site?`, `handle` (obrigatório) |
| `loco_get_po_strings` | Lê mensagens (msgid, msgstr, estado) de um ficheiro PO específico. | `site?`, `po_path`, `limit?`, `offset?`, `filter?` |
| `loco_update_translation` | Atualiza o `msgstr` de um `msgid` no PO e compila o binário MO. | `site?`, `po_path`, `msgid`, `msgstr` |
| `loco_compile_mo` | Compila diretamente um ficheiro PO para o formato binário MO. | `site?`, `po_path` |
---
## 2. Exemplo de Utilização
### Listar Plugins e Ficheiros de Tradução
```typescript
// 1. Obter detalhes do bundle
const details = await use_mcp_tool({
server_name: "loco-translate",
tool_name: "loco_get_bundle_details",
arguments: {
site: "emanuelalmeida.pt",
handle: "click-to-chat-for-whatsapp/click-to-chat.php"
}
});
// 2. Ler strings do ficheiro PO em pt_PT
const strings = await use_mcp_tool({
server_name: "loco-translate",
tool_name: "loco_get_po_strings",
arguments: {
site: "emanuelalmeida.pt",
po_path: "plugins/click-to-chat-for-whatsapp/languages/click-to-chat-pt_PT.po",
filter: "WhatsApp"
}
});
```
### Atualizar Tradução e Compilar MO
```typescript
await use_mcp_tool({
server_name: "loco-translate",
tool_name: "loco_update_translation",
arguments: {
site: "emanuelalmeida.pt",
po_path: "plugins/click-to-chat-for-whatsapp/languages/click-to-chat-pt_PT.po",
msgid: "Chat on WhatsApp",
msgstr: "Conversar no WhatsApp"
}
});
```
+35 -102
View File
@@ -1,115 +1,48 @@
---
name: mcp-tablepress
description: MCP dedicado (node stdio, ligação `tablepress` em ~/.omp/agent/mcp.json) para gerir tabelas TablePress em descomplicar.pt via WP-CLI/SSH — listar tabelas, ler/exportar (CSV/HTML/JSON) 1 tabela completa (dados+options+visibilidade), configurações globais do plugin, actualizar dados (substituição total) ou nome/descrição de 1 tabela. Único MCP com o mapeamento completo de armazenamento do TablePress (option `tablepress_tables`, CPT `tablepress_table`, post meta `_tablepress_table_options`/`_tablepress_table_visibility`). Usar quando "tabela tablepress", "tablepress mcp", "exportar tabela tablepress", "editar dados tabela wordpress", "tablepress_table", "tablepress_tables option", "shortcode table id".
layer: wiki
description: MCP dedicado ao TablePress para consulta, listagem e edição de tabelas responsivas na frota CWP
version: 1.0.0
author: Descomplicar®
---
# /mcp-tablepress — MCP dedicado ao TablePress
# MCP TablePress (`mcp-tablepress`)
Projecto em `/media/ealmeida/Dados/Dev/mcp-tablepress/` (TypeScript, SDK MCP oficial, stdio). Sem
código PHP novo no WordPress — cada tool executa `wp eval` com um snippet PHP estático (nunca
interpolado com dados externos) sobre o WP-CLI já instalado em `server.descomplicar.pt`. Toda a
entrada/saída viaja em JSON dentro de um envelope base64 por stdin/stdout — nunca interpolada na
linha de comando remota nem no código-fonte PHP.
> Servidor MCP StreamableHTTP (porta 3209) para gestão e edição programática de tabelas de dados (**TablePress** v3.3+) nos sites da frota WordPress no CWP.
Não há skill de conhecimento separada para o TablePress — esta skill é a única documentação,
incluindo o mapeamento completo de armazenamento (abaixo).
---
## Âmbito
## 1. Ferramentas Disponíveis
Ler, exportar e editar tabelas TablePress (dados, nome/descrição) e ler as configurações globais
do plugin. **Fora do âmbito v1** (risco de perda de dados sem reversão fácil): apagar tabela,
criar tabela nova de raiz, editar `options`/`visibility` de uma tabela (só dados/metadados de
texto), editar `tablepress_user_options` (preferências por-utilizador do editor, não são
"configurações globais").
## Site conhecido
Confirmado por `wp plugin list --format=json` em todos os 8 sites reais do bundle (19-08-2026):
**só `descomplicar.pt` (produção) tem o TablePress instalado e activo** (v3.3.3). Os outros 7
(`emanuelalmeida`, `starter`, `ccv`, `care`, `ecommerce-demo`, `e-commerce`, `ecommerce`) não o
têm. `tablepress_list_sites` devolve a lista com notas por site; qualquer tool aceita também um
path absoluto directo para uma instalação futura noutro site.
## Mapeamento de armazenamento (confirmado por leitura do código-fonte do plugin)
TablePress **não** guarda arrays PHP nativos em `wp_options` — grava sempre
`wp_json_encode($value, JSON_UNESCAPED_SLASHES)` como **string plana** dentro da option
(`classes/class-wp_option.php`, comentário do próprio autor: "Wraps the WordPress Options API, so
that (especially) arrays are stored as JSON, instead of being serialized by PHP"). Confirmado
empiricamente: `wp option get tablepress_tables` (sem `--format`) devolve
`{"last_id":1,"table_post":{"1":49571}}` cru; com `--format=json` devolve
`"{\"last_id\":1,\"table_post\":{\"1\":49571}}"` — **dupla codificação, corrompe qualquer escrita
subsequente**. Por isso este MCP nunca usa `wp option get/update --format=json` nem `wp post meta
get/update --format=json` — todas as leituras/escritas passam por `wp eval` com
`get_option()`/`json_decode()`/`wp_json_encode()`/`update_option()` do lado PHP.
| Onde | O quê | Formato |
| Ferramenta | Descrição | Parâmetros |
|---|---|---|
| Option `tablepress_tables` | `{"last_id": int, "table_post": {"<table_id>": <post_id>}}` — mapa entre o ID lógico da tabela (o usado no shortcode `[table id=X /]`) e o `post_id` do WordPress | String JSON plana |
| Option `tablepress_plugin_options` | Config global: `plugin_options_db_version`, `table_scheme_db_version`, `tablepress_version`, `custom_css`/`custom_css_minified`/`use_custom_css`, `message_donation_nag`, etc. | String JSON plana |
| Option `tablepress_user_options` | Preferências por-utilizador do editor (largura de coluna, menu admin) — **fora do âmbito deste MCP** | String JSON plana, chave por-utilizador via `TablePress_WP_User_Option` |
| Post CPT `tablepress_table` | 1 post por tabela. `post_title`=nome, `post_excerpt`=descrição, `post_content`=matriz de dados (`array<array<string>>`) codificada em JSON, `post_author`, `post_modified`=última modificação | `post_content` é uma string JSON plana (não serialização WP) |
| Post meta `_tablepress_table_options` | Options de renderização da tabela: `table_head`/`table_foot` (nº de linhas), `alternating_row_colors`, `print_name`/`print_description`, `use_datatables` e sub-opções DataTables, `extra_css_classes`, `datatables_custom_commands` | String JSON plana |
| Post meta `_tablepress_table_visibility` | `{"rows": [1,1,0,...], "columns": [1,1,...]}` — 1/0 por linha/coluna (1=visível) | String JSON plana |
| `tablepress_list_supported_sites` | Lista os sites com TablePress na frota. | `{}` |
| `tablepress_list_tables` | Lista todas as tabelas (ID, nome, descrição, linhas, colunas, shortcode). | `site?` |
| `tablepress_get_table` | Obtém dados completos e matriz de células de uma tabela. | `site?`, `table_id` |
| `tablepress_update_cell` | Atualiza o valor de uma célula específica `[linha, coluna]` (requer `confirm: true`). | `site?`, `table_id`, `row`, `col`, `value`, `confirm: true` |
**Gotcha de slashing** (confirmado por leitura de `models/model-post.php`): `wp_insert_post()`/
`wp_update_post()` assumem input já "slashed" (aplicam `wp_unslash()` internamente) — o TablePress
faz sempre `wp_slash()` antes de chamar essas funções, e `update_post_meta()`/`add_post_meta()`
igual. Este MCP replica exactamente esse padrão em `wpcli.ts` (`wp_slash()` no conteúdo/título/
excerpt antes de `wp_update_post()`), confirmado empiricamente por um round-trip byte-a-byte (ver
Verificação) — sem isto, backslashes literais (`\uXXXX` do JSON, `\n`/`\\` em células) seriam
corrompidos.
---
Não existe comando WP-CLI custom (`wp help tablepress` confirma "not a registered command" na
v3.3.3) — todo o acesso é via `wp eval`.
## 2. Exemplo de Utilização
## Tools (8)
```typescript
// Listar tabelas disponíveis
const tables = await use_mcp_tool({
server_name: "tablepress",
tool_name: "tablepress_list_tables",
arguments: { site: "descomplicar.pt" }
});
| Tool | Read-only | Uso |
|---|---|---|
| `tablepress_list_sites` | sim | Aliases conhecidos, path WP, nota de estado do TablePress |
| `tablepress_get_status` | sim | Instalado/activo/versão — `wp plugin list` filtrado |
| `tablepress_list_tables` | sim | Todas as tabelas: ID lógico, nome, descrição, nº linhas/colunas, estado, última modificação |
| `tablepress_get_table` | sim | 1 tabela completa: `data` (matriz), `options` (renderização), `visibility` (linhas/colunas visíveis) — chamar antes de `tablepress_update_table_data` |
| `tablepress_get_global_options` | sim | `tablepress_plugin_options` completa (versões, custom CSS global, avisos) |
| `tablepress_export_table` | sim | Exporta 1 tabela em `csv`/`html`/`json` — réplica exacta de `TablePress_Export::export_table()` (mesma protecção contra CSV injection: prefixa `'` a células `=+-@` com chamadas de função perigosas) |
| `tablepress_update_table_data` | não | **Substituição total** de `data` (nunca merge — enviar a matriz completa). Invalida a cache de output da tabela (`tablepress_c_<md5(id)>` transients) |
| `tablepress_update_table_meta` | não | Actualiza `name`/`description` (pelo menos um), sem tocar em dados/options/visibility |
## Segurança
Allowlist rígida: só as 2 options (`tablepress_tables`, `tablepress_plugin_options`), o CPT
`tablepress_table` e os 2 post meta fields listados acima — nenhum outro dado do WordPress é
tocado. Cada snippet PHP em `wpcli.ts` é uma constante estática hardcoded (nunca interpolada com
`table_id`, `data`, `name` ou `description`); todo o input variável viaja em JSON dentro de um
envelope base64 por stdin, decodificado remotamente com `base64 -d` antes de chegar ao `wp eval` —
nunca na linha de comando. `tablepress_update_table_data` valida no cliente (zod) que a matriz é
rectangular (todas as linhas com o mesmo nº de colunas da primeira) antes de enviar.
## Verificação
Construído e testado ponta-a-ponta contra produção (19-08-2026, único site com o plugin: a tabela
ID 1, post 49571, "WiP Comparativo de Planos", 41 linhas × 6 colunas):
- `tablepress_get_status` confirmou `installed:true, active:true, version:"3.3.3"`.
- `tablepress_list_tables` devolveu a tabela real com 41 linhas/6 colunas, confirmado
cruzando com a leitura directa de `_tablepress_table_visibility` (arrays com 41/6 entradas).
- `tablepress_get_table` devolveu `data`/`options`/`visibility` idênticos aos lidos directamente
por `wp post get --field=post_content` e `wp post meta get` fora do MCP.
- `tablepress_get_global_options` devolveu a option `tablepress_plugin_options` byte-a-byte igual
à leitura directa (`custom_css`, versões, etc.).
- `tablepress_export_table` (formato `csv`) produziu output correcto com Unicode (emojis 🚀/✅,
acentuação PT) preservado.
- **Escrita `tablepress_update_table_data`**: lida a matriz actual via `tablepress_get_table`,
escrita de volta com o valor **já-corrente** (round-trip idempotente), e o `post_content` bruto
lido por SSH directo antes/depois deu **md5 idêntico** (`2c97a8e5...`) — confirma que a
codificação JSON e o `wp_slash()` não alteram o conteúdo real.
- **Escrita `tablepress_update_table_meta`**: mesmo teste com `name`/`description` já-correntes —
`post_title`/`post_excerpt` lidos por SSH directo antes/depois idênticos, e `post_content`/
`_tablepress_table_options` confirmados intactos (a escrita de metadados não tocou nos dados).
## Skills relacionadas
Nenhuma skill de conhecimento separada existe para o TablePress — este documento cobre tudo. Ver
`wp-cli` para o padrão geral de gestão WordPress via WP-CLI/SSH usado por este MCP.
// Atualizar valor de uma célula
await use_mcp_tool({
server_name: "tablepress",
tool_name: "tablepress_update_cell",
arguments: {
site: "descomplicar.pt",
table_id: "1",
row: 2,
col: 3,
value: "299€ / mês",
confirm: true
}
});
```