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:
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.
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/mcptows://localhost:3001, so the browser talks to the same MCP tool surface. - WebSocket API — listens on
ws://localhost:3001/mcp(WS_PORTto 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 →