# Tripwire

> Context injection for AI agents, triggered by the codebase itself

- **Type:** MCP server
- **Install:** `agentstack add mcp-simonrueba-tripwire`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [simonrueba](https://agentstack.voostack.com/s/simonrueba)
- **Installs:** 0
- **Category:** [Integrations](https://agentstack.voostack.com/c/integrations)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [simonrueba](https://github.com/simonrueba)
- **Source:** https://github.com/simonrueba/tripwire

## Install

```sh
agentstack add mcp-simonrueba-tripwire
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# Tripwire

[](https://www.npmjs.com/package/@tripwire-mcp/tripwire)
[](https://github.com/simonrueba/tripwire/actions/workflows/ci.yml)
[](https://opensource.org/licenses/MIT)
[](https://nodejs.org/)
[](https://www.typescriptlang.org/)

**Context injection for AI agents, triggered by the codebase itself.**

Tripwire is a local MCP server that auto-injects relevant context when an agent reads files in your project. Define tripwires on paths — when an agent steps on one, it gets the knowledge it needs before it can do damage.

Agents don't know what they don't know. Tripwire fixes that.

> **Mental model:** Tripwires are path-based policies. They inject context into file reads. They are deterministic and repo-native. Enforcement depends on client support (hooks) or proxy mode.

```
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
```

---

## How It Works

1. **Tripwires live in your repo** as small YAML files in `.tripwires/`
2. **The MCP server handles file read tool calls** and glob-matches against tripwire triggers
3. **Matched context is prepended** to the file content — automatic for the agent, inspectable via `tripwire explain`
4. **Agents author new tripwires** when they make mistakes and get corrected
5. **Everything syncs via git** — tripwires travel with the code, get reviewed in PRs, and propagate across the team

No external services. No databases. No setup beyond starting the server.

> **Threat model:** Tripwires are a privileged instruction channel — a malicious tripwire can steer agents into introducing vulnerabilities. Tripwire is guidance/policy injection, not a permission system. Protect `.tripwires/` with CODEOWNERS, require CI review for all changes, and reject agent-authored `critical` tripwires without human approval. See [SECURITY.md](SECURITY.md) for the full threat model and CI recipes.

---

## Installation

Requires **Node.js >= 18**.

### Quick try (no install)

Add to `.mcp.json` and go:

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

For Cursor, use `.cursor/mcp.json` with the same config.

### Team setup (recommended)

Pin as a dev dependency so everyone gets the same version:

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

Add scripts to `package.json`:

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

Point `.mcp.json` at the local install (no `-y` needed):

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

### Alternative: global install

```bash
npm install -g @tripwire-mcp/tripwire
```

### Any MCP-compatible client

Tripwire speaks standard MCP over stdio. For a complete working setup, see [`examples/hello-tripwire/`](examples/hello-tripwire/).

---

## Quickstart

### Initialize in your project

```bash
cd your-project
tripwire init
```

Creates a `.tripwires/` directory with a starter example.

### Define your first tripwire

```yaml
# .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
```

That's it. Any agent reading files matching those globs now receives this context automatically.

### Let agents learn

When an agent makes a mistake and you correct it, the agent can create a tripwire to prevent the same mistake in future sessions:

```yaml
# .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"
```

---

## Tripwire Format

Each `.yml` file in `.tripwires/` defines one tripwire:

```yaml
# 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
```

### Glob patterns

Tripwire uses standard glob syntax:

| Pattern | Matches |
|---|---|
| `src/auth/**` | Any file under `src/auth/`, any depth |
| `*.sql` | SQL files in root |
| `**/*.sql` | SQL files anywhere |
| `src/api/v{1,2}/**` | Files in v1 or v2 API directories |
| `!**/*.test.ts` | Exclude test files (prefix with `!`) |

### Naming conventions

**Tripwire names** are derived from the YAML filename and normalized to `a-z`, `0-9`, and hyphens. Spaces and underscores become hyphens. Names are case-insensitive — `No_Raw_SQL.yml` becomes `no-raw-sql`. `tripwire lint` checks for duplicate names.

**`created_by`** is required. `tripwire lint` errors if missing. Canonical values:

| Value | Meaning |
|---|---|
| `human` | Hand-written by a developer |
| `agent:` | Created via MCP tool (e.g. `agent:mcp`, `agent:claude-code`) |
| `tool:` | Created by automation (e.g. `tool:ci-generate`) |

`lint --strict` errors on invalid format (bare `agent` or `tool` without a client name is invalid). The MCP `create_tripwire` tool sets `created_by: agent:mcp` automatically.

**Tags** are a YAML string array. Tag names must match `/^[a-z0-9][a-z0-9-]{0,31}$/` (lowercase alphanumeric + hyphens, max 32 chars). `tripwire lint` errors on invalid tags. In injection headers, tags are rendered as an unescaped comma-separated string: `tags="security,architecture"`. The tight regex makes escaping unnecessary.

---

## Behavior Specification

This section documents the exact runtime semantics. Useful for debugging, writing tests, or building alternative clients. If this document conflicts with implementation, the implementation is the source of truth until the next spec revision.

### Path matching

Tripwire uses [micromatch](https://github.com/micromatch/micromatch) for glob matching. Supports brace expansion (`{a,b}`) and negation (`!`).

**Case sensitivity:** Matching is case-sensitive by default (`match_case: true`). When `match_case: false`, matching is case-insensitive (defined as: both the normalized path and trigger patterns are compared without regard to case). On case-insensitive filesystems (macOS, Windows), path casing reported by tools may not match trigger casing — set `match_case: false` in `.tripwirerc.yml` to avoid mismatches.

**Normalization:** Before matching, paths are normalized: backslashes become forward slashes, leading `./` is stripped. Matching uses `dot: true` (dotfiles match `**`).

**Evaluation order:** Config `exclude_paths` is checked first. If a path is excluded, no tripwire evaluation happens — even if a tripwire's triggers would match. Within a tripwire, negation patterns (`!`) apply after positive patterns.

**Positive vs. negation patterns:**
- Positive patterns (e.g. `src/auth/**`) match files for inclusion.
- Negation patterns start with `!` (e.g. `!**/*.test.ts`) and exclude files that would otherwise match.
- A path matches if it matches **at least one** positive pattern AND **zero** negation patterns.
- If **all** patterns are negation, an implicit `**` positive pattern is added (i.e. "match everything except...").

### Ordering

When multiple tripwires match a path, they are sorted deterministically:

1. **Severity descending:** critical (0) > high (1) > warning (2) > info (3)
2. **Name ascending** (alphabetical) within the same severity

This order determines the evaluation and emission order of **root tripwire groups**. A group consists of the root tripwire plus its resolved dependencies (see Dependencies). Dependencies do not participate in global severity/name sorting; they are emitted as part of their root group.

**Severity affects ordering and truncation priority.** It does not enforce hard blocking or write gating. All matched groups are injected when budget allows — higher severity survives truncation first. The level also signals to the agent how seriously to treat the context.

### Truncation

When `max_context_length > 0`, Tripwire enforces a character budget on the injected context (not tokens — different clients may truncate independently). The separator and file content are not part of the budget.

**What counts toward the budget:** the fully rendered injection string — each block's header (`>>`), context body, footer (`>>`), and trailing newline. The suppression block itself is not counted.

- **Whole-tripwire granularity** — a tripwire block is either fully included or fully omitted. Context is never cut mid-block.
- **Budget includes dependencies** — dependency blocks count toward the same budget.
- **Best-effort in sort order** — groups are attempted in sorted order (root severity DESC, root name ASC). Higher-severity groups are attempted first but there is no hard guarantee they fit. If a single group exceeds the budget, it is suppressed — even if it's critical. **Recommended:** keep `max_context_length: 0` (unlimited, the default) for safety-critical repos where every tripwire must fire.
- **Suppressed block** — when groups are omitted, a `>>` block lists the root tripwire name and severity for each suppressed group. Dependencies suppressed as part of an atomic group are not listed individually — the root name identifies the group. **Suppressed entry format:** one line per suppressed root group: ` ` (e.g. `critical billing-freeze`). The block ends with `>>`.

### Dependencies

Tripwires can declare `depends_on: [name1, name2]` to pull in other tripwires' context when they fire.

- **Transitive resolution** — dependencies are resolved transitively up to `max_dependency_depth` (default: 5).
- **Cycle detection** — a visited-set tracks the walk. If a cycle is detected, a warning is emitted and the cycle edge is skipped.
- **Missing dependencies** — if a named dependency doesn't exist, a warning is emitted and resolution continues.
- **Global deduplication** — each dependency block appears at most once per response. A dependency is considered "already emitted" if its full `>> ... >>` block has been included in the rendered injection (suppression does not count as emission). If multiple root groups reference the same dependency, it is emitted **once** with the earliest root group in sort order; its `originator=""` attribute reflects the root tripwire whose group first caused this dependency to be emitted.
- **Group construction** — for each matched root tripwire, a *group* is constructed: the dependency closure (DFS, traversed in `depends_on` list order) followed by the root. Groups are ordered by root severity DESC, then root name ASC. Within a group, dependencies appear in DFS traversal order (stable: sibling order matches `depends_on` declaration order).
- **Atomic truncation** — when `max_context_length > 0`, the entire group (deps + root) must fit within the remaining budget. If the group doesn't fit, all of it is suppressed — the root is never emitted without its dependencies. The group size is computed **after global deduplication**: dependencies already emitted by an earlier group are not re-counted and are not required for group fit. This is safe because dependencies are always emitted with the earliest root group in sort order, so any later root that references that dependency can omit it — the dependency block will appear earlier in the same response.
- **Rendering** — dependencies are rendered with `origin="dependency" originator=""` attributes. `originator` is the root tripwire whose group first caused this dependency to be emitted. The `name` always matches the tripwire filename (e.g. `name="depName"`), never a synthetic composite.

### Conflicts

Tripwire does not attempt to resolve conflicts between contexts. If two tripwires match the same path and give contradictory instructions, both are injected and the agent sees both.

`tripwire lint` checks (always):
- Missing `created_by` field (error)
- Agent-authored tripwire (`created_by: agent:*`) missing `learned_from` when `require_learned_from` is true (error)
- Agent-authored tripwire (`created_by: agent:*`) missing `expires` when `auto_expire_days > 0` (error) — prevents handwritten `agent:*` entries from bypassing auto-expiry
- Invalid tag names — must match `/^[a-z0-9][a-z0-9-]{0,31}$/` (error)

`tripwire lint --strict` adds:
- **Identical trigger sets** (warning) — two tripwires whose sorted trigger arrays are equal (order-insensitive). Exact match, not overlap detection.
- **Critical overlap** (warning) — enumerates project files (glob `**`, files only, filtered by `exclude_paths`, sorted lexicographically, capped at 5000). `.gitignore` is not honored to keep lint results stable across environments; use `exclude_paths` to control scan scope. Warns if any file matches >1 `critical` tripwire. Reports the specific tripwire names.
- **`created_by` format** (error) — must be `human`, `agent:`, or `tool:`. Bare `agent` or `tool` without a client/tool name is invalid.
- **Individual context > 4 KB** (warning) — suggests splitting.
- **Aggregate context > 16 KB** (warning) — total across all tripwires.
- **Critical tripwire exceeds `max_context_length`** (warning) — will be suppressed at runtime.

`tripwire explain ` surfaces all matching tripwires for a given path, making conflicts visible before they cause problems.

---

## MCP Tools

The server exposes these tools to connected agents:

### `read_file`

Drop-in replacement for standard file reading. Checks tripwires and prepends matched context.

```
Agent calls: read_file("src/auth/login.ts")
Returns:
>>
The auth module uses session-based auth, NOT JWT.
See ADR-012 for the migration rationale.
>>

>>

```

**Delimiter format:**

```
" name="" [origin="dependency" originator=""] [tags=""]>>>

>>
```

| Attribute | Always present | Values |
|---|---|---|
| `severity` | yes | `info`, `warning`, `high`, `critical` |
| `name` | yes | tripwire filename without `.yml` |
| `origin` | only on dependencies | `dependency` |
| `originator` | only on dependencies | root tripwire whose group first caused this dependency to be emitted |
| `tags` | only if non-empty | comma-separated, no escaping (commas not allowed in tag names) |

File content follows after a `>>` sentinel (chosen to be unlikely in real code; if you need unambiguous separation, use `inject_mode: metadata`). When tripwires are suppressed, a `>>` block lists suppressed root groups as ` ` lines and ends with `>>`.

**Injection modes:**
- `prepend` (default) — context + sentinel + file content in a single response. Universal compatibility; works even when clients flatten multi-block tool outputs.
- `metadata` — context and file content returned as separate response blocks. Cleaner separation but relies on the client preserving block boundaries.

### `create_tripwire`

Allows agents to author new tripwires. Creates a `

…

## Source & license

This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [simonrueba](https://github.com/simonrueba)
- **Source:** [simonrueba/tripwire](https://github.com/simonrueba/tripwire)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** no
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/mcp-simonrueba-tripwire
- Seller: https://agentstack.voostack.com/s/simonrueba
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
