Skip to main content
Glama
README.md
# ShadowRun

A local-first stdio proxy for MCP servers. It sits between an AI agent
(Claude Code, Cursor, etc.) and a real MCP server, traps destructive tool
calls (writes, deletes, SQL mutations, ...) before they execute, and holds
them in memory until you **commit** or **discard** them from a local
dashboard.

Unlike a naive "fake success" interceptor, ShadowRun does **not** reply to
the agent until a trapped call is resolved. Faking a response (e.g. for an
`INSERT ... RETURNING id`) lets the agent act on data that doesn't exist yet
and diverges its belief state from reality — so trapped calls simply wait
(with a timeout) instead.

## Scope (v0.1)

This is intentionally narrow: a single-developer CLI for local MCP servers
(Postgres, filesystem, etc.) used with Claude Code / Cursor. It is **not**
a team policy-enforcement gateway, has no auth, and no persistence across
restarts — see [Limitations](#limitations) below before relying on it for
anything beyond your own machine.

## Install & run

```bash
npm install
npm run build
```

Point your agent config at the proxy instead of the real server:

```json
{
  "mcpServers": {
    "postgres": {
      "command": "node",
      "args": [
        "/path/to/shadowrun-mcp/dist/index.js",
        "npx", "-y", "@modelcontextprotocol/server-postgres",
        "postgresql://localhost:5432/devdb"
      ]
    }
  }
}
```

Open http://127.0.0.1:4040 to see pending mutations, and Commit or
Discard each one. Read-only calls (`get*`, `list*`, `search*`, ...) pass
through immediately and never appear in the dashboard.

## How classification works

See `src/interceptor.ts` — `DEFAULT_CONFIG`. A tool call is trapped if its
name matches a mutating verb pattern (`write`, `delete`, `create`, ...) and
doesn't match a safe-read pattern first, or if any string argument contains
a SQL mutation keyword (`insert into`, `drop table`, ...). This is a
heuristic, not a guarantee — see Limitations.

## Limitations

- **Heuristic classifier.** Regex on tool names and argument text will
  miss cleverly-named mutating tools and may over-trap oddly-named
  read tools. Treat this as a speed bump, not a security boundary.
- **No auth on the dashboard.** It binds to `127.0.0.1` only, but any
  local process (or a malicious page doing DNS rebinding, in theory) that
  can reach that port can commit/discard. Don't run this on a shared or
  untrusted machine.
- **In-memory only.** Restarting the proxy drops all pending mutations —
  the agent's original call will simply time out.
- **Single developer, local use.** There's no shared audit log or
  team-wide policy enforcement. If you need that, look at a hosted MCP
  gateway instead.

## License

AGPL-3.0

---

*Test note: small commit pushed via Composio (2026-08-18) to verify author config.*