@kirjapro/mcp-server 0.18.0 → 0.18.1

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/CHANGELOG.md CHANGED
@@ -1,5 +1,20 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.18.1] - 2026-10-19
4
+
5
+ No database migration; one tool fingerprint changes (`kirjapro_book_sale`).
6
+
7
+ - `kirjapro_book_sale` books the sale of a company outside the VAT register gross even when
8
+ the receipt or invoice it gave showed VAT (founder decision 19.10.2026, audit T2-3): a
9
+ `vatRate` above 0 is no longer refused with `NOT_VAT_REGISTERED_SALE`, it is the rate the
10
+ receipt showed. No VAT is booked (no 4210 line, `vat: 0`, `vat_rate: "0 %"`), and the
11
+ result and the dry run add `vat_notice`, a Finnish note the agent relays to the user: the
12
+ company charges no VAT, the sale was booked in full as revenue, and a receipt that showed
13
+ VAT is wrong and is replaced with a corrected receipt without VAT, attached as the voucher
14
+ in the Kirjapro app.
15
+ - A sale template with VAT (`cash_sale_25` and the like) is still refused for such a
16
+ company, and the refusal now points to `kirjapro_book_sale` with the receipt's rate.
17
+
3
18
  ## [0.18.0] - 2026-10-19
4
19
 
