@kirjapro/mcp-server 0.18.1 → 0.20.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/CHANGELOG.md CHANGED
@@ -1,5 +1,207 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.20.0] - 2026-10-20
4
+
5
+ PR D of the MCP audit of 18.10.2026 (batches 7 to 12 and 14). Against 0.19.0, 3 of the 56
6
+ tool fingerprints change: `kirjapro_book_vat_settlement`, `kirjapro_send_invoice` and
7
+ `kirjapro_send_offer`. The package now bundles its runtime dependencies (no `dependencies`
8
+ in `package.json`).
9
+
10
+ **PR D release order** (one checklist for every section below; the rollout runbook row 7d0b
11
+ in `docs/guides/ai-workspace-rollout.md` is its source): (1) merge by hand, which deploys the
12
+ web app (until step 2 its Settings page can neither create nor revoke an API key); (2) `npm
13
+ run db:deploy` from clean `main` at low traffic, all six migrations `20261019140000`,
14
+ `20261019150000`, `20261019150100`, `20261019164710`, `20261019170000` and `20261019180000`;
15
+ (3) `npm run functions:deploy` of `dispatch-invoice`, `send-offer-email`, `prh-lookup`,
16
+ `generate-recurring-invoices` and `send-payment-reminders`; (4) `mcp-auth`; (5) `mcp` last;
17
+ (6) this package. For about 11 minutes after step 2 an OAuth connection of a user with MFA
18
+ that was approved just before it may answer 401 once and authorize again.
19
+
20
+ API key lifecycle and DB-boundary hygiene (MCP audit of 18.10.2026, PR D batch 9). Server
21
+ side only: no tool, description or fingerprint changes, and every published package gets
22
+ the behaviour once migrations `20261019150000` and `20261019150100` and the `mcp-auth`
23
+ deploy are live (steps 2 and 4). `src/database.types.ts` gains `api_keys.membership_id`
24
+ and the RPCs `create_api_key`, `revoke_api_key` and `mcp_api_key_access`.
25
+
26
+ - A revoked or expired key's live token, or that of a key whose creator left the company,
27
+ now gets `CREDENTIAL_INVALID` from its next read instead of empty lists ("0 invoices",
28
+ "not found"): the Data API gate answers such a key token with 401 and a message that
29
+ starts with the code.
30
+ - `mcp-auth` answers the key of a creator who was removed from the company (even if
31
+ invited again) with 401, which the server reads as a permanent `CREDENTIAL_INVALID`,
32
+ instead of the `API_ENTITLEMENT_REQUIRED` 403; a failed check is a transient 503.
33
+ - A credential holds at most 1 000 unresolved idempotency claims. Beyond them a write is
34
+ refused before it runs (`IDEMPOTENCY_BACKEND_UNAVAILABLE`, the write was not executed).
35
+ - Keys are created and revoked only in the Kirjapro app (Asetukset → MCP-palvelin), which
36
+ now generates the key in the database and, before revoking, lists the key's writes and
37
+ offers to pause the recurring invoices with automatic sending that it touched; the revoke
38
+ button waits for that list. A key stays bound to its creator's membership for good: no
39
+ later write, not even an operator's, moves or restores the binding.
40
+
41
+ Untrusted text and send friction (MCP audit of 18.10.2026, PR D batch 7: T2-7, T2-8, T3-40,
42
+ T3-42 to T3-45, T4-13, T4-18; T3-41 was fixed by PR A). Released by the PR D order above
43
+ (the migration `20261019164710` and the Edge functions before this package). Three
44
+ fingerprints change:
45
+ `kirjapro_send_invoice`, `kirjapro_send_offer` and `kirjapro_book_vat_settlement`.
46
+
47
+ - `kirjapro_send_invoice` and `kirjapro_send_offer` take `dryRun`: nothing is claimed or
48
+ sent, and the preview names the recipient (wrapped), the channel and the invoice or offer
49
+ number, with `recipient_confirmation_required`. The results name the recipient(s),
50
+ wrapped. The preview asks the Edge function with `previewInvoiceId` or `previewOfferId`,
51
+ never with `invoiceId` or `offerId`, so a function deployed before previews refuses it
52
+ (`PREVIEW_UNAVAILABLE: … Nothing was sent`) and a dry run can never deliver. The text says
53
+ `Nothing was sent` only for a refusal or a lost answer.
54
+ - Recipient confirmation (founder decision 19.10.2026): when the customer's e-mail or
55
+ e-invoice address was created or changed through an MCP credential (an API key or an
56
+ OAuth connection) in the last 24 hours, the send is refused with a cached
57
+ `RECIPIENT_CONFIRMATION_REQUIRED` naming the address, unless the call passes
58
+ `confirmRecipient` equal to it (an e-mail address in any case). A person who saves the
59
+ customer in the Kirjapro app confirms it too. The rule runs in the Edge functions, so the
60
+ remote endpoint enforces it as well; signers configured for a contract in the app need no
61
+ confirmation. The tool descriptions and the server instructions ask the agent to show the
62
+ address to the user first. An e-invoice refusal also names the operator. The automatic
63
+ sends have nobody to confirm, so they hold any recipient an MCP credential set that no
64
+ person has saved since, however old: the daily recurring run leaves the invoice a draft
65
+ and the template's generation log says why, and the payment reminders skip the customer.
66
+ An offer without any recipient answers the missing e-mail address, not
67
+ `RECIPIENT_CONFIRMATION_REQUIRED`.
68
+ - Invoice, reference, offer and customer numbers are no longer trusted as "generated": they
69
+ stay bare only in the shape Kirjapro allocates (`2026-0001`, digits, `TAR00001`/`SOP00001`,
70
+ `C00001`) and are wrapped otherwise, in the read tools (also the ALV reconciliation, the
71
+ offer events and the recurring invoice log) and in the write tools' results and messages
72
+ (a partial reversal of U-65). The company's own IBAN is bare only with a numeric account
73
+ part. The server instructions and `kirjapro://security/data-handling` say so.
74
+ - Refusal texts of the bank reconciliation tools and of `kirjapro_book_vat_settlement` that
75
+ quote stored text (an e-invoice number, a voucher number, the line's currency) are wrapped.
76
+ - An argument that contains `⟦redacted⟧`, which a read result shows in place of text that
77
+ looked like an instruction, is refused with `INVALID_ARGUMENTS` instead of being stored.
78
+ - `kirjapro_get_received_invoice` wraps `pdf_storage_path` (the sender's file name).
79
+ - `kirjapro_get_recurring_invoice` keeps a `template_data` code bare only when it is a VAT
80
+ treatment code, VAT category, price-entry mode or account id the server writes.
81
+ - `kirjapro_get_general_ledger` echoes an unknown account wrapped unless it is a number;
82
+ `kirjapro_book_vat_settlement` takes a 4- or 5-digit `paymentAccount` only.
83
+ - `kirjapro_get_offer` keeps the status codes `from_status` and `to_status` of an offer event
84
+ bare.
85
+
86
+ PR D of the MCP audit of 18.10.2026 (batches 8, 11 and 14). No tool definition changes and
87
+ no fingerprint changes. Released by the PR D order above (`20261019170000`, the server-side
88
+ `batch_size` clamp, is in its `db:deploy`; the package does not need it). Before the first
89
+ tag, run the publish workflow once by hand on `main`: its `publish` job now runs in the
90
+ `npm-publish` environment.
91
+
92
+ - **No runtime dependencies** (T3-58): `@modelcontextprotocol/sdk`, `zod` and
93
+ `@supabase/supabase-js` are bundled into `dist/index.js` (about 2.7 MB) and are
94
+ devDependencies; the optional `@supabase/supabase-js` peer dependency is gone. `npx -y
95
+ @kirjapro/mcp-server` installs this one package, so no unpinned third-party package or
96
+ install script runs with `KIRJAPRO_API_KEY` in its environment. Up to 0.19.0 about 105
97
+ packages were resolved at install time.
98
+ - **Stable code for a schema refusal** (T4-16): arguments that fail a tool's input schema
99
+ answer `INVALID_ARGUMENTS: Input validation error: Invalid arguments for tool …` instead
100
+ of `MCP error -32602: Input validation error: …`, so every failed call starts with a code.
101
+ Telemetry already recorded these as `INVALID_ARGUMENTS`.
102
+ - **Telemetry `batch_size`** (T3-60): only a transactions count within 1–250 is sent. A
103
+ batch call with `transactions: []` or more than 250 items (which the SDK then refuses)
104
+ made the database refuse the whole telemetry flush, its neighbours' events included.
105
+ - **Release pipeline** (T2-12, T3-78; no package change): `publish-mcp.yml` builds and packs
106
+ in a job without secrets or publish rights, checks the live types in a job that holds
107
+ only the read token and installs nothing but the checksum-pinned Supabase CLI 2.111.0
108
+ release, and publishes the packed tarball from a job
109
+ in the `npm-publish` environment that installs nothing. `check:release-version` keeps
110
+ `package.json`, `server.json`, `mcpb/manifest.json` and this file's version heading in
111
+ step on every pull request; `mcpb:validate` and `mcpb:pack` pin `@anthropic-ai/mcpb@2.1.2`.
112
+ `check:types-drift` (also in `prepublishOnly`) runs `supabase` from `PATH` and fails unless
113
+ `supabase --version` is exactly 2.111.0; it no longer runs `npx -y supabase@latest`.
114
+
115
+ ## [0.19.0] - 2026-10-19
116
+
117
+ PR C of the MCP audit of 18.10.2026 (batches 3 and 4: posting guards and e-invoice send-state
118
+ guards). **Release order:** `npm run db:deploy` of `20261019120000`–`20261019120300` and
119
+ `20261019130000` first (`kirjapro_get_invoice` fails against a database without
120
+ `20261019130000`, and `check:types-drift` fails until it is live), then the Edge functions
121
+ `dispatch-invoice`, `generate-recurring-invoices`, `process-dead-letters`,
122
+ `send-einvoice-maventa`, `send-invoice-email` and `mcp`, then this package. Against 0.18.1,
123
+ 12 of the 56 tool fingerprints change: `kirjapro_book_purchase`,
124
+ `kirjapro_create_from_template`, `kirjapro_create_invoice`, `kirjapro_create_transaction`,
125
+ `kirjapro_create_transactions_batch`, `kirjapro_delete_invoice`, `kirjapro_get_invoice`,
126
+ `kirjapro_link_bank_transaction`, `kirjapro_list_bank_link_candidates`,
127
+ `kirjapro_match_bank_transaction`, `kirjapro_send_invoice` and
128
+ `kirjapro_update_invoice_status`. The two sections below list the changes per batch.
129
+
130
+ E-invoice send-state guards (MCP audit of 18.10.2026, PR C batch 4: T2-6, T3-53 to T3-57).
131
+ **Needs migration `20261019130000` before the release:** `kirjapro_get_invoice` reads the
132
+ computed field `invoice_delivery_in_progress`, which a database without the migration
133
+ refuses (the call fails). Deploy the Edge functions before publishing: `dispatch-invoice`
134
+ (names the channel of another delivery in `inProgressChannel`, re-reads the invoice after
135
+ its attempt mark), `generate-recurring-invoices`, `process-dead-letters`,
136
+ `send-einvoice-maventa`, `send-invoice-email` and `mcp` (the shared read definitions and the
137
+ generated core).
138
+ Four fingerprints change: `kirjapro_get_invoice`, `kirjapro_send_invoice`,
139
+ `kirjapro_update_invoice_status` and `kirjapro_delete_invoice`.
140
+
141
+ - `kirjapro_get_invoice` returns an optional `delivery` object once the invoice has a
142
+ delivery through Kirjapro: `in_progress` (with its `channel`) while a send is queued or
143
+ started and its outcome is not settled, or a draft was delivered but is not yet marked
144
+ sent; `einvoice_status` and `email_sent_at` as the providers reported them. Without
145
+ `delivery`, no delivery was started. A failed read of it fails the call. A client that
146
+ cached the previous output schema and checks results refuses the results that carry
147
+ `delivery` until it lists the tools again.
148
+ - `kirjapro_update_invoice_status` does not cancel a draft whose delivery is in progress or
149
+ done: the database refuses it for every client and the tool answers `DELIVERY_IN_PROGRESS`.
150
+ - `kirjapro_send_invoice` delivers an invoice once. A web, scheduled or earlier e-invoice
151
+ (pending or accepted) or a sent e-mail refuses another delivery, and another channel's
152
+ delivery in progress is now a definite, cached `DELIVERY_IN_PROGRESS` that names that
153
+ channel, not `IDEMPOTENCY_OUTCOME_UNKNOWN`. The outcome-unknown answer says not to cancel,
154
+ delete or use the other channel, points to `delivery` in `kirjapro_get_invoice` and says
155
+ that a new `idempotencyKey` for the same invoice and channel resumes the same delivery.
156
+ - `kirjapro_send_invoice` of an invoice that is already sent (`sent`, `partial`, `paid` or
157
+ `overdue`), for example the retry of a send whose outcome was unknown but which in fact
158
+ delivered it, answers a cached success with `already_sent: true`, `email_sent_at` and
159
+ `einvoice_status`, without a second delivery; before, it was an error. Its `channel` is
160
+ the one the evidence shows (`email`, `einvoice`), and an invoice marked sent in the app
161
+ without a Kirjapro delivery answers `channel: null` and says that Kirjapro sent nothing.
162
+ - `kirjapro_delete_invoice` does not delete a draft whose delivery is in progress or done
163
+ (a live e-invoice transmission, a sent e-mail, or an e-mail whose outcome a person has yet
164
+ to resolve): the database refuses it and the tool answers a cached `DELIVERY_IN_PROGRESS`.
165
+ - The `vat_notice` of `kirjapro_send_invoice` for a sales credit note gives its effect on the
166
+ VAT payable as negative (the credit note is stored with positive amounts and reverses the
167
+ VAT); it was positive.
168
+
169
+ MCP audit of 18.10.2026, batch 3 (posting guards). Needs the database migrations
170
+ `20261019120000`–`20261019120300` first; nine tool fingerprints change
171
+ (`kirjapro_book_purchase`, `kirjapro_create_from_template`, `kirjapro_create_transaction`,
172
+ `kirjapro_create_transactions_batch`, `kirjapro_create_invoice`, `kirjapro_send_invoice`,
173
+ `kirjapro_match_bank_transaction`, `kirjapro_list_bank_link_candidates`,
174
+ `kirjapro_link_bank_transaction`).
175
+
176
+ - A VAT posting dated in a VAT period already settled with `kirjapro_book_vat_settlement`
177
+ is still booked, and the result adds `vat_notice`, a Finnish note the agent relays to the
178
+ user: the period's settlement does not include this VAT (the note gives its net effect on
179
+ the VAT payable with its sign), so the period's VAT return is corrected in OmaVero and the
180
+ difference settled with a voucher (founder decision 19.10.2026, audit T3-16). Reductions
181
+ count too (a purchase credit note, a 4210 debit); VAT settlements, payments and refunds do
182
+ not. Covered: `kirjapro_book_purchase` (and its dry run), a purchase
183
+ template with VAT in `kirjapro_create_from_template`, `kirjapro_create_transaction` and
184
+ `kirjapro_create_transactions_batch` lines on 2320/4210 (preview and commit, one line per
185
+ voucher), and `kirjapro_send_invoice` (the sales journal is dated on the invoice date).
186
+ - `kirjapro_create_invoice` takes an optional `deliveryDate` (supply date). VAT treatments
187
+ are judged by it, as the app and the database do, and it is stored on the invoice
188
+ (audit T3-17): food delivered in December 2025 and invoiced in January 2026 keeps 14 %.
189
+ - `kirjapro_match_bank_transaction` refuses with `ALREADY_BOOKED` when a voucher already
190
+ moved the bank account by exactly the receipt's amount; link the line to that voucher
191
+ with `kirjapro_link_bank_transaction` instead (audit T3-19).
192
+ - `kirjapro_link_bank_transaction` to a purchase invoice answers `ALREADY_BOOKED` when the
193
+ payment already has a voucher that debits the invoice's payable (the database refuses it,
194
+ audit T2-1), and `kirjapro_list_bank_link_candidates` lists vouchers first. A same-amount
195
+ voucher that does not touch the payable no longer blocks the invoice link, and a line with
196
+ a payment-batch EndToEndId links to the batch item's separate payment voucher. The refusal
197
+ text is built from structured fields (the voucher number wrapped, the supplier's invoice
198
+ number not echoed). An item accepted by hand without a bank line no longer closes the cap
199
+ for a line without its EndToEndId (audit T3-27).
200
+ - An archived account is refused before any write with `ACCOUNT_ARCHIVED` in the voucher,
201
+ template and booking tools (audit T3-26).
202
+ - The install examples use `@kirjapro/mcp-server@latest`, so an older npm does not reuse a
203
+ cached copy; the package updates when the app restarts the server.
204
+
3
205
  ## [0.18.1] - 2026-10-19
