CLI reference

kervan create, kervan dev and kervan run. The summary below is the real --help output, minus one line about the optional web UI.

Where this fits: Run and operate. The command line that creates projects and serves specs and code.

On this page

Until the packages are published, run the CLI from a clone as node packages/cli/bin/kervan.js <command>; afterwards, npx kervan <command>. The CLI refuses Node.js versions outside 22.23.3 or a later 22.x, or 24.21.0 or later, with one line.

kervan --help
Usage: kervan <command> [options]

Commands:
  create <dir>   Create a new Kervan MCP server project
    --name <name>        Package name (default: the directory name)
    --pm <manager>       npm, pnpm, yarn or bun (default: the one running this command, else npm)
    --no-install         Skip installing dependencies
  dev <entry>    Run a server (a .ts/.js entry or a kervan.yaml spec) with hot reload
    --http               Serve on http://127.0.0.1:<port>/mcp with a REPL (default in a terminal)
    --stdio              Serve on stdin/stdout (default when started by an MCP client)
    --port <port>        HTTP port (default 3000)
    --drain-timeout <ms> How long a reload waits for running calls (default 10000)
    --repl / --no-repl   Force the terminal inspector on or off
    --no-watch           Do not restart on file changes
    --env-file <path>    Load environment variables (repeatable; set variables win)
    --allow-private-network  Specs only: let tools reach private and loopback addresses
    --allow-insecure-secrets Specs only: let tools send secrets over plain http
    --deny-network <cidr>    Specs only: an address or range tools may never reach (repeatable)
  run <spec>     Serve a kervan.yaml spec
    --http               Serve Streamable HTTP instead of stdio
    --port <port>        HTTP port (default 3000)
    --host <host>        HTTP bind address (default 127.0.0.1)
    --allowed-host <h>   Host name clients use (repeatable; required off localhost)
    --env-file <path>    Load environment variables (repeatable; set variables win)
    --watch              Reload the spec when it changes
    --allow-private-network  Let tools reach private addresses (refused in production)
    --allow-insecure-secrets Let tools send secrets over plain http (refused in production)
    --deny-network <cidr>    An address or range tools may never reach (repeatable)

Options:
  -h, --help     Show this help
  -v, --version  Show the version

kervan create

Before the packages are on npm

kervan create installs @kervan/core, @kervan/transport and kervan from the npm registry, where they are not published yet: the install fails, or, once someone else registers those names, installs their packages. Until the release, use pnpm try:new <dir> from a clone, which installs the packages built from that clone (quickstart), or pass --no-install.

Creates a project from the basic template: an app with two tools, a test using createTestClient, and scripts for dev, start, build and test.

OptionDescription
--name <name>npm package name (default: the directory name)
--pm <manager>npm, pnpm, yarn or bun (default: the one that ran create, else npm)
--no-installDo not install dependencies

The target directory must be new or empty.

Generated projects run TypeScript directly with Node.js’s built-in type stripping. Kervan’s tools and generated projects need Node.js 22.23.3 or a later 22.x, or 24.21.0 or later (the oldest releases the whole test suite has passed on); create, dev and run refuse older versions with one line, and a generated project’s npm start does too. Relative imports use the .ts extension, and the tsconfig.json enables rewriteRelativeImportExtensions (so tsc emits .js imports) and erasableSyntaxOnly (no enums or namespaces, which type stripping cannot run).

kervan run

Serves a kervan.yaml spec (see @kervan/spec-runtime).

sh
kervan run kervan.yaml                                   # stdio
kervan run kervan.yaml --http --port 8080                # http://127.0.0.1:8080/mcp
kervan run kervan.yaml --http --host 0.0.0.0 --allowed-host mcp.example.com
kervan run kervan.yaml --env-file .env --watch
OptionDescription
--httpStreamable HTTP instead of stdio
--port, --hostDefault 3000 and 127.0.0.1
--allowed-host <name>Host names clients use (repeatable). Required when --host is not localhost.
--env-file <path>Variables for {{secrets.X}} (repeatable). Variables already set win.
--watchReload the spec when it changes; an invalid edit keeps the last good version.
--allow-private-networkLet tools reach internal addresses. Development only; refused with NODE_ENV=production.
--deny-network <cidr>An address or range tools may never reach (repeatable); wins over --allow-private-network.
--allow-insecure-secretsLet tools send secrets to plain http:// URLs (a local API). Development only; refused with NODE_ENV=production.

An invalid spec stops run with the file, line and column of every problem. Secret values never appear in the output. Note: Node.js itself checks --env-file arguments, even after the script name, and exits with <file>: not found (code 9) when the file is missing.

kervan dev

Runs your server with hot reload. Your code runs in a child process; kervan dev is a stable MCP server in front of it that clients stay connected to. Given a .yaml/.yml spec instead, it reloads the spec in its own process (--env-file, --allow-private-network and --allow-insecure-secrets work as for run).

sh
kervan dev src/index.ts            # in a terminal: HTTP on 127.0.0.1:3000 plus a REPL
claude mcp add my-server -- node /path/to/kervan/packages/cli/bin/kervan.js dev /abs/path/src/index.ts   # stdio, for MCP clients
OptionDescription
--http / --stdioDefault: HTTP with a REPL in a terminal, stdio when started by a client
--port <port>HTTP port (default 3000). The host is always 127.0.0.1.
--drain-timeout <ms>How long a reload waits for running calls (default 10000)
--repl / --no-replForce the terminal inspector on or off (HTTP mode)
--no-watchDo not restart on file changes
  • Reloads. Saving a .ts/.js/.json file (outside node_modules, dist, .git) starts a new child first; only when it is up does kervan dev switch to it, so a syntax error keeps the last good version running. Clients get list_changed only if the tools actually changed. The server’s own runtime changes (app.tool() at runtime) are followed too.
  • Running calls. The previous child keeps running until its calls finish, up to --drain-timeout. Calls still running then fail with “interrupted because the server reloaded”.
  • Stopping the child never uses signals, which cannot ask a Windows process to shut down: kervan dev closes the child’s stdin (a stdio MCP server exits on EOF), and if the process is still alive after 2 seconds it kills the process tree (taskkill /T /F on Windows).
  • Security. HTTP mode only binds to 127.0.0.1 and keeps the Host/Origin checks, so a web page cannot reach your tools through DNS rebinding. Values of secret-looking environment variables (*_TOKEN, *_API_KEY, *PASSWORD*, DATABASE_URL, …) and credentials in URLs are replaced with [redacted] in everything kervan dev prints and in error results it forwards.
  • Development only. kervan dev refuses to start with NODE_ENV=production. File watching lives only in this CLI; @kervan/core and @kervan/transport never watch files.

REPL commands: tools, call <tool> [json], reload, help, exit. Calls go through the same app that serves clients, so validation and error masking match what a client sees.