@kirjapro/mcp-server 0.6.3 → 0.8.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 (67) hide show
  1. package/CHANGELOG.md +115 -0
  2. package/README.md +73 -9
  3. package/dist/index.js +1472 -657
  4. package/package.json +10 -4
  5. package/server.json +6 -2
  6. package/tool-fingerprints.json +55 -51
  7. package/dist/accounts.d.ts +0 -40
  8. package/dist/accounts.js +0 -45
  9. package/dist/auth.d.ts +0 -17
  10. package/dist/auth.js +0 -245
  11. package/dist/compliance/rates.d.ts +0 -53
  12. package/dist/compliance/rates.js +0 -57
  13. package/dist/database.types.d.ts +0 -6525
  14. package/dist/database.types.js +0 -20
  15. package/dist/index.d.ts +0 -2
  16. package/dist/lib/incomeStatementSynthesis.d.ts +0 -47
  17. package/dist/lib/incomeStatementSynthesis.js +0 -140
  18. package/dist/resources/company.d.ts +0 -2
  19. package/dist/resources/company.js +0 -75
  20. package/dist/resources/compliance.d.ts +0 -2
  21. package/dist/resources/compliance.js +0 -338
  22. package/dist/resources/index.d.ts +0 -2
  23. package/dist/resources/index.js +0 -10
  24. package/dist/resources/schema.d.ts +0 -2
  25. package/dist/resources/schema.js +0 -63
  26. package/dist/resources/security.d.ts +0 -2
  27. package/dist/resources/security.js +0 -33
  28. package/dist/schemas.d.ts +0 -12
  29. package/dist/schemas.js +0 -12
  30. package/dist/tools/accounts.d.ts +0 -2
  31. package/dist/tools/accounts.js +0 -48
  32. package/dist/tools/banking.d.ts +0 -2
  33. package/dist/tools/banking.js +0 -196
  34. package/dist/tools/bookings.d.ts +0 -2
  35. package/dist/tools/bookings.js +0 -294
  36. package/dist/tools/customers.d.ts +0 -2
  37. package/dist/tools/customers.js +0 -320
  38. package/dist/tools/financialNotes.d.ts +0 -2
  39. package/dist/tools/financialNotes.js +0 -255
  40. package/dist/tools/fingerprints.d.ts +0 -6
  41. package/dist/tools/fingerprints.js +0 -28
  42. package/dist/tools/fiscal-years.d.ts +0 -2
  43. package/dist/tools/fiscal-years.js +0 -35
  44. package/dist/tools/index.d.ts +0 -9
  45. package/dist/tools/index.js +0 -105
  46. package/dist/tools/invoices.d.ts +0 -2
  47. package/dist/tools/invoices.js +0 -489
  48. package/dist/tools/offers.d.ts +0 -2
  49. package/dist/tools/offers.js +0 -443
  50. package/dist/tools/received-invoices.d.ts +0 -2
  51. package/dist/tools/received-invoices.js +0 -134
  52. package/dist/tools/recurring-invoices.d.ts +0 -2
  53. package/dist/tools/recurring-invoices.js +0 -348
  54. package/dist/tools/reports.d.ts +0 -2
  55. package/dist/tools/reports.js +0 -869
  56. package/dist/tools/templates.d.ts +0 -89
  57. package/dist/tools/templates.js +0 -636
  58. package/dist/tools/transactions.d.ts +0 -2
  59. package/dist/tools/transactions.js +0 -597
  60. package/dist/tools/validation.d.ts +0 -26
  61. package/dist/tools/validation.js +0 -127
  62. package/dist/types.d.ts +0 -388
  63. package/dist/types.js +0 -34
  64. package/dist/utils.d.ts +0 -276
  65. package/dist/utils.js +0 -637
  66. package/dist/version.d.ts +0 -1
  67. package/dist/version.js +0 -3
