anvil init, walks through a static route and a validated dynamic route, runs the dev server, exposes that route as an MCP tool with zero duplicated code, and turns a second route into a streaming AI agent — all with the same file-based routing convention.
Coming from an empty directory? Every command below works as-is. Adding Anvil to an existing project? Skip to Installation —
anvil init merges into an existing package.json instead of overwriting it.1
Install and scaffold
Create a project directory and install Anvil plus Zod (used for route and tool schemas):Then scaffold the project structure:Pick 1) Basic API for this walkthrough — press Enter to accept the default. Plain objects returned from a handler are automatically serialized to JSON — no
anvil init writes:package.json— adds"type": "module", thedev/build/start/lintscripts, andanvil-sdk/zodtodependencies(merged in, not overwritten, if the file already exists)tsconfig.json— a strict, ESM-ready config.gitignore— excludesnode_modules/,dist/,.gen/,.anvil/server/routes/get.ts— a starter route:
server/routes/get.ts
res.json(...) boilerplate to write. anvil init never overwrites a file that already exists, so re-running it is always safe.2
Install dependencies and start the dev server
jiti — no separate compile step, and no restart needed when you edit a handler. Confirm it’s working:3
Add a dynamic route
File-based routing maps folders to URL segments. A
[param] folder captures a path parameter, typed from the folder name — add one under server/routes/:server/routes/users/[id]/get.ts
ctx.params.id is typed as a string because the compiler reads the [id] folder name at build time — no manual param typing, and no way for the folder structure and your handler to drift apart. Try it:HttpError sets the response status (404 here) and serializes a clean JSON error body — no manual ctx.res.status(...) calls.4
Expose the route as an MCP tool
Add a Serve it over MCP:Any MCP client — Claude Desktop, an agent framework, or a raw
meta export and a paramsSchema, and the exact same handler becomes callable by any MCP client — no second implementation, no schema drift:server/routes/users/[id]/get.ts
curl JSON-RPC call — can now discover and call get_users_by_id. The paramsSchema becomes the tool’s input schema automatically; there is no separate tool definition to keep in sync with the route. See MCP Overview for stdio transport and standalone tools that don’t back an HTTP route.5
Turn a route into a streaming agent
Agent routes use the same file convention — an See Agent Routes for tool calling, LLM Client for the OpenAI and Gemini drivers, and Multi-Agent Orchestration for composing agents together.
agent.ts file instead of get.ts/post.ts — and stream responses using the Vercel AI SDK data-stream protocol, so useChat works against them with no adapter code:server/routes/chat/agent.ts
No API key handy? Scaffold the agent template instead (
npx anvil init --template agent) — it wires up MockDriver, which returns canned responses with no network calls or API key required, so you can see the streaming protocol working immediately.6
Validate before you ship
anvil lint checks that every paramsSchema key matches the route’s dynamic segments, and that every MCP-exposed schema (paramsSchema, bodySchema, querySchema, outputSchema) converts losslessly to JSON Schema — a .transform() or .refine() on an exposed schema is a build-time error, not a runtime surprise discovered by a caller. Run it in CI alongside anvil build, which also fails hard on structural route conflicts.What you just built
A single route file (server/routes/users/[id]/get.ts) that is simultaneously a typed REST endpoint, a schema-validated MCP tool, and lint-checked at build time — with no duplicated logic between any of those surfaces. That’s the core idea behind Anvil: one file-based route definition, multiple protocols.
Next steps
File-Based Routing
The full routing convention: verbs, groups, catch-alls, and the generated route manifest.
Dynamic Routes
[param] and [...param] segments, Zod validation, and route-conflict rules.MCP Overview
Expose routes and standalone tools as MCP tools — stdio and Streamable HTTP.
Agent Routes
Tool calling, streaming, context assembly, and the
LlmClient driver model.anvil init
Every template, flag, and file
anvil init writes — including merging into an existing project.Observability
Every agent run traced automatically, with a built-in dashboard at
/_anvil.