Documentation · Setup

First run

This guide documents demo data, authentication, and the development loop that will be available when the public repository opens in January 2027.

Seed the demo company

pnpm seed:demo          # seed demo data (tsx packages/migration/src/cli.ts seed)
pnpm seed:demo:clear    # clear existing data first, then seed

The seeder creates Acme Gear Co. (slug acme-gear) with deterministic IDs — tenant 00000000-0000-0000-0000-000000000001 and owner user …0002 — plus three users (admin@ / sales@ / warehouse@acmegear.demo), an owner role and active membership, and a full operating dataset: products, customers, addresses, contacts, orders with line items, suppliers, purchase orders, tax jurisdictions, carriers, rate bands, and carrier shipments. It prints a summary of every count when it finishes.

The oclif CLI wraps the same seeder with more control — pnpm openmom db seed runs migrations first and accepts --count 200 (customers/orders to generate, default 100), --clear, --no-migrate, --json, and --url. The CLI also provides db up / down / init / migrate / status.

Choose an authentication mode

There are no login tools in the API — every call carries its own identity. The mode is selected with OPENMOM_AUTH_MODE:

Default

OPENMOM_AUTH_MODE=static

Every call runs as one fixed caller — by default the seeded Acme Gear Co. tenant and owner user (00000000-…-0001:00000000-…-0002, overridable with OPENMOM_STATIC_CALLER as tenantId:userId). This is what makes the OSS demo work with no login screen. The resolver still validates against the database on every call that the tenant, membership, and user are active.

Per-call keys

OPENMOM_AUTH_MODE=keys

Calls authenticate with an API key supplied as the x-openmom-api-key header, an Authorization: Bearer header, or an openmom_api_key cookie (name configurable via OPENMOM_AUTH_COOKIE_NAME). Keys map to callers in the environment:

OPENMOM_AUTH_MODE=keys
OPENMOM_API_KEYS=s3cr3t-ops=00000000-0000-0000-0000-000000000001:00000000-0000-0000-0000-000000000002
OPENMOM_DEV_CALLER=00000000-0000-0000-0000-000000000001:00000000-0000-0000-0000-000000000002

OPENMOM_API_KEYS is a comma-separated key=tenantId:userId map. OPENMOM_DEV_CALLER is the caller used when a request presents no key — a development convenience that the server refuses to start with in production (NODE_ENV=production). A key that maps to an inactive tenant, membership, or user is rejected.

These values are operator-injected (environment or secret store) — the repo only ships dev-shaped examples in .env.example, and the real .env is gitignored.

Provision a real tenant

pnpm identity:provision --name "Northwind Supply" --slug northwind \
  --owner-email owner@northwind.example --owner-name "Pat Doe"

identity-cli.ts provision creates a tenant, its owner user, and the active owner membership in one step (platform-side, via DATABASE_URL). Point OPENMOM_API_KEYS at the printed tenant/user IDs to call the API as that tenant. Inside the API, the identity.* tools (invite users, create and assign roles, inspect effective permissions) handle day-to-day tenant administration — see the API reference.

Run the apps

pnpm dev          # WS API (:3001/mcp) + web app (:5173) together
pnpm dev:ws       # WebSocket MCP server only
pnpm dev:api      # stdio MCP server only (for MCP desktop clients)
pnpm web          # Vite dev server only
  • Web app — React 19 + Vite on port 5173 (strict). In dev it proxies /mcp to ws://localhost:3001, so the browser talks to the same MCP tool surface.
  • WebSocket API — listens on ws://localhost:3001/mcp (WS_PORT to change). One MCP server instance per connection.
  • stdio API — the same tool registry over stdio, for MCP clients that spawn processes (Claude Desktop, IDEs, scripts).

Sanity-check the stack with system.health (server + database connectivity over the app-role path) and system.whoami (the caller the resolver picked for your call) — both are documented with the rest of the surface in the API reference. When you're ready for production, continue to Self-Hosting →