jaz-clio 5.8.0 → 5.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/assets/skills/api/SKILL.md +13 -5
- package/assets/skills/cli/SKILL.md +1 -1
- package/assets/skills/conversion/SKILL.md +1 -1
- package/assets/skills/jaz-pseudo-sql/SKILL.md +1 -1
- package/assets/skills/jobs/SKILL.md +2 -2
- package/assets/skills/jobs/references/bank-match.md +11 -0
- package/assets/skills/jobs/references/bank-recon.md +46 -18
- package/assets/skills/practice/SKILL.md +1 -1
- package/assets/skills/transaction-recipes/SKILL.md +1 -1
- package/assets/templates/platform-rules/jaz-agent-rules.md +2 -2
- package/cli.mjs +355 -355
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -19,7 +19,7 @@ Requires **Node.js 18+** ([nodejs.org](https://nodejs.org)). Also fully compatib
|
|
|
19
19
|
|
|
20
20
|
- [Three Ways In](#three-ways-in) — CLI, MCP, Skills
|
|
21
21
|
- [CLI](#cli) — 55 command groups
|
|
22
|
-
- [MCP Server](#mcp-server) —
|
|
22
|
+
- [MCP Server](#mcp-server) — 288 tools for AI agents
|
|
23
23
|
- [Skills](#skills) — Teach any AI the Jaz API
|
|
24
24
|
- [Setup](#setup) — Auth, multi-org, automation
|
|
25
25
|
|
|
@@ -54,7 +54,7 @@ clio practice create-engagement acme-pte-ltd --type monthly-close --period 2026-
|
|
|
54
54
|
|
|
55
55
|
## MCP Server
|
|
56
56
|
|
|
57
|
-
|
|
57
|
+
288 CLI tools, available to any AI agent that speaks MCP. Runs locally — no cloud, no ports. Includes the v5.2.0 `practice_*` tools (init, onboard_client, list_clients, load_client, create_engagement, load_engagement) so an agent in Claude Desktop or Claude Code can scaffold and load client workspaces conversationally.
|
|
58
58
|
|
|
59
59
|
**Claude Code:**
|
|
60
60
|
```bash
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: jaz-api
|
|
3
|
-
version: 5.
|
|
3
|
+
version: 5.9.0
|
|
4
4
|
description: >-
|
|
5
5
|
Use this skill whenever you call, debug, or review code that touches the Jaz
|
|
6
6
|
REST API. Covers field names, response shapes, 141 production gotchas, error
|
|
@@ -161,7 +161,7 @@ The rest of this skill — field names, gotchas, error catalog, dependency order
|
|
|
161
161
|
37a. **Data exports use simpler field names**: P&L export uses `startDate`/`endDate` (NOT `primarySnapshotDate`). AR/AP export uses `endDate`.
|
|
162
162
|
|
|
163
163
|
### Pagination
|
|
164
|
-
38. **All list/search endpoints use `limit`/`offset` pagination** — NOT `page`/`size`. Default limit=100, offset=0. Max limit=1000, max offset=65536. `page`/`size` params are silently ignored. Response shape: `{ totalPages, totalElements, truncated, data: [...] }`. When `truncated: true`, a `_meta: { fetchedRows, maxRows }` field explains why (offset cap or `--max-rows` soft cap — default 10,000). Use `--max-rows <n>` to override. Always check `truncated` before assuming the full dataset was returned.
|
|
164
|
+
38. **All list/search endpoints use `limit`/`offset` pagination** — NOT `page`/`size`. **`offset` is a 0-indexed PAGE NUMBER, not a row-skip** (offset=1 = second page of `limit` rows). Default limit=100, offset=0. Max limit=1000, max offset=65536. `page`/`size` params are silently ignored. Response shape: `{ totalPages, totalElements, truncated, data: [...] }`. When `truncated: true`, a `_meta: { fetchedRows, maxRows }` field explains why (offset cap or `--max-rows` soft cap — default 10,000). Use `--max-rows <n>` to override. Always check `truncated` before assuming the full dataset was returned.
|
|
165
165
|
|
|
166
166
|
### Other
|
|
167
167
|
39. **Currency rates use `/organization-currencies/:code/rates`** — note the HYPHENATED path (NOT `/organization/currencies`). Enable currencies first via `POST /organization/currencies`, then set rates via `POST /organization-currencies/:code/rates` with body `{ "rate": 0.74, "rateApplicableFrom": "YYYY-MM-DD" }` (see Rule 49 for direction). Cannot set rates for org base currency. Full CRUD: POST (create), GET (list), GET/:id, PUT/:id, DELETE/:id.
|
|
@@ -177,7 +177,7 @@ The rest of this skill — field names, gotchas, error catalog, dependency order
|
|
|
177
177
|
49. **Currency rate direction: `rate` = functionalToSource (1 base = X foreign)** — POST `rate: 0.74` for a SGD org means 1 SGD = 0.74 USD. **If your data stores rates as "1 USD = 1.35 SGD" (sourceToFunctional), you MUST invert: `rate = 1 / 1.35 = 0.74`.** GET confirms both: `rateFunctionalToSource` (what you POSTed) and `rateSourceToFunctional` (the inverse).
|
|
178
178
|
|
|
179
179
|
### Search & Filter
|
|
180
|
-
50. **Search endpoint universal pattern** — All 28 `POST /*/search` endpoints share identical structure: `{ filter?, sort: { sortBy: ["field"], order: "ASC"|"DESC" }, limit: 1-1000, offset: 0-65536 }`. Sort is REQUIRED when offset is present (even `offset: 0`). Default limit: 100. `sortBy` is always an array on all endpoints (no exceptions). See `references/search-reference.md` for per-endpoint filter/sort fields.
|
|
180
|
+
50. **Search endpoint universal pattern** — All 28 `POST /*/search` endpoints share identical structure: `{ filter?, sort: { sortBy: ["field"], order: "ASC"|"DESC" }, limit: 1-1000, offset: 0-65536 }`. `offset` is a 0-indexed page number (not row-skip). Sort is REQUIRED when offset is present (even `offset: 0`). Default limit: 100. `sortBy` is always an array on all endpoints (no exceptions). See `references/search-reference.md` for per-endpoint filter/sort fields.
|
|
181
181
|
50a. **`query` field — Jaz search operators** — 14 endpoints accept an optional `query` string alongside `filter`: invoices, bills, customer/supplier credit notes, journals, cashflow-transactions, bank-records, contacts, items, capsules, fixed-assets, scheduled-transactions, chart-of-accounts, tax-profiles. Example: `{ "query": "status:unpaid AND $500+", "limit": 50 }`. Key syntax: amounts (`$500+`, `$100-500`, `amount:>2m`, magnitude suffixes `5k`/`2m`/`1b`), negative (`$-500`), absolute value (`abs:1000+`), dates (`date:this month`, `date:-30d`, `due:overdue`, `submitted:last week`, `lastpayment:-7d`), status/enum (`status:unpaid`, `currency:SGD,USD` — comma = OR), string fields (`customer:acme`, `ref:INV-*` wildcard, `=ref:INV-001` exact, `ref:/\d{4}/` regex), blank checks (`ref:blank`, `tag:!blank`), booleans (`hasattachment:yes`, `customer:yes`), negation (`!status:paid` or `NOT status:void` — **never `-`** for negation), logic (`AND`/`OR` with implicit AND on space), grouping, inline sort (`sort:amount:desc`). Full syntax spec (all fields, aliases, entity field lists, examples): **`references/search-syntax.md`**.
|
|
182
182
|
50b. **`query` + `filter` merge** — When both are present, they are merged at the filter level. Explicit `filter` keys win on conflict. Use `query` for human-readable shorthand, `filter` for programmatic precision, or combine both: `{ "query": "date:this year", "filter": { "currencyCode": { "in": ["SGD"] } } }`.
|
|
183
183
|
50c. **`query` error handling** — Unknown field name → `query_not_understood` (400). Bad enum value (e.g. `status:BADVALUE`) → **empty results, no error** (silent miss). Unsupported endpoint → `query_not_supported` (400). Parser unavailable → `query_parse_error` (502). Empty/null/whitespace query → passthrough (ignored). In CLI/MCP: use `--query` / `query` param only on supported entities — unsupported entities have no `--query` flag.
|
|
@@ -402,9 +402,10 @@ Bills, invoices, and credit notes share identical mandatory field specs. Adding
|
|
|
402
402
|
|
|
403
403
|
### Reconciliation actions (write-side)
|
|
404
404
|
|
|
405
|
-
123. **
|
|
405
|
+
123. **11 reconciliation action endpoints under `/api/v1/reconciliations/*`** — these *commit* a reconciliation decision against a bank statement entry, distinct from `view_auto_reconciliation` (which queries `/search-magic-reconciliation` for *suggestions*):
|
|
406
406
|
- **Async (jobId):** `quick_reconcile` (bulk match entries to journals, max 500), `apply_bank_rule` (bulk apply a rule to entries, max 500). Poll `search_background_jobs` filtered by `resourceId`; on `PARTIAL_SUCCESS` read `data[0].errorDetails` for per-row failures.
|
|
407
|
-
- **Sync (single bank entry):** `reconcile_direct_cash_entry`, `reconcile_cash_journal`, `reconcile_manual_journal`, `reconcile_cash_transfer`, `reconcile_invoice_receipt`, `reconcile_bill_receipt`. Each returns `{bankStatementEntryResourceId, status, reference, valueDate}`.
|
|
407
|
+
- **Sync (single bank entry):** `reconcile_direct_cash_entry`, `reconcile_cash_journal`, `reconcile_manual_journal`, `reconcile_cash_transfer`, `reconcile_invoice_receipt`, `reconcile_bill_receipt`, `reconcile_with_payments` (match EXISTING — see Rule 158), `reconcile_learned_prediction`. Each returns `{bankStatementEntryResourceId, status, reference, valueDate}`.
|
|
408
|
+
- **Sync bulk:** `reconcile_magic_match` (bulk-accept MAGIC_MATCH suggestions, max 500) returns `{reconciled[], failed[]}`.
|
|
408
409
|
|
|
409
410
|
124. **Recon prefill from the bank statement entry** — when caller omits `valueDate`, `dueDate`, payment `amount`, or direction (cash-in vs cash-out), the API fills these from the bank entry. Best-effort: a missing entry lookup logs a warning and forwards the payload as-is. Caller can always override by passing the field explicitly.
|
|
410
411
|
|
|
@@ -532,6 +533,13 @@ Supports `--json` for structured output. 186 articles across 20 sections. Automa
|
|
|
532
533
|
- **Scheduled journals**: Flat: `{ status, startDate, endDate, repeat, valueDate, schedulerEntries, reference }`. `valueDate` is required.
|
|
533
534
|
- **FX currency (invoices, bills, credit notes, AND journals)**: `currency: { sourceCurrency: "USD" }` (auto-fetches platform rate) or `currency: { sourceCurrency: "USD", exchangeRate: 1.35 }` (custom rate). Same object form on all transaction types. **Never use `currencyCode` string** — silently ignored.
|
|
534
535
|
|
|
536
|
+
158. **Match-to-EXISTING reconciliation — `reconcile_with_payments` / `reconcile_magic_match` / `reconcile_learned_prediction`.** These reconcile a bank entry against transactions/payments the org ALREADY has, vs `invoice_receipt`/`bill_receipt` which CREATE new ones. Prefer match-to-existing to avoid duplicates.
|
|
537
|
+
- **`reconcile_with_payments`** — the headline. `businessTransactionPayments[]` each carry an open bill/invoice's `cashflowTransactionResourceId` (from `search_cashflow_transactions` or a suggestion's `cftBtResourceId`) + `transactionAmount`; the endpoint CREATES the payment AND reconciles in one call — **no `pay_bill`/`pay_invoice` first.** Also accepts `matchedPayments[]` (existing payments) / `matchedBatchPayments[]` / `adjustment` (over/under-payment + FX write-off). Guard: ≥1 match array non-empty. **FX is auto-resolved server-side — pass NO `currencySettings`/rate for the common case.** Only the rare bill-currency ≠ bank-currency case needs explicit `paymentAmount` (bank ccy) + `currencySettings`. FX gain/loss is NOT auto-posted — post it via `adjustment.cashAdjustmentEntries[]` to an FX account. Errors: `PAYMENT_AMOUNT_REQUIRED_IN_BUSINESS_TRANSACTION_SOURCE_CURRENCY` (cross-ccy missing paymentAmount), `INVALID_EXCHANGE_RATE_ERROR` (adjustment leg in non-functional ccy missing rate), `TOTAL_RECONCILIATION_AMOUNT_MISMATCHED_WITH_STATEMENT_ENTRY_AMOUNT` (sum ≠ entry → add adjustment leg). **NOT idempotent, no client key — a blind retry double-creates a payment; re-check `search_bank_records(status:'RECONCILED')` before retry.**
|
|
538
|
+
- **`reconcile_magic_match`** — bulk-accept MAGIC_MATCH suggestions (max 500 entries). Returns `{reconciled[], failed[]}` — a 200 with non-empty `failed[]` is a PARTIAL success (per-entry `errorCode`); loop on failed only. Entry-level idempotency-keyed server-side (re-submit returns done entries in `reconciled[]`).
|
|
539
|
+
- **`reconcile_learned_prediction`** — accept an ML prediction. `predictedPayload` + `predictedPayloadSchemaVersion` come VERBATIM from a `view_auto_reconciliation` (MAGIC_RECONCILE_WITH_CASH_IN_OUT) suggestion — never hand-construct. `retryToken` forces a fresh journal on edit-retry; omit for idempotent replay. On failure (stale payload), fall back to `reconcile_with_payments` — don't retry the blob.
|
|
540
|
+
|
|
541
|
+
159. **`view_auto_reconciliation` returns execution-ready `suggestions[]` — the suggestion→commit seam.** Each suggestion carries `recommendedTool` (the commit tool to call), `execute` (ready-to-pass args — merge `bankAccountResourceId` for `reconcile_magic_match`), `confidenceTier` (high/medium/low, code-derived), and `autoCommitEligible` (true ⇒ high confidence + executable plan + under any `autoCommitMaxAmount` cap). **Decision gate:** `autoCommitEligible===true` → auto-commit via `recommendedTool`+`execute`; everything else → surface for confirmation. **Amount threshold is a HARD VETO over confidence** (pass `autoCommitMaxAmount`). Field mapping under the hood: `cftBtResourceId`→`cashflowTransactionResourceId` (single → `reconcile_with_payments`), `cftBtResourceIds[]`/`isBatch`→`matchedBusinessTransactions` (batch → `reconcile_magic_match`), `recommendationType`→tool, `confidenceScore`→tier. Pass `includeRaw:true` for the unmapped payload. On 500 (high-volume OOM) it returns `{degraded:true}` — scope by period or use the `clio jobs bank-recon match` cascade. NOT idempotent applies to every commit — see Rules 125 + 158.
|
|
542
|
+
|
|
535
543
|
## See Also
|
|
536
544
|
|
|
537
545
|
- **jaz-recipes** — 16 IFRS-compliant transaction recipes with journal entries, capsules, and calculators
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: jaz-jobs
|
|
3
|
-
version: 5.
|
|
3
|
+
version: 5.9.0
|
|
4
4
|
description: >-
|
|
5
5
|
Use this skill for recurring accounting workflows — month/quarter/year-end
|
|
6
6
|
close, bank reconciliation, GST/VAT filing, payment runs, credit control,
|
|
@@ -48,7 +48,7 @@ Period-close jobs build on each other. Quarter = month + extras. Year = quarter
|
|
|
48
48
|
|
|
49
49
|
| Job | CLI Command | Description |
|
|
50
50
|
|-----|-------------|-------------|
|
|
51
|
-
| **Bank Recon** (`generate_bank_recon_blueprint`) | `clio jobs bank-recon` | Clear unreconciled items: match, categorize, resolve. Paired tool: `clio jobs bank-recon match`. *Used in: monthly-close engagement (run as part of every period close; see `jaz-practice/references/monthly-close.md`).* |
|
|
51
|
+
| **Bank Recon** (`generate_bank_recon_blueprint`) | `clio jobs bank-recon` | Clear unreconciled items: match, categorize, resolve. **Match to EXISTING open bills/invoices/payments (`reconcile_with_payments`) is the primary path — create-new only when nothing matches.** Drive end-to-end via the `view_auto_reconciliation` decision gate (auto-commit high-confidence, checkpoint the rest — see `references/bank-recon.md` Step 4a). Paired tool: `clio jobs bank-recon match`. *Used in: monthly-close engagement (run as part of every period close; see `jaz-practice/references/monthly-close.md`).* |
|
|
52
52
|
| **Document Collection** (`generate_document_collection_blueprint`) | `clio jobs document-collection` | Scan and classify client documents from local directories and cloud links (Dropbox, Drive, OneDrive). Outputs file paths for agent upload. Paired tool: `clio jobs document-collection ingest`. *Used in: onboarding flow (initial client doc capture; see `jaz-practice/references/onboarding.md`) and the open phase of every engagement (monthly-close, quarterly-gst, annual-statutory).* |
|
|
53
53
|
| **GST/VAT Filing** (`generate_gst_vat_blueprint`) | `clio jobs gst-vat --period YYYY-QN` | Tax ledger review, discrepancy check, filing summary. *Used in: quarterly-gst engagement (see `jaz-practice/references/quarterly-gst.md`).* |
|
|
54
54
|
| **Payment Run** (`generate_payment_run_blueprint`) | `clio jobs payment-run` | Select outstanding bills by due date, process payments. *Used in: monthly-close engagement (AP cycle inside the period close; see `jaz-practice/references/monthly-close.md`).* |
|
|
@@ -223,6 +223,17 @@ clio jobs bank-recon match --input data.json --find-all --json
|
|
|
223
223
|
| `1:N` | Multiple bank records match one transaction | Split payment (1 payment across 2 bank entries) |
|
|
224
224
|
| `N:M` | Multiple bank records match multiple transactions | Complex group match within a contact |
|
|
225
225
|
|
|
226
|
+
### Committing a match → route to the right reconcile tool
|
|
227
|
+
|
|
228
|
+
The matcher finds matches against transactions the org **already has** — so commit via the MATCH-EXISTING path, not create-new:
|
|
229
|
+
|
|
230
|
+
- A 1:1 (or N:1) match to an **existing open bill/invoice** at `exact` / `fuzzy-high` (≥0.85) confidence → **`reconcile_with_payments`** (pass the matched transaction's `cashflowTransactionResourceId` in `businessTransactionPayments[]`). Do NOT use `reconcile_invoice_receipt`/`reconcile_bill_receipt` — those CREATE a duplicate.
|
|
231
|
+
- A batch of high-confidence matches → **`reconcile_magic_match`** in one call.
|
|
232
|
+
- Only when the matcher finds NO existing transaction → create one (`reconcile_invoice_receipt`/`reconcile_bill_receipt` or `create_cash_*`).
|
|
233
|
+
- `fuzzy-medium` (0.70–0.85) / `nm-confident` → surface for confirmation before committing (checkpoint), don't auto-commit.
|
|
234
|
+
|
|
235
|
+
See `bank-recon.md` Step 4a for the full auto-commit-vs-checkpoint decision gate.
|
|
236
|
+
|
|
226
237
|
---
|
|
227
238
|
|
|
228
239
|
## Worked Example
|
|
@@ -10,18 +10,24 @@
|
|
|
10
10
|
- **`search_accounts(filter: {accountType: {eq: 'Bank Accounts'}})`** — step 1 alternative: same data via standard CoA-search envelope if downstream wants pagination.
|
|
11
11
|
- **`search_bank_records(accountResourceId: <id>, status: 'UNRECONCILED', valueDateRange: {from, to}, limit: 200, sort: 'valueDate:asc')`** — step 2: per-account work queue.
|
|
12
12
|
- **`search_bank_records(accountResourceId: <id>, status: 'POSSIBLE_DUPLICATE')`** — step 3: handle dups FIRST or you'll double-create reconciling them.
|
|
13
|
-
- **`view_auto_reconciliation(bankAccountResourceId: <id>, recommendationType: 'MAGIC_MATCH' | 'MAGIC_RECONCILE_WITH_CASH_TRANSFER' | 'MAGIC_RECONCILE_WITH_BANK_RULE' | 'MAGIC_QUICK_RECONCILE' | 'MAGIC_RECONCILE_WITH_CASH_IN_OUT')`** — step 4: READ-ONLY auto-match suggestions. `
|
|
13
|
+
- **`view_auto_reconciliation(bankAccountResourceId: <id>, recommendationType: 'MAGIC_MATCH' | 'MAGIC_RECONCILE_WITH_CASH_TRANSFER' | 'MAGIC_RECONCILE_WITH_BANK_RULE' | 'MAGIC_QUICK_RECONCILE' | 'MAGIC_RECONCILE_WITH_CASH_IN_OUT', autoCommitMaxAmount?: <number>)`** — step 4: READ-ONLY auto-match suggestions. Returns **execution-ready `suggestions[]`** — each carries `recommendedTool`, `execute` (ready-to-pass args), `confidenceTier`, and `autoCommitEligible`. This is the entry point for the auto-match decision gate (step 4a). `MAGIC_RECONCILE_WITH_CASH_IN_OUT` returns Learned-Predictions. Does NOT write. NOTE: 500 quirk on high-volume accounts → degrades to `{degraded:true}`; scope by period or fall back to the cascade matcher (see error table).
|
|
14
14
|
- **`search_cashflow_transactions(filter: {organizationAccountResourceId: <bank-id>, totalAmount: {eq: <amt>}, valueDate: {between: [<-3d>, <+3d>]}})`** — step 5 manual match: search book-side transactions for the same amount within ±3 day window.
|
|
15
15
|
|
|
16
16
|
### MCP tools — execute reconciliation (NOT idempotent — see error table)
|
|
17
|
-
|
|
18
|
-
- **`
|
|
19
|
-
- **`
|
|
20
|
-
- **`
|
|
21
|
-
- **`
|
|
22
|
-
- **`
|
|
23
|
-
|
|
24
|
-
|
|
17
|
+
**Match to EXISTING (preferred — no duplicates):**
|
|
18
|
+
- **`reconcile_with_payments(bankStatementEntryResourceId, businessTransactionPayments: [{cashflowTransactionResourceId, transactionAmount}], matchedPayments?, matchedBatchPayments?, adjustment?)`** — **the primary match path.** Match a bank entry to an EXISTING open bill/invoice/payment; creates the payment AND reconciles in one call (no `pay_bill`/`pay_invoice` first). FX auto-resolved server-side — pass no rate. Sync.
|
|
19
|
+
- **`reconcile_magic_match(bankAccountResourceId, entries: [{workflowType:'MAGIC_MATCH', bankStatementEntryResourceId, matchedBusinessTransactions}])`** — bulk-accept MAGIC_MATCH suggestions (max 500). Returns `{reconciled[], failed[]}` — a non-empty `failed[]` is a partial success; loop on it.
|
|
20
|
+
- **`reconcile_learned_prediction(bankStatementEntryResourceId, learnedPredictionResourceId, predictedPayload, predictedPayloadSchemaVersion, retryToken?)`** — accept an ML learned-prediction (payload passed verbatim from a `MAGIC_RECONCILE_WITH_CASH_IN_OUT` suggestion).
|
|
21
|
+
- **`apply_bank_rule(actionShortcutResourceId, businessTransactionResourceIds)`** — rule-driven recon (async; returns jobId).
|
|
22
|
+
- **`quick_reconcile(bankAccountResourceId, journalsForReconciliation)`** — bulk async (max 500); returns jobId.
|
|
23
|
+
|
|
24
|
+
**CREATE new (only when no existing open transaction matches):**
|
|
25
|
+
- **`reconcile_invoice_receipt(...)`** — CREATE a new AR invoice + reconcile. ⚠️ To match an EXISTING invoice use `reconcile_with_payments` instead.
|
|
26
|
+
- **`reconcile_bill_receipt(...)`** — CREATE a new AP bill + reconcile. ⚠️ To match an EXISTING bill use `reconcile_with_payments` instead.
|
|
27
|
+
- **`reconcile_direct_cash_entry(...)`** — bank entry to a single cash-in / cash-out line (no source document).
|
|
28
|
+
- **`reconcile_cash_journal(...)`** — bank entry to a multi-line cash journal.
|
|
29
|
+
- **`reconcile_manual_journal(...)`** — bank entry to a manual journal.
|
|
30
|
+
- **`reconcile_cash_transfer(...)`** — inter-account transfer.
|
|
25
31
|
|
|
26
32
|
### MCP tools — create missing transactions
|
|
27
33
|
- **`mcp magic create --file <pdf>` / `create_business_transaction_from_attachment(...)`** — step 6 path B: OCR + autofill bill or invoice from receipt PDF/JPG.
|
|
@@ -94,20 +100,37 @@ clio jobs bank-recon match \
|
|
|
94
100
|
--json
|
|
95
101
|
```
|
|
96
102
|
|
|
97
|
-
Returns matches with confidence scores: `exact` (Phase 1 hash), `fuzzy-high` (Phase 2 weighted ≥ 0.85), `fuzzy-medium` (0.70-0.85), `nm-confident` (Phase 5). For each match returned:
|
|
103
|
+
Returns matches with confidence scores: `exact` (Phase 1 hash), `fuzzy-high` (Phase 2 weighted ≥ 0.85), `fuzzy-medium` (0.70-0.85), `nm-confident` (Phase 5). For each match returned — **prefer MATCH-EXISTING over CREATE-NEW** to avoid duplicating a bill/invoice the org already has:
|
|
98
104
|
|
|
99
105
|
| Match type | Tool to invoke |
|
|
100
106
|
|------------|----------------|
|
|
101
|
-
|
|
|
102
|
-
|
|
|
103
|
-
|
|
|
107
|
+
| **AP bill ↔ bank cash-out (MATCH EXISTING open bill)** | **`reconcile_with_payments(bankStatementEntryResourceId, businessTransactionPayments:[{cashflowTransactionResourceId, transactionAmount}])`** ← primary |
|
|
108
|
+
| **AR invoice ↔ bank cash-in (MATCH EXISTING open invoice)** | **`reconcile_with_payments(...)`** ← primary |
|
|
109
|
+
| Existing payment ↔ bank | `reconcile_with_payments(..., matchedPayments:[...])` |
|
|
110
|
+
| Bulk accept magic suggestions | `reconcile_magic_match(bankAccountResourceId, entries:[...])` → `{reconciled[],failed[]}` |
|
|
111
|
+
| Learned-prediction (cash-in-out) | `reconcile_learned_prediction(...)` |
|
|
112
|
+
| AR invoice — CREATE NEW (no existing match) | `reconcile_invoice_receipt(...)` |
|
|
113
|
+
| AP bill — CREATE NEW (no existing match) | `reconcile_bill_receipt(...)` |
|
|
114
|
+
| Cash entry (single line, no document) ↔ bank | `reconcile_direct_cash_entry(...)` |
|
|
104
115
|
| Cash journal (multi-line) ↔ bank | `reconcile_cash_journal(...)` |
|
|
105
116
|
| Manual journal ↔ bank | `reconcile_manual_journal(...)` |
|
|
106
117
|
| Inter-account transfer | `reconcile_cash_transfer(...)` |
|
|
107
|
-
| Bulk same-shape (>5 items) | `quick_reconcile(
|
|
108
|
-
| Bank rule applies | `apply_bank_rule(
|
|
118
|
+
| Bulk same-shape (>5 items) | `quick_reconcile(...)` (async, returns jobId) |
|
|
119
|
+
| Bank rule applies | `apply_bank_rule(...)` (async) |
|
|
109
120
|
|
|
110
|
-
|
|
121
|
+
## Step 4a — Auto-match decision gate (the end-to-end driver)
|
|
122
|
+
|
|
123
|
+
Call `view_auto_reconciliation`. It returns execution-ready `suggestions[]`. On high-volume accounts the engine can 500 (OOM) and the tool returns `{degraded:true}` — recover via the `clio jobs bank-recon match` cascade matcher (Step 4, above), which doesn't hit this endpoint. Walk the suggestions:
|
|
124
|
+
|
|
125
|
+
- **`autoCommitEligible === true`** (high confidence, has an `execute` plan, under any amount cap) → **auto-commit**: call the suggestion's `recommendedTool` with its `execute` args. For many high-confidence matches, prefer ONE `reconcile_magic_match` call (server idempotency-keyed) over looping `reconcile_with_payments` (non-idempotent).
|
|
126
|
+
- **everything else** (medium/low tier, `recommendedTool` undefined, CREATE-NEW, or amount over threshold) → **checkpoint**: surface to the user for confirmation. **The amount threshold is a HARD VETO over confidence** — a high-confidence but large match still checkpoints (pass `autoCommitMaxAmount` to enforce in code).
|
|
127
|
+
- **`{degraded:true}`** (500) → fall back to the `clio jobs bank-recon match` cascade (Step 4, above).
|
|
128
|
+
|
|
129
|
+
**Safety (recon is NOT idempotent):** before EACH auto-commit, re-check `search_bank_records(status:'RECONCILED')` for that entry (guards a concurrent second agent — `reconcile_with_payments` has no client idempotency key). Enforce a per-run auto-commit cap; above it, checkpoint the remainder rather than firing hundreds of irreversible sequential writes.
|
|
130
|
+
|
|
131
|
+
## Step 4b — Match a bank entry to an existing open bill/invoice
|
|
132
|
+
|
|
133
|
+
When you have a specific open bill/invoice to match (e.g. from `search_cashflow_transactions`), pass its `cashflowTransactionResourceId` to `reconcile_with_payments` — one call creates the payment AND reconciles. **No `pay_bill`/`pay_invoice` first.** Cross-currency (bank ccy ≠ bill ccy) is auto-resolved server-side — pass no rate; only the rare bill-ccy≠bank-ccy case needs explicit `paymentAmount` + `currencySettings`. On `TOTAL_RECONCILIATION_AMOUNT_MISMATCHED...`, put the delta into an `adjustment.cashAdjustmentEntries[]` leg (over/under-payment or FX write-off — the platform does NOT auto-post FX gain/loss) so the total equals the bank entry, then resend.
|
|
111
134
|
|
|
112
135
|
## Step 5 — Manual match (residuals)
|
|
113
136
|
|
|
@@ -207,10 +230,15 @@ Per account: `bookBalance == bankStatementBalance ± documentedTimingDifference`
|
|
|
207
230
|
|
|
208
231
|
| Source | Error | Recovery |
|
|
209
232
|
|--------|-------|----------|
|
|
210
|
-
| `view_auto_reconciliation` | 500 on high-volume account
|
|
211
|
-
| `view_auto_reconciliation` | 404 | Endpoint not enabled for the org's plan tier. Use cascade matcher only. |
|
|
233
|
+
| `view_auto_reconciliation` | 500 on high-volume account → returns `{degraded:true}` | Documented OOM quirk on accounts with thousands of unreconciled rows. The tool degrades (doesn't throw): scope per-period (`valueDateRange`) OR fall back to `clio jobs bank-recon match` cascade. |
|
|
234
|
+
| `view_auto_reconciliation` | 404 → returns `{notSupported:true}` | Endpoint not enabled for the org's plan tier. Use cascade matcher only. |
|
|
212
235
|
| `quick_reconcile` | PARTIAL_SUCCESS jobId | Async result. Poll `search_background_jobs(filter: {resourceId: {eq: <jobId>}})` until terminal. Read `data[0].errorDetails[]` for per-row failures; loop back to step 4 for the failed rows. |
|
|
213
236
|
| `quick_reconcile` / `reconcile_*` | (any) — NOT idempotent (rule 124) | On 500 / network error, do NOT retry. Confirm reconciled state via `view_auto_reconciliation` OR `search_bank_records(status: 'RECONCILED')` first. |
|
|
237
|
+
| `reconcile_with_payments` | (any 5xx/network) — NOT idempotent, **no client key** | A blind retry **double-creates a payment**. ALWAYS re-check `search_bank_records(status:'RECONCILED')` for the entry before retrying. (magic_match is entry-level idempotency-keyed; learned_prediction takes a `retryToken`.) |
|
|
238
|
+
| `reconcile_magic_match` | 200 with non-empty `failed[]` | PARTIAL success — `reconciled[]` succeeded, `failed[]` carries per-entry `errorCode`. Surface failures + loop only on the failed entries. **All-fail** (empty `reconciled[]`) = hard stop, surface. A re-submit returns already-done entries in `reconciled[]` (not `failed[]`) — don't treat them as new failures. |
|
|
239
|
+
| `reconcile_learned_prediction` | error (stale/invalid `predictedPayload`) | Do NOT retry the same opaque payload. Fall back to `reconcile_with_payments` or manual match. `retryToken` forces a fresh journal on an intentional edit-retry; omit for idempotent replay. |
|
|
240
|
+
| `reconcile_with_payments` | 422 `TOTAL_RECONCILIATION_AMOUNT_MISMATCHED...` | Payments + adjustments ≠ bank entry amount. Add the delta as an `adjustment.cashAdjustmentEntries[]` leg (over/under-payment or FX write-off) so the total matches, then resend. |
|
|
241
|
+
| `reconcile_with_payments` | 422 `...does not exist` / invalid status | The BT isn't an open bill/invoice (wrong id, already paid, or draft). Re-fetch via `search_cashflow_transactions`; finalize if draft. |
|
|
214
242
|
| `reconcile_invoice_receipt` | 422 `invoice_status_invalid` | Matched invoice still DRAFT. `finalize_invoice(resourceId: <id>)` first. |
|
|
215
243
|
| `reconcile_invoice_receipt` | 422 `amount_mismatch` | Bank amount ≠ invoice balance. Either partial payment (post via `create_invoice_payment` with partial amount, then reconcile), or wrong match (revisit step 4/5). |
|
|
216
244
|
| `apply_bank_rule` | 422 `rule_action_unsupported` | Rule's configured action doesn't match the bank entry shape (e.g., rule expects positive amount, entry is negative). Edit the rule via `update_bank_rule`. |
|
|
@@ -6,7 +6,7 @@ Source of truth lives in the installed skills (`.claude/skills/jaz-*/SKILL.md` o
|
|
|
6
6
|
|
|
7
7
|
## Discovery
|
|
8
8
|
|
|
9
|
-
The Jaz MCP server exposes
|
|
9
|
+
The Jaz MCP server exposes 288 tools across 34 namespaces via 3 meta-tools. **Use the meta-tool flow — never enumerate tools blindly.**
|
|
10
10
|
|
|
11
11
|
1. `search_tools(query)` → top-N tool names + namespaces.
|
|
12
12
|
2. `describe_tools(names)` → full parameter schemas.
|
|
@@ -20,7 +20,7 @@ Offline tools (no API key needed): `plan_recipe`, `search_help_center`, all `pra
|
|
|
20
20
|
2. **Transaction dates are `valueDate`** (YYYY-MM-DD) — never `issueDate` / `invoiceDate` / `date`.
|
|
21
21
|
3. **Line item text field is `name`** — never `description`.
|
|
22
22
|
4. **`saveAsDraft` defaults `false`** at the API; CLI/MCP create-tools default `true`. Set explicitly when the user says "finalize".
|
|
23
|
-
5. **Pagination uses `limit` / `offset`** —
|
|
23
|
+
5. **Pagination uses `limit` / `offset`** — `offset` is a 0-indexed page number (offset=1 = second page), not a row-skip. Sort is required when `offset` is set.
|
|
24
24
|
6. **Create responses return `{ resourceId }` only** — re-GET to load the full entity.
|
|
25
25
|
|
|
26
26
|
## Transactions — never hand-construct journals for IFRS
|