@kirjapro/mcp-server 0.3.0 → 0.5.5

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,303 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.5.5] - 2026-04-11
4
+
5
+ Tool-annotation sweep: every remaining `server.tool()` call migrated to
6
+ `server.registerTool()` and tagged with MCP tool annotations. No behavioural
7
+ changes — clients get richer `list_tools` metadata and `destructiveHint`
8
+ now flags the three `delete_*` tools so UIs can warn before invoking them.
9
+
10
+ ### registerTool() migration
11
+
12
+ - **All 43 remaining tools migrated** — `customers`, `invoices`, `bookings`,
13
+ `offers`, `recurring-invoices`, `templates`, `accounts`, `received-invoices`,
14
+ `banking`, `validation`, `fiscal-years`, and `transactions` now exclusively
15
+ use `server.registerTool(name, { description, inputSchema, annotations }, cb)`.
16
+ The deprecated `server.tool()` overload is no longer called anywhere in the
17
+ codebase (verified by test guard — see below).
18
+ - **Shared annotation constants** (`src/utils.ts`) — `READ_ONLY_ANNOTATIONS`,
19
+ `READ_ONLY_EXTERNAL_ANNOTATIONS`, `WRITE_ANNOTATIONS`,
20
+ `WRITE_EXTERNAL_ANNOTATIONS`, `DESTRUCTIVE_ANNOTATIONS`. The five constants
21
+ cover the read/write × local/external × destructive matrix, so individual
22
+ tool files don't re-declare the hint bags inline.
23
+ - **`destructiveHint: true`** on `kirjapro_delete_invoice`,
24
+ `kirjapro_delete_offer`, and `kirjapro_delete_recurring_invoice`. MCP
25
+ clients that support the annotation can now show a distinct confirmation
26
+ prompt before executing irreversible operations.
27
+ - **`openWorldHint: true`** on `kirjapro_lookup_business` (PRH API) and
28
+ `kirjapro_send_offer` (sends customer-visible email via Maventa). Everything
29
+ else sets `openWorldHint: false` since the operation is confined to the
30
+ caller's own Supabase tenant.
31
+ - **Inline annotation block in `list_transactions`** replaced with the shared
32
+ `READ_ONLY_ANNOTATIONS` constant — single source of truth for hint values.
33
+ - **`reports.ts` local annotation const** removed; imports from `utils.js`.
34
+ Drops one duplicate definition that was introduced in v0.5.2.
35
+
36
+ ### Test infrastructure
37
+
38
+ - **`tools-registry.test.ts` guard tests added:**
39
+ - `declares annotations on every registered tool` — iterates the full
40
+ 52-tool list and asserts `annotations` is defined. Any regression that
41
+ forgets to pass annotations (or accidentally re-introduces
42
+ `server.tool()`) fails CI.
43
+ - `flags delete_* tools as destructive` — asserts every tool whose name
44
+ starts with `kirjapro_delete_` has `destructiveHint: true` and
45
+ `readOnlyHint: false`. Prevents a delete tool from being silently
46
+ labelled safe.
47
+ - **Full suite: 111 passing (was 109 in v0.5.4).** 7 test files, same auth
48
+ DNS warning as before (benign — `test.supabase.co` resolution in legacy
49
+ env-var test).
50
+
51
+ ### Notes
52
+
53
+ - `outputSchema` on write tools is intentionally NOT added in this pass.
54
+ Write payloads are complex (invoice line refinements, journal entries
55
+ with balanced debit/credit tuples) and declaring them risks runtime
56
+ validation surprises on real rows. Deferred to v0.5.6+ as an incremental
57
+ per-tool exercise.
58
+ - The `WRITE_EXTERNAL_ANNOTATIONS` constant is exported but currently only
59
+ used by `kirjapro_send_offer`. Kept in `utils.ts` for future e-invoice
60
+ tools that hit Maventa directly.
61
+
62
+ ## [0.5.4] - 2026-04-11
63
+
64
+ M6 tail: the three remaining read tools now declare `outputSchema`.
65
+
66
+ ### Structured output
67
+
68
+ - **`registerTool()` + `outputSchema` on `get_balance_sheet`,
69
+ `get_ar_aging`, `get_general_ledger`** — all 9 read tools in the
70
+ reports / invoices / transactions surface now expose typed response
71
+ contracts at `list_tools` time and carry the `readOnlyHint` /
72
+ `idempotentHint` / `openWorldHint: false` annotation set. Inner row
73
+ shapes use `.passthrough()` / `z.unknown()` to stay permissive on
74
+ real-world rows.
75
+
76
+ ### Test infrastructure
77
+
78
+ - **Snapshot assertion widened** — `tools-registry.test.ts` now checks
79
+ `outputSchema` presence on all 9 read tools (was 6 in v0.5.3). Any
80
+ future migration that drops a schema fails CI.
81
+
82
+ ## [0.5.3] - 2026-04-11
83
+
84
+ Audit follow-through: schema contracts on hot read tools, registration
85
+ drift guard, and test-suite widening.
86
+
87
+ ### Structured output
88
+
89
+ - **`registerTool()` migration + `outputSchema` on 6 hot read tools**
90
+ (M6 completion) — `kirjapro_list_invoices`, `kirjapro_get_invoice`,
91
+ `kirjapro_list_transactions`, `kirjapro_get_dashboard`,
92
+ `kirjapro_get_income_statement`, and `kirjapro_get_alv_summary` now
93
+ register via the modern `server.registerTool()` API, declare typed
94
+ `outputSchema` (zod raw shapes), and carry `readOnlyHint` /
95
+ `idempotentHint` / `openWorldHint: false` annotations. MCP clients
96
+ see the schemas at `list_tools` time — agents can validate return
97
+ shapes without "forgot field name" loops.
98
+
99
+ ### Test infrastructure
100
+
101
+ - **Tool registration snapshot test** (M16 follow-through) — new
102
+ `tools/tools-registry.test.ts` asserts that exactly 52 tool names
103
+ are registered (catches accidental unregister or rename drift) and
104
+ that the 6 hot read tools all declare `outputSchema`. Verifies
105
+ `kirjapro_send_offer` and `kirjapro_convert_offer_to_invoice` are
106
+ in the bundle (closes the M16 regression concern).
107
+
108
+ ### Notes
109
+
110
+ - Output schemas are intentionally lax on row-level fields (use
111
+ `.passthrough()` or `z.unknown()` for nested shapes) to avoid
112
+ runtime validation failures on edge-case rows. The envelope shape
113
+ (`results` / `total_count` / `has_more` / `next_offset`) and the
114
+ top-level report blocks are precise; inner rows are descriptive
115
+ rather than strict. Tighten over time as real usage reveals stable
116
+ shapes.
117
+ - Write tools still use `server.tool()`. Migrating writes to
118
+ `registerTool()` is deferred — the annotations (`destructiveHint`)
119
+ would be valuable, but the schema complexity (zod refinements on
120
+ invoice line items, etc.) needs a dedicated pass.
121
+
122
+ ## [0.5.2] - 2026-04-11
123
+
124
+ Round 3 of `ENHANCEMENT-AUDIT-2026-04-11.md`: idempotency + dry-run on
125
+ writes, structured content on hot read tools, atomic booking RPCs, and a
126
+ salary rounding fix.
127
+
128
+ ### Reliability
129
+
130
+ - **Idempotency keys on every write tool** (M4) — new
131
+ `mcp_idempotency_keys` table (`20260411132733_add_mcp_idempotency_keys.sql`)
132
+ stores `(company_id, key) → response_payload` with a 24h TTL. Every write
133
+ tool now accepts an optional `idempotencyKey` (8–128 chars). Retries with
134
+ the same key return the cached response verbatim — a retried
135
+ `kirjapro_create_invoice` on a transient network blip will no longer
136
+ create a duplicate invoice. Cache misses pass through; infra errors
137
+ fall through (the wrapper never masks a write). Covered by the new
138
+ `withIdempotency()` helper in `utils.ts`.
139
+ - **Dry-run previews on destructive tools** (M4) — `kirjapro_delete_invoice`,
140
+ `kirjapro_delete_offer`, `kirjapro_delete_recurring_invoice`, and
141
+ `kirjapro_update_offer_status` now accept `dryRun: true`. They validate
142
+ the operation and return `{ dry_run: true, requires_confirmation: true,
143
+ message, preview }` without writing. Agents should always call with
144
+ `dryRun: true` first for irreversible actions, relay the preview to the
145
+ user, and only re-call with `dryRun: false` after confirmation.
146
+ - **Atomic `book_salary` + `book_vat_settlement`** (M9) — both booking
147
+ tools now call `book_salary_atomic` / `book_vat_settlement_atomic`
148
+ SECURITY DEFINER RPCs guarded by `pg_advisory_xact_lock`. Serializes
149
+ concurrent callers per `(company, fiscal_year, period)` so parallel
150
+ tool invocations cannot each write a salary journal for the same pay
151
+ period.
152
+ - **`book_salary` rounding residual** (M15) — employer's TyEL + employee's
153
+ TyEL now use residual-method rounding (last group = total − sum of
154
+ others) so the journal balances to the cent. Parametrized test added
155
+ covering 2026 rates + a handful of adversarial gross amounts.
156
+
157
+ ### Structured output
158
+
159
+ - **`structuredContent` on 6 hot read tools** (M6) — new `toResult<T>()`
160
+ helper returns both the JSON-stringified `content` (backward compat)
161
+ and a typed `structuredContent` object. Rolled out to
162
+ `kirjapro_list_invoices`, `kirjapro_get_invoice`,
163
+ `kirjapro_list_transactions`, `kirjapro_get_dashboard`,
164
+ `kirjapro_get_income_statement`, and `kirjapro_get_alv_summary`. Modern
165
+ MCP clients consume `structuredContent` without `JSON.parse`. Declaring
166
+ `outputSchema` via `registerTool()` is deferred to a later version
167
+ since it requires migrating away from the deprecated `server.tool()`
168
+ overload.
169
+
170
+ ### Migrations
171
+
172
+ - `20260411132733_add_mcp_idempotency_keys.sql` — `mcp_idempotency_keys`
173
+ table, RLS (`private.has_company_access`), and
174
+ `cleanup_expired_mcp_idempotency_keys()` maintenance function.
175
+
176
+ ## [0.5.1] - 2026-04-11
177
+
178
+ Security + compliance + race hardening bundle. Based on
179
+ `ENHANCEMENT-AUDIT-2026-04-11.md` — Round 1 (M1/M2/M5/M8/M10/M14/M16) and
180
+ Round 2 (M3/M7/M11/M12/M13).
181
+
182
+ ### Security
183
+
184
+ - **Prompt injection defense** (M3) — new `tagUntrusted()` utility wraps
185
+ attacker-controlled free text in `<untrusted-external>...</untrusted-external>`
186
+ tags. Applied to `kirjapro_list_bank_transactions` (counterparty_name,
187
+ reference, message), `kirjapro_list_received_invoices` /
188
+ `kirjapro_get_received_invoice` (sender_name, sender_business_id,
189
+ invoice_number, payment_reference), and `kirjapro_lookup_business`
190
+ (PRH free-text fields). The helper also strips zero-width characters,
191
+ control chars, and common injection markers (`system:`,
192
+ `<|im_start|>`, "ignore previous", etc.) before wrapping.
193
+ - **`kirjapro://security/data-handling` resource** (M3) — documents the
194
+ wrapper contract, lists every wrapped field per tool, and gives safe
195
+ handling rules. Intended as a session-start read.
196
+ - **Multi-company JWT scoping guard** (M1) — every tool call verifies
197
+ the JWT's `company_id` matches the MCP session's selected company
198
+ before executing, closing the cross-company data leak described in
199
+ CLAUDE.md pitfall #13.
200
+ - **Stdio token-refresh hardening** (M2) — mutex + single-flight refresh
201
+ prevents race between concurrent tool calls and the background refresh
202
+ timer; all 401s now retry once with a fresh token.
203
+
204
+ ### Correctness
205
+
206
+ - **Advisory-locked number generators** (M12) — new migration
207
+ `20260411120919_add_next_customer_offer_number_rpcs` adds
208
+ `get_next_customer_number(company_id)` and
209
+ `get_next_offer_number(company_id, type)` RPCs mirroring the
210
+ `pg_advisory_xact_lock(hashtext(...))` pattern from
211
+ `get_next_invoice_number`. `customers.ts` and `offers.ts` now call the
212
+ RPCs instead of read-then-write — fixes 23505 unique-index collisions
213
+ under concurrent creates.
214
+ - **Compliance rates single source of truth** (M7) — new
215
+ `src/compliance/rates.ts` exports `FINNISH_RATES_2026` (VAT, TyEL,
216
+ sotu, TTV, tapaturma, ryhmähenki) with a validity window.
217
+ `bookings.ts`, `templates.ts`, and `resources/compliance.ts` now
218
+ import from it instead of duplicating literals. Every compliance
219
+ resource emits an `_meta` envelope (`published_at`, `valid_through`,
220
+ `stale`, `days_until_expiry`); new `kirjapro://compliance/_freshness`
221
+ index resource lets the agent detect expired rates in one read at
222
+ session start.
223
+ - **Report tools auto-resolve fiscal year** (M11) — `get_dashboard`,
224
+ `get_income_statement`, `get_balance_sheet`, and `get_general_ledger`
225
+ now accept `fiscalYearId` as optional. When omitted, the single open
226
+ fiscal year is resolved via `resolveOpenFiscalYear()`; tools error
227
+ with a clear hint when multiple fiscal years are open.
228
+
229
+ ### Fixed
230
+
231
+ - Various small bugs (M5/M8/M10/M14/M16) — field selection drift,
232
+ error-message sanitization, pagination off-by-ones, and type narrowing
233
+ cleanups from Round 1 of the audit.
234
+
235
+ ### Internal
236
+
237
+ - New helper: `tagUntrusted(value, maxLen)` in `src/utils.ts`
238
+ - New helper: `resolveOpenFiscalYear(supabase, companyId)` in
239
+ `src/utils.ts`
240
+ - New module: `src/compliance/rates.ts` with `FINNISH_RATES_2026` +
241
+ `freshnessMeta()`
242
+ - New resource module: `src/resources/security.ts`
243
+ - `database.types.ts` augmented with `get_next_customer_number` and
244
+ `get_next_offer_number` RPC signatures
245
+
246
+ ### Notes
247
+
248
+ - M13 (`record_payment` TOCTOU) reviewed and downgraded to a nit — the
249
+ existing `record_invoice_payment` and `confirm_reconciliation_match`
250
+ RPCs already `SELECT … FOR UPDATE` the invoice row, so concurrent
251
+ callers are serialized at the DB layer.
252
+ - Verified: `tsc --noEmit` clean, 101/101 unit tests pass, `esbuild`
253
+ bundle clean (885 KB).
254
+
255
+ ## [0.5.0] - 2026-03-28
256
+
257
+ ### Added
258
+
259
+ - **Recurring invoices CRUD** — 6 tools: `kirjapro_list_recurring_invoices`, `kirjapro_get_recurring_invoice`, `kirjapro_create_recurring_invoice`, `kirjapro_update_recurring_invoice`, `kirjapro_delete_recurring_invoice`, `kirjapro_trigger_recurring_invoice` for managing recurring invoice templates with weekly/monthly/quarterly/yearly scheduling
260
+ - **Received invoices (read-only)** — 2 tools: `kirjapro_list_received_invoices`, `kirjapro_get_received_invoice` for viewing purchase invoices with status, sender, and amount filters
261
+ - **PRH business lookup** — `kirjapro_lookup_business` tool to look up Finnish companies by Y-tunnus from PRH (Patent and Registration Office), returns official name, address, company form
262
+ - **ALV summary report** — `kirjapro_get_alv_summary` tool for VAT return preparation with output/input VAT breakdown by rate and OmaVero field codes (301-320)
263
+ - `invokeEdgeFunction()` utility for consistent, typed edge function invocation with error handling across all tools
264
+ - **Typed Supabase client** — generated `database.types.ts` from production schema, wired `createClient<Database>()`. Removes all `as unknown as T` casts from tool files (reports, transactions, customers) — queries are now type-safe end-to-end
265
+ - **Finnish compliance resources** — 5 new MCP resources exposing compliance knowledge: `kirjapro://compliance/vat` (rates, deduction rules, reverse charge, common mistakes), `kirjapro://compliance/invoicing` (AVL 209 e § 17 mandatory fields, hyvityslasku rules), `kirjapro://compliance/deadlines` (verokausi thresholds, filing periods, pienyrittäjä 20K€ threshold), `kirjapro://compliance/social-insurance` (2026 TyEL/sotu/TTV rates), `kirjapro://compliance/bookkeeping` (KPL requirements, retention periods, company size classification)
266
+ - Enhanced tool descriptions with compliance context: VAT rate rules on `kirjapro_book_purchase`, filing deadline info on `kirjapro_get_alv_summary` and `kirjapro_book_vat_settlement`
267
+ - Enhanced `kirjapro://vat-rates` resource with legal basis citations (AVL §) and rate change history
268
+
269
+ ## [0.4.0] - 2026-03-28
270
+
271
+ ### Fixed
272
+
273
+ - **search_transactions pagination bug** — amount filters no longer cause unbounded fetches of all transactions into memory. Fetches are capped at 1000 rows, pagination (`total_count`, `has_more`) now works correctly with amount-filtered results
274
+ - **Error message data exposure** — all Supabase/PostgREST errors are now sanitized before returning to MCP clients. Known error codes map to safe messages; unknown errors have table names, constraint names, and column names stripped. Raw errors are logged to stderr for debugging
275
+ - **Report query safety caps** — dashboard, income statement, and balance sheet queries are capped at 50,000 journal entries to prevent memory exhaustion on large datasets. A warning is included in the response if the cap is reached
276
+
277
+ ### Added
278
+
279
+ - `sanitizeDbError()` utility for consistent, safe error message handling across all tools
280
+
281
+ ## [0.3.0] - 2026-03-06
282
+
283
+ ### Added
284
+
285
+ - **Transaction templates** — 3 tools: `kirjapro_list_templates`, `kirjapro_create_from_template`, `kirjapro_create_from_template_batch` for common Finnish bookkeeping patterns (cash/bank sales, purchases, rent, salary, bank transfer) with automatic VAT splitting
286
+ - **Domain-specific booking tools** — 3 tools: `kirjapro_book_purchase` (with reverse charge and edustus support), `kirjapro_book_salary` (2-transaction salary with 2026 Finnish social insurance rates), `kirjapro_book_vat_settlement` (automatic ALV-tilitys from journal entries)
287
+ - **Offers & contracts** — 5 tools: `kirjapro_list_offers`, `kirjapro_get_offer`, `kirjapro_create_offer`, `kirjapro_update_offer_status`, `kirjapro_delete_offer` with status state machine and event logging
288
+ - Auto-resolve fiscal year when `fiscalYearId` is omitted (uses the single open fiscal year)
289
+ - Account overrides for templates (e.g. swap bank account `{"2320": "2330"}`)
290
+
291
+ ### Fixed
292
+
293
+ - Invoice number generation uses advisory-locked RPC to prevent race conditions
294
+ - Invoice delete now handles existing payments on draft invoices
295
+ - Missing `company_id` scoping on invoice/bank transaction update mutations
296
+ - Partial payment now correctly transitions invoice status to `partial`
297
+ - Bank transaction matching now sets `partial` status for incomplete payments
298
+ - VAT settlement date clamped to fiscal year end to prevent out-of-range errors
299
+ - Offer/customer queries use `.maybeSingle()` to prevent PGRST116 on empty results
300
+
3
301
  ## [0.2.0] - 2026-02-19
