From bacf65df338ea7a7bb25a58a0c621688e3eb4ebe Mon Sep 17 00:00:00 2001 From: McpComplianz Agent Date: Wed, 19 Aug 2026 07:35:53 +0100 Subject: [PATCH] skill: adicionar mcp-complianz (MCP dedicado Complianz GDPR/CMP) --- wordpress/skills/mcp-complianz/SKILL.md | 136 ++++++++++++++++++++++++ 1 file changed, 136 insertions(+) create mode 100644 wordpress/skills/mcp-complianz/SKILL.md diff --git a/wordpress/skills/mcp-complianz/SKILL.md b/wordpress/skills/mcp-complianz/SKILL.md new file mode 100644 index 0000000..afdae25 --- /dev/null +++ b/wordpress/skills/mcp-complianz/SKILL.md @@ -0,0 +1,136 @@ +--- +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 +--- + +# /mcp-complianz — MCP dedicado ao Complianz GDPR/CMP + +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. + +Não há skill de conhecimento separada para o Complianz — esta skill é a única documentação, +incluindo o mapeamento completo de armazenamento (abaixo). + +## Âmbito + +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 | +|---|---|---| +| `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`) | + +## 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). + +## Verificação + +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.