Capacidades extras via MCP — receitas com política de segurança
Complemento de docs/hardening-gateway.md. As tools nativas (
bash,file_read,file_write,web_fetch,repo_search,git_diff, agendamento) já cobrem o essencial de um agente de terminal. Capacidades ALÉM disso entram como servidores MCP — cada um com escopo mínimo, limites de recurso e secrets no cofre.
Onde configurar
Servidores MCP vivem em <config_dir>/mcp.json (formato compatível com
Claude Desktop, chaves em camelCase) ou na seção mcp: do
config.yml (snake_case, com o extra allowed_tools). Campos de
política disponíveis:
Campo (mcp.json) | Campo (config.yml) | Efeito |
|---|---|---|
memoryLimitMb | memory_limit_mb | cap de memória virtual do processo (Unix) |
maxRestarts / restartDelaySecs | max_restarts / restart_delay_secs | política de restart com backoff |
timeoutSecs | timeout | timeout de inicialização |
| — | allowed_tools | allowlist de tools do servidor (vazio = todas) |
| — | inherit_env | válvula de escape do isolamento de ambiente (padrão false) |
env com valores sensíveis | idem | viram vault:mcp.<server>.<KEY> quando GARRAIA_VAULT_PASSPHRASE está setada — apenas no caminho mcp.json + admin API (ver abaixo) |
Ambiente do processo filho
O processo de um servidor MCP stdio não herda o ambiente do gateway. Ele é montado do zero, nesta ordem:
- Uma allowlist mínima do ambiente do gateway —
PATH,HOME,LANG,LC_ALL,LC_CTYPE,TERM,USER,LOGNAME,TMPDIR,TZ,SSL_CERT_FILE,SSL_CERT_DIR,NODE_EXTRA_CA_CERTS(mais o complemento da plataforma:SystemRoot/COMSPEC/APPDATAe afins no Windows,PREFIX/LD_PRELOADno Termux). Só caminhos, locale e identidade: nada que carregue credencial.HTTP_PROXY/HTTPS_PROXYficam de fora porque uma URL de proxy pode embutir usuário e senha — declare noenvdo servidor se precisar. - O mapa
envdaquele servidor, por cima — é aqui que o operador coloca de propósito oGITHUB_TOKEN, a URL do banco, etc. O que está no mapa vence o que veio da allowlist.
Até a versão anterior o filho recebia o ambiente inteiro do gateway:
GARRAIA_JWT_SECRET, ANTHROPIC_API_KEY/OPENROUTER_API_KEY,
GarraIA_VAULT_PASSPHRASE e tudo que o .env tivesse carregado. Como
servidores MCP são rotineiramente pacotes de terceiro baixados na hora
por npx, isso entregava o cofre inteiro a código não auditado.
Se um servidor legado depender de alguma variável do gateway, o caminho
certo é declará-la no env dele. inherit_env: true existe só como
destravamento temporário — devolve o ambiente completo ao filho e emite
um warn! nomeando o servidor a cada conexão:
mcp:
servidor-legado:
command: npx
args: ["-y", "algum-server"]
env:
GITHUB_TOKEN: "vault:mcp.servidor-legado.GITHUB_TOKEN"
# inherit_env: true # NÃO faça isto sem entender o que entrega
vault:vale noconfig.ymle nomcp.json. O boot do gateway resolve referênciasvault:<chave>no mapaenvantes de lançar o processo filho (#1237) — a mesma resolução do registry (GAR-291). A referência precisa apontar para uma entrada do cofre (vault:mcp.<servidor>.<VARIAVEL>) e o cofre precisa estar aberto (GARRAIA_VAULT_PASSPHRASEdefinida): referência que não resolve é fail-closed — o servidor não sobe, com aviso nomeando o servidor e a chave, nunca o valor.garra config checkavisa quando hávault:noenvcom o cofre indisponível.
inherit_env só existe no config.yml/mcp.json. Servidores criados ou
reiniciados pela admin API conectam sempre isolados, mesmo que o
config.yml declare inherit_env: true para aquele nome: o registro do
gateway (crates/garraia-gateway/src/mcp/mod.rs::McpServerConfig) não
carrega o campo, e o restart passa false explicitamente. Na prática, um
POST /admin/mcp/<nome>/restart num servidor que subiu do config.yml com
inherit_env: true o traz de volta SEM a herança — a diferença é
silenciosa, e é o motivo de inherit_env ser destravamento temporário e não
configuração de regime.
Receita 1 — Filesystem com escopo restrito
O provisionamento automático aponta o server filesystem para o $HOME
inteiro. Restrinja ao(s) diretório(s) que o agente realmente precisa:
{
"mcpServers": {
"filesystem": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem@2.0.0", "/home/voce/projetos"],
"memoryLimitMb": 512
}
}
}
E, se quiser só leitura, corte as tools de escrita na seção mcp: do
config.yml:
mcp:
filesystem:
command: npx
args: ["-y", "@modelcontextprotocol/server-filesystem@2.0.0", "/home/voce/projetos"]
memory_limit_mb: 512
allowed_tools: ["read_file", "read_multiple_files", "list_directory", "search_files", "get_file_info", "directory_tree"]
Receita 2 — Navegação web real (browser)
O web_fetch nativo baixa páginas; para interação real (JS, cliques,
screenshots) use um MCP de browser:
{
"mcpServers": {
"browser": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-puppeteer"],
"memoryLimitMb": 1024,
"timeoutSecs": 60
}
}
}
Política recomendada: browser dá exfiltração bidirecional (o agente lê
E envia dados a qualquer site). Use com tool_confirmation_enabled: true
e prefira modos restritos nos canais públicos.
Receita 3 — Banco de dados (Postgres) com credencial no cofre
{
"mcpServers": {
"postgres": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-postgres"],
"env": {
"DATABASE_URL": "postgres://usuario:senha@localhost:5432/app"
},
"memoryLimitMb": 512
}
}
}
Com GARRAIA_VAULT_PASSPHRASE exportada, no primeiro save o valor de
DATABASE_URL (nome contém pattern sensível? não — atenção: a detecção
cobre nomes com key/token/secret/password/auth/credential/pass; um
env chamado DATABASE_URL não é movido ao cofre automaticamente.
Prefira nomeá-lo DB_PASSWORD + montar a URL no server, ou aceite que
a URL fica no mcp.json e proteja o arquivo com chmod 0600). Use um
usuário de banco read-only para o agente sempre que possível.
Receita 4 — "Controle de aplicativos" (estado honesto)
Não existe tool nativa para controlar aplicativos GUI. Os caminhos reais, todos com implicações fortes de segurança:
- MCP dedicado por SO — ex.: um server de automação (AppleScript no
macOS,
xdotool/AT-SPI no Linux, UIA no Windows). Nenhum vem embutido; ao adotar um de terceiros, revise o código antes (ele roda com os seus privilégios) e apliqueallowed_tools+ confirmação. - Plugin WASM (
--features plugins) — sandbox com caps de memória e deadline, mas exige escrever o plugin. - Não usar o
bashcomo atalho para isso em canal público — modosask/searchexistem exatamente para esse contexto.
Checklist ao adicionar QUALQUER servidor MCP
- Escopo mínimo (diretório, banco, credencial read-only)
-
memoryLimitMbdefinido -
allowed_toolsnoconfig.ymlquando o servidor expõe mais do que você quer - Variáveis que o servidor precisa declaradas no
envdele (o filho não herda o ambiente do gateway) einherit_envdeixado emfalse - Secrets com nome sensível (para irem ao cofre) +
GARRAIA_VAULT_PASSPHRASEsetada -
tool_confirmation_enabled: truenoagent -
garra mcp list/garra mcp inspect <nome>para conferir o que ficou exposto - Nunca um segundo shell via MCP (contorna o safety_gate do
bashnativo)