Tripwire

Injeção de contexto para agentes de IA via MCP. Defina políticas baseadas em caminhos em YAML — quando um agente lê um arquivo correspondente, o conhecimento relevante é injetado automaticamente. Previne erros antes que aconteçam. Funciona com Claude Code, Cursor e qualquer cliente MCP.

Documentação

Tripwire

npm version CI License: MIT Node.js TypeScript

Injeção de contexto para agentes de IA, acionada pelo próprio código.

Tripwire é um servidor MCP local que injeta automaticamente contexto relevante quando um agente lê arquivos no seu projeto. Defina tripwires em caminhos — quando um agente aciona um, ele recebe o conhecimento necessário antes de causar danos.

Agentes não sabem o que não sabem. Tripwire resolve isso.

Modelo mental: Tripwires são políticas baseadas em caminhos. Eles injetam contexto em leituras de arquivos. São determinísticos e nativos do repositório. A aplicação depende do suporte do cliente (hooks) ou do modo proxy.

Agent opens payments/stripe.py
  → Tripwire fires
  → Context injected: "All secrets from vault. Never hardcode keys. See docs/security/secrets.md"
  → Agent proceeds with the right context, without having to ask

Como Funciona

  1. Tripwires vivem no seu repositório como pequenos arquivos YAML em .tripwires/
  2. O servidor MCP lida com chamadas de ferramentas de leitura de arquivos e faz correspondência glob contra os gatilhos dos tripwires
  3. O contexto correspondente é prefixado ao conteúdo do arquivo — automático para o agente, inspecionável via tripwire explain
  4. Agentes criam novos tripwires quando cometem erros e são corrigidos
  5. Tudo sincroniza via git — tripwires viajam com o código, são revisados em PRs e se propagam pela equipe

Sem serviços externos. Sem bancos de dados. Sem configuração além de iniciar o servidor.

Modelo de ameaça: Tripwires são um canal de instruções privilegiado — um tripwire malicioso pode direcionar agentes a introduzir vulnerabilidades. Tripwire é injeção de orientação/política, não um sistema de permissões. Proteja .tripwires/ com CODEOWNERS, exija revisão de CI para todas as alterações e rejeite tripwires critical criados por agentes sem aprovação humana. Consulte SECURITY.md para o modelo de ameaça completo e receitas de CI.


Instalação

Requer Node.js >= 18.

Teste rápido (sem instalação)

Adicione ao .mcp.json e pronto:

{
  "mcpServers": {
    "tripwire": {
      "command": "npx",
      "args": ["-y", "@tripwire-mcp/tripwire", "serve", "--project", "."]
    }
  }
}

Para Cursor, use .cursor/mcp.json com a mesma configuração.

Configuração de equipe (recomendado)

Fixar como dependência de desenvolvimento para que todos recebam a mesma versão:

npm install --save-dev @tripwire-mcp/tripwire

Adicione scripts ao package.json:

{
  "scripts": {
    "tripwire": "tripwire",
    "tripwire:lint": "tripwire lint --strict",
    "tripwire:doctor": "tripwire doctor"
  }
}

Aponte .mcp.json para a instalação local (sem necessidade de -y):

{
  "mcpServers": {
    "tripwire": {
      "command": "npx",
      "args": ["tripwire", "serve", "--project", "."]
    }
  }
}

Alternativa: instalação global

npm install -g @tripwire-mcp/tripwire

Qualquer cliente compatível com MCP

Tripwire fala MCP padrão via stdio. Para uma configuração completa e funcional, consulte examples/hello-tripwire/.


Início Rápido

Inicialize no seu projeto

cd your-project
tripwire init

Cria um diretório .tripwires/ com um exemplo inicial.

Defina seu primeiro tripwire

# .tripwires/no-hardcoded-secrets.yml
triggers:
  - "payments/**"
  - "billing/**"
  - "**/stripe*.py"

context: |
  CRITICAL: Never hardcode API keys or secrets in this module.
  All credentials must be loaded from the vault service.
  See docs/security/secrets-policy.md for the approved pattern.

severity: critical
created_by: human

Pronto. Qualquer agente lendo arquivos que correspondam a esses globs agora recebe este contexto automaticamente.

Deixe os agentes aprenderem

Quando um agente comete um erro e você o corrige, o agente pode criar um tripwire para prevenir o mesmo erro em sessões futuras:

# .tripwires/api-v1-versioning.yml
triggers:
  - "src/api/v1/**"