5
20
  **Breaking: Node.js 22 or newer is required** (`engines.node` `>=22`; Node.js 20 reached its
package/README.md CHANGED
@@ -201,9 +201,10 @@ See the [full tool reference](https://kirjapro.fi/docs/mcp/) for parameters, usa
201
201
  cents (`INVALID_AMOUNT` otherwise), and `documentNumber` is the company's own
202
202
  voucher number: leave it out for the next number (a supplier's receipt number
203
203
  belongs in the description).
204
- - A company outside the VAT register books its sales without VAT
205
- (`kirjapro_book_sale` takes only `vatRate "0"`, and the sale templates with
206
- VAT are not offered). Recurring invoice templates take prices of 0 or more
204
+ - A company outside the VAT register books its sales without VAT: the sale
205
+ templates with VAT are not offered, and `kirjapro_book_sale` books the gross
206
+ amount as revenue. If the receipt showed VAT, the result's `vat_notice` tells
207
+ the user to give the customer a corrected receipt without VAT (0.18.1). Recurring invoice templates take prices of 0 or more
207
208
  (a discount is `discountPercent`) and a first date from today on.
208
209
  - Update tools are annotated `destructiveHint: true` and the recurring invoice
209
210
  writes `openWorldHint: true`, so a host that auto-approves non-destructive
package/dist/index.js CHANGED
@@ -35743,7 +35743,7 @@ import { AsyncLocalStorage } from "node:async_hooks";
35743
35743
  import { createClient } from "@supabase/supabase-js";
35744
35744
 
35745
35745
  // src/version.ts
35746
- var VERSION = "0.18.0";
35746
+ var VERSION = "0.18.1";
35747
35747
 
35748
35748
  // src/auth.ts
35749
35749
  var SUPABASE_PROJECT_URL = "https://tifewzsimmyoiepblhld.supabase.co";
@@ -41808,7 +41808,11 @@ var ACCOUNTS = {
41808
41808
 
41809
41809
  // src/compliance/vat-guard.ts
41810
41810
  var ALV_REGISTERED_SALE_REFUSAL = "This company is VAT-registered (ALV). A sale booked as a journal voucher never reaches the ALV report (fields 301-303 and 309), so Kirjapro refuses it. Create the sale with kirjapro_create_invoice, deliver it with kirjapro_send_invoice and record the payment with kirjapro_record_payment or bank matching.";
41811
- var NOT_VAT_REGISTERED_SALE_REFUSAL = 'NOT_VAT_REGISTERED_SALE: this company is not VAT-registered (ALV), so it charges no VAT and its sale is booked gross as revenue. Use vatRate "0" (the cash_sale_0 template), with no VAT split. If a receipt or invoice the company gave did show VAT, ask an accountant how to book that VAT; Kirjapro does not book it automatically.';
41811
+ var SALE_TEMPLATE_NOT_VAT_REGISTERED_REFUSAL = "NOT_VAT_REGISTERED_SALE: this company is not VAT-registered (ALV), so a sale template with VAT cannot be used. Use kirjapro_book_sale with the vatRate the receipt showed (the sale is booked gross as revenue and the result says how to correct the receipt) or the cash_sale_0 template.";
41812
+ var euros = (amount2) => `${amount2.toFixed(2).replace(".", ",")} \u20AC`;
41813
+ function saleVatNotice(gross, vatRate, vat2, preview) {
41814
+ return `Yritys ei ole ALV-rekisteriss\xE4, joten se ei peri arvonlis\xE4veroa. Myynti ${preview ? "kirjataan" : "kirjattiin"} kokonaan myyntituloksi (${euros(gross)}) ilman ALV-osuutta. Jos asiakkaalle annetussa kuitissa tai laskussa n\xE4kyi arvonlis\xE4vero (${vatRate.replace(".", ",")} %, ${euros(vat2)}), kuitti on virheellinen: anna asiakkaalle alkuper\xE4isen tilalle korjattu kuitti ilman arvonlis\xE4veroa ja liit\xE4 korjattu kuitti tositteeksi Kirjapro-sovelluksessa.`;
41815
+ }
41812
41816
  var NOT_VAT_REGISTERED_PURCHASE_REFUSAL = "This company is not VAT-registered, so it cannot deduct VAT. General-rule services from a foreign supplier can still incur full buyer VAT: use kirjapro_book_purchase with reverseCharge, eu_services/non_eu_services, deductionPercent 0 and documented vatRateBasis, or the atomic purchase form in the web app. Do not add a separate VAT row or duplicate voucher. EU goods, construction and scrap-metal registration requirements need separate assessment; do not change ordinary registration settings merely to bypass this guard. Customs collects import VAT for a buyer outside the VAT register.";
41813
41817
  var REVERSE_CHARGE_CATEGORIES = [
41814
41818
  "eu_goods",
@@ -42333,7 +42337,7 @@ function registerTemplateTools(server2) {
42333
42337
  return toErrorContent(ALV_REGISTERED_SALE_REFUSAL);
42334
42338
  }
42335
42339
  if (!alvRegistered && isVatSaleTemplate(params.template)) {
42336
- return toErrorContent(NOT_VAT_REGISTERED_SALE_REFUSAL);
42340
+ return toErrorContent(SALE_TEMPLATE_NOT_VAT_REGISTERED_REFUSAL);
42337
42341
  }
42338
42342
  }
42339
42343
  return withIdempotency(
@@ -42452,7 +42456,7 @@ Nothing was written.`);
42452
42456
  );
42453
42457
  if (vatSaleIndexes.length > 0) {
42454
42458
  return toErrorContent(
42455
- `${NOT_VAT_REGISTERED_SALE_REFUSAL} Sale templates with VAT at index ${vatSaleIndexes.join(", ")}; nothing was written.`
42459
+ `${SALE_TEMPLATE_NOT_VAT_REGISTERED_REFUSAL} Sale templates with VAT at index ${vatSaleIndexes.join(", ")}; nothing was written.`
42456
42460
  );
42457
42461
  }
42458
42462
  }
@@ -43045,12 +43049,12 @@ function registerBookingTools(server2) {
43045
43049
  server2.registerTool(
43046
43050
  "kirjapro_book_sale",
43047
43051
  {
43048
- description: 'Book a sale (myynti) of a company that is not VAT-registered: it charges no VAT, so the gross amount is revenue in full (vatRate "0"; a VAT rate is refused). Payment types: invoice (default, D Myyntisaamiset), cash (D bank), prepaid. A VAT-registered (ALV) company is refused: its sales reach the ALV report only as invoices (kirjapro_create_invoice + kirjapro_send_invoice).',
43052
+ description: "Book a sale (myynti) of a company that is not VAT-registered: it charges no VAT, so the gross amount is revenue in full and no VAT is booked. If the receipt or invoice the company gave showed VAT, pass that vatRate: the sale is still booked gross, and the result and the dry run carry vat_notice, which you relay to the user (the receipt is replaced with a corrected one without VAT). Payment types: invoice (default, D Myyntisaamiset), cash (D bank), prepaid. A VAT-registered (ALV) company is refused: its sales reach the ALV report only as invoices (kirjapro_create_invoice + kirjapro_send_invoice).",
43049
43053
  inputSchema: {
43050
43054
  amount: external_exports.number().finite().positive().max(1e9).describe("EUR amount the customer pays"),
43051
43055
  description: external_exports.string().min(1).max(500).describe('Transaction description (e.g. "Konsultointi Acme Oy, 40h \xD7 95 \u20AC")'),
43052
43056
  date: ISO_DATE_SCHEMA.describe("Transaction date (YYYY-MM-DD)"),
43053
- vatRate: external_exports.enum(["25.5", "13.5", "10", "0"]).default("0").describe('Only "0" (the default) is accepted: a company outside the VAT register charges no VAT'),
43057
+ vatRate: external_exports.enum(["25.5", "13.5", "10", "0"]).default("0").describe('The VAT rate the receipt or invoice the company gave showed, if any (default "0"). No VAT is booked at any rate; a rate above 0 adds vat_notice'),
43054
43058
  revenueAccount: external_exports.string().default(ACCOUNTS.MYYNTI_0).describe(`Revenue account number (default "${ACCOUNTS.MYYNTI_0}", the 0 % sales account invoices of a company outside the VAT register also use)`),
43055
43059
  paymentType: external_exports.enum(["invoice", "cash", "prepaid"]).default("invoice").describe(`invoice = receivable (${ACCOUNTS.MYYNTISAAMISET}), cash/prepaid = bank payment (${ACCOUNTS.PANKKITILI})`),
43056
43060
  paymentAccount: external_exports.string().default(ACCOUNTS.PANKKITILI).describe(`Bank account for cash/prepaid payments (default "${ACCOUNTS.PANKKITILI}")`),
@@ -43065,9 +43069,10 @@ function registerBookingTools(server2) {
43065
43069
  const companyVat = await readCompanyVat(getSupabase(), getCompanyId());
43066
43070
  if ("isError" in companyVat) return companyVat;
43067
43071
  if (companyVat.alvRegistered) return toErrorContent(ALV_REGISTERED_SALE_REFUSAL);
43068
- if (params.vatRate !== "0") return toErrorContent(NOT_VAT_REGISTERED_SALE_REFUSAL);
43069
43072
  const gross = roundCents(params.amount);
43070
43073
  if (gross <= 0) return toErrorContent("Myynnin summan on oltava v\xE4hint\xE4\xE4n yksi sentti.");
43074
+ const receiptVatRate = params.vatRate === "0" ? null : params.vatRate;
43075
+ const vatNotice = (preview) => saleVatNotice(gross, params.vatRate, splitVat(gross, Number(params.vatRate)).vat, preview);
43071
43076
  const debitAccount = params.paymentType === "invoice" ? ACCOUNTS.MYYNTISAAMISET : params.paymentAccount;
43072
43077
  const entries = [
43073
43078
  { accountNumber: debitAccount, debitAmount: gross, creditAmount: 0 },
@@ -43082,13 +43087,14 @@ function registerBookingTools(server2) {
43082
43087
  gross,
43083
43088
  net,
43084
43089
  vat: vat2,
43085
- vat_rate: `${params.vatRate} %`,
43090
+ vat_rate: "0 %",
43086
43091
  payment_type: params.paymentType,
43087
43092
  debit_account: tagAccountRef(debitAccount),
43088
43093
  revenue_account: tagAccountRef(params.revenueAccount),
43089
43094
  date: params.date,
43090
43095
  entries: echoEntries(entries),
43091
- ...saleAccountWarning && { account_warning: saleAccountWarning }
43096
+ ...saleAccountWarning && { account_warning: saleAccountWarning },
43097
+ ...receiptVatRate && { vat_notice: vatNotice(true) }
43092
43098
  });
43093
43099
  }
43094
43100
  return withIdempotency(
@@ -43112,12 +43118,13 @@ function registerBookingTools(server2) {
43112
43118
  gross,
43113
43119
  net,
43114
43120
  vat: vat2,
43115
- vat_rate: `${params.vatRate} %`,
43121
+ vat_rate: "0 %",
43116
43122
  payment_type: params.paymentType,
43117
43123
  debit_account: tagAccountRef(debitAccount),
43118
43124
  revenue_account: tagAccountRef(params.revenueAccount),
43119
43125
  entries: echoEntries(entries),
43120
- ...saleAccountWarning && { warning: saleAccountWarning }
43126
+ ...saleAccountWarning && { warning: saleAccountWarning },
43127
+ ...receiptVatRate && { vat_notice: vatNotice(false) }
43121
43128
  });
43122
43129
  }
43123
43130
  );
@@ -45523,7 +45530,7 @@ var INSTRUCTIONS_FULL_ADDENDUM = `
45523
45530
 
45524
45531
  ### Booking Shortcuts
45525
45532
  Faster than composing journal entries via \`kirjapro_create_transaction\`:
45526
- - \`kirjapro_book_sale\` / \`kirjapro_book_purchase\` \u2014 one-liner with auto VAT splitting. A VAT-registered (ALV) company books sales as invoices (\`kirjapro_create_invoice\` + \`kirjapro_send_invoice\`): \`kirjapro_book_sale\` is refused for it. Purchases use \`kirjapro_book_purchase\` with source \`vatRateBasis\` and a documented deduction share; reverse charge records the full buyer tax, including when deduction is zero. Import means customs-tax assessment only on the complete customs base, with no duplicate supplier purchase/payment
45533
+ - \`kirjapro_book_sale\` / \`kirjapro_book_purchase\` \u2014 one-liners. A VAT-registered (ALV) company books sales as invoices (\`kirjapro_create_invoice\` + \`kirjapro_send_invoice\`): \`kirjapro_book_sale\` is refused for it. A company outside the VAT register books its sale gross with no VAT; if its receipt showed VAT, relay the result's \`vat_notice\` to the user (the receipt is replaced with a corrected one). Purchases use \`kirjapro_book_purchase\` with source \`vatRateBasis\` and a documented deduction share; reverse charge records the full buyer tax, including when deduction is zero. Import means customs-tax assessment only on the complete customs base, with no duplicate supplier purchase/payment
45527
45534
  - \`kirjapro_book_vat_settlement\` \u2014 settles the company's VAT period from ALV-saamiset/ALV-velka. Call \`kirjapro_get_alv_summary\` for the period first to preview the net and its reconciliation.
45528
45535
  - **Payroll is intentionally NOT exposed.** Direct users to Palkkaus.fi / Palkka.fi for salary calculation; the payslip can then be booked manually via \`kirjapro_create_transaction\`.
45529
45536
  - \`kirjapro_list_templates\` \u2192 \`kirjapro_create_from_template\` for common patterns (built-in templates; the sale templates are hidden and refused for a VAT-registered company)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kirjapro/mcp-server",
3
- "version": "0.18.0",
3
+ "version": "0.18.1",
4
4
  "description": "MCP server for Finnish accounting — exposes Kirjapro bookkeeping, invoicing, and reporting tools to Claude, ChatGPT, Mistral, and other MCP clients.",
5
5
  "type": "module",
6
6
  "bin": {
package/server.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@kirjapro/mcp-server",
3
3
  "displayName": "Kirjapro - Finnish Accounting",
4
4
  "description": "Finnish double-entry bookkeeping, invoicing, and financial reporting for growing businesses. Create transactions, generate invoices with VAT calculation, produce income statements and balance sheets, and validate Finnish business identifiers.",
5
- "version": "0.18.0",
5
+ "version": "0.18.1",
6
6
  "homepage": "https://kirjapro.fi",
7
7
  "repository": "https://github.com/Jaollo/kirja-pro",
8
8
  "license": "MIT",
@@ -6,7 +6,7 @@
6
6
  },
7
7
  {
8
8
  "name": "kirjapro_book_sale",
9
- "hash": "4a397f56677421fb"
9
+ "hash": "7a4971b42657b6b5"
10
10
  },
11
11
  {
12
12
  "name": "kirjapro_book_vat_settlement",