Skip to content

Quickstart

This walkthrough takes you from zero to a running Kozou stack you understand. You write a PostgreSQL schema; Kozou reads it once and serves an Admin UI, a REST layer, and MCP context from the same DDL and COMMENT — no duplicate definitions.

Plan for about 10 minutes. By the end you will have a stack running locally and an AI agent reading your schema over MCP.

  • PostgreSQL — the single source of truth for your schema.
  • A REST layer — served by PostgREST in v0.1, brought up as a side-by-side container.
  • An Admin UI — a browser CRUD interface generated from your tables and views, on port 3333.
  • An MCP endpoint — read-only schema context for AI agents, over HTTP on port 3334, or over stdio for a direct agent connection.
  • PostgreSQL 16 or later — the canonical source of truth. The scaffolded stack brings up its own PostgreSQL container, so a local install is not required for this walkthrough.
  • Docker 24 or later — recommended, for the docker compose up stack.
  • Node.js 20 or later — for running the published packages directly with npx.

If you would rather install the CLI globally or pull the runtime image instead of using npx, see Installation.

create-kozou ships as a secondary bin of the kozou package rather than a standalone npm package, so npx needs -p kozou to find it on a clean machine:

Terminal window
npx -p kozou create-kozou my-project
cd my-project

This writes a project directory from the bundled templates. Look at what was generated:

my-project/
├── docker-compose.yml # PostgreSQL + PostgREST + a `kozou` service
├── kozou.config.yaml # database URL, adapter, and UI-hints path
├── ui-hints.yaml # optional per-column label / widget overrides
├── .env.example # template for the env vars the stack reads
└── migrations/ # your schema; starts with a placeholder 0001_init.sql

One line each:

  • docker-compose.yml — brings up PostgreSQL, PostgREST (the REST layer), and a kozou service that runs kozou dev to host the Admin UI and the MCP HTTP server.
  • kozou.config.yaml — points Kozou at your database (${DATABASE_URL}), selects the REST adapter, and references your UI hints. ${VAR} and ${VAR:-default} are expanded from the environment at load time.
  • ui-hints.yaml — an optional file for overriding a column’s label, input widget, or display field without touching the database. Heuristics and COMMENT tags cover most cases, so this starts mostly empty.
  • .env.example — a template for the environment variables the stack reads, including DATABASE_URL. Copy it to .env in the next step.

The starter migrations/0001_init.sql is an empty placeholder. Add your own CREATE TABLE / CREATE VIEW / COMMENT ON … statements there — for example a products table, an orders table, and an authors/books relation. Kozou turns that schema into the Admin UI and MCP context you tour below.

Copy the env template, then bring everything up:

Terminal window
cp .env.example .env
docker compose up

Because the kozou service runs kozou dev (the bundled SvelteKit Admin UI plus the MCP HTTP server), docker compose up brings the full stack online in one command. The default ports are:

  • Admin UIhttp://localhost:3333
  • MCP HTTPhttp://localhost:3334

To change them, set server.ui / server.mcp.http in kozou.config.yaml. To run in the background, add -d.

Open http://localhost:3333. The Admin UI is generated entirely from your schema — there is no UI code to write.

  1. Dashboard — lists every table and, in a separate section, every view, each with its label and a description excerpt. Click an entry to open it.
  2. List view — for a table, shows rows with the display field first and the top columns alongside. It supports search (case-insensitive match across columns), sort (click a column header to toggle ascending/descending), and pagination (1-based, 50 rows per page by default).
  3. Create and edit forms — generated from the table’s columns, with widget-aware inputs: an enum column renders as a dropdown, a boolean as a checkbox, a date as a date picker, and so on. Columns filled only by a database default (such as created_at) are read-only on the edit form.
  4. Relation pickers for foreign keys — a foreign-key column renders as a searchable combobox that resolves the referenced row’s label, so you pick a related record by name rather than by id.
  5. Read-only views — a view opens as a list with the same search, sort, and pagination, but no create, edit, or delete controls.

Kozou exposes your schema to AI agents over the Model Context Protocol. For a direct connection from Claude Code or Claude Desktop, register kozou mcp --stdio as an MCP server.

Add an entry to your agent’s MCP configuration. The ${DATABASE_URL} placeholder in the bundled kozou.config.yaml consumes the DATABASE_URL env var, so pass it here:

{
"mcpServers": {
"kozou": {
"command": "npx",
"args": ["-y", "kozou", "mcp", "--stdio"],
"env": {
"DATABASE_URL": "postgres://kozou:kozou@localhost:5432/kozou"
}
}
}
}

Once registered, the agent can call six read-only tools. They are context providers only — they never generate SQL, execute SQL, or write data:

  • list_tables — table names with their labels and descriptions.
  • describe_table — the full schema and COMMENT for one table.
  • list_views — view names with their purpose.
  • describe_view — a view’s columns, purpose, and underlying tables.
  • list_concepts — the business concepts, one per view.
  • get_concept_context — a concept’s related tables and recommended query path.

The stack you started in step 2 also serves these same tools over HTTP on port 3334, which is the transport an agent uses when it connects to the running container rather than spawning its own process.

Kozou reads ordinary PostgreSQL COMMENT text. A few prefix tags are extracted as structured hints — @ai, @widget, @policy, and @example. Add a comment to a column:

COMMENT ON COLUMN products.status IS
'Lifecycle state of the product.
draft: not yet visible
published: visible in public listings
archived: retired from sale
@ai: prefer the published view for public listings
@widget: enum-select';

Two things happen from that one comment:

  • @widget: enum-select changes the Admin UI input. Instead of a plain text field, products.status now renders as a dropdown. @widget is only honored on column comments. (Even without it, Kozou infers enum-select for a column whose CHECK constraint is a value list like status IN ('draft','published','archived') — the tag is the explicit override.)
  • @ai: … reaches the MCP context. The note surfaces through tools such as describe_table and get_concept_context, so an agent writing a query sees your guidance. The @ai line stays in the human-readable body too, so the comment still reads naturally.

For the full set of conventions, see COMMENT conventions.

  • Port already in use — another process is bound to 3333 or 3334. Stop it, or remap the ports via server.ui / server.mcp.http in kozou.config.yaml (and the matching mappings in docker-compose.yml).
  • Database not reachable — confirm DATABASE_URL in your .env matches the PostgreSQL service in docker-compose.yml, and that the database container is healthy (docker compose ps). On a slow first start the other services may come up before PostgreSQL is ready to accept connections.
  • Admin UI form POSTs are rejected — the Admin UI is served over plain HTTP, so SvelteKit needs an ORIGIN. The scaffold sets ORIGIN=${KOZOU_ORIGIN:-http://localhost:3333} for you; keep it in sync with your Admin UI port if you remap it.
  • create-kozou not found — make sure you ran it as npx -p kozou create-kozou …. It is a secondary bin of the kozou package, not a standalone one.
  • COMMENT conventions — every tag (@ai, @widget, @policy, @example) and how each is parsed.
  • Emitted surfaces — what the Admin UI, the REST layer, and MCP each expose, and why.
  • Installation — global install, the runtime image, and using the workspace packages (@kozou/core, @kozou/introspect, @kozou/mcp, @kozou/svelte-ui) as libraries.

The REST layer in v0.1 is provided by PostgREST. The v0.2 line adds an experimental in-house REST layer, @kozou/api, enabled with kozou dev --adapter api; it is experimental and not the default.