context: |
  This is a frozen API version. Do not modify existing endpoint
  signatures or response shapes. Add new functionality to v2 only.
  Breaking changes here will fail the contract test suite.

severity: high
created_by: agent:claude-code
learned_from: "Changed a v1 response field, broke 3 downstream consumers"

Formato do Tripwire

Cada arquivo .yml em .tripwires/ define um tripwire:

# Required
triggers:           # Glob patterns matched against file paths (relative to repo root)
  - "src/auth/**"
  - "middleware/auth*.ts"
context: |          # Free-text context injected when triggered (markdown supported)
  The auth module uses session-based auth, NOT JWT.
  See ADR-012 for the migration rationale.
created_by: human   # Who authored this (required — see format below)

# Optional
severity: info | warning | high | critical    # Default: warning (affects ordering only)
learned_from: "..."                            # Required if created_by starts with agent:
tags:                                          # For filtering and organization
  - security
  - architecture
expires: 2026-06-01                            # Auto-remove after this date
depends_on:                                    # Other tripwires that must also fire
  - no-hardcoded-secrets

Padrões glob

Tripwire usa sintaxe glob padrão:

PadrãoCorrespondência
src/auth/**Qualquer arquivo sob src/auth/, em qualquer profundidade
*.sqlArquivos SQL na raiz
**/*.sqlArquivos SQL em qualquer lugar
src/api/v{1,2}/**Arquivos nos diretórios de API v1 ou v2
!**/*.test.tsExcluir arquivos de teste (prefixo com !)

Convenções de nomenclatura

Nomes de tripwires são derivados do nome do arquivo YAML e normalizados para a-z, 0-9 e hífens. Espaços e sublinhados tornam-se hífens. Nomes não diferenciam maiúsculas de minúsculas — No_Raw_SQL.yml torna-se no-raw-sql. tripwire lint verifica nomes duplicados.

created_by é obrigatório. tripwire lint gera erro se ausente. Valores canônicos:

ValorSignificado
humanEscrito à mão por um desenvolvedor
agent:<client>Criado via ferramenta MCP (ex.: agent:mcp, agent:claude-code)
tool:<name>Criado por automação (ex.: tool:ci-generate)

lint --strict gera erro em formato inválido (agent ou tool sem nome de cliente é inválido). A ferramenta MCP create_tripwire define created_by: agent:mcp automaticamente.

Tags são um array de strings YAML. Nomes de tags devem corresponder a /^[a-z0-9][a-z0-9-]{0,31}$/ (alfanumérico minúsculo + hífens, máx. 32 caracteres). tripwire lint gera erro em tags inválidas. Em cabeçalhos de injeção, tags são renderizadas como uma string separada por vírgulas sem escape: tags="security,architecture". A regex estrita torna o escape desnecessário.


Especificação de Comportamento

Esta seção documenta a semântica exata de tempo de execução. Útil para depuração, escrita de testes ou construção de clientes alternativos. Se este documento conflitar com a implementação, a implementação é a fonte da verdade até a próxima revisão da especificação.

Correspondência de caminhos

Tripwire usa micromatch para correspondência glob. Suporta expansão de chaves ({a,b}) e negação (!).

Sensibilidade a maiúsculas/minúsculas: A correspondência diferencia maiúsculas de minúsculas por padrão (match_case: true). Quando match_case: false, a correspondência não diferencia maiúsculas de minúsculas (definido como: tanto o caminho normalizado quanto os padrões de gatilho são comparados sem considerar maiúsculas/minúsculas). Em sistemas de arquivos sem distinção de maiúsculas/minúsculas (macOS, Windows), a capitalização de caminhos relatada pelas ferramentas pode não corresponder à capitalização dos gatilhos — defina match_case: false em .tripwirerc.yml para evitar incompatibilidades.

Normalização: Antes da correspondência, os caminhos são normalizados: barras invertidas tornam-se barras normais, ./ inicial é removido. A correspondência usa dot: true (arquivos ocultos correspondem a **).

Ordem de avaliação: A configuração exclude_paths é verificada primeiro. Se um caminho for excluído, nenhuma avaliação de tripwire ocorre — mesmo que os gatilhos de um tripwire correspondam. Dentro de um tripwire, padrões de negação (!) aplicam-se após padrões positivos.

