e-arveldaja-mcp 0.1.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.
Files changed (124) hide show
  1. package/.claude/commands/book-invoice.md +108 -0
  2. package/.claude/commands/month-end.md +88 -0
  3. package/.claude/commands/new-supplier.md +61 -0
  4. package/.claude/commands/reconcile-bank.md +74 -0
  5. package/CLAUDE.md +169 -0
  6. package/LICENSE +24 -0
  7. package/README.md +155 -0
  8. package/dist/api/base-resource.d.ts +22 -0
  9. package/dist/api/base-resource.d.ts.map +1 -0
  10. package/dist/api/base-resource.js +64 -0
  11. package/dist/api/base-resource.js.map +1 -0
  12. package/dist/api/clients.api.d.ts +13 -0
  13. package/dist/api/clients.api.d.ts.map +1 -0
  14. package/dist/api/clients.api.js +34 -0
  15. package/dist/api/clients.api.js.map +1 -0
  16. package/dist/api/journals.api.d.ts +16 -0
  17. package/dist/api/journals.api.d.ts.map +1 -0
  18. package/dist/api/journals.api.js +55 -0
  19. package/dist/api/journals.api.js.map +1 -0
  20. package/dist/api/products.api.d.ts +12 -0
  21. package/dist/api/products.api.d.ts.map +1 -0
  22. package/dist/api/products.api.js +28 -0
  23. package/dist/api/products.api.js.map +1 -0
  24. package/dist/api/purchase-invoices.api.d.ts +27 -0
  25. package/dist/api/purchase-invoices.api.d.ts.map +1 -0
  26. package/dist/api/purchase-invoices.api.js +117 -0
  27. package/dist/api/purchase-invoices.api.js.map +1 -0
  28. package/dist/api/readonly.api.d.ts +29 -0
  29. package/dist/api/readonly.api.d.ts.map +1 -0
  30. package/dist/api/readonly.api.js +137 -0
  31. package/dist/api/readonly.api.js.map +1 -0
  32. package/dist/api/sale-invoices.api.d.ts +13 -0
  33. package/dist/api/sale-invoices.api.d.ts.map +1 -0
  34. package/dist/api/sale-invoices.api.js +33 -0
  35. package/dist/api/sale-invoices.api.js.map +1 -0
  36. package/dist/api/transactions.api.d.ts +16 -0
  37. package/dist/api/transactions.api.d.ts.map +1 -0
  38. package/dist/api/transactions.api.js +53 -0
  39. package/dist/api/transactions.api.js.map +1 -0
  40. package/dist/auth.d.ts +2 -0
  41. package/dist/auth.d.ts.map +1 -0
  42. package/dist/auth.js +17 -0
  43. package/dist/auth.js.map +1 -0
  44. package/dist/cache.d.ts +9 -0
  45. package/dist/cache.d.ts.map +1 -0
  46. package/dist/cache.js +43 -0
  47. package/dist/cache.js.map +1 -0
  48. package/dist/config.d.ts +19 -0
  49. package/dist/config.d.ts.map +1 -0
  50. package/dist/config.js +138 -0
  51. package/dist/config.js.map +1 -0
  52. package/dist/file-validation.d.ts +5 -0
  53. package/dist/file-validation.js +86 -0
  54. package/dist/http-client.d.ts +22 -0
  55. package/dist/http-client.d.ts.map +1 -0
  56. package/dist/http-client.js +127 -0
  57. package/dist/http-client.js.map +1 -0
  58. package/dist/index.d.ts +2 -0
  59. package/dist/index.d.ts.map +1 -0
  60. package/dist/index.js +217 -0
  61. package/dist/index.js.map +1 -0
  62. package/dist/paginator.d.ts +8 -0
  63. package/dist/paginator.d.ts.map +1 -0
  64. package/dist/paginator.js +13 -0
  65. package/dist/paginator.js.map +1 -0
  66. package/dist/resources/static-resources.d.ts +3 -0
  67. package/dist/resources/static-resources.d.ts.map +1 -0
  68. package/dist/resources/static-resources.js +62 -0
  69. package/dist/resources/static-resources.js.map +1 -0
  70. package/dist/tools/account-balance.d.ts +3 -0
  71. package/dist/tools/account-balance.d.ts.map +1 -0
  72. package/dist/tools/account-balance.js +129 -0
  73. package/dist/tools/account-balance.js.map +1 -0
  74. package/dist/tools/aging-analysis.d.ts +3 -0
  75. package/dist/tools/aging-analysis.d.ts.map +1 -0
  76. package/dist/tools/aging-analysis.js +155 -0
  77. package/dist/tools/aging-analysis.js.map +1 -0
  78. package/dist/tools/bank-reconciliation.d.ts +3 -0
  79. package/dist/tools/bank-reconciliation.d.ts.map +1 -0
  80. package/dist/tools/bank-reconciliation.js +234 -0
  81. package/dist/tools/bank-reconciliation.js.map +1 -0
  82. package/dist/tools/crud-tools.d.ts +22 -0
  83. package/dist/tools/crud-tools.d.ts.map +1 -0
  84. package/dist/tools/crud-tools.js +472 -0
  85. package/dist/tools/crud-tools.js.map +1 -0
  86. package/dist/tools/document-audit.d.ts +3 -0
  87. package/dist/tools/document-audit.d.ts.map +1 -0
  88. package/dist/tools/document-audit.js +168 -0
  89. package/dist/tools/document-audit.js.map +1 -0
  90. package/dist/tools/estonian-tax.d.ts +3 -0
  91. package/dist/tools/estonian-tax.d.ts.map +1 -0
  92. package/dist/tools/estonian-tax.js +253 -0
  93. package/dist/tools/estonian-tax.js.map +1 -0
  94. package/dist/tools/financial-statements.d.ts +15 -0
  95. package/dist/tools/financial-statements.d.ts.map +1 -0
  96. package/dist/tools/financial-statements.js +300 -0
  97. package/dist/tools/financial-statements.js.map +1 -0
  98. package/dist/tools/lightyear-investments.d.ts +3 -0
  99. package/dist/tools/lightyear-investments.d.ts.map +1 -0
  100. package/dist/tools/lightyear-investments.js +883 -0
  101. package/dist/tools/lightyear-investments.js.map +1 -0
  102. package/dist/tools/pdf-workflow.d.ts +3 -0
  103. package/dist/tools/pdf-workflow.d.ts.map +1 -0
  104. package/dist/tools/pdf-workflow.js +434 -0
  105. package/dist/tools/pdf-workflow.js.map +1 -0
  106. package/dist/tools/purchase-vat-defaults.d.ts +11 -0
  107. package/dist/tools/purchase-vat-defaults.js +109 -0
  108. package/dist/tools/recurring-invoices.d.ts +3 -0
  109. package/dist/tools/recurring-invoices.d.ts.map +1 -0
  110. package/dist/tools/recurring-invoices.js +115 -0
  111. package/dist/tools/recurring-invoices.js.map +1 -0
  112. package/dist/tools/vat-reports.d.ts +3 -0
  113. package/dist/tools/vat-reports.d.ts.map +1 -0
  114. package/dist/tools/vat-reports.js +264 -0
  115. package/dist/tools/vat-reports.js.map +1 -0
  116. package/dist/types/api.d.ts +473 -0
  117. package/dist/types/api.d.ts.map +1 -0
  118. package/dist/types/api.js +2 -0
  119. package/dist/types/api.js.map +1 -0
  120. package/package.json +52 -0
  121. package/workflows/book-invoice.md +116 -0
  122. package/workflows/month-end.md +84 -0
  123. package/workflows/new-supplier.md +60 -0
  124. package/workflows/reconcile-bank.md +76 -0
