@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 +199 -0
- package/README.md +44 -19
- package/dist/index.js +12869 -2100
- package/package.json +13 -10
- package/server.json +1 -1
- package/tool-fingerprints.json +216 -0
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
|
-
**
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
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
|
|