Padrões positivos vs. negação:

  • Padrões positivos (ex.: src/auth/**) correspondem a arquivos para inclusão.
  • Padrões de negação começam com ! (ex.: !**/*.test.ts) e excluem arquivos que de outra forma corresponderiam.
  • Um caminho corresponde se corresponde a pelo menos um padrão positivo E zero padrões de negação.
  • Se todos os padrões forem de negação, um padrão positivo implícito ** é adicionado (ou seja, "corresponder a tudo exceto...").

Ordenação

Quando múltiplos tripwires correspondem a um caminho, eles são ordenados deterministicamente:

  1. Severidade decrescente: crítica (0) > alta (1) > aviso (2) > informativa (3)
  2. Nome crescente (alfabético) dentro da mesma severidade

Esta ordem determina a ordem de avaliação e emissão dos grupos de tripwires raiz. Um grupo consiste no tripwire raiz mais suas dependências resolvidas (consulte Dependências). Dependências não participam da ordenação global por severidade/nome; elas são emitidas como parte do seu grupo raiz.

A severidade afeta a ordenação e a prioridade de truncamento. Ela não impõe bloqueio rígido ou controle de escrita. Todos os grupos correspondentes são injetados quando o orçamento permite — maior severidade sobrevive ao truncamento primeiro. O nível também sinaliza ao agente quão seriamente tratar o contexto.

Truncamento

Quando max_context_length > 0, Tripwire aplica um orçamento de caracteres ao contexto injetado (não tokens — clientes diferentes podem truncar independentemente). O separador e o conteúdo do arquivo não fazem parte do orçamento.

O que conta para o orçamento: a string de injeção totalmente renderizada — o cabeçalho de cada bloco (<<<TRIPWIRE ...>>>), corpo do contexto, rodapé (<<<END_TRIPWIRE>>>) e nova linha final. O bloco de supressão em si não é contado.

  • Granularidade de tripwire inteiro — um bloco de tripwire é totalmente incluído ou totalmente omitido. O contexto nunca é cortado no meio do bloco.
  • Orçamento inclui dependências — blocos de dependência contam para o mesmo orçamento.
  • Melhor esforço na ordem de classificação — grupos são tentados na ordem classificada (severidade raiz DESC, nome raiz ASC). Grupos de maior severidade são tentados primeiro, mas não há garantia rígida de que caberão. Se um único grupo exceder o orçamento, ele é suprimido — mesmo que seja crítico. Recomendado: mantenha max_context_length: 0 (ilimitado, o padrão) para repositórios críticos de segurança onde todo tripwire deve disparar.
  • Bloco suprimido — quando grupos são omitidos, um bloco <<<TRIPWIRE_SUPPRESSED count="N" reason="context_budget">>> lista o nome do tripwire raiz e a severidade para cada grupo suprimido. Dependências suprimidas como parte de um grupo atômico não são listadas individualmente — o nome raiz identifica o grupo. Formato da entrada suprimida: uma linha por grupo raiz suprimido: <severity> <name> (ex.: critical billing-freeze). O bloco termina com <<<END_TRIPWIRE_SUPPRESSED>>>.

Dependências

Tripwires podem declarar depends_on: [name1, name2] para puxar o contexto de outros tripwires quando disparam.

  • Resolução transitiva — dependências são resolvidas transitivamente até max_dependency_depth (padrão: 5).
  • Detecção de ciclos — um conjunto de visitados rastreia a caminhada. Se um ciclo for detectado, um aviso é emitido e a aresta do ciclo é ignorada.
  • Dependências ausentes — se uma dependência nomeada não existir, um aviso é emitido e a resolução continua.
  • Deduplicação global — cada bloco de dependência aparece no máximo uma vez por resposta. Uma dependência é considerada "já emitida" se seu bloco <<<TRIPWIRE ...>>> ... <<<END_TRIPWIRE>>> completo foi incluído na injeção renderizada (supressão não conta como emissão). Se múltiplos grupos raiz referenciam a mesma dependência, ela é emitida uma vez com o grupo raiz mais antigo na ordem de classificação; seu atributo originator="<rootName>" reflete o tripwire raiz cujo grupo primeiro causou a emissão dessa dependência.
  • Construção de grupo — para cada tripwire raiz correspondido, um grupo é construído: o fechamento de dependências (DFS, percorrido na ordem da lista depends_on) seguido pela raiz. Grupos são ordenados por severidade raiz DESC, depois nome raiz ASC. Dentro de um grupo, dependências aparecem na ordem de travessia DFS (estável: ordem dos irmãos corresponde à ordem de declaração depends_on).
  • Truncamento atômico — quando max_context_length > 0, o grupo inteiro (dependências + raiz) deve caber no orçamento restante. Se o grupo não couber, tudo é suprimido — a raiz nunca é emitida sem suas dependências. O tamanho do grupo é calculado após a deduplicação global: dependências já emitidas por um grupo anterior não são recontadas e não são necessárias para o ajuste do grupo. Isso é seguro porque dependências são sempre emitidas com o grupo raiz mais antigo na ordem de classificação, então qualquer raiz posterior que referencie essa dependência pode omiti-la — o bloco de dependência aparecerá antes na mesma resposta.
  • Renderização — dependências são renderizadas com atributos origin="dependency" originator="<rootName>". originator é o tripwire raiz cujo grupo primeiro causou a emissão dessa dependência. O name sempre corresponde ao nome do arquivo do tripwire (ex.: name="depName"), nunca a um composto sintético.

