@kirjapro/mcp-server 0.5.6 → 0.5.8

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,204 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.5.8] - 2026-05-18
4
+
5
+ Three coordinated dep-migration waves (W1, W3, W4b) of the pre-launch
6
+ version-migration campaign. No runtime behavior changes for MCP consumers;
7
+ tool input schemas gain explicit `z.record(string, unknown)` form (Zod 4
8
+ requirement) which shifts JSON-schema hashes — fingerprint baseline updated.
9
+
10
+ ### Changed
11
+
12
+ - **Dependencies (W1)** — `@modelcontextprotocol/sdk` 1.12 → 1.29,
13
+ `@supabase/supabase-js` 2.49 → 2.105, `tsx` 4.19 → 4.22.
14
+ - **Dependencies (W3)** — `esbuild` 0.25 → 0.28, `typescript` 5.7 → 6.0,
15
+ `vitest` 3.0 → 4.1. Added `@types/node` ^22.18.0 as direct devDep
16
+ (was transitive — TS 6 dropped that auto-discovery).
17
+ - **Dependencies (W4b)** — `zod` 3.24 → 4.4.
18
+
19
+ ### Fixed
20
+
21
+ - **(W1) supabase-js v2.100+ `RejectExcessProperties` rejects `Record<string, unknown>`**
22
+ at `.update()` / `.insert()` call sites — the new generic wrapper
23
+ resolves to `{ [x: string]: never }` for any source carrying an open
24
+ index signature. Re-typed `updates` / `updateFields` in four tool files
25
+ as `Database['public']['Tables']['<table>']['Update']`:
26
+ `customers.ts`, `invoices.ts`, `offers.ts`, `recurring-invoices.ts`.
27
+ Skill: `supabase-js-update-rejectexcessproperties`.
28
+ - **(W1) `customers.ts` latent NOT-NULL bug** — `updates.name = sanitizeText(...)`
29
+ would attempt to set `name = null` (and trip the column's NOT NULL
30
+ CHECK at the DB) when the sanitizer collapsed whitespace-only input.
31
+ Now coalesces `?? undefined` so the field is skipped instead.
32
+ - **(W1) `offers.ts` dynamic-key write** refactored from a `timestampMap[newStatus]`
33
+ lookup into an explicit `switch` on the discriminator — typed Update
34
+ rejects open-string indexing.
35
+ - **(W1) `recurring-invoices.ts` `template_data` assignment** — cast as `Json`
36
+ at the assignment site; `Record<string, unknown>` is not a subtype of
37
+ the recursive `Json` type.
38
+ - **(W3) `tsconfig.json` — added `"types": ["node"]`.** TS 6 with
39
+ `moduleResolution: "bundler"` stopped auto-including `@types/node` from
40
+ transitive deps. Without explicit declaration, 21 TS2591 errors hit
41
+ (`process`, `Buffer`, `node:crypto`, `.unref` on `setTimeout` return).
42
+ Skill: `ts6-bundler-resolution-types-node-explicit`.
43
+ - **(W4b) Zod 4 `z.record` API requires explicit key schema.** Migrated
44
+ 11 sites from `z.record(z.unknown())` → `z.record(z.string(), z.unknown())`
45
+ across `schemas.ts` and six tool files. Tool fingerprints regenerated
46
+ via `npm run fingerprints:update` — the rug-pull guard correctly caught
47
+ the JSON-schema-shape shift even though it's semantically equivalent.
48
+
49
+ ## [0.5.7] - 2026-05-09
50
+
51
+ ## [0.5.7] - 2026-05-09
52
+
53
+ Pre-launch trim and supply-chain hardening. Two coordinated changes shape
54
+ the launch posture: a curated default surface that keeps the agent under
55
+ the empirical tool-selection accuracy cliff, and a fingerprint guard that
56
+ defends against silent description / annotation / inputSchema tampering
57
+ between releases.
58
+
59
+ ### Added — `KIRJAPRO_MCP_SURFACE` env var
60
+
61
+ - **Default `core` surface (26 of 53 tools)** — daily-use shape per 2025-2026
62
+ SOTA research (Anthropic Opus 4 dropped to 49% accuracy at large MCP
63
+ catalogs, recovered to 79.5% with Tool Search). 27 tools deferred:
64
+ booking shortcuts (`book_*`), templates, recurring invoices, received
65
+ invoices, batch tools, deletes, financial notes, manual offer status,
66
+ search/get_transaction, general_ledger, list_bank_accounts,
67
+ update_customer. All kept in code; restored on flip of
68
+ `KIRJAPRO_MCP_SURFACE=full`.
69
+ - **Surface-aware `INSTRUCTIONS`** — common preamble + core-mode addendum
70
+ ("redirect to web UI for these workflows") OR full-mode addendum
71
+ ("extended workflows for the deferred set"). The agent never reads
72
+ workflow hints for tools missing from its `tools/list`. Closes the
73
+ worst-class failure mode: agent reaches for closest-match tool and
74
+ ships a one-off invoice when the user wanted a recurring template.
75
+ - **Capabilities NOT in this MCP** section in `INSTRUCTIONS_COMMON` —
76
+ always-missing tasks (file uploads, bank account configuration,
77
+ e-invoice sending, multi-company switching, year-end disclosure form)
78
+ redirected to the web UI in any surface mode.
79
+ - **Boot log** announces `surface=core — registered 26 tools, deferred 27`
80
+ or `surface=full — registered all 53 tools`. Unknown values fall back
81
+ to `core` with a stderr warning.
82
+ - **`kirjapro-aloita`** prompt computes the active tool count dynamically
83
+ from `_registeredTools` size — accurate for both surfaces, no copy
84
+ drift.
85
+
86
+ ### Added — Tool description fingerprint guard
87
+
88
+ - **`tool-fingerprints.json`** ships with the package. Each tool's
89
+ `description + annotations + inputSchema` is hashed via SHA-256
90
+ truncated to 64 bits and persisted alphabetically by tool name.
91
+ Defends against the rug-pull vector documented by Pipelock and CyberArk
92
+ — silent description tampering or schema relaxation between releases.
93
+ - **CI guard** (`tools-registry.test.ts`) asserts the running build's
94
+ fingerprint set matches the persisted file. Failure message tells the
95
+ operator: bump `package.json` version and run
96
+ `npm run fingerprints:update` if intentional, revert otherwise.
97
+ - **`fingerprints:update` script** logs every `ADDED` / `REMOVED` /
98
+ `CHANGED <name> <oldhash> → <newhash>` entry before writing. Silent
99
+ laundering of a malicious description through "version-bump + regen"
100
+ must also falsify CI logs to slip past review.
101
+ - **Schema coverage in v0.5.7** — `inputSchema` now part of the hash
102
+ payload. v0.5.6 had description+annotations only, leaving Zod-enum
103
+ relaxation as a coverage gap. Closed in this release per the
104
+ pre-launch code review (docs/reviews/2026-05-09-mcp-fingerprint-guard.md).
105
+
106
+ ### Tests
107
+
108
+ - **187 passing** (was 172 in v0.5.6). Three new registry tests cover
109
+ surface=core (26-tool exact match), deferred tools NOT registered, and
110
+ CORE_TOOL_NAMES is a strict subset of the full registration set. One
111
+ new test asserts current build matches the persisted fingerprint file.
112
+
113
+ ### Fixed
114
+
115
+ - **Stale `52 tools` claim** in `INSTRUCTIONS` and the `kirjapro-aloita`
116
+ Finnish prompt — was last updated before DT-045 added
117
+ `kirjapro_get_financial_notes`. Both now derive count dynamically.
118
+ - **Supabase CLI version banner pollution** in `database.types.ts` — the
119
+ CLI emits its update-notification banner to STDOUT, which had been
120
+ concatenated to the bottom of the generated file by a prior
121
+ `gen types ... > database.types.ts` redirect. Broke `tsc --noEmit`
122
+ inside `mcp-server/` until removed. Skill
123
+ `supabase-gen-types-cli-banner-pollution` documents the failure mode
124
+ and the `grep -v` filter pipeline that prevents it.
125
+
126
+ ### Notes
127
+
128
+ - The npm package now ships `tool-fingerprints.json` alongside
129
+ `dist/index.js`. Downstream operators who want Pipelock-style pinning
130
+ can read the JSON and reject mid-release tampering.
131
+ - Part of the broader MCP SOTA enhancement track filed in
132
+ `docs/roadmap/features/planned/mcp-server-*` — Phase 1 (observability,
133
+ per-call telemetry, CI fingerprint enforcement at scale) is sequenced
134
+ for post-launch when real traffic exists to inform the eager-tool set.
135
+
136
+ ## [0.5.6] - 2026-04-20
137
+
138
+ Pre-production adversarial audit hardening. Ten findings verified and patched
139
+ across auth, idempotency, numbering, account scoping, and calendar validation.
140
+ No tool-surface changes — all tool names, parameters, and return shapes are
141
+ stable. One nullable DB column added (`mcp_idempotency_keys.body_sha256`);
142
+ legacy rows continue to work without backfill.
143
+
144
+ ### Security & correctness
145
+
146
+ - **`.or()` grammar injection blocked** — `escapeOrValue()` percent-encodes
147
+ `,`, `(`, `)` before interpolation into PostgREST `.or(...)` filters. Applied
148
+ at all four sites: `accounts.ts`, `customers.ts`, `received-invoices.ts`,
149
+ `banking.ts`. Five new test cases.
150
+ - **Audit-log IP source trustworthiness** — `mcp-auth` edge function prefers
151
+ `x-real-ip`, then `cf-connecting-ip`, then leftmost of `x-forwarded-for`
152
+ before attributing a request to a caller IP. Requires `--no-verify-jwt`
153
+ redeploy.
154
+ - **Idempotency burst fail-open** — `withIdempotency()` now polls a pending
155
+ claim in `CLAIM_WAIT_MS` slices until either the response lands or the claim
156
+ ages past `CLAIM_STALE_MS`; on exhaustion returns an explicit `retry_later`
157
+ error instead of racing into a duplicate write.
158
+ - **Idempotency body-hash check** (T3-6, migration
159
+ `20260420192510_mcp_idempotency_body_hash.sql`) — each claim stores
160
+ `sha256(canonical JSON of params ∖ idempotencyKey)`. On cache hit the server
161
+ recomputes and compares; mismatch returns `IDEMPOTENCY_BODY_MISMATCH`
162
+ instead of silently replaying the wrong cached response. Nullable column,
163
+ legacy rows and tests without params skip the check.
164
+ - **`initLegacyAuth` bypass closed** — `auth.ts` requires explicit
165
+ `ALLOW_LEGACY_AUTH=true` opt-in; otherwise throws with an actionable error.
166
+ Opt-in path logs a deprecation warning.
167
+
168
+ ### Validation & data integrity
169
+
170
+ - **`accountOverrides` allowlist** — `validateAccountOverrides()` in
171
+ `templates.ts` rejects missing or inactive target accounts, enforces type
172
+ parity with the source account, and merges per-line overrides while
173
+ rejecting conflicts where a single source maps to multiple targets.
174
+ - **Calendar-invalid dates rejected at parse** — new `isValidCalendarDate()`
175
+ + `ISO_DATE_SCHEMA` helpers validate via UTC round-trip (Feb 31 no longer
176
+ silently rolls over to Mar 3). Wired across nine tool files (27 call sites);
177
+ month-only patterns (e.g. `YYYY-MM` on ALV-kausi) are intentionally not
178
+ swapped. Six new unit tests.
179
+ - **Invoice-numbering RPC audit** (T3-5) — verified all three monotonic
180
+ mints (`customers`, `invoices`, `offers`) plus `convert_offer_to_invoice`
181
+ use advisory-locked server-side RPCs. No in-tool `MAX(n)+1` anywhere.
182
+ Documented as clean; no code change required.
183
+
184
+ ### Tooling
185
+
186
+ - **Tests:** 172 passing (up from 154 in v0.5.5). +6 ISO_DATE_SCHEMA,
187
+ +6 validateAccountOverrides, +6 body-hash (4 hash-helper + 2
188
+ mismatch/match scenarios).
189
+ - **Typecheck:** `tsc --noEmit` clean.
190
+
191
+ ### Deploy prerequisites
192
+
193
+ Published artefact requires:
194
+
195
+ 1. Apply migration `20260420192510_mcp_idempotency_body_hash.sql` to the
196
+ Supabase project (adds nullable `body_sha256`). Missing column will NOT
197
+ break the server — the INSERT still succeeds with PostgREST schema-cache
198
+ tolerance — but the mismatch check will be inert until migrated.
199
+ 2. Redeploy `mcp-auth` edge function with `--no-verify-jwt` so the IP-source
200
+ hardening (T2-3) takes effect.
201
+
3
202
  ## [0.5.5] - 2026-04-11
