Documentation · API Reference

The MCP tool API

OpenMOM has no REST surface. The entire system — orders, customers, inventory, purchasing, shipping, tax, channels, recurring programs, identity, audit — is exposed as 305 MCP tools across 28 top-level namespaces, so operators, scripts, and AI agents all drive the same validated surface.

305
Tools
28
Namespaces
61
Typed IDs

The contract

The API is an MCP server (built on the official @modelcontextprotocol/sdk) named openmom. Every tool follows the same rules:

  • Zod-validated inputs. Each tool's input schema is a strict Zod object, validated before the handler runs — unknown keys are rejected, and the SDK surfaces invalid arguments as InvalidParams. Nullable columns accept null (clearing the value); NOT NULL columns reject explicit null.
  • Discriminated results. Tools never throw at the caller. Every result is { ok: true, data } or { ok: false, error: { code, message } }, returned both as JSON text and MCP structuredContent.
  • Typed IDs. All identifiers are RFC-4122 UUIDs with compile-time brands (OrderId, CustomerId, … 61 branded types) — plain UUID strings on the wire, but unmixable in code.
  • Per-call identity. Every call resolves a caller (tenantId:userId); the data layer sets app.tenant_id inside each transaction and Postgres row-level security does the isolation. There are no login tools.

Error codes

Code Meaning
invalidInputSchema or semantic validation failure
notFoundEntity missing or soft-deleted
ambiguousLookup matched more than one candidate
conflictUniqueness violation or illegal state transition
unauthorizedNo/unknown key, or caller not active for the tenant
forbiddenCaller active but lacking the required role
tenantNotSetRequest reached the data layer without a tenant context
notImplementedDeclared seam not yet wired
internalUnexpected failure (details in server logs, never leaked to callers)

Authentication

Auth is configured per deployment, not per call session — see Setup for the full configuration. In short: static mode pins one demo caller (OSS default); keys mode authenticates every call from an API key sent as the x-openmom-api-key header, an Authorization: Bearer header, or the openmom_api_key cookie. Every call — in either mode — re-validates that the caller's tenant, membership, and user are active before touching data, and every query runs under the openmom_app role with SET LOCAL app.tenant_id and forced row-level security.

Worked example: orders.create

Creating an order is one atomic call — header, line items, and payments are persisted in a single transaction, the order number is allocated from a per-tenant sequence, and unit prices default server-side from the product catalog when omitted:

{
  "customerId": "6a1f2b3c-4d5e-4f60-a718-9b0c1d2e3f40",
  "shipVia": "UPS Ground",
  "items": [
    { "productId": "a1b2c3d4-e5f6-4a70-8291-3c4d5e6f7a80", "quantity": 2 },
    { "productId": "b9c8d7e6-f5a4-43b2-910f-6e5d4c3b2a19", "quantity": 1, "discountPct": 10 }
  ],
  "payments": [
    {
      "method": "credit_card",
      "amount": "149.9700",
      "brand": "visa",
      "lastFour": "4242",
      "expiryMonth": 12,
      "expiryYear": 2028,
      "processorToken": "tok_visa_9f8e7d6c5b4a"
    }
  ]
}

The payment union is deliberately tokenized-only: method selects one of seven payment shapes (credit_card, ach, check, cod, invoice_terms, paypal, gift_card), and the strict schemas reject a stray PAN- or CVV-shaped key with invalidInput instead of silently storing it. The response:

{
  "ok": true,
  "data": {
    "id": "0f1e2d3c-4b5a-4968-8776-5a4b3c2d1e0f",
    "orderNumber": 1042,
    "status": "draft",
    "customerId": "6a1f2b3c-4d5e-4f60-a718-9b0c1d2e3f40",
    "subtotal": "149.9700",
    "total": "149.9700",
    "lineItems": [
      { "id": "11aa22bb-cc33-4d44-8e55-ff66aa77bb88", "productId": "a1b2c3d4-e5f6-4a70-8291-3c4d5e6f7a80", "quantityOrdered": 2, "unitPrice": "49.9900" },
      { "id": "77aa88bb-cc99-4d00-9e11-22aa33bb44cc", "productId": "b9c8d7e6-f5a4-43b2-910f-6e5d4c3b2a19", "quantityOrdered": 1, "unitPrice": "59.9700", "discountPct": 10 }
    ]
  }
}