Conflitos

Tripwire não tenta resolver conflitos entre contextos. Se dois tripwires correspondem ao mesmo caminho e dão instruções contraditórias, ambos são injetados e o agente vê ambos.

Verificações tripwire lint (sempre):

  • Campo created_by ausente (erro)
  • Tripwire criado por agente (created_by: agent:*) sem learned_from quando require_learned_from é verdadeiro (erro)
  • Tripwire criado por agente (created_by: agent:*) sem expires quando auto_expire_days > 0 (erro) — impede que entradas agent:* escritas à mão contornem a expiração automática
  • Nomes de tags inválidos — devem corresponder a /^[a-z0-9][a-z0-9-]{0,31}$/ (erro) tripwire lint --strict adiciona:
  • Conjuntos de gatilhos idênticos (aviso) — dois tripwires cujos arrays de gatilhos ordenados são iguais (insensível à ordem). Correspondência exata, não detecção de sobreposição.
  • Sobreposição crítica (aviso) — enumera arquivos do projeto (glob **, apenas arquivos, filtrados por exclude_paths, ordenados lexicograficamente, limitados a 5000). .gitignore não é respeitado para manter resultados de lint estáveis entre ambientes; use exclude_paths para controlar o escopo da varredura. Avisa se qualquer arquivo corresponder a >1 tripwire critical. Relata os nomes específicos dos tripwires.
  • Formato created_by (erro) — deve ser human, agent:<client> ou tool:<name>. agent ou tool sem um nome de cliente/ferramenta é inválido.
  • Contexto individual > 4 KB (aviso) — sugere dividir.
  • Contexto agregado > 16 KB (aviso) — total em todos os tripwires.
  • Tripwire crítico excede max_context_length (aviso) — será suprimido em tempo de execução.

tripwire explain <path> exibe todos os tripwires correspondentes para um determinado caminho, tornando os conflitos visíveis antes que causem problemas.


Ferramentas MCP

O servidor expõe estas ferramentas aos agentes conectados:

read_file

Substituto direto para leitura padrão de arquivos. Verifica tripwires e antepõe o contexto correspondente.

Agent calls: read_file("src/auth/login.ts")
Returns:
<<<TRIPWIRE severity="high" name="auth-session-based" tags="security">>>
The auth module uses session-based auth, NOT JWT.
See ADR-012 for the migration rationale.
<<<END_TRIPWIRE>>>

<<<TRIPWIRE_FILE_CONTENT>>>
<actual file contents>

Formato do delimitador:

<<<TRIPWIRE severity="<level>" name="<name>" [origin="dependency" originator="<rootName>"] [tags="<csv>"]>>>
<context text>
<<<END_TRIPWIRE>>>
AtributoSempre presenteValores
severitysiminfo, warning, high, critical
namesimnome do arquivo tripwire sem .yml
originapenas em dependênciasdependency
originatorapenas em dependênciastripwire raiz cujo grupo primeiro causou a emissão desta dependência
tagsapenas se não vazioseparados por vírgula, sem escape (vírgulas não permitidas em nomes de tags)

O conteúdo do arquivo segue após um sentinela <<<TRIPWIRE_FILE_CONTENT>>> (escolhido para ser improvável em código real; se precisar de separação inequívoca, use inject_mode: metadata). Quando tripwires são suprimidos, um bloco <<<TRIPWIRE_SUPPRESSED count="N" reason="context_budget">>> lista grupos raiz suprimidos como linhas <severity> <name> e termina com <<<END_TRIPWIRE_SUPPRESSED>>>.