4
206
 
5
207
  No database migration; one tool fingerprint changes (`kirjapro_book_sale`).
package/README.md CHANGED
@@ -39,6 +39,9 @@ sending, or when you automate Kirjapro from a local MCP client.
39
39
 
40
40
  ### 2. Configure your MCP client
41
41
 
42
+ The examples use `@kirjapro/mcp-server@latest`: the package updates whenever your app
43
+ restarts the server, and a running session keeps the version it started with.
44
+
42
45
  #### Claude Code
43
46
 
44
47
  Add the server with `claude mcp add`. User scope (every project) and local scope (this
@@ -47,7 +50,7 @@ project root:
47
50
 
48
51
  ```bash
49
52
  claude mcp add --transport stdio --env KIRJAPRO_API_KEY=kp_your_key_here --scope user \
50
- kirjapro -- npx -y @kirjapro/mcp-server
53
+ kirjapro -- npx -y @kirjapro/mcp-server@latest
51
54
  ```
52
55
 
53
56
  A project-scope `.mcp.json` is usually committed, so reference the key from your
@@ -59,7 +62,7 @@ environment instead of pasting it:
59
62
  "kirjapro": {
60
63
  "type": "stdio",
61
64
  "command": "npx",
62
- "args": ["-y", "@kirjapro/mcp-server"],
65
+ "args": ["-y", "@kirjapro/mcp-server@latest"],
63
66
  "env": {
64
67
  "KIRJAPRO_API_KEY": "${KIRJAPRO_API_KEY}"
65
68
  }
@@ -85,7 +88,7 @@ Add to `claude_desktop_config.json`:
85
88
  "mcpServers": {
86
89
  "kirjapro": {
87
90
  "command": "npx",
88
- "args": ["-y", "@kirjapro/mcp-server"],
91
+ "args": ["-y", "@kirjapro/mcp-server@latest"],
89
92
  "env": {
90
93
  "KIRJAPRO_API_KEY": "kp_your_key_here"
91
94
  }
@@ -105,7 +108,7 @@ Add to `~/.vibe/config.toml`:
105
108
  name = "kirjapro"
106
109
  transport = "stdio"
107
110
  command = "npx"
108
- args = ["-y", "@kirjapro/mcp-server"]
111
+ args = ["-y", "@kirjapro/mcp-server@latest"]
109
112
  env = { KIRJAPRO_API_KEY = "kp_your_key_here" }
110
113
  ```
111
114
 
@@ -113,7 +116,7 @@ Restart Vibe and verify the connection from `/mcp`.
113
116
 
114
117
  #### ChatGPT
115
118
 
116
- For read-only use, add the [remote endpoint](#remote-endpoint-no-install) as a connector instead. ChatGPT cannot launch this local `stdio` package directly; for write tools use [OpenAI Secure MCP Tunnel](https://developers.openai.com/api/docs/guides/secure-mcp-tunnels) to bridge ChatGPT to `npx -y @kirjapro/mcp-server`. Full write/modify support currently requires ChatGPT Business or Enterprise/Edu; see the [full setup guide](https://kirjapro.fi/docs/mcp/) for the tunnel commands and plan limitations.
119
+ For read-only use, add the [remote endpoint](#remote-endpoint-no-install) as a connector instead. ChatGPT cannot launch this local `stdio` package directly; for write tools use [OpenAI Secure MCP Tunnel](https://developers.openai.com/api/docs/guides/secure-mcp-tunnels) to bridge ChatGPT to `npx -y @kirjapro/mcp-server@latest`. Full write/modify support currently requires ChatGPT Business or Enterprise/Edu; see the [full setup guide](https://kirjapro.fi/docs/mcp/) for the tunnel commands and plan limitations.
117
120
 
118
121
  Mistral Le Chat accepts only a remote MCP server URL, so it cannot launch this package; it can use the [remote endpoint](#remote-endpoint-no-install) for read-only access. The local npm package works directly with Mistral Vibe.
119
122
 
@@ -147,7 +150,7 @@ A few prompts to feel out the daily workflows the agent handles cleanly:
147
150
  "mcpServers": {
148
151
  "kirjapro": {
149
152
  "command": "npx",
150
- "args": ["-y", "@kirjapro/mcp-server"],
153
+ "args": ["-y", "@kirjapro/mcp-server@latest"],
151
154
  "env": {
152
155
  "KIRJAPRO_API_KEY": "kp_your_key_here",
153
156
  "KIRJAPRO_MCP_SURFACE": "full" // 56 tools instead of 29