Output abridged — IDs and totals illustrative; structure per the orders schema

From there the order walks the same staged pipeline as MOM, with each stage latched by its own tool so nothing skips ahead: orders.pickorders.packorders.readyToShiporders.ship (consumes stock FIFO, backorders short lines) → orders.invoice, with orders.hold, orders.cancel, and the orders.forceShip escape hatch (audited, doesn't consume stock) when reality disagrees with the happy path.

Conventions

  • IDs — all 61 entity identifiers are UUID strings with compile-time brands (OrderId, CustomerId, …). No prefixed IDs, no cross-domain type confusion in TypeScript.
  • Pagination — list tools take limit (default 50, max 200; audit.list defaults to 25) and an opaque cursor string.
  • Patches — update tools take a partial patch object; empty patches are rejected.
  • Money — monetary inputs and outputs are canonical four-decimal strings such as "149.9700", never JSON numbers. Inventory and purchasing unit costs retain five decimals.
  • Soft deletedelete tools set deleted_at; deleted entities vanish from get/list but keep their history.

The catalog

Every tool, by domain

305 tools across 28 top-level namespaces. Expand a group for its scope, full tool list, and the inputs of its key tools — all names and fields copied from the Zod schemas in packages/api/src/.

orders · 35 tools

Multi-channel order intake, line items, tokenized payments, address and note editing, pick/pack progress, manager stop-point authorizations, and the full staged pipeline (pick → pack → ready → ship → invoice), including quotes, drop-ship PO generation, and refunds.

create · get · list · update · addItem · updateItem · removeItem · addPayment · addNote · hold · cancel · pick · pack · readyToShip · ship · invoice · reconcileShipmentCost · forceShip · saveToQuote · saveFromQuote · processDropShip · recalculateTotalsBatch · capturePayment · refundPayment · updatePayment · removePayment · setAddresses · updateNote · removeNote · setLinePicked · setLinePacked · requestAuthorization · getAuthorization · reviewAuthorization · listAuthorizations

ToolKey inputs
orders.createcustomerId (uuid); billingAddressId, shippingAddressId, soldToAddressId (uuid, optional); header fields — sourceKey, orderType, salesRepMembershipId, shipVia, shipAhead, shippingAmount, taxAmount, otherAmount, holdReason, holdUntil, isQuote, quoteExpiresAt, orderedAt; items[] (productId, quantity, unitPrice?, discountPct?, per-line shipToAddressId/shipVia/shipWhen); payments[] (max 20, see above)
orders.liststatus?, customerId?, query?, limit (default 50), cursor?
orders.holdreason? / until? — required unless clear: true
orders.shiporderId — consumes on-hand stock FIFO, backorders short lines, re-callable from partial_backorder/backorder
orders.refundPaymentorderId, paymentId, amount? (defaults to remaining refundable), reason?, authorizationId?; runtime invoice settlement is refreshed after capture/refund
orders.setAddressesorderId plus billingAddressId, shippingAddressId, soldToAddressId (UUID or null)
orders.setLinePicked / setLinePackedorderLineItemId, quantity — absolute progress during picking/packing
orders.requestAuthorization / reviewAuthorizationMaker/checker approval for force_ship, cancel, refund, or hold_release
orders.reconcileShipmentCostlines[] with orderLineItemId, saleTransactionIds[], forcedQuantity, forcedUnitCost? — atomic permission-gated reconciliation of split-line historical COGS provenance
orders.forceShiporderId, reason (required) — escape hatch, audited as a note

Order status FSM: quote, draft, on_hold, committed, picking, packing, ready_to_ship, shipped, invoiced, plus partial_backorder / backorder and terminal cancelled. Stage tools latch — an order must be committed, and not on hold, before picking.

counterSales · 15 tools

Scanner-first Point-of-Purchase checkout over real OpenMOM orders: tenant-local walk-in policy, product/customer lookup, exact tax and split tenders, concurrency-safe stock consumption, runtime invoices, structured receipts, draft voids, and the existing returns/refund path.

register · create · get · list · scanItem · addItem · updateItem · removeItem · selectCustomer · setTax · addTender · removeTender · complete · void · getReceipt

counterSales.complete is atomic and idempotent: exact applied tenders must equal the order total, cash received records change separately, stock is locked and consumed, the linked order ships and invoices, and a structured receipt is returned. Tender is limited to cash, check, tokenized card, and tokenized gift card.

products · 24 tools

Catalog management: products with kit/breakout bundle components, images, variant attributes, customer-qualified pricing rules, supplier buy prices, and retail price updates that cascade to open orders.

create · get · update · delete · list · addImage · updateImage · deleteImage · addComponent · updateComponent · removeComponent · addPricingRule · updatePricingRule · deletePricingRule · listPricingRules · addAttribute · deleteAttribute · addAttributeValue · deleteAttributeValue · createBuyPrice · updateBuyPrice · deleteBuyPrice · listBuyPrices · updateRetailPrice

Kit components (bundleType: "kit" | "breakout") ship together or break out with their own timing and price overrides. Pricing rules qualify by qty break, source/catalog key, customer type or id, date range, RFM, order type, and web/non-web price level. updateRetailPrice cascades to unshipped open-order lines unless cascadeToOpenOrders: false.

customers · 18 tools

Customer records with per-tenant numbers, addresses (billing / shipping / sold_to / gift_recipient / alternate / contact), tokenized payment methods, contact history, and relationships between customers (bill_to, ship_to, sold_to, gift_recipient, contact).

create · get · update · delete · find · list · addAddress · updateAddress · deleteAddress · addPaymentMethod · deletePaymentMethod · addContact · listContacts · deleteContact · createRelationship · updateRelationship · deleteRelationship · listRelationships

customers.find supports dedupe at intake — exact email/phone matches first, then fuzzy name/company matching. Payment methods store brand, lastFour, expiry, and processorToken — never a PAN.

ncoa · 10 tools

Provider-neutral National Change of Address processing: create a batch, select eligible customer addresses, export a minimized deterministic snapshot, import provider results, review every proposed change, and apply accepted updates with stale-address conflict protection.

createJob · listJobs · getJob · selectAddresses · export · importResults · listResults · reviewResults · applyAccepted · cancel

Job status moves through draft → exported → review → completed, with cancelled terminal. Applying accepted results is transactional and idempotent; changed or deleted source addresses become explicit conflicts instead of being overwritten.

inventory · 19 tools

Warehouses and bins, lot/stock rows with FIFO or FEFO lot methods, signed adjustments, bin transfers, on-hand snapshots, an append-only transaction ledger, and backorder processing.

warehouses.create · warehouses.get · warehouses.update · warehouses.list · bins.create · bins.get · bins.update · bins.delete · bins.list · lots.receive · lots.get · lots.update · lots.list · adjustUnits · adjustLotCost · transfer · stock.get · transactions.list · processUpdates

inventory.adjustUnits takes productId, warehouseId, binId, lotId?, signed adjQty (≠ 0), unitCost?, notation? — every movement appends a ledger row with a running total (receipt / sale / adjustment / transfer / kit_build / kit_break / return).

purchasing · 12 tools

Purchase orders with header/line CRUD, submit, line-by-line or bulk receiving (which creates inventory lots and receipt ledger rows), close, and cancel.

create · get · list · update · addItem · updateItem · removeItem · submit · receiveLine · receiveAll · close · cancel

PO status FSM: draft → submitted → partially_received → received → closed, with cancelled terminal. Receiving writes lots and receipt transactions; drop-ship POs (optionally generated by orders.processDropShip) skip stock.

returns · 7 tools

RMA creation and the requested → authorized → received → processed/cancelled lifecycle, with restock, disposal, exchange links, and optional linked payment refunds.

create · get · list · authorize · markReceived · process · cancel

returns.list reports independent canManage and canAuthorize capabilities; mutation tools still enforce their permissions server-side.

payables · 9 tools

Supplier invoices from received purchase-order quantities, supplier payments, exact-decimal applications, unapplication, and payment voiding.

createInvoiceFromPurchaseOrder · getInvoice · listInvoices · recordPayment · getPayment · listPayments · applyPayment · unapplyPayment · voidPayment

deposits · 5 tools

End-of-day reporting over undeposited captured funds, followed by an atomic batch claim, lookup/list, or void that releases the claimed payments.

report · create · get · list · void

documents · 4 tools

Deterministic structured packing-slip, shipping-label, and invoice payloads plus cursor-paginated generation history. Rendering and browser printing remain caller concerns.

generatePackingSlip · generateShippingLabel · generateInvoice · listGenerations

Generation requires documents.print; history requires documents.view. The history response reports canView and canPrint separately.

vendors · 5 tools

Supplier master records with payment terms and custom fields; deletion is rejected once purchase orders exist — deactivate instead.

create · get · update · delete · list

tax · 12 tools

One tax-jurisdiction model replacing MOM's four parallel tables — national / state / county / zip levels with per-class rates and caps — plus provider configs (Avalara, TaxJar) with secret_ref credentials, a redacted provider call log, and bulk Avalara rate import.

jurisdictions.create · jurisdictions.get · jurisdictions.update · jurisdictions.delete · jurisdictions.list · providers.create · providers.get · providers.update · providers.delete · providers.list · providerTransactions.list · avalara.importRates

shipping · 22 tools

Carriers, one carrier-shipment model replacing a dozen per-carrier manifest tables, provider configs (shippo, shipstation, ups, usps, fedex, dhl) with secret_refs, offline rate bands, and deterministic rate estimates.

carriers.create · carriers.get · carriers.update · carriers.delete · carriers.list · carrierShipments.create · carrierShipments.get · carrierShipments.update · carrierShipments.delete · carrierShipments.list · shipping.providers.create · shipping.providers.get · shipping.providers.update · shipping.providers.delete · shipping.providers.list · shipping.providerTransactions.list · shipping.rateBands.create · shipping.rateBands.get · shipping.rateBands.update · shipping.rateBands.delete · shipping.rateBands.list · shipping.rates.estimate

Shipment status FSM: label_created → shipped → delivered, with voided terminal from any pre-delivered state. shipping.rates.estimate takes weight, zone?, carrierIds? (max 20) and prices from the rate-band matrix — the fallback seam for live provider rate shopping.

channels · 11 tools

Marketplace and storefront connections (amazon, miva, magento, bigcommerce, shopify, salesforce, google_base, shopsite, yahoo, storefront, ebay) with per-listing stock-sync thresholds and a publish state machine (draft → ready → published, error retryable).

connections.create · connections.get · connections.update · connections.delete · connections.list · listings.create · listings.get · listings.update · listings.delete · listings.list · listings.setStatus

Connection credentials are stored as a secretRef (KMS pointer) plus non-secret jsonb config — never in plaintext.

membership · 19 tools

Auto-ship clubs (MOM's continuity programs): plans with cycle definitions, plan products with price overrides, enrollments with billing/member customer split, an enrollment status FSM (active / paused / cancelled / completed), shipment history, and due-shipment batch generation that creates quote orders.

plans.create · plans.get · plans.list · plans.update · plans.delete · plan_products.create · plan_products.get · plan_products.list · plan_products.update · plan_products.delete · enrollments.create · enrollments.get · enrollments.list · enrollments.update · enrollments.delete · enrollments.setStatus · shipment_history.record · shipment_history.list · shipments.generate

subscriptions · 6 tools

Magazine/periodical-style subscriptions: issues remaining/sent, next mail date, hold flag, and renewal processing that issues renewal quote orders.

create · get · list · update · delete · renew

identity · 9 tools

Users, tenant memberships, roles, and permissions. Lives outside tenant RLS by design (it manages the platform-side tables), so it runs on its own restricted pool. User creation is platform-admin only; roles and invitations are tenant-admin operations.

createUser (email, fullName) · listUsers · inviteUser (userId, role: owner | admin | member, default member) · createRole (name, description?) · listRoles · setRolePermissions (roleId, permissionKeys[]) · assignRole (membershipId, roleId) · revokeRole · getEffectivePermissions (userId)

audit · 2 tools

A maker/checker audit trail (generalized from legacy USERACTIVITY): filterable, cursor-paginated log of create/update/delete actions, plus explicit review/authorization of entries.

list (entityType?, entityId?, action?: create | update | delete, actorUserId?, limit default 25, cursor?) · review (entryId)

import_export · 23 tools

Configurable import/export jobs — the modern replacement for MOM's Order Import/Export Wizard: job definitions, source-file structures, field mappings with transform rules (uppercase, lowercase, trim, regex, lookup, concat, dateFormat, custom), run history, and dry-run execution.

jobs.create · jobs.get · jobs.list · jobs.update · jobs.delete · jobs.execute (dryRun?) · source_files.create · source_files.get · source_files.list · source_files.update · source_files.delete · source_files.setContent · field_mappings.create · field_mappings.get · field_mappings.list · field_mappings.update · field_mappings.delete · history.create · history.list · executions.get · executions.list · executions.process · executions.errors

Job types: order, customer, stock, order_export, rates, zones. File types: csv, xml, xlsx, fixed-width, json.

migration · 4 tools

Operator review of durable migration rejection classes and their cutover-gate acceptances.

listRejections · listRejectionAcceptances · acceptRejectionClass · revokeRejectionAcceptance

purge · 5 tools

Permission-gated retention policy, preview, execution, and run evidence for eligible tenant records.

setPolicy · preview · execute · getRun · listRunItems

telemarketing · 12 tools

Call scripts, customer call lists, scheduled/follow-up calls, cancellation, and outcomes recorded into contact history.

createScript · updateScript · listScripts · createCallList · listCallLists · addCallListMembers · removeCallListMember · listCallListMembers · scheduleCall · listScheduledCalls · recordOutcome · cancelScheduledCall

lists · 9 tools

Manual customer lists and criteria-driven segments with evaluation and convergent membership synchronization.

create · update · list · get · evaluate · addMembers · removeMember · listMembers · syncMembership

metrics · 3 tools

Manager-level reporting over optional date ranges: profitability (revenue / COGS / gross margin), salesperson performance (orders, revenue, AOV), and top-N valuable customers.

profitability (from?, to?) · salespersonPerformance (from?, to?) · valuableCustomers (from?, to?, limit default 10)

system · 5 tools

Operational introspection: health (server + database connectivity exercised over the app-role RLS path), the caller identity of the current call, planner maintenance, table sizing, and per-tenant feature flags.

health () · whoami () · reindex () — ANALYZE all tenant tables · files () — row estimates and sizes per table · setting (key, value?) — read/write a tenant flag

Usage metering (orders processed, storage, active users, migration rows) is an internal seam — a UsageRecorder injected into metered handlers, consumed today by the managed cloud edition. It is not exposed as tools; there is no billing surface in the OSS core.

Transports

stdio

pnpm dev:api runs packages/api/src/index.ts, which connects the MCP server to StdioServerTransport — the standard integration for desktop MCP clients and scripts that spawn the server as a child process.

WebSocket

pnpm dev:ws runs ws-server.ts: a WebSocket server on ws://localhost:3001/mcp (WS_PORT to change, 1 MB max payload). Each connection gets its own MCP server instance — cheap schema registration, no shared mutable state, connections never evict each other. Authentication headers are read from the WebSocket upgrade request. In production, browser origins are verified against OPENMOM_ALLOWED_ORIGINS (non-browser clients, which authenticate with headers instead of an Origin, pass through).

The web app

The React app is itself an MCP client: in dev, Vite proxies /mcp to ws://localhost:3001, so the UI drives the exact same tools an external agent would — no privileged back door.

Schemas in packages/api/src/*/schemas.ts are the runtime contract — the same Zod definitions validate every call and document every field. The implementation remains authoritative. Public issue reporting opens with the repository in January 2027.