Modos de injeção:

  • prepend (padrão) — contexto + sentinela + conteúdo do arquivo em uma única resposta. Compatibilidade universal; funciona mesmo quando clientes achatam saídas de ferramentas de múltiplos blocos.
  • metadata — contexto e conteúdo do arquivo retornados como blocos de resposta separados. Separação mais limpa, mas depende do cliente preservar os limites dos blocos.

create_tripwire

Permite que agentes criem novos tripwires. Cria um arquivo .yml em .tripwires/.

{
  "name": "db-migration-checklist",
  "triggers": ["migrations/**"],
  "context": "Always run migrations against a copy of prod data first...",
  "severity": "high",
  "learned_from": "Migration #47 corrupted the users table in staging",
  "force": false
}

Comportamento:

  • O name é normalizado para um nome de arquivo canônico (a-z, 0-9, apenas hífens). Db_Migration Checklist torna-se db-migration-checklist.yml.
  • Se um tripwire com o mesmo nome normalizado já existir, a chamada falha (sem sobrescritas silenciosas). Passe force: true para sobrescrever, ou exclua/desative o tripwire existente primeiro.
  • A ferramenta MCP define created_by: "agent:mcp" automaticamente. YAML escrito à mão deve incluir created_by explicitamente — não há padrão; tripwire lint gera erro se ausente.
  • A sobrescrita é atômica (escreve em arquivo temporário, depois renomeia).
  • Se created_by não for "human" e auto_expire_days > 0, uma data expires é adicionada automaticamente.
  • Se require_learned_from for true (padrão) e created_by começar com agent:, learned_from é obrigatório. tripwire lint impõe isso.

list_tripwires

Retorna todos os tripwires ativos, opcionalmente filtrados por caminho, tag ou severidade.

check_tripwires

Dado um caminho de arquivo, retorna quais tripwires seriam acionados — útil para agentes visualizarem antes de ler.

explain

Dado um caminho de arquivo, retorna uma análise estruturada do que seria injetado e por quê: tripwires correspondentes com seus globs, dependências resolvidas, entradas suprimidas, configuração ativa e a injeção renderizada completa. Útil para depuração.

deactivate_tripwire

Desativa suavemente um tripwire sem excluir o arquivo. Adiciona active: false ao YAML.


CLI

tripwire serve [--project <path>]                   # Start MCP server (stdio by default)
tripwire init [--force]                              # Initialize .tripwires/ in current directory
tripwire check <filepath>                            # Show which tripwires match a file
tripwire list [--tag <tag>] [--severity <level>]     # List all tripwires
tripwire lint [--strict] [--prune]                   # Validate all tripwire YAML files
tripwire stats [--json]                              # Show tripwire coverage and statistics
tripwire doctor [--json]                             # Check enforcement setup
tripwire explain <filepath> [--json]                 # Show what would be injected and why

Integração com Git

Tripwires são arquivos simples em .tripwires/. Eles fazem diff, merge e revisão como código.

Fluxo de trabalho recomendado

  1. Agente cria um tripwire após uma correção → aparece em git diff
  2. Desenvolvedor revisa no PR — aceita, edita ou rejeita o tripwire
  3. Tripwires mesclados propagam para toda a equipe no próximo pull
  4. Tripwires expirados são limpos com tripwire lint --prune

Nota de segurança: Tripwires influenciam o comportamento do agente. Trate-os como código — revise-os em PRs, não faça auto-merge de tripwires criados por agentes, e tenha cuidado especial com a severidade critical, pois ela molda como agentes interagem com módulos sensíveis. Veja SECURITY.md para o modelo de ameaças completo, configuração de CODEOWNERS e receitas de CI.

.gitattributes (avançado, opcional)