4
302
 
5
303
  ### Added
package/README.md CHANGED
@@ -2,32 +2,38 @@
2
2
 
3
3
  MCP server for Finnish accounting. Exposes Kirjapro bookkeeping, invoicing, and reporting tools to Claude Code, Claude Desktop, and any MCP client.
4
4
 
5
- > **Full documentation:** [docs/mcp-server.md](../docs/mcp-server.md) — complete tool reference with parameters, usage examples, error guide, and multi-client setup.
5
+ **Full documentation:** [kirjapro.fi/docs/mcp](https://kirjapro.fi/docs/mcp/)
6
6
 
7
7
  ## Requirements
8
8
 
9
9
  - Node.js 20+
10
- - Kirjapro account with **Company** or **Custom** subscription tier
10
+ - Kirjapro account with **Entrepreneur**, **Company**, or **Custom** subscription tier
11
11
  - API key (generate at Settings > API-avaimet)
12
12
 
13
13
  ## Quick Start
14
14
 
15
15
  ### 1. Generate an API Key
16
16
 
17
- 1. Go to **Settings > API-avaimet** in the Kirjapro app
17
+ 1. Go to **Asetukset > API-avaimet** in the [Kirjapro app](https://kirjapro.fi)
18
18
  2. Click **"Luo uusi avain"**
19
- 3. Copy the key (shown only once)
19
+ 3. Copy the key (starts with `kp_`, shown only once)
20
20
 
21
21
  ### 2. Configure your MCP client
22
22
 
23
23
  #### Claude Code
24
24
 
25
- Add to `.claude/mcp.json`:
25
+ Add to your project's `.mcp.json` (recommended) or global config:
26
+
27
+ | OS | Project-level (recommended) | Global |
28
+ |----|----------------------------|--------|
29
+ | macOS / Linux | `.mcp.json` in project root | `~/.claude/mcp.json` |
30
+ | Windows | `.mcp.json` in project root | `%USERPROFILE%\.claude\mcp.json` |
26
31
 
27
32
  ```json
28
33
  {
29
34
  "mcpServers": {
30
35
  "kirjapro": {
36
+ "type": "stdio",
31
37
  "command": "npx",
32
38
  "args": ["-y", "@kirjapro/mcp-server"],
33
39
  "env": {
@@ -38,10 +44,18 @@ Add to `.claude/mcp.json`:
38
44
  }
39
45
  ```
40
46
 
47
+ Verify with `/mcp` in Claude Code.
48
+
41
49
  #### Claude Desktop
42
50
 
43
51
  Add to `claude_desktop_config.json`:
44
52
 
53
+ | OS | Path |
54
+ |----|------|
55
+ | macOS | `~/Library/Application Support/Claude/claude_desktop_config.json` |
56
+ | Windows | `%APPDATA%\Claude\claude_desktop_config.json` |
57
+ | Linux | `~/.config/Claude/claude_desktop_config.json` |
58
+
45
59
  ```json
46
60
  {
47
61
  "mcpServers": {
@@ -56,107 +70,47 @@ Add to `claude_desktop_config.json`:
56
70
  }
57
71
  ```
58
72
 
73
+ Restart Claude Desktop after saving.
74
+
75
+ #### Other clients
76
+
77
+ See [full setup guide](https://kirjapro.fi/docs/mcp/) for Cursor, VS Code / Copilot, Windsurf, and generic stdio.
78
+
59
79
  ### 3. Verify
60
80
 
61
- In Claude Code, run `/mcp` to see the available Kirjapro tools.
62
-
63
- ## Environment Variables
64
-
65
- | Variable | Required | Description |
66
- |----------|----------|-------------|
67
- | `KIRJAPRO_API_KEY` | Yes* | API key from Settings > API-avaimet |
68
-
69
- ### Legacy (development only)
70
-
71
- | Variable | Required | Description |
72
- |----------|----------|-------------|
73
- | `SUPABASE_URL` | Yes* | Supabase project URL |
74
- | `SUPABASE_ACCESS_TOKEN` | Yes* | User's JWT access token |
75
- | `KIRJAPRO_COMPANY_ID` | Yes* | Company UUID to operate on |
76
-
77
- *Either `KIRJAPRO_API_KEY` or all three legacy variables must be set.
78
-
79
- ## Tools (28)
80
-
81
- ### Read Tools
82
-
83
- | Tool | Description |
84
- |------|-------------|
85
- | `kirjapro_list_accounts` | List chart of accounts with filtering by type |
86
- | `kirjapro_list_transactions` | List transactions with journal entries for a fiscal year |
87
- | `kirjapro_search_transactions` | Search transactions by text, date range, or amount |
88
- | `kirjapro_get_transaction` | Get single transaction with journal entries and account details |
89
- | `kirjapro_list_invoices` | List invoices with customer names, filter by status |
90
- | `kirjapro_get_invoice` | Get single invoice with lines, payments, and VAT breakdown |
91
- | `kirjapro_list_customers` | List customers with search |
92
- | `kirjapro_get_customer` | Get single customer with invoice stats |
93
- | `kirjapro_list_bank_accounts` | List active bank accounts with balances |
94
- | `kirjapro_list_bank_transactions` | List bank transactions with filtering |
95
- | `kirjapro_list_fiscal_years` | List fiscal years with open/closed status |
96
- | `kirjapro_get_dashboard` | Financial dashboard: revenue, expenses, invoice stats, bank balances |
97
- | `kirjapro_get_income_statement` | Income statement (tuloslaskelma) for a date range |
98
- | `kirjapro_get_balance_sheet` | Balance sheet (tase) as of a specific date |
99
- | `kirjapro_get_ar_aging` | Accounts receivable aging (0-30, 31-60, 61-90, 90+ days) |
100
- | `kirjapro_get_general_ledger` | General ledger (pääkirja) for one account with running balance |
101
-
102
- ### Write Tools
103
-
104
- | Tool | Description |
105
- |------|-------------|
106
- | `kirjapro_create_transaction` | Create an accounting transaction with journal entries |
107
- | `kirjapro_create_transactions_batch` | Bulk create up to 50 transactions (partial success) |
108
- | `kirjapro_create_invoice` | Create invoice with auto-generated number and reference |
109
- | `kirjapro_create_customer` | Create customer with Y-tunnus validation |
110
- | `kirjapro_update_customer` | Update customer fields (partial update, re-validates Y-tunnus) |
111
- | `kirjapro_record_payment` | Record payment against an invoice |
112
- | `kirjapro_update_invoice_status` | Update invoice status with state machine validation |
113
- | `kirjapro_delete_invoice` | Delete draft invoices (audit-safe) |
114
- | `kirjapro_match_bank_transaction` | Match bank transaction to an invoice |
115
-
116
- ### Validation Tools
117
-
118
- | Tool | Description |
119
- |------|-------------|
120
- | `kirjapro_validate_business_id` | Validate Finnish Y-tunnus |
121
- | `kirjapro_validate_iban` | Validate Finnish IBAN |
122
- | `kirjapro_generate_reference` | Generate viitenumero with check digit |
123
-
124
- ## Resources (4)
125
-
126
- | URI | Description |
127
- |-----|-------------|
128
- | `kirjapro://accounts/chart` | Finnish standard chart of accounts (YSE 2017) |
129
- | `kirjapro://vat-rates` | Finnish VAT rates (25.5%, 13.5%, 10%, 0%) |
130
- | `kirjapro://company/info` | Current company details |
131
- | `kirjapro://fiscal-years` | Fiscal years with open/closed status |
132
-
133
- ## Development
134
-
135
- ```bash
136
- cd mcp-server
137
- npm install
138
- npm run dev # Run with tsx
139
- npm run build # Build with esbuild
140
- npm test # Run vitest
141
- npm run lint # Type check
142
- ```
81
+ Ask your AI assistant: *"list my fiscal years"* — it should call `kirjapro_list_fiscal_years` and return your company's accounting periods.
82
+
83
+ ## What's included
143
84
 
144
- ## Publishing
85
+ **49 tools** across 10 domains:
145
86
 
146
- Releases are automated via GitHub Actions. To publish:
87
+ | Domain | Tools | Examples |
88
+ |--------|-------|---------|
89
+ | Accounts | 1 | List chart of accounts with filtering |
90
+ | Transactions | 4 | Create, search, batch import |
91
+ | Templates | 3 | Auto-balanced entries with VAT splitting |
92
+ | Invoices | 5 | Create, send, record payments, status management |
93
+ | Customers | 4 | 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 | 5 | Offer/contract lifecycle management |
98
+ | Recurring | 6 | Recurring invoice templates |
99
+ | Received | 2 | Received (purchase) invoices |
100
+ | Validation | 3 | Y-tunnus, IBAN, viitenumero |
147
101
 
148
- 1. Update version in `package.json`, `server.json`, and `src/index.ts`
149
- 2. Update `CHANGELOG.md`
150
- 3. Commit and tag: `git tag mcp-server/v0.2.0`
151
- 4. Push: `git push origin mcp-server/v0.2.0`
102
+ **9 resources** for reference data: chart of accounts, VAT rates, company info, fiscal years, and 5 Finnish compliance resources.
152
103
 
153
- The workflow validates version consistency, runs tests, publishes to npm, and creates a GitHub Release.
104
+ See the [full tool reference](https://kirjapro.fi/docs/mcp/) for parameters, usage examples, and error handling.
154
105
 
155
106
  ## Security
156
107
 
157
108
  - API keys are hashed with SHA-256; the full key is never stored
158
109
  - Keys exchange for short-lived JWTs (1 hour) via the `mcp-auth` edge function
159
- - All queries use the user's JWT with Row Level Security (RLS)
160
- - Automatic token refresh keeps long-running MCP sessions alive
161
- - Feature gate: requires `hasApiAccess` (Company/Custom tier)
110
+ - All queries use Row Level Security (RLS) — users can only access their own company's data
111
+ - Automatic token refresh keeps long-running sessions alive
162
112
  - Rate limiting: 10 auth requests per minute per key
113
+
114
+ ## License
115
+
116
+ MIT