Skip to main content
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

anvil lint [options]

Flags

-r, --routes <dir>
string
default:"server/routes"
Directory Anvil scans for route files. Must match the layout used by your application.
--strict
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.

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-missingparamsSchema exists but is missing one or more params declared by the folder path.
  • params-extraparamsSchema 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

  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

[anvil] lint: no issues found
The process exits with code 0.

Example output: warnings with --strict

anvil lint --strict
  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. Add anvil lint as an early gate in your CI pipeline, especially before deploying MCP tools:
# .github/workflows/ci.yml
- name: Lint routes
  run: npx anvil lint --strict
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.
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.