teqo-backup/docs/plans/ops92-consolidar-mcps-impl.md
Francisco Solla d816e3ff41 chore(OPS92): consolidar MCPs — global só jina+playwright; penpot/postgres subagentes; gh CLI; re-homed (Closes #857)
Global (~/.config/opencode/opencode.jsonc) fica só com jina+playwright (remove github/postgres/forgejo/stalwart/office-word/jobspy) — manual como OPS89.
Repo Teqo opencode.json: penpot+postgres com permission gated (penpot*/postgres*/query deny no build, allow só nos subagentes penpot/postgres).
Novos .opencode/agent/penpot.md + postgres.md (mode subagent, docs de limite teqo vs teqo_wt*).
Re-homed: jobspy→jobs, forgejo+office-word→lei-mercados-digitais, forgejo+stalwart→infra-solla (remove postgres pin, AGENTS.md sem office-word), forgejo→iara-pwa (limpa pins postgres/stalwart).
Prosa: AGENTS-infra.md, prompt-montagem-home.md, project-status/engineering-audit sem MCP/pnpm issue.
Validação: opencode debug config nos 5 repos (Teqo 4, jobs 3, lei 6, infra 7, iara 3 MCPs), gh auth ok, gate:fast verde.
2026-08-24 17:18:53 -03:00

21 KiB
Raw Permalink Blame History

Impl: Consolidar MCPs do opencode: global fica só com playwright + jina; penpot/postgres viram subagentes; GitHub MCP morre (CLI gh); forgejo/jobspy/office-word/stalwart re-homed para os projetos donos

Status: aprovado Atualizado em: 2026-08-24 Issue: #857 Intenção: docs/plans/ops92-consolidar-mcps.md Appetite restante: ~0,5–1 dia herdado (config-only + 2 subagentes + prosa; sem migration, sem testes novos; tracer bullet)

Leitura da intenção

  • Outcome: abrir o opencode no Teqo expõe só jina + playwright (e built-ins) no global; penpot e postgres vivem só em subagentes do repo Teqo; GitHub via gh CLI; cada projeto irmão expõe localmente só o MCP que usa — sessões baratas sem perder ferramenta quando chamada.
  • O que NÃO negociar: anti-goals da intenção — NÃO criar gerenciador de MCPs; NÃO automatizar config global (continua manual do dono, como OPS89); NÃO criar config morta em projeto que não pediu; NÃO tocar eur-lex/mcp-brasil no lei-mercados-digitais; NÃO mexer em credenciais/tokens além de mover blocos; NÃO auditar/limpar configs fora dos destinos confirmados; freeze de migrations/LGPD/URLs não afetado.
  • O que reavaliar: hipóteses de "Direção no codebase" — confirmadas com leitura ao vivo:
    • Global real ~/.config/opencode/opencode.jsonc tem 7 MCPs (github:false + jina + playwright + postgres + forgejo + stalwart + office-word + jobspy) — remover 5 blocos inteiros, manter 2.
    • Repo Teqo opencode.json (10 linhas) hoje só $schema + mcp.penpot (:4-8, token em .opencode/secrets/penpot-token via {file:…}) — vai ganhar postgres irmão.
    • Subagentes existentes .opencode/agent/*.md (4 arquivos) — design-vision*.md com mode: subagent + model: deepinfra/Qwen…, designer-campanha-solla.md com mode: all — dão o precedente de frontmatter (description/mode/model/temperature).
    • Irmãos verificados: jobs/opencode.json só provider (herda tudo do global); lei-mercados-digitais/opencode.json só eur-lex+mcp-brasil; infra-solla/opencode.jsonc desliga postgres:false e herda forgejo/stalwart/office-word dos globais; iara-pwa/opencode.jsonc desliga postgres:false + stalwart:false (Issue #5 dela) e herda forgejo.
    • scripts/worktree.mjs:239-258 (copyOpendevSecrets) copia .opencode/secrets/* — vira no-op se o repo não declarar penpot (mas penpot permanece declarado, então continua vivo).
    • Menções (MCP|pnpm issue) em skills: .agents/skills/project-status/SKILL.md:25, .agents/skills/work-issue/SKILL.md:82 + engineering-audit/SKILL.md:69 — trocar para gh/sem MCP.

Abordagem recomendada

flowchart LR
  G["~/.config/opencode/opencode.jsonc\n(global, manual, fora do git)\nANTES 7 MCPs -> DEPOIS só jina + playwright\nREMOVE github/postgres/forgejo/stalwart/office-word/jobspy"] --> T["Sessão opencode no Teqo\nbuilt-ins + 2 MCPs globais"]
  R["opencode.json (repo Teqo)\nANTES só penpot (1)\nDEPOIS penpot + postgres\n + permission gate"] --> T
  R --> S1[".opencode/agent/penpot.md\nsubagent, permission: penpot/* allow"]
  R --> S2[".opencode/agent/postgres.md\nsubagent, permission: postgres/* allow"]
  S1 --> T
  S2 --> T
  T -->|usa quando precisa| GH["GitHub via gh CLI\n(gh 2.98 auth ok)"]
  G2["Re-homed (repos donos)\njobs/opencode.json -> jobspy\nlei/opencode.json -> forgejo+office-word\ninfra/opencode.jsonc -> forgejo+stalwart\niara/opencode.jsonc -> forgejo"] --> O["Sessões nesses repos\nexpõem só o dono"]

Decisões caras (deliberadas com rejeitadas):

D1 — Onde declarar penpot + postgres (caro: muda quem paga contexto em toda sessão)

Opções: A | B | C
Recomendação: A — ambos em opencode.json do repo Teqo (commitado) + 2 subagentes no repo
Alternativas rejeitadas: B porque global voltaria a pagar contexto em TODO projeto (anula o outcome: abrir no Teqo custa mínimo mas abrir em jobs/lei também pagaria penpot/postgres); C porque remover postgres totalmente perde a ferramenta local deste projeto (banco teqo é ferramenta diária, não "outro projeto" — a intenção fixa "ficam no Teqo mas só dentro de subagentes")
  • A mantém o princípio "edit the owner, don't twin" (OPS82/OPS89): repo é o dono de penpot (design do site) e do postgres local; global paga 0.
  • B (global) foi cogitado no gate aberto — rejeitado exatamente pelo corte "repo Teqo (opencode.json + .opencode/agent/*.md)" registrado na intenção.
  • C (matar postgres) barateia ainda mais mas remove capacidade que o plano de intenção marca como aceito explícito (postgres consulta o banco local).

D2 — Gate de tools por agente: permission vs tools (caro: se errar o mecanismo, o gate é silenciosamente ignorado)

Opções: A | B | C
Recomendação: A — permission por agente (mecanismo vigente)
Alternativas rejeitadas: B porque AgentConfig.tools está deprecated no schema e opencode debug config já mostra agent.<nome>.permission vazio — tools seria ignorado sem erro visível, sessão primária continuaria vendo penpot/postgres e o outcome "só nos subagentes" falharia silenciosamente; C porque sem gate nenhum, penpot/postgres voltam a custar em toda sessão (anula D1)
  • Validar na hora com opencode debug config | grep -A2 permission e opencode debug agent penpot / postgres — o executor valida o mecanismo vigente, sem inventar paralelo.
  • Precedente: intenção já sinaliza "mecanismo oficial de gate … marcado como deprecated em favor de permission — o executor valida o mecanismo vigente na hora".

D3 — Global manual vs automação (caro: automação reverte decisão de propriedade)

Opções: A | B
Recomendação: A — edição manual pelo dono, fora do git (mesmo padrão OPS89, sem CI lendo opencode.json)
Alternativas rejeitadas: B porque automatizar o global cria gerenciador de MCPs (rabbit hole nomeado da intenção) e acopla CI a arquivo fora do repo que nenhum gate valida estruturalmente — já provado que nenhum gate/CI lê opencode.json (OPS89: zero readFileSync/JSON.parse em tests/, zero match em .github/)
  • Arquivo ~/.config/opencode/opencode.jsonc é JSONC com comentários // pt-BR (estilo cheapestinception/deepinfra) — blocos removidos manualmente, validado com opencode debug config após.

D4 — Destinos do re-home (caro: colocar no projeto errado cria config morta = mesmo desperdício)

Opções: A | B | C
Recomendação: A — só os destinos confirmados no gate 2026-08-24 (intenção "Questões em aberto"): forgejo -> lei-mercados-digitais + infra-solla + iara-pwa; jobspy -> jobs; office-word -> lei-mercados-digitais; stalwart -> só infra-solla
Alternativas rejeitadas: B porque adicionar stalwart em iara-pwa contradiz decisão versionada da própria iara-pwa (opencode.jsonc Issue #5 "e-mail pessoal; fora do fluxo de dev") — já desabilita stalwart; C porque adicionar office-word em infra-solla cria twin sem dono (intenção decide "não — só lei-mercados-digitais; AGENTS.md do infra-solla sai coerente sem office-word")
  • Prova: iara-pwa/opencode.jsonc: stalwart { enabled:false } com comentário Issue #5; infra-solla/AGENTS.md:65 lista hoje office-word em uso — vai sair da lista.
  • jobs/opencode.json hoje sem mcp — herda tudo do global; após re-home, declara explicitamente só jobspy.

D5 — Morte do GitHub MCP e validação (caro: se gh não cobre, perde capacidade)

Opções: A | B
Recomendação: A — remover bloco github do global e usar gh CLI (já autenticado, já fallback real nos scripts do repo)
Alternativas rejeitadas: B porque reativar GitHub MCP exige OAuth nunca autorizado desde 17/08 (bloco já com enabled:false) e duplicaria canal com gh — scripts/check-changelog-append-only.mjs e check-plans-only-pr-closes.mjs já provam gh como fallback
  • Verificação ao vivo: gh auth status → fsolla logged in (GITHUB_TOKEN + keyring); opencode debug config após limpeza não lista github em mcp.

Componentes / mudanças

  • ~/.config/opencode/opencode.jsonc (global, FORA do repo — MANUAL, dono aplica; não commitar) — remover 5 blocos de mcp: github (já enabled:false mas ainda declara tipo/url — deletar inteiro), postgres, forgejo, stalwart, office-word, jobspy. Mantém só jina + playwright + provider (cheapestinference/deepinfra/vercel) + permission + model/compaction. Validar com opencode debug config (deve listar só 2 MCPs globais + o repo penpot/postgres quando dentro do Teqo).
  • opencode.json (repo Teqo, raiz) — de 10 linhas ($schema + mcp.penpot) para penpot + postgres como siblings em mcp. postgres bloco: type:local, command: [npx -y @modelcontextprotocol/server-postgres, postgresql://teqo:teqo@localhost:5432/teqo], enabled:true (mesmo command hoje no global). Adicionar permission top-level para gating (mecanismo A da D2): denegar por default na sessão primária e liberar por agente — validar schema vigente (opencode debug config deve mostrar agent.penpot.permission e agent.postgres.permission com allows). Sem permission, o Teqo voltaria a pagar 2 MCPs em toda sessão (anula D1 — B rejeitada).
  • .opencode/agent/penpot.md (novo) — mode: subagent, description fixa "usa Penpot MCP para geometria do site", model herdado ou sem override, permission liberando penpot:*. Reusa frontmatter de design-vision.md (mode: subagent, model: deepinfra/Qwen…, temperature: 0.2) como precedente; não cria gerenciador dinâmico.
  • .opencode/agent/postgres.md (novo) — mode: subagent, description "consulta o banco local teqo (read-only por padrão)", permission liberando postgres:*. Mesmo molde. O MCP aponta para teqo fixo (não teqo_wt* do worktree) — documentar limitação e nunca usar contra prod teqo_1313 (guard guard-dev-db/assertTestDatabase continuam).
  • scripts/worktree.mjs:239-258, 345 — nenhuma mudança de código: copyOpendevSecrets continua copiando .opencode/secrets/penpot-token; com penpot ainda declarado no repo, não vira no-op. Só nota de verificação: sem penpot no repo, o {file:.opencode/secrets/penpot-token} dangling faria opencode recusar abrir — por isso penpot permanece declarado (intenção: "a cópia de secrets continua necessária — penpot permanece declarado no repo").
  • Projetos irmãos (edits commitados nesses repos, não no Teqo — listar como verificação cruzada; no Teqo o diff é só prosa/docs):
    • jobs/opencode.json — adicionar mcp.jobspy (bloco hoje no global: command: [.venv/bin/python, mcp/jobspy_server.py]).
    • lei-mercados-digitais/opencode.json — adicionar mcp.forgejo + mcp.office-word; manter eur-lex + mcp-brasil intactos.
    • infra-solla/opencode.jsonc — declarar mcp.forgejo + mcp.stalwart locais (blocos copiados do global, com FORGEJO_*/JMAP_*); remover pin morto "postgres": {enabled:false} ; atualizar AGENTS.md:65 para remover office-word da lista "Em uso" (fica forgejo, jina, playwright, stalwart + locais airbnb/homeexchange/whatsapp).
    • iara-pwa/opencode.jsonc — declarar mcp.forgejo local; limpar pins mortos "postgres": {enabled:false} e "stalwart": {enabled:false} (este último já é enabled:false proposital, mas com re-home global sem stalwart, o pin vira ruído — remover e deixar comentário da Issue #5).
  • Prosa/docs no Teqo:
    • AGENTS-infra.md:13 — atualizar frase que cita .opencode/secrets/* (ex.: penpot-token, referenciado pelo opencode.json MCP config → agora penpot/postgres gated por subagentes).
    • docs/campanha/prompt-montagem-home.md:24 — atualizar "Use penpotUtils …" para "via subagente penpot (penpot MCP)" — hoje diz "MCP do Penpot (já configurado)" sem mencionar subagente.
    • .agents/skills/project-status/SKILL.md:25 — trocar MCP/pnpm issue por gh CLI / pnpm issue (remove menção a MCP morto); engineering-audit/SKILL.md:69 mesma limpeza.
    • docs/campanha/plano-site-campanha-2026.md se citar penpot MCP como ativo — verificar e atualizar.
  • Migration: sem migration — config-only; nenhum schema Payload muda (push:false não tocado).
  • Access / Consent: N/A — sem collection/PII; não afeta CampaignUser/Consent fail-closed.
  • UI: N/A — Impeccable A (sem UI); TUI do opencode é consumidor de verificação, não produto.

Dados → forma (se aplicável)

Não há dado de negócio. Forma é tooling de dev — a única "forma" deliberada é a de gate (D2: permission vs tools), já decidida acima com rejeitadas e gatilho de revisitação (se o schema estabilizar outro mecanismo, validar com opencode debug config antes de replicar).

Fases verificáveis

  1. Tracer Teqo (repo + subagentes) — 40% do appetite — opencode.json com penpot+postgres + permission gate; criar .opencode/agent/penpot.md + postgres.md (frontmatter no molde design-vision*.md). Verificar dentro do Teqo: opencode debug config lista penpot+postgres no mcp mas agent penpot/postgres têm permission allow; sessão primária opencode debug agent build não lista tools penpot/postgres; node -e "JSON.parse(require('fs').readFileSync('opencode.json','utf8'))" passa; pnpm gate:fast verde (nenhum teste lê opencode.json estruturalmente — já provado em OPS89). Push via pnpm push → CI checks verde.
  2. Global manual (dono) — condiciona o aceite, ordem recomendada: antes do merge — remover do global os 5 blocos (github/postgres/forgejo/stalwart/office-word/jobspy — github já false, deletar). Verificar fora de qualquer repo ou no Teqo após: opencode debug config mostra só jina+playwright em mcp global; gh auth status continua Logged in; opencode agent list sem github. Se o dono não aplicar antes do merge, a janela é aceita (global com twin temporário vs Teqo já limpo — configs são merged, sem perda) — gatilho: aceitar fecha só com Fase 2 verde.
  3. Re-home irmãos (nos repos donos) — 30% do appetite, em PRs separados por repo — jobs (+jobspy), lei-mercados-digitais (+forgejo+office-word), infra-solla (+forgejo+stalwart, remove postgres pin, AGENTS.md sem office-word), iara-pwa (+forgejo, limpa pins postgres/stalwart). Verificar por repo: opencode debug config dentro de cada repo lista só os MCPs donos + os 2 globais (jina/playwright); nenhum lista MCP de outro dono.
  4. Prosa + validação de ponta a ponta — 30% do appetite — atualizar AGENTS-infra.md, prompt-montagem-home.md, project-status/SKILL.md, engineering-audit/SKILL.md; grep -rn "MCP.*pnpm issue\|penpot MCP.*ativo" .agents docs AGENTS-infra.md deve retornar só histórico ou nada; validar fluxo desejado: abrir opencode no Teqo → Task para penpot executa penpotUtils.getPageById com sucesso; Task para postgres executa SELECT 1 no teqo; gh issue view 857 funciona; pnpm dev sobe e pnpm worktree next --stay --no-migrate provisiona com penpot-token copiado (não "bad file reference").

Rabbit holes / Não escopo (engenharia)

  • NÃO criar gerenciador/descoberta dinâmica de MCPs — só 2 subagentes fixos (corte da intenção; D1-B/C já rejeitados).
  • NÃO automatizar o global (script que reescreve ~/.config/opencode/opencode.jsonc) — continua manual do dono (D3-B rejeitada; OPS89 já provou manual sem CI).
  • NÃO editar credenciais/tokens em claro — mover blocos e só; validar lendo ({env:…} / {file:…} continuam referenciando env/arquivo, sem inline).
  • NÃO tocar eur-lex/mcp-brasil no lei-mercados-digitais nem auditar/limpar configs de projetos fora da lista de 4 irmãos.
  • NÃO reformatar JSONC globais além dos blocos removidos — tocar só mcp.*, manter provider.*/permission/model/compaction.
  • NÃO alterar scripts/worktree.mjs — com penpot ainda no repo, a cópia de secrets não é no-op; mexer vira risco de "bad file reference".
  • NÃO trocar postgres para teqo_wt* dinâmico — o MCP continua apontando para teqo fixo; worktrees com banco isolado usam psql/DATABASE_URL direto, não o MCP.

Riscos e mitigação

  • Global JSONC inválido após edição manual → loader do opencode falha alto; mitigar com opencode debug config imediatamente após colar e python3 -m json.tool não serve (JSONC) — usar opencode debug config como validator; manter backup do arquivo antes.
  • Token leak no debug → opencode debug config no global imprime secrets resolvidos (FORGEJO_ACCESS_TOKEN, JMAP_PASSWORD, penpot userToken); não colar saída em Issue/PR/log; ao validar nos irmãos, redigir tokens (grep por enabled sem debug quando só precisa listar keys).
  • Permission gate silenciosamente ignorado (tools vs permission) → sessão primária continuaria vendo penpot/postgres e o custo volta; mitigar validando opencode debug agent penpot/postgres e opencode debug agent build após D1; se o schema mudar, o plano volta a D2 com evidência (gatilho explícito).
  • Editar 4 repos irmãos cria config morta → só os destinos confirmados no gate (D4); cada PR irmão verificado com opencode debug config dentro daquele repo (deve listar só dono + jina/playwright).
  • scripts/worktree.mjs vira no-op sem penpot → não acontece porque penpot permanece declarado no repo Teqo (intenção trava); se alguém remover penpot do opencode.json, o worktree falha com "bad file reference" — gatilho de reversão imediata.
  • postgres MCP aponta para teqo fixo, não para teqo_wt* do worktree → subagente postgres no worktree consulta o banco errado se o dev espera teqo_wt; documentar nos dois .md que o MCP é para teqo (main/shared) e que worktrees isolados devem usar psql $DATABASE_URL direto; nunca apontar DATABASE_URL para teqo_1313 prod (guard guard-dev-db/assertTestDatabase continuam).
  • Global editado sem CI (sem rede de segurança automatizada) → nenhum gate lê opencode.jsonc global; mitigar com verificação manual opencode debug config + gh auth status + opencode agent list na Fase 2; manter twin temporário (global+repo com mesmo bloco) até Fase 2 verde — configs são merged, sem janela de perda (só custo temporário).
  • Infra-solla AGENTS.md stale → após re-home, grep -n office-word AGENTS.md deve dar zero; CI de infra-solla (docker compose config -q) não valida MCP, então a verificação é manual via opencode debug config naquele repo.

Aceite de engenharia

  • Aceite de produto da intenção coberto: Teqo expõe só playwright+jina no global; penpot e postgres só via subagentes no repo Teqo (com permission gate validado); GitHub via gh sem perda; cada irmão expõe só o dono (forgejo/jobspy/office-word/stalwart nos destinos confirmados); pnpm dev, worktree next e docs que citam penpot coerentes.
  • Invariantes AGENTS/engineering-standards: sem twin — global é owner só de jina/playwright, cada repo é owner do seu MCP; sem gerenciador; sem automação do global; sem credencial inline; sem migration retroativa.
  • Testes de domínio previstos: sem testes novos — config-only; pnpm gate:fast verde já cobre que nenhum teste lê opencode.json estruturalmente (OPS89); verificação é opencode debug config + gh auth status + Task penpot/postgres.
  • Prosa/docs vivos sem menção stale a "MCP/ pnpm issue" (skills) nem "penpot MCP ativo" sem subagente.

Self-score decision-quality

  1. Decisões caras têm rejeitadas? Sim — D1 (A|B|C: B paga contexto em todo projeto, C perde ferramenta local), D2 (A|B|C: B é deprecated silencioso, C anula gate), D3 (A|B: B vira gerenciador contra anti-goal), D4 (A|B|C: B contradiz Issue #5 iara, C cria config morta), D5 (A|B: B reanima OAuth morto) — formato Opções: A | B | C / Recomendação: … — porque … / Alternativas rejeitadas: … porque … em todas.
  2. Cabe no appetite? Sim — config-only + 2 subagentes + prosa + opencode debug config; ~0,5–1 dia herdado mantido; sem migration, sem testes novos; tracerbullet Fase 1 entrega Teqo isolado antes de tocar irmãos.
  3. Rabbit holes nomeados? Sim — gerenciador de MCPs, automação do global, credenciais em claro, reformatar global inteiro, tocar eur-lex/mcp-brasil, auditar outros projetos, worktree.mjs, postgres dinâmico — todos com corte "não fazer" explícito.
  4. Depth check reusa? Sim — reusa opencode.json existente (não duplica global), frontmatter de .opencode/agent/design-vision*.md (mode subagent/model/temperature), bloco postgres idêntico ao global, copyOpendevSecrets existente, gh CLI já fallback nos scripts, permission vigente (não inventa paralelo).
  5. Intenção (aceite de produto) permanece satisfeita? Sim — engenharia não reescreveu outcome; só concretizou "penpot/postgres viram subagentes" + gate + re-home confirmado no gate 2026-08-24; nenhuma hipótese reavaliada muda resultado nem escopo.

Score: 5/5 — gate ≥4 atendido.