> ## Documentation Index
> Fetch the complete documentation index at: https://anvil.thatdevguy.in/llms.txt
> Use this file to discover all available pages before exploring further.

# anvil lint: Validate Routes, Params, and Tool Schemas

> Validate routes for param mismatches and lossy MCP schemas, printing structured diagnostics and exiting non-zero on errors or strict-mode warnings.

Run `anvil lint` to validate your routes directory without starting a server or emitting any build artifacts. Lint catches two classes of problems: route parameter inconsistencies (where the folder name declares a param that the schema does not cover, or vice versa) and schema serializability issues (where a Zod schema used on an MCP-exposed route cannot be losslessly converted to JSON Schema). Catching these problems at lint time prevents silent failures at runtime.

## Usage

```bash theme={null}
anvil lint [options]
```

## Flags

<ParamField query="-r, --routes <dir>" type="string" default="server/routes">
  Directory Anvil scans for route files. Must match the layout used by your application.
</ParamField>

<ParamField query="--strict" type="boolean">
  Treat warnings as errors. When set, `anvil lint` exits with code `1` if there are any warnings, even if there are no hard errors. Use this in CI pipelines where warnings must be resolved before merging.
</ParamField>

## Rule categories

### `param-mismatch` — errors

Anvil derives expected URL parameters from your folder names (e.g. a folder named `[id]` declares an `id` param). Lint raises an error if:

* **`params-missing`** — `paramsSchema` exists but is missing one or more params declared by the folder path.
* **`params-extra`** — `paramsSchema` declares a key that has no corresponding folder segment.

These are always `error`-level and cause a non-zero exit regardless of `--strict`.

### `mcp-schema-not-serializable` — errors

For MCP-exposed routes, every schema export (`paramsSchema`, `querySchema`, `bodySchema`, `outputSchema`) must round-trip losslessly to JSON Schema. If a Zod type cannot be converted — for example, a `z.transform()` or a custom refinement — lint reports an `error`-level diagnostic with rule `mcp-schema-not-serializable`.

### `mcp-missing-description` — warnings

An MCP-exposed route with no `meta.mcp.description` string gets a `warning`-level diagnostic. The tool will still register, but agents typically rely on descriptions to decide when to call a tool. Pass `--strict` to promote this to an error in CI.

## Example output: errors present

```text theme={null}
  error  POST /api/orders/[id]     paramsSchema is missing route parameter(s): "id". The folder declares [id].
         server/routes/api/orders/[id]/POST.ts  [params-missing]

  warn   GET /api/chat             MCP-exposed route has no meta.mcp.description. Tools without descriptions are hard for agents to use.
         server/routes/api/chat/GET.ts  [mcp-missing-description]

[anvil] lint: 1 error(s), 1 warning(s)
```

The process exits with code `1` because there is at least one error.

## Example output: clean run

```text theme={null}
[anvil] lint: no issues found
```

The process exits with code `0`.

## Example output: warnings with `--strict`

```bash theme={null}
anvil lint --strict
```

```text theme={null}
  warn   GET /api/chat             MCP-exposed route has no meta.mcp.description. Tools without descriptions are hard for agents to use.
         server/routes/api/chat/GET.ts  [mcp-missing-description]

[anvil] lint: 0 error(s), 1 warning(s)
```

Exits with code `1` because `--strict` is set and there is one warning.

## Recommended CI step

Add `anvil lint` as an early gate in your CI pipeline, especially before deploying MCP tools:

```yaml theme={null}
# .github/workflows/ci.yml
- name: Lint routes
  run: npx anvil lint --strict
```

<Note>
  `anvil lint` does not start a server, write any files, or run your handler functions. It imports each route module purely to inspect its exported schemas and metadata, then exits.
</Note>

<Tip>
  Combine `anvil lint --strict` with `anvil build --manifest-only` as a fast, artifact-free CI validation pass. Both commands finish in seconds and together cover the full range of compile-time issues.
</Tip>
