Skip to main content
Glama
THE-KIPDEV

saas-audit-mcp

by THE-KIPDEV
README.md
# saas-audit

**Tell a Next.js codebase's claims from its behaviour.** One command reports the
gaps between what a repository declares and what it actually runs — a Prisma
model nothing queries, an environment variable nothing reads, a locale that
drifted out of sync.

Zero dependencies. It reads files. It never runs your code, opens your database,
or sends anything anywhere.

```bash
npx saas-audit
```

```
  Codebase audit
  ────────────────────────────────────────────────

  Size   (code = non-blank, non-comment lines)
  src/app          40 files    2375 code
  src/components   27 files    1890 code
  src/lib          10 files     858 code
  ────────────────────────────────────────────
  total           101 files    6248 code

  Data model   (uses = Prisma client calls in src/)
  User            16 fields    25 uses
  Organization     8 fields     2 uses
  ApiKey          10 fields     6 uses

  Locales   (8 declared · 374 keys in en)
  en  complete    fr  complete    de  complete    …

  No findings. Every model is queried, every env var is wired,
  every locale is complete.
```

---

## Why

Three defects are invisible to TypeScript, invisible to your test runner, and
invisible in review — and each one ships regularly:

| Defect | What you see | What actually happens |
|---|---|---|
| A Prisma model nothing queries | a feature in the schema | an empty table, forever |
| `process.env.X` missing from `.env.example` | works on your machine | `undefined` on a fresh clone, failing silently |
| A translation key in `en.json` only | the English page is fine | every other language throws at render |

`saas-audit` looks for exactly those. When it prints nothing, that is a result.

It came out of a commercial Next.js starter whose landing page makes claims about
its own code. Running this in CI is how those claims stay true — and the first
run reported six findings against the very repository that shipped it.

## What it reports

- **Size** — files, total lines, and lines that are neither blank nor a comment,
  per directory. Two numbers, because "lines of code" means whatever the author
  wants it to.
- **Routes** — derived from `src/app/`, never a hand-kept list, with whether
  `middleware.ts` matches each one. A blank is not a guarantee: a route can guard
  itself.
- **Data model** — every Prisma model with how many times `src/` calls its
  generated accessor.
- **Environment** — `.env.example` cross-checked against every `process.env.X` in
  `src/` and every `env("X")` in the schema, in both directions. Variables read
  by an SDK rather than by your code are listed apart instead of called dead.
- **Locales** — for a `next-intl` project: per language, keys missing against the
  default, extra keys, empty values, and **ICU placeholder drift** — `{count}` in
  one file and `{n}` in another, which typechecks and throws for that language's
  visitors.

## Use

```bash
npx saas-audit                  # report on the current directory
npx saas-audit ../other-app     # somewhere else
npx saas-audit --json           # for a script
npx saas-audit --strict         # exit 1 on any finding
```

In CI:

```yaml
- run: npx saas-audit --strict
```

## For coding agents (MCP)

The same analysis, over the Model Context Protocol. An agent asking `route_map`
gets every route and its protection in one call, instead of reading twenty files
and guessing.

```bash
claude mcp add saas-audit -- npx -y saas-audit-mcp
```

Any MCP client works — stdio transport, JSON-RPC 2.0:

```json
{
  "mcpServers": {
    "saas-audit": { "command": "npx", "args": ["-y", "saas-audit-mcp"] }
  }
}
```

Eight read-only tools: `audit`, `route_map`, `data_model`, `plans`, `locales`,
`env_check`, `size`, `conventions`. Nothing writes a file, runs a migration or
touches a database, so an agent can explore without asking permission.

## What it expects

A Next.js **App Router** project. Everything else is optional and skipped when
absent:

- `prisma/schema.prisma` → the data model section
- `.env.example` → the environment section
- `src/middleware.ts` with `createRouteMatcher([...])` → route protection
- `src/i18n/routing.ts` + `src/messages/*.json` (next-intl) → the locale section

Pages Router is not supported. Drizzle is not read yet — open an issue if you
want it.

## What it is not

Not a linter, not a formatter, not a type checker, not a security scanner. Those
exist and are good. This answers one narrower question: **does this repository do
what it says it does?**

---

Extracted from [SaaS Starter](https://saas-starter.com), a Next.js 15 SaaS
boilerplate that publishes this command's output on its own landing page. MIT.