@@ -1,255 +0,0 @@
1
- import { z } from 'zod';
2
- import { getSupabase, getCompanyId } from '../auth.js';
3
- import { toErrorContent, toResult, sanitizeDbError, helsinkiDateString, formatFinnishDate, READ_ONLY_ANNOTATIONS, } from '../utils.js';
4
- /**
5
- * Liitetiedot (Notes to Financial Statements)
6
- *
7
- * Sister-tool of `kirjapro_get_income_statement` and `kirjapro_get_balance_sheet`
8
- * (skill `wave-sibling-rpc-doctrine-parity`):
9
- * - Same input shape (company_id auto-derived from auth, fiscalYearId optional)
10
- * - Same READ_ONLY_ANNOTATIONS (read-only, idempotent, closed-world)
11
- * - Same toResult() / toErrorContent() envelope
12
- *
13
- * READ-ONLY by design (DT-045): the web form is the only write surface for
14
- * liitetiedot — finalization carries audit columns + 42501 lock semantics that
15
- * the UI is responsible for enforcing. AI agents read; humans finalize.
16
- *
17
- * Phase 1 (DT-045) added `finalized_at` and `finalized_by` to the row; this
18
- * tool surfaces them in `structuredContent` so the agent can render audit
19
- * status without separate calls.
20
- */
21
- /**
22
- * 11 user-facing liitetiedot fields, matching `FinancialNotes.tsx:FIELDS`
23
- * (10 narrative textarea + 1 numeric `henkilosto_lkm`). Used to compute
24
- * `filled_field_count` for the human-readable summary.
25
- */
26
- const NARRATIVE_FIELDS = [
27
- 'arvostusperiaatteet',
28
- 'poikkeukselliset_erat',
29
- 'tilikauden_jalkeiset',
30
- 'vakuudet_ja_vastuut',
31
- 'lainat_johdolle',
32
- 'henkiloston_maara',
33
- 'poistomenetelmat',
34
- 'pitkaikaiset_velat',
35
- 'oman_paoman_muutokset',
36
- 'olennaiset_tapahtumat',
37
- ];
38
- const TOTAL_FIELD_COUNT = NARRATIVE_FIELDS.length + 1; // +1 for henkilosto_lkm
39
- const STATUS_ENUM = z.enum(['draft', 'final']);
40
- const FINANCIAL_NOTES_OUTPUT_SHAPE = {
41
- fiscal_year_id: z.string().uuid(),
42
- fiscal_year: z.object({
43
- id: z.string().uuid(),
44
- start_date: z.string(),
45
- end_date: z.string(),
46
- is_closed: z.boolean(),
47
- }),
48
- status: STATUS_ENUM,
49
- finalized_at: z.string().nullable(),
50
- finalized_by: z.string().nullable(),
51
- arvostusperiaatteet: z.string(),
52
- poikkeukselliset_erat: z.string(),
53
- tilikauden_jalkeiset: z.string(),
54
- vakuudet_ja_vastuut: z.string(),
55
- lainat_johdolle: z.string(),
56
- henkiloston_maara: z.string(),
57
- poistomenetelmat: z.string(),
58
- pitkaikaiset_velat: z.string(),
59
- oman_paoman_muutokset: z.string(),
60
- olennaiset_tapahtumat: z.string(),
61
- henkilosto_lkm: z.number().nullable(),
62
- filled_field_count: z.number(),
63
- total_field_count: z.number(),
64
- exists: z.boolean(),
65
- note: z.string().optional(),
66
- };
67
- /**
68
- * Format finalized_at (ISO timestamp string) as "DD.MM.YYYY HH:MM" Finnish.
69
- * Returns null when input is null or unparseable so the caller can decide.
70
- */
71
- function formatFinnishTimestamp(iso) {
72
- if (!iso)
73
- return null;
74
- const ms = Date.parse(iso);
75
- if (Number.isNaN(ms))
76
- return null;
77
- // Render in Europe/Helsinki — the audit timestamp is for human review and
78
- // should match the user's wall clock when they finalized.
79
- const parts = new Intl.DateTimeFormat('fi-FI', {
80
- timeZone: 'Europe/Helsinki',
81
- year: 'numeric',
82
- month: '2-digit',
83
- day: '2-digit',
84
- hour: '2-digit',
85
- minute: '2-digit',
86
- hour12: false,
87
- }).formatToParts(new Date(ms));
88
- const pick = (t) => parts.find((p) => p.type === t)?.value ?? '';
89
- return `${pick('day')}.${pick('month')}.${pick('year')} ${pick('hour')}:${pick('minute')}`;
90
- }
91
- export function registerFinancialNotesTools(server) {
92
- server.registerTool('kirjapro_get_financial_notes', {
93
- description: 'Hae liitetiedot (notes to financial statements) yhdelle tilikaudelle. Palauttaa KPL 3:1 / PMA 3:2 mukaiset narratiivikentät (10), henkilöstön keskimääräinen lukumäärä, statuksen (draft/final) ja vahvistustiedot (finalized_at/by). READ-ONLY — luominen ja muokkaus tapahtuvat web-lomakkeella. If fiscalYearId is omitted, the fiscal year covering today (Europe/Helsinki) is auto-resolved.',
94
- inputSchema: {
95
- fiscalYearId: z
96
- .string()
97
- .uuid()
98
- .optional()
99
- .describe('Fiscal year UUID (auto-resolved to the FY covering today in Europe/Helsinki if omitted)'),
100
- },
101
- outputSchema: FINANCIAL_NOTES_OUTPUT_SHAPE,
102
- annotations: READ_ONLY_ANNOTATIONS,
103
- }, async (params) => {
104
- const supabase = getSupabase();
105
- const companyId = getCompanyId();
106
- // Resolve fiscal year. Sister tool `kirjapro_get_balance_sheet` filters
107
- // `is_closed=false` via `resolveOpenFiscalYear` — we mirror that posture
108
- // here (skill `wave-sibling-rpc-doctrine-parity`). Auto-resolve picks the
109
- // OPEN fiscal year covering today; if today falls inside a closed FY (a
110
- // legitimate scenario when the new FY hasn't been provisioned yet), we
111
- // surface a clear error instead of silently returning the closed row.
112
- // An explicit `fiscalYearId` still works for closed FYs — read access is
113
- // intentional for tilinpäätös history.
114
- let fiscalYear;
115
- if (params.fiscalYearId) {
116
- const { data, error } = await supabase
117
- .from('fiscal_years')
118
- .select('id, start_date, end_date, is_closed')
119
- .eq('company_id', companyId)
120
- .eq('id', params.fiscalYearId)
121
- .maybeSingle();
122
- if (error) {
123
- return toErrorContent(sanitizeDbError('Failed to load fiscal year', error));
124
- }
125
- if (!data) {
126
- return toErrorContent(`Fiscal year ${params.fiscalYearId} not found. Use kirjapro_list_fiscal_years to find available fiscal years.`);
127
- }
128
- fiscalYear = data;
129
- }
130
- else {
131
- const today = helsinkiDateString();
132
- // Mirror resolveOpenFiscalYear posture (skill
133
- // `wave-sibling-rpc-doctrine-parity`): error explicitly on 0 or >1
134
- // matches rather than silently picking one. The date-range filter is
135
- // intentional — liitetiedot is per-FY narrative, so we resolve to the
136
- // open FY that covers TODAY rather than just any open FY (sister
137
- // `kirjapro_get_balance_sheet` uses any-open semantics, which is fine
138
- // for a balance sheet but wrong for a "this year's notes" surface).
139
- // `.limit(2)` is the minimum needed to detect the >1 case.
140
- const { data, error } = await supabase
141
- .from('fiscal_years')
142
- .select('id, start_date, end_date, is_closed')
143
- .eq('company_id', companyId)
144
- .eq('is_closed', false)
145
- .lte('start_date', today)
146
- .gte('end_date', today)
147
- .order('end_date', { ascending: false })
148
- .limit(2);
149
- if (error) {
150
- return toErrorContent(sanitizeDbError('Failed to resolve current fiscal year', error));
151
- }
152
- if (!data || data.length === 0) {
153
- return toErrorContent(`No open fiscal year covers today (${today}). The fiscal year covering today may be closed, or no fiscal year has been created. Specify fiscalYearId explicitly (closed years are still readable) or list fiscal years with kirjapro_list_fiscal_years.`);
154
- }
155
- if (data.length > 1) {
156
- return toErrorContent(`Multiple open fiscal years cover today (${data.length}). Specify fiscalYearId explicitly. Use kirjapro_list_fiscal_years to list them.`);
157
- }
158
- fiscalYear = data[0];
159
- }
160
- // Fetch the liitetiedot row. RLS enforces company_id isolation, but we
161
- // still pass it explicitly so a misconfigured policy can't widen access
162
- // (CLAUDE.md §12 cross-company isolation).
163
- // Long select strings return PostgREST `GenericStringError | T` because
164
- // supabase-js can't compile the column list at the type level — narrow
165
- // back to the row type below after error-branching.
166
- const { data: row, error: rowError } = await supabase
167
- .from('liitetiedot')
168
- .select('id, fiscal_year_id, status, finalized_at, finalized_by, ' +
169
- 'arvostusperiaatteet, poikkeukselliset_erat, tilikauden_jalkeiset, ' +
170
- 'vakuudet_ja_vastuut, lainat_johdolle, henkiloston_maara, ' +
171
- 'poistomenetelmat, pitkaikaiset_velat, oman_paoman_muutokset, ' +
172
- 'olennaiset_tapahtumat, henkilosto_lkm')
173
- .eq('company_id', companyId)
174
- .eq('fiscal_year_id', fiscalYear.id)
175
- .maybeSingle();
176
- if (rowError) {
177
- return toErrorContent(sanitizeDbError('Failed to load financial notes', rowError));
178
- }
179
- const normalizedRow = row ?? null;
180
- const status = normalizedRow?.status === 'final' ? 'final' : 'draft';
181
- // Build the text payload. Empty placeholder when no row exists yet —
182
- // matches the web hook's EMPTY_LIITETIEDOT shape so agents see consistent
183
- // structure regardless of fill state.
184
- const fields = {
185
- arvostusperiaatteet: normalizedRow?.arvostusperiaatteet ?? '',
186
- poikkeukselliset_erat: normalizedRow?.poikkeukselliset_erat ?? '',
187
- tilikauden_jalkeiset: normalizedRow?.tilikauden_jalkeiset ?? '',
188
- vakuudet_ja_vastuut: normalizedRow?.vakuudet_ja_vastuut ?? '',
189
- lainat_johdolle: normalizedRow?.lainat_johdolle ?? '',
190
- henkiloston_maara: normalizedRow?.henkiloston_maara ?? '',
191
- poistomenetelmat: normalizedRow?.poistomenetelmat ?? '',
192
- pitkaikaiset_velat: normalizedRow?.pitkaikaiset_velat ?? '',
193
- oman_paoman_muutokset: normalizedRow?.oman_paoman_muutokset ?? '',
194
- olennaiset_tapahtumat: normalizedRow?.olennaiset_tapahtumat ?? '',
195
- henkilosto_lkm: typeof normalizedRow?.henkilosto_lkm === 'number'
196
- ? normalizedRow.henkilosto_lkm
197
- : null,
198
- };
199
- // Field-fill counter — narrative fields count when their trimmed length
200
- // is > 0; henkilosto_lkm counts when it's a number (zero is a legitimate
201
- // disclosure for "no employees").
202
- let filledFieldCount = 0;
203
- for (const key of NARRATIVE_FIELDS) {
204
- const v = fields[key];
205
- if (typeof v === 'string' && v.trim().length > 0)
206
- filledFieldCount++;
207
- }
208
- if (typeof fields.henkilosto_lkm === 'number')
209
- filledFieldCount++;
210
- const exists = normalizedRow !== null;
211
- const note = exists
212
- ? undefined
213
- : 'Liitetietoja ei vielä luotu tälle tilikaudelle.';
214
- const payload = {
215
- fiscal_year_id: fiscalYear.id,
216
- fiscal_year: {
217
- id: fiscalYear.id,
218
- start_date: fiscalYear.start_date,
219
- end_date: fiscalYear.end_date,
220
- is_closed: fiscalYear.is_closed,
221
- },
222
- status,
223
- finalized_at: normalizedRow?.finalized_at ?? null,
224
- finalized_by: normalizedRow?.finalized_by ?? null,
225
- ...fields,
226
- filled_field_count: filledFieldCount,
227
- total_field_count: TOTAL_FIELD_COUNT,
228
- exists,
229
- ...(note ? { note } : {}),
230
- };
231
- // Human-readable summary line in `content[0].text` — matches sister tools'
232
- // toResult() shape but the JSON is fronted by a Finnish status sentence
233
- // for agents that don't parse structuredContent. Plan §4 Wave 1C wording.
234
- const yearLabel = fiscalYear.start_date.slice(0, 4);
235
- const statusLabel = status === 'final' ? 'Valmis' : 'Luonnos';
236
- const finalizedFi = formatFinnishTimestamp(payload.finalized_at);
237
- const finalizedSentence = status === 'final' && finalizedFi
238
- ? ` Vahvistettu ${finalizedFi}.`
239
- : '';
240
- const summary = `Liitetiedot tilikaudelle ${yearLabel} ` +
241
- `(${formatFinnishDate(fiscalYear.start_date)} – ${formatFinnishDate(fiscalYear.end_date)}, ` +
242
- `status: ${statusLabel}).${finalizedSentence} ` +
243
- `Täytetyt kentät: ${filledFieldCount} / ${TOTAL_FIELD_COUNT}.`;
244
- const result = toResult(payload);
245
- // Prepend the summary line so MCP clients displaying only `content` see
246
- // the human-readable status before the JSON blob.
247
- return {
248
- ...result,
249
- content: [
250
- { type: 'text', text: summary },
251
- ...result.content,
252
- ],
253
- };
254
- });
255
- }
@@ -1,6 +0,0 @@
1
- import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
- export interface ToolFingerprint {
3
- name: string;
4
- hash: string;
5
- }
6
- export declare function computeFingerprints(server: McpServer): ToolFingerprint[];
@@ -1,28 +0,0 @@
1
- import { createHash } from 'node:crypto';
2
- function canonicalize(value) {
3
- if (value === null || value === undefined)
4
- return 'null';
5
- if (typeof value === 'function')
6
- return 'fn';
7
- if (typeof value !== 'object')
8
- return JSON.stringify(value);
9
- if (Array.isArray(value)) {
10
- return `[${value.map(canonicalize).join(',')}]`;
11
- }
12
- const keys = Object.keys(value).sort();
13
- const entries = keys.map((k) => `${JSON.stringify(k)}:${canonicalize(value[k])}`);
14
- return `{${entries.join(',')}}`;
15
- }
16
- function hashTool(tool) {
17
- const canonical = canonicalize({
18
- description: tool.description ?? '',
19
- annotations: tool.annotations ?? {},
20
- inputSchema: tool.inputSchema ?? {},
21
- });
22
- return createHash('sha256').update(canonical).digest('hex').slice(0, 16);
23
- }
24
- export function computeFingerprints(server) {
25
- const registered = server._registeredTools;
26
- const names = Object.keys(registered).sort();
27
- return names.map((name) => ({ name, hash: hashTool(registered[name]) }));
28
- }
@@ -1,2 +0,0 @@
1
- import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
- export declare function registerFiscalYearTools(server: McpServer): void;
@@ -1,35 +0,0 @@
1
- import { getSupabase, getCompanyId } from '../auth.js';
2
- import { z } from 'zod';
3
- import { toResult, toErrorContent, sanitizeDbError, READ_ONLY_ANNOTATIONS } from '../utils.js';
4
- export function registerFiscalYearTools(server) {
5
- server.registerTool('kirjapro_list_fiscal_years', {
6
- description: 'List fiscal years (tilikaudet) for the company. Shows start/end dates and open/closed status. Many tools require a fiscal year ID — use this to find the right one.',
7
- inputSchema: {},
8
- outputSchema: {
9
- fiscal_years: z.array(z.object({
10
- id: z.string().uuid(),
11
- start_date: z.string(),
12
- end_date: z.string(),
13
- is_closed: z.boolean(),
14
- created_at: z.string(),
15
- }).passthrough()),
16
- count: z.number(),
17
- },
18
- annotations: READ_ONLY_ANNOTATIONS,
19
- }, async () => {
20
- const supabase = getSupabase();
21
- const companyId = getCompanyId();
22
- const { data, error } = await supabase
23
- .from('fiscal_years')
24
- .select('id, start_date, end_date, is_closed, created_at')
25
- .eq('company_id', companyId)
26
- .order('start_date', { ascending: false });
27
- if (error) {
28
- return toErrorContent(sanitizeDbError("Failed to list fiscal years", error));
29
- }
30
- return toResult({
31
- fiscal_years: data || [],
32
- count: (data || []).length,
33
- });
34
- });
35
- }
@@ -1,9 +0,0 @@
1
- import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
- export type Surface = 'core' | 'full';
3
- export declare const CORE_TOOL_NAMES: ReadonlySet<string>;
4
- interface RegisterToolsOptions {
5
- surface?: Surface;
6
- }
7
- export declare function resolveSurface(explicit?: Surface): Surface;
8
- export declare function registerTools(server: McpServer, options?: RegisterToolsOptions): void;
9
- export {};
@@ -1,105 +0,0 @@
1
- import { registerAccountTools } from './accounts.js';
2
- import { registerTransactionTools } from './transactions.js';
3
- import { registerInvoiceTools } from './invoices.js';
4
- import { registerCustomerTools } from './customers.js';
5
- import { registerReportTools } from './reports.js';
6
- import { registerBankingTools } from './banking.js';
7
- import { registerValidationTools } from './validation.js';
8
- import { registerFiscalYearTools } from './fiscal-years.js';
9
- import { registerTemplateTools } from './templates.js';
10
- import { registerBookingTools } from './bookings.js';
11
- import { registerOfferTools } from './offers.js';
12
- import { registerRecurringInvoiceTools } from './recurring-invoices.js';
13
- import { registerReceivedInvoiceTools } from './received-invoices.js';
14
- import { registerFinancialNotesTools } from './financialNotes.js';
15
- // 26 tools that ship in the default `core` surface — the daily-use shape that
16
- // keeps the agent under the empirical degradation cliff (~25-50 tools per
17
- // 2025-2026 SOTA research) while preserving the headline workflows (read books,
18
- // invoice flow, transactions + banking, contract create→send→convert).
19
- //
20
- // Adjust this list based on Phase 1 observability data post-launch (see
21
- // roadmap: mcp-server-progressive-disclosure). Adding a tool here — and only
22
- // here — promotes it from deferred to eager.
23
- export const CORE_TOOL_NAMES = new Set([
24
- // Read everything
25
- 'kirjapro_list_fiscal_years',
26
- 'kirjapro_list_accounts',
27
- 'kirjapro_get_dashboard',
28
- 'kirjapro_get_income_statement',
29
- 'kirjapro_get_balance_sheet',
30
- 'kirjapro_get_alv_summary',
31
- 'kirjapro_get_ar_aging',
32
- // Customers
33
- 'kirjapro_list_customers',
34
- 'kirjapro_get_customer',
35
- 'kirjapro_create_customer',
36
- 'kirjapro_lookup_business',
37
- // Invoice lifecycle
38
- 'kirjapro_list_invoices',
39
- 'kirjapro_get_invoice',
40
- 'kirjapro_create_invoice',
41
- 'kirjapro_record_payment',
42
- 'kirjapro_update_invoice_status',
43
- // Transactions + banking
44
- 'kirjapro_list_transactions',
45
- 'kirjapro_create_transaction',
46
- 'kirjapro_list_bank_transactions',
47
- 'kirjapro_match_bank_transaction',
48
- // Contracts (create → send → convert)
49
- 'kirjapro_create_offer',
50
- 'kirjapro_send_offer',
51
- 'kirjapro_convert_offer_to_invoice',
52
- // Pure validators (zero database cost, useful for any agent flow)
53
- 'kirjapro_validate_business_id',
54
- 'kirjapro_validate_iban',
55
- 'kirjapro_generate_reference',
56
- ]);
57
- export function resolveSurface(explicit) {
58
- if (explicit)
59
- return explicit;
60
- const env = process.env.KIRJAPRO_MCP_SURFACE?.toLowerCase();
61
- if (env === 'full')
62
- return 'full';
63
- if (env === 'core')
64
- return 'core';
65
- if (env && env !== 'core') {
66
- console.error(`[kirjapro-mcp] Unknown KIRJAPRO_MCP_SURFACE="${env}" — falling back to "core". ` +
67
- `Valid values: "core" (default, 26 tools), "full" (52 tools).`);
68
- }
69
- return 'core';
70
- }
71
- export function registerTools(server, options = {}) {
72
- const surface = resolveSurface(options.surface);
73
- registerAccountTools(server);
74
- registerTransactionTools(server);
75
- registerTemplateTools(server);
76
- registerBookingTools(server);
77
- registerInvoiceTools(server);
78
- registerCustomerTools(server);
79
- registerReportTools(server);
80
- registerBankingTools(server);
81
- registerValidationTools(server);
82
- registerFiscalYearTools(server);
83
- registerOfferTools(server);
84
- registerRecurringInvoiceTools(server);
85
- registerReceivedInvoiceTools(server);
86
- registerFinancialNotesTools(server);
87
- if (surface === 'core') {
88
- // Strip deferred tools from the registered map. Each register*Tools()
89
- // function keeps its own local logic intact (no scattered surface-flag
90
- // gates); we centralize the trim here so the deferred set is one list.
91
- const internals = server;
92
- let removed = 0;
93
- for (const name of Object.keys(internals._registeredTools)) {
94
- if (!CORE_TOOL_NAMES.has(name)) {
95
- delete internals._registeredTools[name];
96
- removed++;
97
- }
98
- }
99
- console.error(`[kirjapro-mcp] surface=core — registered ${CORE_TOOL_NAMES.size} tools, deferred ${removed}. ` +
100
- `Set KIRJAPRO_MCP_SURFACE=full to access the complete tool catalog.`);
101
- }
102
- else {
103
- console.error(`[kirjapro-mcp] surface=full — registered all 52 tools (CORE_TOOL_NAMES bypass active).`);
104
- }
105
- }
@@ -1,2 +0,0 @@
1
- import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
- export declare function registerInvoiceTools(server: McpServer): void;