@@ -0,0 +1,108 @@
1
+ # Book Purchase Invoice from PDF
2
+
3
+ Read a PDF invoice, extract data, find or create the supplier, create the purchase invoice, upload the PDF, and confirm.
4
+
5
+ ## Arguments
6
+
7
+ $ARGUMENTS should be the absolute file path to the PDF invoice. If not provided, look for PDF files in the current directory and ask the user which one to book.
8
+
9
+ ## Workflow
10
+
11
+ ### Step 1: Read the PDF
12
+
13
+ Use the Read tool to visually read the PDF file. Extract these fields:
14
+ - Supplier name and registry code (registrikood, 8 digits)
15
+ - Supplier VAT number (KMKR, starts with EE)
16
+ - Invoice number
17
+ - Invoice date (convert to YYYY-MM-DD)
18
+ - Due date or payment term in days
19
+ - Reference number (viitenumber) if present
20
+ - Supplier IBAN
21
+ - Line items: description, quantity, unit price, net total, VAT rate
22
+ - Invoice totals: net (without VAT), VAT amount, gross (with VAT)
23
+
24
+ Also call `extract_pdf_invoice` with the file_path to get machine-readable hints (IBAN, registry code, VAT number, reference number). Cross-check against what you read visually.
25
+
26
+ ### Step 2: Validate the numbers
27
+
28
+ Call `validate_invoice_data`:
29
+ - total_net: invoice net total
30
+ - total_vat: invoice VAT total
31
+ - total_gross: invoice gross total
32
+ - items: JSON array of items, each with `total_net_price` and `vat_rate_dropdown` (e.g. "24", "22", "9", "0", or "-")
33
+ - invoice_date: YYYY-MM-DD
34
+ - due_date: YYYY-MM-DD (if available)
35
+
36
+ Do NOT proceed until validation passes (valid: true). If errors, re-check the extracted values.
37
+
38
+ ### Step 3: Check for duplicates
39
+
40
+ Call `detect_duplicate_purchase_invoice` (no params needed) to scan all existing invoices.
41
+
42
+ If a duplicate is found with the same supplier and invoice number, STOP and tell the user.
43
+
44
+ ### Step 4: Resolve the supplier
45
+
46
+ Call `resolve_supplier`:
47
+ - name: supplier name
48
+ - reg_code: registry code (if found)
49
+ - vat_no: VAT number (if found)
50
+ - iban: IBAN (if found)
51
+ - auto_create: true
52
+
53
+ Note the returned client ID.
54
+
55
+ If the supplier was found (not created) and the invoice has an IBAN or VAT number missing from the existing client, call `update_client` to add it.
56
+
57
+ ### Step 5: Look up booking suggestions
58
+
59
+ Call `suggest_booking`:
60
+ - clients_id: the supplier client ID
61
+ - description: first line item description (helps find similar past invoices)
62
+
63
+ Use the returned past invoice data to determine:
64
+ - Which `cl_purchase_articles_id` to use
65
+ - Which `purchase_accounts_id` (expense account) to use
66
+
67
+ If no past invoices exist, call `list_purchase_articles` and choose the most appropriate article. Common expense articles:
68
+ - 35 (Leases/Üür, acct 5020) - office rent, coworking
69
+ - 37 (Office expenses/Bürookulud, acct 5040)
70
+ - 45 (Internet, acct 5230)
71
+ - 49 (Consultation/Konsultatsioon, acct 5340)
72
+ - 62 (Other operating/Muud tegevuskulud, acct 5990)
73
+
74
+ ### Step 6: Create the purchase invoice
75
+
76
+ Call `create_purchase_invoice_from_pdf`:
77
+ - supplier_client_id: from step 4
78
+ - invoice_number: from the PDF
79
+ - invoice_date: YYYY-MM-DD
80
+ - journal_date: same as invoice_date
81
+ - term_days: from due date calculation, or 0 if already paid
82
+ - items: JSON array where each item has:
83
+ - custom_title: description from PDF
84
+ - cl_purchase_articles_id: from step 5
85
+ - purchase_accounts_id: from step 5
86
+ - total_net_price: net amount
87
+ - vat_rate_dropdown: VAT rate as string (e.g. "24")
88
+ - amount: quantity
89
+ - vat_price: EXACT total VAT from the original invoice
90
+ - gross_price: EXACT total gross from the original invoice
91
+ - ref_number: reference number (if found)
92
+ - bank_account_no: supplier IBAN (spaces removed)
93
+ - notes: PDF filename
94
+
95
+ ### Step 7: Upload the PDF
96
+
97
+ Call `upload_invoice_document`:
98
+ - invoice_id: the ID from step 6
99
+ - file_path: the original PDF path
100
+
101
+ ### Step 8: Confirm the invoice
102
+
103
+ Call `confirm_purchase_invoice`:
104
+ - id: the invoice ID
105
+
106
+ ### Step 9: Summary
107
+
108
+ Report: invoice number, supplier, net/VAT/gross, expense account used, invoice ID, whether supplier was new or existing, confirmation status.
@@ -0,0 +1,88 @@
1
+ # Month-End Close Checklist
2
+
3
+ Run the month-end close checklist, compute financial statements, and flag issues.
4
+
5
+ ## Arguments
6
+
7
+ $ARGUMENTS should be the month in YYYY-MM format (e.g. 2026-02). If not provided, use the previous calendar month.
8
+
9
+ ## Workflow
10
+
11
+ ### Step 1: Run the checklist
12
+
13
+ Call `month_end_close_checklist`:
14
+ - month: the YYYY-MM value
15
+
16
+ ### Step 2: Flag blocking issues
17
+
18
+ Present in priority order:
19
+
20
+ **BLOCKERS (must fix before closing):**
21
+ 1. Unconfirmed purchase invoices - not registered in ledger
22
+ 2. Unconfirmed sale invoices - revenue not recorded
23
+ 3. Unconfirmed journal entries - adjustments not posted
24
+ 4. Unconfirmed bank transactions - cash not reconciled
25
+
26
+ For each, show ID, date, amount/title, and suggest the fix:
27
+ - Purchase invoices: `confirm_purchase_invoice` or delete if duplicate
28
+ - Sale invoices: `confirm_sale_invoice`
29
+ - Journals: `confirm_journal`
30
+ - Transactions: suggest running `/reconcile-bank`
31
+
32
+ **WARNINGS:**
33
+ - Overdue receivables - may need follow-up
34
+ - Overdue payables - check if payment was made
35
+
36
+ ### Step 3: Check for missing documents
37
+
38
+ Call `find_missing_documents`:
39
+ - date_from: YYYY-MM-01
40
+ - date_to: last day of the month
41
+
42
+ Report confirmed purchase invoices without attached PDFs.
43
+
44
+ ### Step 4: Check for duplicates
45
+
46
+ Call `detect_duplicate_purchase_invoice`:
47
+ - date_from: YYYY-MM-01
48
+ - date_to: last day of the month
49
+
50
+ Report any exact duplicates or suspicious matches.
51
+
52
+ ### Step 5: Compute financial statements
53
+
54
+ Call `compute_trial_balance`:
55
+ - date_from: YYYY-MM-01
56
+ - date_to: last day of the month
57
+
58
+ Verify total debits = total credits.
59
+
60
+ Call `compute_profit_and_loss`:
61
+ - date_from: YYYY-01-01 (fiscal year start)
62
+ - date_to: last day of the month
63
+
64
+ Show YTD P&L: total revenue, expenses, net profit.
65
+
66
+ Call `compute_balance_sheet`:
67
+ - date_to: last day of the month
68
+
69
+ Verify balanced (assets = liabilities + equity).
70
+
71
+ ### Step 6: Summary report
72
+
73
+ ```
74
+ Month-End Close: YYYY-MM
75
+ ================================
76
+ Blockers: X issues
77
+ Warnings: X items
78
+ Missing docs: X invoices
79
+ Duplicates: X found
80
+
81
+ Trial Balance: BALANCED / IMBALANCED by X EUR
82
+ Balance Sheet: BALANCED / IMBALANCED
83
+ YTD Net Profit: X.XX EUR
84
+
85
+ Status: READY TO CLOSE / HAS BLOCKERS
86
+ ```
87
+
88
+ If blockers exist, list specific actions. Offer to help fix them.
@@ -0,0 +1,61 @@
1
+ # Create New Supplier
2
+
3
+ Create a new supplier (client) in e-arveldaja with proper fields.
4
+
5
+ ## Arguments
6
+
7
+ $ARGUMENTS should be the supplier name or Estonian registry code (8 digits). If not provided, ask the user.
8
+
9
+ ## Workflow
10
+
11
+ ### Step 1: Determine input type
12
+
13
+ - 8-digit number: treat as registry code
14
+ - Text: treat as supplier name
15
+
16
+ ### Step 2: Check if supplier already exists
17
+
18
+ If registry code: call `find_client_by_code` with code: the registry code.
19
+ If name: call `search_client` with name: the supplier name.
20
+
21
+ If found, show the existing client and ask if the user wants to use it or create a new one. If using existing, stop and report details.
22
+
23
+ ### Step 3: Resolve supplier details
24
+
25
+ Call `resolve_supplier`:
26
+ - name: supplier name (if provided)
27
+ - reg_code: registry code (if provided)
28
+ - auto_create: false (check registry data first)
29
+ - country: "EST" (default)
30
+
31
+ If an Estonian code was provided, the tool queries the business registry for the official company name and address. Show this to the user.
32
+
33
+ ### Step 4: Gather additional information
34
+
35
+ Ask the user for any details they want to add:
36
+ - Bank account (IBAN)
37
+ - VAT number (KMKR, e.g. EE123456789)
38
+ - Email address
39
+ - Phone number
40
+ - Address (if not found from registry)
41
+
42
+ ### Step 5: Create the supplier
43
+
44
+ Call `create_client`:
45
+ - name: official name from registry, or user-provided name
46
+ - code: registry code (if known)
47
+ - is_client: false
48
+ - is_supplier: true
49
+ - cl_code_country: "EST" (or as specified)
50
+ - is_juridical_entity: true (default, false for natural persons)
51
+ - bank_account_no: IBAN (if provided)
52
+ - invoice_vat_no: VAT number (if provided)
53
+ - email: (if provided)
54
+ - telephone: (if provided)
55
+ - address_text: from registry or user
56
+
57
+ ### Step 6: Report
58
+
59
+ Show created supplier: client ID, name, registry code, country, any additional fields.
60
+
61
+ Remind user this supplier is now available for `/book-invoice`.
@@ -0,0 +1,74 @@
1
+ # Reconcile Bank Transactions
2
+
3
+ Match unconfirmed bank transactions to open invoices and confirm the matches.
4
+
5
+ ## Arguments
6
+
7
+ $ARGUMENTS can be:
8
+ - empty or "auto" - dry run first, then confirm high-confidence matches with user approval
9
+ - "review" - show all matches for manual review without confirming
10
+ - a transaction ID number - show match details for that specific transaction
11
+
12
+ ## Workflow
13
+
14
+ ### Step 1: Get matches
15
+
16
+ Call `reconcile_transactions`:
17
+ - min_confidence: 30 (to see all potential matches)
18
+
19
+ Review the output:
20
+ - total_unconfirmed: bank transactions needing attention
21
+ - matched: transactions with at least one candidate
22
+ - unmatched: no match found
23
+
24
+ If total_unconfirmed is 0, tell the user everything is reconciled and stop.
25
+
26
+ ### Step 2: Present matches
27
+
28
+ Show a summary table grouped by confidence:
29
+
30
+ **HIGH (>=80):** safe to auto-confirm
31
+ - Transaction date, amount, type (D=incoming, C=outgoing), description
32
+ - Matched invoice: number, client, gross amount, confidence, reasons
33
+
34
+ **MEDIUM (50-79):** needs review
35
+ **LOW (<50):** unlikely matches, shown for reference
36
+
37
+ ### Step 3: Handle based on mode
38
+
39
+ **If "auto" or empty:**
40
+
41
+ Call `auto_confirm_exact_matches`:
42
+ - execute: false (dry run first)
43
+ - min_confidence: 90
44
+
45
+ Show what would be confirmed. Ask user for approval.
46
+
47
+ If approved, call `auto_confirm_exact_matches`:
48
+ - execute: true
49
+ - min_confidence: 90
50
+
51
+ Report results.
52
+
53
+ **If "review":**
54
+
55
+ Show all matches. For each, ask user to confirm or skip.
56
+
57
+ For approved matches, call `confirm_transaction`:
58
+ - id: transaction ID
59
+ - distributions: JSON string `[{"related_table": "sale_invoices" or "purchase_invoices", "related_id": invoice_id, "amount": transaction_amount}]`
60
+
61
+ **If transaction ID:**
62
+
63
+ Call `get_transaction` with that ID. Show details and matches. Offer to confirm if a match exists.
64
+
65
+ ### Step 4: Unmatched transactions
66
+
67
+ List transactions with no matches and suggest:
68
+ - Small amounts (<1 EUR): likely bank fees/interest, need manual journal entry
69
+ - Description contains "teenustasu", "intress", "service fee": bank charges
70
+ - Larger amounts: check if corresponding invoice exists
71
+
72
+ ### Step 5: Summary
73
+
74
+ Report: confirmed count, remaining unconfirmed, unmatched needing manual attention.
package/CLAUDE.md ADDED
@@ -0,0 +1,169 @@
1
+ # e-arveldaja MCP Server
2
+
3
+ TypeScript MCP server for the Estonian e-arveldaja (RIK e-Financials) REST API.
4
+ 84 tools across 11 modules + 6 resources. Supports multiple companies/accounts.
5
+
6
+ ## Quick Start
7
+
8
+ ```bash
9
+ npm run build # tsc -> dist/
10
+ npm run start # node dist/index.js (stdio transport)
11
+ npm run dev # tsx src/index.ts (development)
12
+ ```
13
+
14
+ ## Credentials
15
+
16
+ All `apikey*.txt` files are scanned from the project root and its parent directory. Multiple files = multiple connections (companies).
17
+
18
+ Credentials are loaded in this priority order (see `src/config.ts`):
19
+
20
+ 1. **Environment variables**: `EARVELDAJA_API_KEY_ID`, `EARVELDAJA_API_PUBLIC_VALUE`, `EARVELDAJA_API_PASSWORD`
21
+ 2. **`EARVELDAJA_API_KEY_FILE`** env var pointing to a specific file
22
+ 3. **`apikey*.txt` files** — scanned from the project root. Set `EARVELDAJA_SCAN_PARENT=true` to also scan the parent directory.
23
+
24
+ The `apikey.txt` format:
25
+ ```
26
+ ApiKey ID: <key_id>
27
+ ApiKey public value: <public_value>
28
+ Password: <password>
29
+ ```
30
+
31
+ Set `EARVELDAJA_SERVER=demo` for the demo API (default: `live`).
32
+
33
+ ### Multi-account (multiple companies)
34
+
35
+ Place multiple `apikey*.txt` files (e.g. `apikey.txt`, `apikey (1).txt`) next to the project.
36
+ Use `list_connections` to see all available accounts and `switch_connection` to switch between them.
37
+ Switching clears all cached data to prevent cross-company data leaks.
38
+
39
+ **NEVER commit `.env` or `apikey.txt` to git.** The `.gitignore` is configured to exclude them.
40
+
41
+ ## Authentication
42
+
43
+ HMAC-SHA-384 signing (`src/auth.ts`):
44
+ - Message: `{keyId}:{utcTime}:{urlPath}`
45
+ - Signature: `BASE64(HMAC-SHA-384(message, password))`
46
+ - Headers: `X-AUTH-KEY: {publicValue}:{signature}`, `X-AUTH-QUERYTIME: {utcTime}`
47
+ - Signing uses the URL path only (no query params)
48
+
49
+ ## API Endpoints (RIK e-Financials v1)
50
+
51
+ OpenAPI spec: `GET /openapi.yaml` on the API server. HTML docs: `/api.html`.
52
+
53
+ ### Action endpoints
54
+ - **Confirm/Register**: `PATCH /{entity}/{id}/register` (not `/confirm`)
55
+ - **Invalidate**: `PATCH /{entity}/{id}/invalidate`
56
+ - **Reactivate**: `PATCH /clients|products/{id}/reactivate`
57
+ - **Deactivate**: `PATCH /clients|products/{id}/deactivate`
58
+ - **Deliver sale invoice**: `PATCH /sale_invoices/{id}/deliver` (not `/send_einvoice`)
59
+
60
+ ### Document endpoints
61
+ - **User-uploaded docs**: `GET/PUT/DELETE /{entity}/{id}/document_user` (PUT to upload, not POST)
62
+ - **System-generated sale invoice PDF**: `GET /sale_invoices/{id}/pdf_system`
63
+
64
+ ### Transaction registration
65
+ - Body is a **top-level JSON array** of `TransactionsDistribution` objects (not wrapped in `{items: [...]}`)
66
+ - Each distribution: `{related_table, amount, related_id?, related_sub_id?}`
67
+ - Example: `PATCH /transactions/{id}/register` with body `[{"related_table":"purchase_invoices","related_id":123,"amount":59.94}]`
68
+ - **Card payments often have `clients_id: null`** — confirmation fails with "buyer or supplier is missing". `TransactionsApi.confirm()` auto-fixes this by looking up the client from the linked invoice.
69
+
70
+ ### Purchase invoice creation (non-VAT company)
71
+ - Do **not** pass `gross_price` at creation — the API computes it
72
+ - For VAT tracking on items: set `vat_rate_dropdown`, `vat_accounts_id`, `cl_vat_articles_id`, `project_no_vat_gross_price`
73
+ - The API will compute `vat_amount` on the item but invoice-level `vat_price` stays 0 for non-VAT companies
74
+
75
+ ## Architecture
76
+
77
+ ```
78
+ src/
79
+ config.ts # Env/file credential loading, server URL selection
80
+ auth.ts # HMAC-SHA-384 request signing
81
+ http-client.ts # Authenticated HTTP client (rate-limited, 60s timeout)
82
+ cache.ts # In-memory TTL cache (300s default, 500 entry max)
83
+ index.ts # Server entry point, wires everything together
84
+ api/
85
+ base-resource.ts # Generic CRUD with caching (listAll max 200 pages)
86
+ clients.api.ts # Clients (buyers/suppliers)
87
+ products.api.ts # Products/services
88
+ journals.api.ts # Journal entries with postings
89
+ transactions.api.ts # Bank transactions
90
+ sale-invoices.api.ts # Sales invoices
91
+ purchase-invoices.api.ts # Purchase invoices
92
+ readonly.api.ts # Reference data (accounts, articles, templates, etc.)
93
+ tools/
94
+ crud-tools.ts # ~50 CRUD tools for all entities + reference data
95
+ purchase-vat-defaults.ts # Purchase VAT article/account resolution from reference data
96
+ account-balance.ts # D/C balance computation, client debt
97
+ pdf-workflow.ts # PDF text extraction, invoice validation, supplier resolution, booking suggestions
98
+ bank-reconciliation.ts # Transaction matching and auto-confirmation
99
+ financial-statements.ts # Trial balance, balance sheet, P&L, month-end close
100
+ aging-analysis.ts # Receivables/payables aging buckets
101
+ recurring-invoices.ts # Clone sale invoices for recurring billing
102
+ estonian-tax.ts # Dividend package, owner expense reimbursement
103
+ document-audit.ts # Duplicate detection, missing documents
104
+ lightyear-investments.ts # Lightyear CSV import (buy/sell/distribution booking)
105
+ types/
106
+ api.ts # All TypeScript interfaces (~530 lines)
107
+ resources/
108
+ static-resources.ts # MCP resources (accounts, articles, templates, etc.)
109
+ ```
110
+
111
+ ## Key Accounting Concepts
112
+
113
+ ### D/C Balance Logic
114
+ - **D-type accounts** (assets, expenses): balance = debits - credits
115
+ - **C-type accounts** (liabilities, equity, revenue): balance = credits - debits
116
+ - Journal postings use `base_amount` (EUR) when available for multi-currency entries
117
+ - Balance sheet handles **contra-accounts** (e.g., accumulated depreciation is C-type within Varad)
118
+
119
+ ### Account Types (Estonian)
120
+ - **Varad** = Assets (normal balance: D, but contra-assets like kulum are C)
121
+ - **Kohustused** = Liabilities (normal: C)
122
+ - **Omakapital** = Equity (normal: C)
123
+ - **Tulud** = Revenue (normal: C)
124
+ - **Kulud** = Expenses (normal: D)
125
+
126
+ ### Cache Invalidation
127
+ All mutating API methods (`create`, `update`, `delete`, `confirm`, `merge`, `deactivate`, `uploadDocument`, `deleteDocument`) call `cache.invalidate(this.basePath)` before the API call.
128
+
129
+ ### Lightyear Investment CSV
130
+ - **BRICEKSP** (IE000GWTNRJ7): money market cash fund, always excluded from trades
131
+ - **FX pairing**: Foreign currency trades (e.g., USD) are paired with CN-xxx Conversion entries by date + amount match. Consumed conversions are tracked to prevent double-matching.
132
+ - **Sells require capital gains file**: Cost basis comes from the FIFO capital gains CSV. Sells without cost basis data are skipped with a warning.
133
+ - **Duplicate detection**: Journal `document_number` field stores `LY:{reference}` (e.g., `LY:OR-EVN9C76R7A`)
134
+ - **Dry run default**: Both `book_lightyear_trades` and `book_lightyear_distributions` default to `dry_run=true`
135
+
136
+ ## Security Notes
137
+
138
+ - File read operations (PDF, CSV) resolve symlinks via `realpath()` and re-check extensions
139
+ - `safeJsonParse` enforces 1MB input size limit
140
+ - `listAll()` is bounded to 200 pages max
141
+ - HTTP client rate-limits to ~10 req/sec
142
+ - Error messages are sanitized (no raw API response bodies)
143
+ - Cache is bounded to 500 entries with LRU eviction
144
+
145
+ ## Estonian Tax Rules
146
+
147
+ - **KMD INF**: Partner detail annex, threshold 1000 EUR net per partner
148
+ - **Standard VAT rate**: 24% (from 1.07.2025)
149
+ - **VD**: Intra-community supply declaration (EU only)
150
+ - **CIT on dividends**: 22/78 corporate income tax rate
151
+ - **Capital gains**: Securities taxed at 22% income tax
152
+
153
+ ## Development
154
+
155
+ ```bash
156
+ npx tsc --noEmit # Type-check without emitting
157
+ npx tsc # Full build to dist/
158
+ ```
159
+
160
+ No test framework is configured. Test via MCP client connection:
161
+ ```typescript
162
+ import { Client } from "@modelcontextprotocol/sdk/client/index.js";
163
+ import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
164
+
165
+ const transport = new StdioClientTransport({ command: "node", args: ["dist/index.js"] });
166
+ const client = new Client({ name: "test", version: "1.0.0" });
167
+ await client.connect(transport);
168
+ const { tools } = await client.listTools(); // 82 tools
169
+ ```
package/LICENSE ADDED
@@ -0,0 +1,24 @@
1
+ This is free and unencumbered software released into the public domain.
2
+
3
+ Anyone is free to copy, modify, publish, use, compile, sell, or
4
+ distribute this software, either in source code form or as a compiled
5
+ binary, for any purpose, commercial or non-commercial, and by any
6
+ means.
7
+
8
+ In jurisdictions that recognize copyright laws, the author or authors
9
+ of this software dedicate any and all copyright interest in the
10
+ software to the public domain. We make this dedication for the benefit
11
+ of the public at large and to the detriment of our heirs and
12
+ successors. We intend this dedication to be an overt act of
13
+ relinquishment in perpetuity of all present and future rights to this
14
+ software under copyright law.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19
+ IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20
+ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21
+ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22
+ OTHER DEALINGS IN THE SOFTWARE.
23
+
24
+ For more information, please refer to <https://unlicense.org/>
package/README.md ADDED
@@ -0,0 +1,155 @@
1
+ # e-arveldaja MCP Server
2
+
3
+ MCP (Model Context Protocol) server for the Estonian e-arveldaja (RIK e-Financials) REST API. Works with any MCP-compatible AI assistant — Claude Code, Cursor, Windsurf, Cline, and others.
4
+
5
+ ## Disclaimer
6
+
7
+ **This is an experimental, unofficial project.** It is not affiliated with, endorsed by, or in any way officially connected to RIK (Registrite ja Infosüsteemide Keskus) or the e-arveldaja / e-Financials service.
8
+
9
+ **Use entirely at your own risk.** This software interacts with live financial data and can create, modify, confirm, and delete accounting records (invoices, journal entries, transactions, etc.). The authors accept no responsibility for any data loss, incorrect bookings, or other damages resulting from the use of this software.
10
+
11
+ By using this software you acknowledge that:
12
+ - You are solely responsible for verifying all data and operations
13
+ - You should test thoroughly on the demo server before using with live data
14
+ - This is experimental software with no warranty of any kind
15
+
16
+ ## Getting an API Key
17
+
18
+ 1. Log in to [e-arveldaja](https://www.earveldaja.ee/)
19
+ 2. Go to **Seadistused** → **Üldised seadistused** → **Lisa uus juurdepääsuluba** (Settings → General settings → Add new access token)
20
+ 3. Enter any name for the token
21
+ 4. Find your public IP address (e.g. at [whatismyipaddress.com](https://whatismyipaddress.com/)) and enter it in the allowed IP field. Multiple IPs can be separated by `;`
22
+ 5. Save — download the `apikey.txt` file and place it next to the project directory (i.e. in the parent folder)
23
+
24
+ If you don't have a static IP address, you will need to update the allowed IP in e-arveldaja settings whenever your IP changes.
25
+
26
+ **Never commit the `apikey.txt` file to git.**
27
+
28
+ For the demo server, set the environment variable `EARVELDAJA_SERVER=demo`.
29
+
30
+ ## Setup
31
+
32
+ ### Option A: npx (no install needed)
33
+
34
+ Just reference `npx e-arveldaja-mcp` in your MCP config — no cloning or building required. See configuration examples below.
35
+
36
+ ### Option B: From source
37
+
38
+ ```bash
39
+ git clone https://github.com/iseppo/e-arveldaja-mcp.git
40
+ cd e-arveldaja-mcp
41
+ npm install
42
+ npm run build # tsc -> dist/
43
+ ```
44
+
45
+ ### Connecting to your AI assistant
46
+
47
+ This is a standard MCP server using stdio transport. Most AI assistants can set this up themselves — just ask:
48
+
49
+ > "Add the e-arveldaja MCP server from /path/to/e-arveldaja-mcp to my MCP configuration"
50
+
51
+ The assistant will read the config format it needs and add the server entry. You can also ask it to install the workflows:
52
+
53
+ > "Copy the workflow files from /path/to/e-arveldaja-mcp/workflows/ into your commands so I can use them"
54
+
55
+ If you prefer to configure manually:
56
+
57
+ **JSON-based config** (Claude Code, Cursor, Windsurf, Cline, Gemini CLI, Antigravity):
58
+
59
+ ```json
60
+ {
61
+ "mcpServers": {
62
+ "e-arveldaja": {
63
+ "command": "npx",
64
+ "args": ["-y", "e-arveldaja-mcp"]
65
+ }
66
+ }
67
+ }
68
+ ```
69
+
70
+ **TOML-based config** (Codex CLI):
71
+
72
+ ```toml
73
+ [mcp_servers.e-arveldaja]
74
+ command = "npx"
75
+ args = ["-y", "e-arveldaja-mcp"]
76
+ ```
77
+
78
+ If running from source, replace `"npx", "-y", "e-arveldaja-mcp"` with `"node", "/path/to/e-arveldaja-mcp/dist/index.js"`.
79
+
80
+ Where this config file lives depends on your tool:
81
+
82
+ | Tool | Config file |
83
+ |---|---|
84
+ | **Claude Code** | `~/.claude/settings.json` or project `.claude/settings.json` |
85
+ | **Codex CLI** | `~/.codex/config.toml` or project `.codex/config.toml` |
86
+ | **Gemini CLI** | `~/.gemini/settings.json` or project `.gemini/settings.json` |
87
+ | **Google Antigravity** | MCP Store UI → Manage MCP Servers → View raw config (`mcp_config.json`) |
88
+ | **Cursor** | `.cursor/mcp.json` in your project |
89
+ | **Windsurf** | `~/.codeium/windsurf/mcp_config.json` |
90
+ | **Cline** | VS Code settings under `cline.mcpServers` |
91
+
92
+ See [CLAUDE.md](CLAUDE.md) for architecture details and full API documentation.
93
+
94
+ ## Workflows
95
+
96
+ The project includes step-by-step workflow guides in [`workflows/`](workflows/) that orchestrate multiple MCP tools into complete accounting tasks. These work with any MCP client — just paste the workflow into your AI assistant's prompt or follow the steps manually.
97
+
98
+ | Workflow | Description |
99
+ |---|---|
100
+ | [book-invoice](workflows/book-invoice.md) | Book a purchase invoice from PDF: extract data, validate, find/create supplier, suggest accounts, create invoice, upload PDF, confirm |
101
+ | [reconcile-bank](workflows/reconcile-bank.md) | Match unconfirmed bank transactions to open invoices and confirm matches |
102
+ | [month-end](workflows/month-end.md) | Run month-end close checklist: blockers, missing docs, duplicates, trial balance, P&L, balance sheet |
103
+ | [new-supplier](workflows/new-supplier.md) | Create a supplier with Estonian business registry lookup and dedup check |
104
+
105
+ ### Claude Code slash commands
106
+
107
+ If you use Claude Code, the same workflows are also available as slash commands in `.claude/commands/`. To install:
108
+
109
+ **Option A:** Run Claude Code from the `e-arveldaja-mcp` directory — skills are auto-detected.
110
+
111
+ **Option B:** Symlink or copy to your global commands:
112
+
113
+ ```bash
114
+ # Symlink (stays up to date)
115
+ ln -s /path/to/e-arveldaja-mcp/.claude/commands/*.md ~/.claude/commands/
116
+
117
+ # Or copy
118
+ cp /path/to/e-arveldaja-mcp/.claude/commands/*.md ~/.claude/commands/
119
+ ```
120
+
121
+ Then use `/book-invoice`, `/reconcile-bank`, `/month-end`, `/new-supplier` in any conversation.
122
+
123
+ ## Usage Examples
124
+
125
+ Once the MCP server is connected, just talk to your AI assistant in natural language:
126
+
127
+ ### Enter purchase invoices from PDF files
128
+
129
+ > "Book this invoice PDF into e-arveldaja and match it to the bank payment"
130
+
131
+ The assistant will extract invoice data from the PDF, create a purchase invoice with the correct accounts and VAT rates, and match it to existing bank transactions.
132
+
133
+ ### Book Lightyear investment trades
134
+
135
+ Download your Lightyear account statement CSV and capital gains report, then:
136
+
137
+ > "Create e-arveldaja journal entries from these Lightyear CSVs"
138
+
139
+ The assistant will parse the trades, pair foreign currency conversions, calculate capital gains from the FIFO report, and create journal entries with the correct securities accounts.
140
+
141
+ ### Generate financial reports
142
+
143
+ > "Generate a P&L and balance sheet as of 28.02.2026"
144
+
145
+ ### Reconcile bank transactions
146
+
147
+ > "Match unconfirmed bank transactions to invoices"
148
+
149
+ ### Month-end close
150
+
151
+ > "Run the month-end close checklist for February 2026"
152
+
153
+ ## License
154
+
155
+ [The Unlicense](LICENSE) — public domain. Do whatever you want with it.