.tripwires/*.yml merge=union

Ressalva: merge=union faz auto-merge mantendo ambos os lados linha por linha. Isso funciona bem quando dois ramos adicionam arquivos de tripwire diferentes, mas pode duplicar silenciosamente chaves YAML se dois ramos editarem o mesmo tripwire. O padrão mais seguro é merges normais com tripwire lint --strict no CI para detectar qualquer quebra. Use merge=union apenas se sua equipe entender a compensação.

Política de CI recomendada

  1. CODEOWNERS — proteja .tripwires/** para que alterações exijam revisão
  2. CI executa tripwire lint --strict — detecta created_by ausentes, violações de formato, sobreposições críticas
  3. Bloquear críticos criados por agentes — falhe o CI se um diff tocar um arquivo com ambos created_by: agent:* e severity: critical. A aprovação do CODEOWNER é aplicada separadamente via proteção de ramo do GitHub ("Exigir revisão dos Code Owners"):
    BASE=$(git merge-base origin/main HEAD)
    FILES=$(git diff --name-only --diff-filter=ACMRT "$BASE"...HEAD -- .tripwires/ || true)
    [ -z "$FILES" ] && exit 0
    echo "$FILES" | while read -r f; do
      [ -f "$f" ] || continue
      grep -q '^severity:\s*critical\b' "$f" || continue
      grep -q '^created_by:\s*agent:' "$f" || continue
      echo "FAIL: $f is agent-authored critical (block by policy)"
      exit 1
    done
    

Hook de pré-commit (opcional)

tripwire lint --strict

Valida todos os arquivos de tripwire antes do commit — detecta YAML malformado, violações de formato e sobreposições críticas.


Configuração

.tripwirerc.yml opcional na raiz do projeto:

# Injection behavior
inject_mode: prepend          # prepend | metadata  (metadata = structured, not inline)
separator: "\n<<<TRIPWIRE_FILE_CONTENT>>>\n"   # Sentinel between context and file content
max_context_length: 2000      # Truncate injected context beyond this (chars)

# Agent authoring
allow_agent_create: true      # Let agents create tripwires via MCP
require_learned_from: true    # Agents must explain what mistake prompted the tripwire
auto_expire_days: 90          # Default expiry for agent-authored tripwires

# Enforcement (Claude Code hooks)
enforcement_mode: strict      # strict = deny raw reads | advisory = allow with warning

# Filtering
exclude_paths:                # Never check tripwires for these paths
  - "node_modules/**"
  - "dist/**"
  - ".git/**"

Padrões de configuração

ChaveTipoPadrãoNotas
inject_mode"prepend" | "metadata""prepend"metadata retorna contexto e conteúdo como blocos separados
separatorstring\n<<<TRIPWIRE_FILE_CONTENT>>>\nsentinela entre contexto e conteúdo do arquivo — improvável em código normal, mas pode aparecer em heredocs, templates ou fixtures de teste que referenciam o próprio Tripwire
max_context_lengthnumber0 (ilimitado)orçamento de caracteres (não tokens) — truncamento de tripwire inteiro, nunca corta no meio do bloco
allow_agent_createbooleantruedefina false para bloquear tripwires criados por agentes
require_learned_frombooleantrueagentes devem explicar o erro
auto_expire_daysnumber900 = sem expiração automática
enforcement_mode"strict" | "advisory""strict"advisory permite leituras brutas com um aviso
exclude_pathsstring[]["node_modules/**", "dist/**", ".git/**"]nunca verifique tripwires para estes
tripwires_dirstring".tripwires"diretório contendo arquivos YAML
max_dependency_depthnumber5profundidade máxima para resolução de cadeia depends_on
match_casebooleantruedefina false para correspondência sem diferenciar maiúsculas/minúsculas (recomendado em macOS/Windows)

Chaves desconhecidas são silenciosamente ignoradas. Use tripwire lint --strict para detectar problemas de configuração.


Aplicação (Hooks do Claude Code)

Sem aplicação, um agente pode contornar o Tripwire usando a ferramenta embutida Read em vez de mcp__tripwire__read_file. Um hook PreToolUse fecha essa lacuna bloqueando leituras brutas e redirecionando-as através do Tripwire.

Compatibilidade: Hooks de aplicação são atualmente específicos do Claude Code. Cursor e outros clientes MCP precisarão de seu próprio mecanismo para redirecionar leituras. O servidor MCP em si é universal — apenas a camada de aplicação é específica do editor.

Configuração

O Tripwire vem com um hook pronto. Copie ambos os arquivos para o seu projeto:

.claude/
  settings.json                  # Hook config: intercepts Read calls
  hooks/
    enforce-tripwire-read.mjs    # Denies raw reads, suggests tripwire read_file

Nenhuma dependência externa necessária — o hook é Node.js puro.

Como funciona

  1. Agente chama Read (ou mcp__filesystem__read_file) para um arquivo do projeto
  2. Hook resolve o caminho real via realpath (previne bypass por symlink/traversal)
  3. Hook verifica se .tripwires/ existe e se .mcp.json tem um servidor "tripwire" configurado
  4. Se ambas as condições forem atendidas e o arquivo não estiver em um diretório excluído, o hook nega a leitura
  5. A mensagem de negação informa ao agente o nome exato da ferramenta e a forma do argumento a usar em vez disso
  6. Agente tenta novamente com mcp__tripwire__read_file — o contexto é injetado automaticamente

Válvulas de segurança:

  • Se .tripwires/ não existir, o hook não faz nada (não é um projeto Tripwire)
  • Se .mcp.json não tiver um servidor "tripwire", o hook permite a leitura (agente não tem alternativa — previne loops)
  • Se a mensagem de negação incluir: "Se o Tripwire MCP não estiver disponível, execute: tripwire doctor"

Diretórios excluídos (sempre permitidos via Read): .git/, node_modules/, dist/, .tripwires/, .claude/.

Modos de aplicação

Definido em .tripwirerc.yml:

ModoComportamentoCaso de uso
strict (padrão)Negar leituras brutas, forçar TripwireProdução, equipes estabelecidas
advisoryPermitir leituras brutas com um avisoAdoção progressiva, avaliação

Verificar

tripwire doctor

Verifica todos os componentes e imprime ENFORCEMENT: ON, PARTIAL ou OFF com instruções de correção acionáveis.

Notas importantes

  • A chave do servidor MCP em .mcp.json deve ser "tripwire" para que o nome da ferramenta resolva para mcp__tripwire__read_file
  • A aplicação é opcional, mas fortemente recomendada — sem ela, o Tripwire depende do agente escolher a ferramenta certa

Princípios de Design

O codebase é a fonte da verdade, não a memória do agente. O Tripwire externaliza conhecimento para o repositório para que sobreviva entre sessões, agentes e membros da equipe.

O conhecimento encontra o agente. Agentes não precisam saber o que procurar. O contexto certo chega no momento certo, acionado pelo que eles estão realmente fazendo.

Git é a camada de sincronização. Sem armazenamento proprietário, sem dependência de nuvem. Tripwires viajam com o código e passam pelo mesmo processo de revisão.

Humanos curadores, agentes acumuladores. Agentes criam tripwires a partir de erros. Humanos revisam e podam. O sistema fica mais inteligente ao longo do tempo sem manutenção manual.

Arquivos simples em vez de abstrações inteligentes. Qualquer pessoa pode abrir um arquivo YAML e entender o que um tripwire faz. Sem bancos de dados, sem embeddings, sem linguagens de consulta.


Exemplos

Prevenir erros comuns

# .tripwires/no-orm-raw-sql.yml
triggers:
  - "src/models/**"
context: |
  Use the ORM for all queries. Raw SQL is not allowed in model files
  due to SQL injection risk. If you need a complex query, add it to
  src/queries/ with parameterized statements.
severity: high
created_by: human

Aplicar decisões arquiteturais

# .tripwires/event-driven-orders.yml
triggers:
  - "src/orders/**"
  - "src/inventory/**"
context: |
  Orders and Inventory communicate via events only (see src/events/).
  Never import directly between these modules.
  ADR-007 has the full rationale.
severity: critical
created_by: human
tags: [architecture]

Preservar conhecimento tribal

# .tripwires/csv-export-encoding.yml
triggers:
  - "src/export/**"
context: |
  Japanese customers require Shift-JIS encoding for CSV exports.
  UTF-8 with BOM also works but some older Excel versions on
  Windows JP break. Always test with the fixtures in test/fixtures/jp/.
severity: warning
created_by: agent:claude-code
learned_from: "Generated UTF-8 CSVs that showed garbled text for JP users"

Proteções temporárias

# .tripwires/frozen-for-audit.yml
triggers:
  - "src/billing/**"
  - "src/compliance/**"
context: |
  These modules are frozen during the Q1 audit (ends 2026-03-15).
  Do not modify without explicit approval from @finance-team.
severity: critical
created_by: human
expires: 2026-03-15
tags: [temporary, compliance]

Solução de problemas

Execute tripwire doctor primeiro — ele verifica todos os componentes e informa exatamente o que está errado.

SintomaCausa provávelCorreção
Nenhum contexto injetadoAgente usou Read em vez de mcp__tripwire__read_fileAtive hooks de aplicação (veja Aplicação)
Contexto injetado, mas hook não bloqueando.claude/settings.json ausente ou matcher erradoExecute tripwire doctor, verifique a configuração do hook
Agente preso em loop de negaçãoServidor MCP do Tripwire não carregadoVerifique se .mcp.json tem a chave "tripwire", reinicie a sessão
tripwire doctor mostra FAIL no MCP.mcp.json ausente ou chave de servidor erradaA chave do servidor deve ser "tripwire" (não "tw", não "tripwire-mcp")
Hook não disparando de forma algumaArquivo de configurações não carregadoReinicie a sessão do Claude Code após criar .claude/settings.json
Funciona no Claude Code, não no CursorCursor não tem hooks PreToolUseVeja Estratégia para Cursor

Modo Proxy de Sistema de Arquivos

O Tripwire inclui 4 ferramentas de sistema de arquivos para que possa servir como o único provedor de FS para clientes MCP. Apenas read_file injeta contexto — as outras 3 são passagens diretas simples:

FerramentaComportamento
read_fileVerifica tripwires, injeta contexto, retorna conteúdo do arquivo
list_directoryLista entradas em um diretório (passagem direta)
file_statRetorna tipo, tamanho, modificado, criado (passagem direta)
search_filesPesquisa glob por arquivos (passagem direta)

Configure o Tripwire como o único servidor de sistema de arquivos. Os agentes descobrem as ferramentas disponíveis no momento da conexão via tools/list do MCP — se nenhum outro servidor fornecer ferramentas de sistema de arquivos, os agentes devem usar as versões do Tripwire e todas as leituras recebem injeção de contexto automaticamente.

Limitação rígida: O modo proxy só funciona se o cliente não tiver acesso a arquivos não-MCP habilitado. Se o cliente fornecer um comando nativo Read, os agentes podem contornar o Tripwire usando esse comando.

Como fechar a lacuna por cliente:

  • Claude Code — tem uma ferramenta nativa Read que contorna o MCP. Use hooks de aplicação (PreToolUse) para negar leituras brutas. O modo proxy sozinho não é suficiente.
  • Cursor — o modo proxy cobre leituras que passam por ferramentas MCP. Se o Tripwire for o único servidor que fornece ferramentas de sistema de arquivos, isso é suficiente. Se o Cursor tiver outros caminhos de leitura (dependendo da versão), o Tripwire não pode interceptá-los. Desative outros servidores de FS, se presentes.
  • Outros clientes MCP — verifique se o cliente tem acesso a arquivos integrado. Se tiver e não houver mecanismo de hook, o modo proxy não pode garantir a cobertura. Ainda não sabemos quais clientes suportam desabilitar FS nativo — se o seu suporta, nos avise.

Quando usar modo proxy vs. hooks

AbordagemMelhor paraLimitação
Hooks de aplicaçãoClaude Code (suporta PreToolUse)Específico do cliente
Modo proxyCursor, qualquer cliente MCPDeve ser o único servidor de FS
AmbosCobertura máximaMais configuração

Estratégia para Cursor

O servidor MCP do Tripwire funciona no Cursor — os agentes podem chamar read_file, list_tripwires, etc. A diferença é a aplicação: o Cursor não suporta hooks PreToolUse, então não há como bloquear leituras brutas de sistema de arquivos.

Recomendado: Use o modo proxy de sistema de arquivos — configure o Tripwire como o único servidor MCP com capacidade de sistema de arquivos. Com read_file, list_directory, file_stat e search_files disponíveis, os agentes têm acesso completo a FS através do Tripwire. Se nenhum outro servidor fornecer ferramentas de sistema de arquivos, os agentes devem usar as versões do Tripwire, e todas as leituras recebem injeção de contexto automaticamente.


Roadmap

  • Modo proxy de sistema de arquivos — servir ferramentas de leitura/lista/status/busca para que o Tripwire seja o único provedor de FS
  • Detecção de obsolescência — sinalizar tripwires cujos arquivos acionados mudaram significativamente desde a criação
  • Análises de disparo — rastrear quais tripwires disparam mais, quais nunca disparam (candidatos para remoção)
  • Correspondência semântica — corresponder por conteúdo/intenção do arquivo, não apenas por globs de caminho
  • Integração com editor — mostrar indicadores de tripwire na margem do VS Code
  • tripwire suggest — analisar git blame e comentários de PR para propor tripwires automaticamente

Licença

MIT