4
203
 
5
204
  Tool-annotation sweep: every remaining `server.tool()` call migrated to
package/README.md CHANGED
@@ -80,27 +80,51 @@ See [full setup guide](https://kirjapro.fi/docs/mcp/) for Cursor, VS Code / Copi
80
80
 
81
81
  Ask your AI assistant: *"list my fiscal years"* — it should call `kirjapro_list_fiscal_years` and return your company's accounting periods.
82
82
 
83
+ ### 4. Try these prompts
84
+
85
+ A few prompts to feel out the daily workflows the agent handles cleanly:
86
+
87
+ - *"Show my dashboard"* — financial snapshot of the current fiscal year
88
+ - *"Create an invoice for Acme Oy, 5000 € for consulting in March"* — full lifecycle from customer lookup to draft invoice
89
+ - *"Draft a contract for Acme Oy and email it to john@acme.fi, 3-month retainer at 5000 € / month"* — `tarjous`/`sopimus` create + customer-visible email link
90
+ - *"Record that invoice #42 was paid yesterday"* — payment recording + auto status transition
91
+ - *"What's my VAT for this quarter?"* — `kirjapro_get_alv_summary` with OmaVero field codes
92
+ - *"Show overdue invoices"* — AR aging report
93
+ - *"Match this bank deposit to invoice #42"* — bank reconciliation in one call
94
+
83
95
  ## What's included
84
96
 
85
- **52 tools** across 13 domains:
86
-
87
- | Domain | Tools | Examples |
88
- |--------|-------|---------|
89
- | Accounts | 1 | List chart of accounts with filtering |
90
- | Transactions | 5 | Create, search, get detail, batch import |
91
- | Templates | 3 | Auto-balanced entries with VAT splitting |
92
- | Invoices | 6 | Create, send, record payments, status management |
93
- | Customers | 5 | CRUD + PRH business lookup |
94
- | Banking | 3 | List accounts/transactions, match to invoices |
95
- | Reports | 6 | Dashboard, income statement, balance sheet, AR aging, general ledger, ALV summary |
96
- | Bookings | 4 | Purchase, sale, salary, VAT settlement — with automatic double-entry |
97
- | Offers | 7 | Offer/contract lifecycle, email send, convert to invoice |
98
- | Recurring | 6 | Recurring invoice templates |
99
- | Received | 2 | Received (purchase) invoices |
100
- | Fiscal Years | 1 | List fiscal years with status |
101
- | Validation | 3 | Y-tunnus, IBAN, viitenumero |
102
-
103
- **9 resources** for reference data: chart of accounts, VAT rates, company info, fiscal years, and 5 Finnish compliance resources.
97
+ **26 tools** in the default `core` surface, focused on the daily-use workflows: read your books, invoice flow, transactions + banking, contract create / send / convert, Finnish validators. The full 53-tool catalog (booking shortcuts, recurring invoices, templates, batch tools, etc.) is available via opt-in:
98
+
99
+ ```jsonc
100
+ {
101
+ "mcpServers": {
102
+ "kirjapro": {
103
+ "command": "npx",
104
+ "args": ["-y", "@kirjapro/mcp-server"],
105
+ "env": {
106
+ "KIRJAPRO_API_KEY": "kp_your_key_here",
107
+ "KIRJAPRO_MCP_SURFACE": "full" // 53 tools instead of 26
108
+ }
109
+ }
110
+ }
111
+ }
112
+ ```
113
+
114
+ **Why default to 26 instead of 53:** 2025-2026 SOTA research on tool catalog scaling (Anthropic, OpenAI, MCP authors) shows tool-selection accuracy degrades between 25-50 tools per catalog. A focused surface produces better first-call selections for the daily workflows. As real usage data informs which deferred tools matter most, they'll be promoted into core.
115
+
116
+ | Domain (core) | Tools |
117
+ |---|---|
118
+ | Read your books | `list_fiscal_years`, `list_accounts`, `get_dashboard`, `get_income_statement`, `get_balance_sheet`, `get_alv_summary`, `get_ar_aging` |
119
+ | Customers | `list_customers`, `get_customer`, `create_customer`, `lookup_business` (PRH) |
120
+ | Invoice lifecycle | `list_invoices`, `get_invoice`, `create_invoice`, `record_payment`, `update_invoice_status` |
121
+ | Transactions + banking | `list_transactions`, `create_transaction`, `list_bank_transactions`, `match_bank_transaction` |
122
+ | Contracts | `create_offer` (`tarjous` / `sopimus`), `send_offer` (email link), `convert_offer_to_invoice` |
123
+ | Validators (free) | `validate_business_id`, `validate_iban`, `generate_reference` |
124
+
125
+ **Deferred in core, available with `KIRJAPRO_MCP_SURFACE=full`:** booking shortcuts (`book_*`), templates, recurring invoices, received invoices, batch tools, `delete_*`, `update_*` (besides invoice status), `search_transactions`, `get_transaction`, `get_general_ledger`, `list_bank_accounts`, `get_financial_notes`, manual offer status / list / get / delete.
126
+
127
+ **11 resources** for reference data: chart of accounts, VAT rates, company info, fiscal years, 5 Finnish compliance resources, compliance freshness index, and security data-handling.
104
128
 
105
129
  See the [full tool reference](https://kirjapro.fi/docs/mcp/) for parameters, usage examples, and error handling.
106
130
 
@@ -111,6 +135,7 @@ See the [full tool reference](https://kirjapro.fi/docs/mcp/) for parameters, usa
111
135
  - All queries use Row Level Security (RLS) — users can only access their own company's data
112
136
  - Automatic token refresh keeps long-running sessions alive
113
137
  - Rate limiting: 10 auth requests per minute per key
138
+ - **Tool description fingerprint guard** — every tool's `description + annotations + inputSchema` is hashed and shipped as `tool-fingerprints.json`. Downstream operators who want supply-chain pinning can verify the running MCP matches the known-good fingerprint set, defending against silent description tampering between releases.
114
139
 
115
140
  ## License
116
141