@frihet/mcp-server 1.7.0-beta.1 → 1.12.0-beta.1
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/README.md +262 -12
- package/dist/__tests__/banking-tools.test.d.ts +18 -0
- package/dist/__tests__/banking-tools.test.d.ts.map +1 -0
- package/dist/__tests__/banking-tools.test.js +252 -0
- package/dist/__tests__/banking-tools.test.js.map +1 -0
- package/dist/__tests__/d4b-hr-payroll-onboarding-tools.test.d.ts +13 -0
- package/dist/__tests__/d4b-hr-payroll-onboarding-tools.test.d.ts.map +1 -0
- package/dist/__tests__/d4b-hr-payroll-onboarding-tools.test.js +420 -0
- package/dist/__tests__/d4b-hr-payroll-onboarding-tools.test.js.map +1 -0
- package/dist/__tests__/einvoice-day4-tools.test.d.ts +16 -0
- package/dist/__tests__/einvoice-day4-tools.test.d.ts.map +1 -0
- package/dist/__tests__/einvoice-day4-tools.test.js +377 -0
- package/dist/__tests__/einvoice-day4-tools.test.js.map +1 -0
- package/dist/__tests__/einvoice-tools.test.d.ts +1 -1
- package/dist/__tests__/einvoice-tools.test.js +25 -12
- package/dist/__tests__/einvoice-tools.test.js.map +1 -1
- package/dist/__tests__/fiscal-tools.test.d.ts +21 -0
- package/dist/__tests__/fiscal-tools.test.d.ts.map +1 -0
- package/dist/__tests__/fiscal-tools.test.js +215 -0
- package/dist/__tests__/fiscal-tools.test.js.map +1 -0
- package/dist/__tests__/pos-tools.test.d.ts +16 -0
- package/dist/__tests__/pos-tools.test.d.ts.map +1 -0
- package/dist/__tests__/pos-tools.test.js +244 -0
- package/dist/__tests__/pos-tools.test.js.map +1 -0
- package/dist/__tests__/recurring-tools.test.d.ts +23 -0
- package/dist/__tests__/recurring-tools.test.d.ts.map +1 -0
- package/dist/__tests__/recurring-tools.test.js +352 -0
- package/dist/__tests__/recurring-tools.test.js.map +1 -0
- package/dist/__tests__/stay-tools.test.d.ts +17 -0
- package/dist/__tests__/stay-tools.test.d.ts.map +1 -0
- package/dist/__tests__/stay-tools.test.js +259 -0
- package/dist/__tests__/stay-tools.test.js.map +1 -0
- package/dist/__tests__/team-tools.test.d.ts +18 -0
- package/dist/__tests__/team-tools.test.d.ts.map +1 -0
- package/dist/__tests__/team-tools.test.js +228 -0
- package/dist/__tests__/team-tools.test.js.map +1 -0
- package/dist/__tests__/time-tools.test.d.ts +19 -0
- package/dist/__tests__/time-tools.test.d.ts.map +1 -0
- package/dist/__tests__/time-tools.test.js +286 -0
- package/dist/__tests__/time-tools.test.js.map +1 -0
- package/dist/client-interface.d.ts +325 -0
- package/dist/client-interface.d.ts.map +1 -1
- package/dist/client.d.ts +325 -0
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +404 -0
- package/dist/client.js.map +1 -1
- package/dist/index.js +4 -4
- package/dist/index.js.map +1 -1
- package/dist/tools/accountingClose.d.ts +20 -0
- package/dist/tools/accountingClose.d.ts.map +1 -0
- package/dist/tools/accountingClose.js +119 -0
- package/dist/tools/accountingClose.js.map +1 -0
- package/dist/tools/audit_gl.d.ts +19 -0
- package/dist/tools/audit_gl.d.ts.map +1 -0
- package/dist/tools/audit_gl.js +86 -0
- package/dist/tools/audit_gl.js.map +1 -0
- package/dist/tools/bank_rules.d.ts +23 -0
- package/dist/tools/bank_rules.d.ts.map +1 -0
- package/dist/tools/bank_rules.js +96 -0
- package/dist/tools/bank_rules.js.map +1 -0
- package/dist/tools/banking.d.ts +19 -0
- package/dist/tools/banking.d.ts.map +1 -0
- package/dist/tools/banking.js +155 -0
- package/dist/tools/banking.js.map +1 -0
- package/dist/tools/einvoice.d.ts +70 -3
- package/dist/tools/einvoice.d.ts.map +1 -1
- package/dist/tools/einvoice.js +421 -3
- package/dist/tools/einvoice.js.map +1 -1
- package/dist/tools/fiscal.d.ts +23 -0
- package/dist/tools/fiscal.d.ts.map +1 -0
- package/dist/tools/fiscal.js +197 -0
- package/dist/tools/fiscal.js.map +1 -0
- package/dist/tools/gestoria.d.ts +28 -0
- package/dist/tools/gestoria.d.ts.map +1 -0
- package/dist/tools/gestoria.js +248 -0
- package/dist/tools/gestoria.js.map +1 -0
- package/dist/tools/hr.d.ts +24 -0
- package/dist/tools/hr.d.ts.map +1 -0
- package/dist/tools/hr.js +219 -0
- package/dist/tools/hr.js.map +1 -0
- package/dist/tools/igic.d.ts +19 -0
- package/dist/tools/igic.d.ts.map +1 -0
- package/dist/tools/igic.js +102 -0
- package/dist/tools/igic.js.map +1 -0
- package/dist/tools/impuesto_sociedades.d.ts +18 -0
- package/dist/tools/impuesto_sociedades.d.ts.map +1 -0
- package/dist/tools/impuesto_sociedades.js +64 -0
- package/dist/tools/impuesto_sociedades.js.map +1 -0
- package/dist/tools/onboard_vies.d.ts +22 -0
- package/dist/tools/onboard_vies.d.ts.map +1 -0
- package/dist/tools/onboard_vies.js +74 -0
- package/dist/tools/onboard_vies.js.map +1 -0
- package/dist/tools/onboarding.d.ts +19 -0
- package/dist/tools/onboarding.d.ts.map +1 -0
- package/dist/tools/onboarding.js +63 -0
- package/dist/tools/onboarding.js.map +1 -0
- package/dist/tools/payroll.d.ts +20 -0
- package/dist/tools/payroll.d.ts.map +1 -0
- package/dist/tools/payroll.js +73 -0
- package/dist/tools/payroll.js.map +1 -0
- package/dist/tools/permissions.d.ts +19 -0
- package/dist/tools/permissions.d.ts.map +1 -0
- package/dist/tools/permissions.js +52 -0
- package/dist/tools/permissions.js.map +1 -0
- package/dist/tools/portal_domain.d.ts +19 -0
- package/dist/tools/portal_domain.d.ts.map +1 -0
- package/dist/tools/portal_domain.js +85 -0
- package/dist/tools/portal_domain.js.map +1 -0
- package/dist/tools/pos.d.ts +15 -0
- package/dist/tools/pos.d.ts.map +1 -0
- package/dist/tools/pos.js +156 -0
- package/dist/tools/pos.js.map +1 -0
- package/dist/tools/recurring.d.ts +21 -0
- package/dist/tools/recurring.d.ts.map +1 -0
- package/dist/tools/recurring.js +239 -0
- package/dist/tools/recurring.js.map +1 -0
- package/dist/tools/register-all.d.ts +2 -2
- package/dist/tools/register-all.d.ts.map +1 -1
- package/dist/tools/register-all.js +53 -3
- package/dist/tools/register-all.js.map +1 -1
- package/dist/tools/shared.d.ts +481 -0
- package/dist/tools/shared.d.ts.map +1 -1
- package/dist/tools/shared.js +396 -0
- package/dist/tools/shared.js.map +1 -1
- package/dist/tools/stay.d.ts +6 -78
- package/dist/tools/stay.d.ts.map +1 -1
- package/dist/tools/stay.js +121 -343
- package/dist/tools/stay.js.map +1 -1
- package/dist/tools/team.d.ts +17 -0
- package/dist/tools/team.d.ts.map +1 -0
- package/dist/tools/team.js +141 -0
- package/dist/tools/team.js.map +1 -0
- package/dist/tools/time.d.ts +19 -0
- package/dist/tools/time.d.ts.map +1 -0
- package/dist/tools/time.js +179 -0
- package/dist/tools/time.js.map +1 -0
- package/dist/tools/webhooks.d.ts.map +1 -1
- package/dist/tools/webhooks.js +27 -1
- package/dist/tools/webhooks.js.map +1 -1
- package/package.json +12 -5
- package/scripts/audit-mcp-refs.mjs +331 -0
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Period close tools for the Frihet MCP server — D4-B megasprint (3 tools).
|
|
3
|
+
*
|
|
4
|
+
* Tools:
|
|
5
|
+
* 1. period_close_status — get the current accounting period state (open/closing/closed)
|
|
6
|
+
* 2. period_close — close a monthly or quarterly period (TRUST AREA)
|
|
7
|
+
* 3. period_reopen — reopen a closed period with required reason (TRUST AREA)
|
|
8
|
+
*
|
|
9
|
+
* REST surface: /v1/periods/current, /v1/periods/{id}, /v1/periods/close, /v1/periods/{id}/reopen
|
|
10
|
+
*
|
|
11
|
+
* Closing a period freezes invoices/expenses/journal entries. Reopening requires a
|
|
12
|
+
* compliance reason logged for audit. These are TRUST AREA operations.
|
|
13
|
+
*
|
|
14
|
+
* NOTE: ERP backend endpoints land in parallel D4-A wave. 404s propagate as isError
|
|
15
|
+
* until backend ships. TODO: confirm callable boundary vs REST shell for closePeriod.
|
|
16
|
+
*/
|
|
17
|
+
import { z } from "zod/v4";
|
|
18
|
+
import { withToolLogging, formatRecord, getContent, mutateContent, READ_ONLY_ANNOTATIONS, periodStatusOutput, } from "./shared.js";
|
|
19
|
+
export function registerAccountingCloseTools(server, client) {
|
|
20
|
+
// -- period_close_status --
|
|
21
|
+
server.registerTool("period_close_status", {
|
|
22
|
+
title: "Period Close Status",
|
|
23
|
+
description: "Get the current accounting period state (open / closing / closed / reopened). " +
|
|
24
|
+
"Without periodId returns the current open or most recently closed period. " +
|
|
25
|
+
"/ Devuelve el estado del periodo contable actual (abierto/cerrando/cerrado/reabierto).",
|
|
26
|
+
annotations: READ_ONLY_ANNOTATIONS,
|
|
27
|
+
inputSchema: {
|
|
28
|
+
periodId: z.string().optional().describe("Specific period ID (default: current) / ID periodo especifico"),
|
|
29
|
+
},
|
|
30
|
+
outputSchema: periodStatusOutput,
|
|
31
|
+
}, async ({ periodId }) => withToolLogging("period_close_status", async () => {
|
|
32
|
+
const result = await client.getCurrentPeriod({ periodId });
|
|
33
|
+
return {
|
|
34
|
+
content: [getContent(formatRecord("Period status", result))],
|
|
35
|
+
structuredContent: result,
|
|
36
|
+
};
|
|
37
|
+
}));
|
|
38
|
+
// -- period_close --
|
|
39
|
+
server.registerTool("period_close", {
|
|
40
|
+
title: "Close Accounting Period",
|
|
41
|
+
description: "TRUST AREA — FISCAL CLOSE. Close a monthly or quarterly accounting period. " +
|
|
42
|
+
"Freezes invoices, expenses, journal entries and bank reconciliations for the period. " +
|
|
43
|
+
"Requires confirm=true. Idempotent: re-closing an already closed period is a no-op. " +
|
|
44
|
+
"Closed periods can be reopened with period_reopen + audit reason. " +
|
|
45
|
+
"/ AREA DE CONFIANZA — CIERRE FISCAL. Cierra un periodo contable mensual o trimestral. " +
|
|
46
|
+
"Congela facturas, gastos, asientos. Requiere confirm=true.",
|
|
47
|
+
annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: true, openWorldHint: false },
|
|
48
|
+
inputSchema: {
|
|
49
|
+
type: z
|
|
50
|
+
.enum(["monthly", "quarterly"])
|
|
51
|
+
.describe("Period type: monthly or quarterly / Tipo: mensual o trimestral"),
|
|
52
|
+
confirm: z
|
|
53
|
+
.boolean()
|
|
54
|
+
.describe("Must be true to perform the close / Debe ser true para ejecutar el cierre"),
|
|
55
|
+
},
|
|
56
|
+
outputSchema: periodStatusOutput,
|
|
57
|
+
}, async ({ type, confirm }) => withToolLogging("period_close", async () => {
|
|
58
|
+
if (!confirm) {
|
|
59
|
+
return {
|
|
60
|
+
content: [
|
|
61
|
+
{
|
|
62
|
+
type: "text",
|
|
63
|
+
text: "Error: confirm=true is required to close an accounting period. " +
|
|
64
|
+
"This freezes all invoices, expenses, journal entries and bank reconciliations for the period. " +
|
|
65
|
+
"Set confirm=true when you are certain. / " +
|
|
66
|
+
"Se requiere confirm=true para cerrar un periodo contable.",
|
|
67
|
+
},
|
|
68
|
+
],
|
|
69
|
+
isError: true,
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
const result = await client.closePeriod({ type });
|
|
73
|
+
return {
|
|
74
|
+
content: [mutateContent(formatRecord("Period closed", result))],
|
|
75
|
+
structuredContent: result,
|
|
76
|
+
};
|
|
77
|
+
}));
|
|
78
|
+
// -- period_reopen --
|
|
79
|
+
server.registerTool("period_reopen", {
|
|
80
|
+
title: "Reopen Accounting Period",
|
|
81
|
+
description: "TRUST AREA — FISCAL REOPEN. Reopen a closed accounting period. " +
|
|
82
|
+
"Requires a compliance reason (audit log) and confirm=true. " +
|
|
83
|
+
"Reopening allows backdated edits to invoices/expenses — use with extreme caution. " +
|
|
84
|
+
"/ AREA DE CONFIANZA — REAPERTURA FISCAL. Reabre un periodo cerrado. Requiere motivo (auditoria) y confirm=true.",
|
|
85
|
+
annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: false, openWorldHint: false },
|
|
86
|
+
inputSchema: {
|
|
87
|
+
periodId: z.string().describe("Closed period ID to reopen / ID del periodo cerrado"),
|
|
88
|
+
reason: z
|
|
89
|
+
.string()
|
|
90
|
+
.min(1)
|
|
91
|
+
.describe("Required audit reason (logged) / Motivo obligatorio (auditoria)"),
|
|
92
|
+
confirm: z
|
|
93
|
+
.boolean()
|
|
94
|
+
.describe("Must be true to reopen / Debe ser true para reabrir"),
|
|
95
|
+
},
|
|
96
|
+
outputSchema: periodStatusOutput,
|
|
97
|
+
}, async ({ periodId, reason, confirm }) => withToolLogging("period_reopen", async () => {
|
|
98
|
+
if (!confirm) {
|
|
99
|
+
return {
|
|
100
|
+
content: [
|
|
101
|
+
{
|
|
102
|
+
type: "text",
|
|
103
|
+
text: "Error: confirm=true is required to reopen a closed accounting period. " +
|
|
104
|
+
"This allows backdated edits and may affect fiscal reporting. " +
|
|
105
|
+
"Set confirm=true when you are certain. / " +
|
|
106
|
+
"Se requiere confirm=true para reabrir un periodo cerrado.",
|
|
107
|
+
},
|
|
108
|
+
],
|
|
109
|
+
isError: true,
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
const result = await client.reopenPeriod({ periodId, reason });
|
|
113
|
+
return {
|
|
114
|
+
content: [mutateContent(formatRecord("Period reopened", result))],
|
|
115
|
+
structuredContent: result,
|
|
116
|
+
};
|
|
117
|
+
}));
|
|
118
|
+
}
|
|
119
|
+
//# sourceMappingURL=accountingClose.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"accountingClose.js","sourceRoot":"","sources":["../../src/tools/accountingClose.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Audit GL tools for the Frihet MCP server — Day 1 Megasprint (3 tools).
|
|
3
|
+
*
|
|
4
|
+
* Tools:
|
|
5
|
+
* 1. frihet_gl_entry_approve — approve a GL journal entry (TRUST AREA)
|
|
6
|
+
* 2. frihet_gl_entry_reject — reject a GL journal entry with reason (TRUST AREA)
|
|
7
|
+
* 3. frihet_gl_entry_audit_log — retrieve the audit trail for a GL entry
|
|
8
|
+
*
|
|
9
|
+
* REST surface: /v1/gl/* proxies Firebase callables:
|
|
10
|
+
* approveGLEntry, rejectGLEntry, getGLEntryAuditLog (eu-west1)
|
|
11
|
+
*
|
|
12
|
+
* Backend status (post-Day 1 Megasprint, May 2026):
|
|
13
|
+
* Frihet-ERP PR #395 — Audit GL approval workflow MERGED.
|
|
14
|
+
* Tools will surface 404 errors until backend REST shell ships.
|
|
15
|
+
*/
|
|
16
|
+
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
17
|
+
import type { IFrihetClient } from "../client-interface.js";
|
|
18
|
+
export declare function registerAuditGLTools(server: McpServer, client: IFrihetClient): void;
|
|
19
|
+
//# sourceMappingURL=audit_gl.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audit_gl.d.ts","sourceRoot":"","sources":["../../src/tools/audit_gl.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEzE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAU5D,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,aAAa,GAAG,IAAI,CA2FnF"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Audit GL tools for the Frihet MCP server — Day 1 Megasprint (3 tools).
|
|
3
|
+
*
|
|
4
|
+
* Tools:
|
|
5
|
+
* 1. frihet_gl_entry_approve — approve a GL journal entry (TRUST AREA)
|
|
6
|
+
* 2. frihet_gl_entry_reject — reject a GL journal entry with reason (TRUST AREA)
|
|
7
|
+
* 3. frihet_gl_entry_audit_log — retrieve the audit trail for a GL entry
|
|
8
|
+
*
|
|
9
|
+
* REST surface: /v1/gl/* proxies Firebase callables:
|
|
10
|
+
* approveGLEntry, rejectGLEntry, getGLEntryAuditLog (eu-west1)
|
|
11
|
+
*
|
|
12
|
+
* Backend status (post-Day 1 Megasprint, May 2026):
|
|
13
|
+
* Frihet-ERP PR #395 — Audit GL approval workflow MERGED.
|
|
14
|
+
* Tools will surface 404 errors until backend REST shell ships.
|
|
15
|
+
*/
|
|
16
|
+
import { z } from "zod/v4";
|
|
17
|
+
import { withToolLogging, formatRecord, getContent, mutateContent, READ_ONLY_ANNOTATIONS, UPDATE_ANNOTATIONS, } from "./shared.js";
|
|
18
|
+
export function registerAuditGLTools(server, client) {
|
|
19
|
+
// -- frihet_gl_entry_approve -----------------------------------------------
|
|
20
|
+
server.registerTool("frihet_gl_entry_approve", {
|
|
21
|
+
title: "Approve GL Entry",
|
|
22
|
+
description: "Approve a General Ledger journal entry pending review. " +
|
|
23
|
+
"Sets entry status to 'approved' and records the approver + timestamp in the audit trail. " +
|
|
24
|
+
"Requires gestor/admin role. This is a TRUST AREA action — double-check entry ID before calling. " +
|
|
25
|
+
"Example: entryId='gl_2026_q1_042'. " +
|
|
26
|
+
"/ Aprueba un asiento contable pendiente de revision. " +
|
|
27
|
+
"Requiere rol gestor/admin. Accion de area de confianza.",
|
|
28
|
+
annotations: UPDATE_ANNOTATIONS,
|
|
29
|
+
inputSchema: {
|
|
30
|
+
entryId: z.string().describe("GL entry ID to approve / ID del asiento contable a aprobar"),
|
|
31
|
+
notes: z.string().optional().describe("Optional approval notes / Notas de aprobacion opcionales"),
|
|
32
|
+
},
|
|
33
|
+
}, async ({ entryId, notes }) => withToolLogging("frihet_gl_entry_approve", async () => {
|
|
34
|
+
const result = await client.approveGLEntry(entryId, notes);
|
|
35
|
+
return {
|
|
36
|
+
content: [
|
|
37
|
+
mutateContent(formatRecord(`GL Entry ${entryId} approved`, result)),
|
|
38
|
+
],
|
|
39
|
+
structuredContent: result,
|
|
40
|
+
};
|
|
41
|
+
}));
|
|
42
|
+
// -- frihet_gl_entry_reject ------------------------------------------------
|
|
43
|
+
server.registerTool("frihet_gl_entry_reject", {
|
|
44
|
+
title: "Reject GL Entry",
|
|
45
|
+
description: "Reject a General Ledger journal entry pending review with a required reason. " +
|
|
46
|
+
"Sets entry status to 'rejected' and records the rejector + reason in the audit trail. " +
|
|
47
|
+
"Requires gestor/admin role. This is a TRUST AREA action. " +
|
|
48
|
+
"Example: entryId='gl_2026_q1_042', reason='Importe incorrecto, revisar factura F-2026-042'. " +
|
|
49
|
+
"/ Rechaza un asiento contable pendiente con una razon obligatoria. " +
|
|
50
|
+
"Requiere rol gestor/admin.",
|
|
51
|
+
annotations: UPDATE_ANNOTATIONS,
|
|
52
|
+
inputSchema: {
|
|
53
|
+
entryId: z.string().describe("GL entry ID to reject / ID del asiento contable a rechazar"),
|
|
54
|
+
reason: z.string().describe("Mandatory rejection reason (visible to submitter) / Razon del rechazo (obligatoria, visible al emisor)"),
|
|
55
|
+
},
|
|
56
|
+
}, async ({ entryId, reason }) => withToolLogging("frihet_gl_entry_reject", async () => {
|
|
57
|
+
const result = await client.rejectGLEntry(entryId, reason);
|
|
58
|
+
return {
|
|
59
|
+
content: [
|
|
60
|
+
mutateContent(formatRecord(`GL Entry ${entryId} rejected`, result)),
|
|
61
|
+
],
|
|
62
|
+
structuredContent: result,
|
|
63
|
+
};
|
|
64
|
+
}));
|
|
65
|
+
// -- frihet_gl_entry_audit_log ---------------------------------------------
|
|
66
|
+
server.registerTool("frihet_gl_entry_audit_log", {
|
|
67
|
+
title: "Get GL Entry Audit Log",
|
|
68
|
+
description: "Retrieve the full audit trail for a General Ledger entry — all state transitions " +
|
|
69
|
+
"(created, submitted, approved, rejected), who acted, and when. " +
|
|
70
|
+
"Use this to investigate approval history or compliance audits. " +
|
|
71
|
+
"Example: entryId='gl_2026_q1_042'. " +
|
|
72
|
+
"/ Obtiene el historial de auditoría completo de un asiento contable. " +
|
|
73
|
+
"Muestra todas las transiciones de estado, quien actuo y cuando.",
|
|
74
|
+
annotations: READ_ONLY_ANNOTATIONS,
|
|
75
|
+
inputSchema: {
|
|
76
|
+
entryId: z.string().describe("GL entry ID / ID del asiento contable"),
|
|
77
|
+
},
|
|
78
|
+
}, async ({ entryId }) => withToolLogging("frihet_gl_entry_audit_log", async () => {
|
|
79
|
+
const result = await client.getGLEntryAuditLog(entryId);
|
|
80
|
+
return {
|
|
81
|
+
content: [getContent(formatRecord(`Audit Log for GL Entry ${entryId}`, result))],
|
|
82
|
+
structuredContent: result,
|
|
83
|
+
};
|
|
84
|
+
}));
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=audit_gl.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audit_gl.js","sourceRoot":"","sources":["../../src/tools/audit_gl.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bank rules tools for the Frihet MCP server — Day 1 Megasprint (2 tools).
|
|
3
|
+
*
|
|
4
|
+
* Tools:
|
|
5
|
+
* 1. frihet_bank_rules_list — list bank auto-categorization rules for the workspace
|
|
6
|
+
* 2. frihet_bank_rule_create — create a new bank categorization rule
|
|
7
|
+
*
|
|
8
|
+
* Skipped (external webhook handlers, not MCP-callable):
|
|
9
|
+
* - plaidWebhook — Plaid inbound webhook
|
|
10
|
+
* - tinkWebhook — Tink/Revolut inbound webhook
|
|
11
|
+
*
|
|
12
|
+
* REST surface: /v1/banking/rules — admin-side rule management.
|
|
13
|
+
* Backend callables: #394 Banking Q3 flag (Frihet-ERP PR #394).
|
|
14
|
+
* Tools surface 404 until backend callable wrapper ships.
|
|
15
|
+
*
|
|
16
|
+
* NOTE: Bank rules are Q3-flagged in Frihet-ERP. These tools are wired here
|
|
17
|
+
* so AI agents can read + create rules once the backend ships, without an MCP
|
|
18
|
+
* bump. Backend may still be Firestore-direct writes; tools will 404 gracefully.
|
|
19
|
+
*/
|
|
20
|
+
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
21
|
+
import type { IFrihetClient } from "../client-interface.js";
|
|
22
|
+
export declare function registerBankRulesTools(server: McpServer, client: IFrihetClient): void;
|
|
23
|
+
//# sourceMappingURL=bank_rules.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bank_rules.d.ts","sourceRoot":"","sources":["../../src/tools/bank_rules.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEzE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AA+B5D,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,aAAa,GAAG,IAAI,CA2ErF"}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bank rules tools for the Frihet MCP server — Day 1 Megasprint (2 tools).
|
|
3
|
+
*
|
|
4
|
+
* Tools:
|
|
5
|
+
* 1. frihet_bank_rules_list — list bank auto-categorization rules for the workspace
|
|
6
|
+
* 2. frihet_bank_rule_create — create a new bank categorization rule
|
|
7
|
+
*
|
|
8
|
+
* Skipped (external webhook handlers, not MCP-callable):
|
|
9
|
+
* - plaidWebhook — Plaid inbound webhook
|
|
10
|
+
* - tinkWebhook — Tink/Revolut inbound webhook
|
|
11
|
+
*
|
|
12
|
+
* REST surface: /v1/banking/rules — admin-side rule management.
|
|
13
|
+
* Backend callables: #394 Banking Q3 flag (Frihet-ERP PR #394).
|
|
14
|
+
* Tools surface 404 until backend callable wrapper ships.
|
|
15
|
+
*
|
|
16
|
+
* NOTE: Bank rules are Q3-flagged in Frihet-ERP. These tools are wired here
|
|
17
|
+
* so AI agents can read + create rules once the backend ships, without an MCP
|
|
18
|
+
* bump. Backend may still be Firestore-direct writes; tools will 404 gracefully.
|
|
19
|
+
*/
|
|
20
|
+
import { z } from "zod/v4";
|
|
21
|
+
import { withToolLogging, formatPaginatedResponse, formatRecord, listContent, mutateContent, READ_ONLY_ANNOTATIONS, CREATE_ANNOTATIONS, paginatedOutput, } from "./shared.js";
|
|
22
|
+
const bankRuleItemOutput = z.object({
|
|
23
|
+
id: z.string(),
|
|
24
|
+
name: z.string(),
|
|
25
|
+
conditions: z.array(z.object({
|
|
26
|
+
field: z.string(),
|
|
27
|
+
operator: z.string(),
|
|
28
|
+
value: z.string(),
|
|
29
|
+
})).optional(),
|
|
30
|
+
actions: z.array(z.object({
|
|
31
|
+
type: z.string(),
|
|
32
|
+
value: z.string(),
|
|
33
|
+
})).optional(),
|
|
34
|
+
isActive: z.boolean().optional(),
|
|
35
|
+
createdAt: z.string().optional(),
|
|
36
|
+
}).passthrough();
|
|
37
|
+
const CONDITION_FIELD = z.enum(["description", "amount", "counterparty", "iban", "reference"]);
|
|
38
|
+
const CONDITION_OPERATOR = z.enum(["contains", "startsWith", "endsWith", "equals", "greaterThan", "lessThan"]);
|
|
39
|
+
export function registerBankRulesTools(server, client) {
|
|
40
|
+
// -- frihet_bank_rules_list -----------------------------------------------
|
|
41
|
+
server.registerTool("frihet_bank_rules_list", {
|
|
42
|
+
title: "List Bank Categorization Rules",
|
|
43
|
+
description: "List all bank auto-categorization rules for the workspace. " +
|
|
44
|
+
"Rules automatically categorize transactions matching conditions (description, amount, counterparty). " +
|
|
45
|
+
"Returns rule name, conditions, actions (category/tag/client assign), and active status. " +
|
|
46
|
+
"/ Lista las reglas de categorizacion automatica de transacciones bancarias del workspace. " +
|
|
47
|
+
"Devuelve nombre, condiciones, acciones (categoria/etiqueta/cliente) y estado activo.",
|
|
48
|
+
annotations: READ_ONLY_ANNOTATIONS,
|
|
49
|
+
inputSchema: {
|
|
50
|
+
isActive: z.boolean().optional().describe("Filter by active/inactive rules / Filtrar por reglas activas/inactivas"),
|
|
51
|
+
limit: z.number().int().min(1).max(100).optional().describe("Max results / Resultados maximos"),
|
|
52
|
+
offset: z.number().int().min(0).optional().describe("Offset / Desplazamiento"),
|
|
53
|
+
},
|
|
54
|
+
outputSchema: paginatedOutput(bankRuleItemOutput),
|
|
55
|
+
}, async ({ isActive, limit, offset }) => withToolLogging("frihet_bank_rules_list", async () => {
|
|
56
|
+
const result = await client.listBankRules({ isActive, limit, offset });
|
|
57
|
+
return {
|
|
58
|
+
content: [listContent(formatPaginatedResponse("bank_rules", result))],
|
|
59
|
+
structuredContent: result,
|
|
60
|
+
};
|
|
61
|
+
}));
|
|
62
|
+
// -- frihet_bank_rule_create ----------------------------------------------
|
|
63
|
+
server.registerTool("frihet_bank_rule_create", {
|
|
64
|
+
title: "Create Bank Categorization Rule",
|
|
65
|
+
description: "Create a new bank auto-categorization rule. " +
|
|
66
|
+
"Rules apply automatically to matching incoming transactions. " +
|
|
67
|
+
"A rule has conditions (AND logic) and actions (assign category, tag, or client). " +
|
|
68
|
+
"Example: name='Mercadona groceries', condition description contains 'MERCADONA', " +
|
|
69
|
+
"action category='groceries'. " +
|
|
70
|
+
"/ Crea una nueva regla de categorizacion automatica de transacciones bancarias. " +
|
|
71
|
+
"Las reglas aplican condiciones (logica AND) y acciones (categoria, etiqueta, cliente).",
|
|
72
|
+
annotations: CREATE_ANNOTATIONS,
|
|
73
|
+
inputSchema: {
|
|
74
|
+
name: z.string().describe("Rule name for identification / Nombre de la regla"),
|
|
75
|
+
conditions: z.array(z.object({
|
|
76
|
+
field: CONDITION_FIELD.describe("Transaction field to match / Campo de transaccion a comparar"),
|
|
77
|
+
operator: CONDITION_OPERATOR.describe("Comparison operator / Operador de comparacion"),
|
|
78
|
+
value: z.string().describe("Value to match against / Valor a comparar"),
|
|
79
|
+
})).min(1).describe("Rule conditions (AND logic — all must match) / Condiciones (logica AND — todas deben cumplirse)"),
|
|
80
|
+
actions: z.array(z.object({
|
|
81
|
+
type: z.enum(["setCategory", "addTag", "assignClient"]).describe("Action type / Tipo de accion"),
|
|
82
|
+
value: z.string().describe("Action value (category name, tag name, or client ID) / Valor de la accion"),
|
|
83
|
+
})).min(1).describe("Actions to apply when rule matches / Acciones a aplicar cuando la regla se cumple"),
|
|
84
|
+
isActive: z.boolean().optional().describe("Whether the rule is active (default true) / Si la regla esta activa (por defecto true)"),
|
|
85
|
+
},
|
|
86
|
+
}, async ({ name, conditions, actions, isActive }) => withToolLogging("frihet_bank_rule_create", async () => {
|
|
87
|
+
const result = await client.createBankRule({ name, conditions, actions, isActive });
|
|
88
|
+
return {
|
|
89
|
+
content: [
|
|
90
|
+
mutateContent(formatRecord(`Bank rule created: ${name}`, result)),
|
|
91
|
+
],
|
|
92
|
+
structuredContent: result,
|
|
93
|
+
};
|
|
94
|
+
}));
|
|
95
|
+
}
|
|
96
|
+
//# sourceMappingURL=bank_rules.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bank_rules.js","sourceRoot":"","sources":["../../src/tools/bank_rules.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Banking tools for the Frihet MCP server — Wave 6 (5 tools).
|
|
3
|
+
*
|
|
4
|
+
* Tools:
|
|
5
|
+
* 1. list_bank_accounts — list connected bank accounts per workspace
|
|
6
|
+
* 2. get_bank_account — get single account with balance + last sync
|
|
7
|
+
* 3. list_transactions — list bank transactions (filter: account, dateRange, status, category)
|
|
8
|
+
* 4. categorize_transaction — apply category to a transaction (manual classification)
|
|
9
|
+
* 5. match_transaction_to_invoice — link transaction to invoice/expense (reconciliation)
|
|
10
|
+
*
|
|
11
|
+
* REST surface: /v1/banking/accounts, /v1/banking/transactions
|
|
12
|
+
*
|
|
13
|
+
* NOTE: ERP backend endpoints /v1/banking/* are planned. Tools are wired
|
|
14
|
+
* and will surface 404 errors until the backend ships (documented: pending).
|
|
15
|
+
*/
|
|
16
|
+
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
17
|
+
import type { IFrihetClient } from "../client-interface.js";
|
|
18
|
+
export declare function registerBankingTools(server: McpServer, client: IFrihetClient): void;
|
|
19
|
+
//# sourceMappingURL=banking.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"banking.d.ts","sourceRoot":"","sources":["../../src/tools/banking.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEzE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAe5D,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,aAAa,GAAG,IAAI,CA4KnF"}
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Banking tools for the Frihet MCP server — Wave 6 (5 tools).
|
|
3
|
+
*
|
|
4
|
+
* Tools:
|
|
5
|
+
* 1. list_bank_accounts — list connected bank accounts per workspace
|
|
6
|
+
* 2. get_bank_account — get single account with balance + last sync
|
|
7
|
+
* 3. list_transactions — list bank transactions (filter: account, dateRange, status, category)
|
|
8
|
+
* 4. categorize_transaction — apply category to a transaction (manual classification)
|
|
9
|
+
* 5. match_transaction_to_invoice — link transaction to invoice/expense (reconciliation)
|
|
10
|
+
*
|
|
11
|
+
* REST surface: /v1/banking/accounts, /v1/banking/transactions
|
|
12
|
+
*
|
|
13
|
+
* NOTE: ERP backend endpoints /v1/banking/* are planned. Tools are wired
|
|
14
|
+
* and will surface 404 errors until the backend ships (documented: pending).
|
|
15
|
+
*/
|
|
16
|
+
import { z } from "zod/v4";
|
|
17
|
+
import { withToolLogging, formatPaginatedResponse, formatRecord, listContent, getContent, mutateContent, READ_ONLY_ANNOTATIONS, UPDATE_ANNOTATIONS, paginatedOutput, bankAccountItemOutput, bankTransactionItemOutput, } from "./shared.js";
|
|
18
|
+
export function registerBankingTools(server, client) {
|
|
19
|
+
// -- list_bank_accounts --
|
|
20
|
+
server.registerTool("list_bank_accounts", {
|
|
21
|
+
title: "List Bank Accounts",
|
|
22
|
+
description: "List all connected bank accounts for the workspace. " +
|
|
23
|
+
"Returns alias, IBAN (last 4 digits only for security), currency, balance, and last sync timestamp. " +
|
|
24
|
+
"/ Lista todas las cuentas bancarias conectadas al espacio de trabajo. " +
|
|
25
|
+
"Devuelve alias, IBAN (solo ultimos 4 digitos por seguridad), divisa, saldo y ultima sincronizacion.",
|
|
26
|
+
annotations: READ_ONLY_ANNOTATIONS,
|
|
27
|
+
inputSchema: {
|
|
28
|
+
limit: z.number().int().min(1).max(100).optional().describe("Max results (1-100) / Resultados maximos"),
|
|
29
|
+
offset: z.number().int().min(0).optional().describe("Offset / Desplazamiento"),
|
|
30
|
+
},
|
|
31
|
+
outputSchema: paginatedOutput(bankAccountItemOutput),
|
|
32
|
+
}, async ({ limit, offset }) => withToolLogging("list_bank_accounts", async () => {
|
|
33
|
+
const result = await client.listBankAccounts({ limit, offset });
|
|
34
|
+
return {
|
|
35
|
+
content: [listContent(formatPaginatedResponse("bank_accounts", result))],
|
|
36
|
+
structuredContent: result,
|
|
37
|
+
};
|
|
38
|
+
}));
|
|
39
|
+
// -- get_bank_account --
|
|
40
|
+
server.registerTool("get_bank_account", {
|
|
41
|
+
title: "Get Bank Account",
|
|
42
|
+
description: "Get a single connected bank account by ID. " +
|
|
43
|
+
"Returns alias, IBAN (last 4 digits), currency, current balance, and last sync timestamp. " +
|
|
44
|
+
"/ Obtiene una cuenta bancaria conectada por su ID. " +
|
|
45
|
+
"Devuelve alias, IBAN (ultimos 4 digitos), divisa, saldo actual y ultima sincronizacion.",
|
|
46
|
+
annotations: READ_ONLY_ANNOTATIONS,
|
|
47
|
+
inputSchema: {
|
|
48
|
+
id: z.string().describe("Bank account ID / ID de la cuenta bancaria"),
|
|
49
|
+
},
|
|
50
|
+
outputSchema: bankAccountItemOutput,
|
|
51
|
+
}, async ({ id }) => withToolLogging("get_bank_account", async () => {
|
|
52
|
+
const result = await client.getBankAccount(id);
|
|
53
|
+
return {
|
|
54
|
+
content: [getContent(formatRecord("Bank Account", result))],
|
|
55
|
+
structuredContent: result,
|
|
56
|
+
};
|
|
57
|
+
}));
|
|
58
|
+
// -- list_transactions --
|
|
59
|
+
server.registerTool("list_transactions", {
|
|
60
|
+
title: "List Bank Transactions",
|
|
61
|
+
description: "List bank transactions with optional filters. " +
|
|
62
|
+
"Filter by account, date range, status (pending/posted/excluded), or category. " +
|
|
63
|
+
"Useful for reconciliation, expense matching, and cash flow analysis. " +
|
|
64
|
+
"/ Lista movimientos bancarios con filtros opcionales. " +
|
|
65
|
+
"Filtra por cuenta, rango de fechas, estado (pendiente/contabilizado/excluido) o categoria. " +
|
|
66
|
+
"Util para conciliacion, asignacion de gastos y analisis de flujo de caja.",
|
|
67
|
+
annotations: READ_ONLY_ANNOTATIONS,
|
|
68
|
+
inputSchema: {
|
|
69
|
+
accountId: z.string().optional().describe("Filter by bank account ID / Filtrar por ID de cuenta"),
|
|
70
|
+
from: z.string().optional().describe("Start date ISO 8601 (YYYY-MM-DD) / Fecha inicio"),
|
|
71
|
+
to: z.string().optional().describe("End date ISO 8601 (YYYY-MM-DD) / Fecha fin"),
|
|
72
|
+
status: z
|
|
73
|
+
.enum(["pending", "posted", "excluded"])
|
|
74
|
+
.optional()
|
|
75
|
+
.describe("Filter by transaction status / Filtrar por estado"),
|
|
76
|
+
category: z.string().optional().describe("Filter by category slug / Filtrar por categoria"),
|
|
77
|
+
limit: z.number().int().min(1).max(100).optional().describe("Max results (1-100) / Resultados maximos"),
|
|
78
|
+
offset: z.number().int().min(0).optional().describe("Offset / Desplazamiento"),
|
|
79
|
+
after: z.string().optional().describe("Cursor for cursor-based pagination / Cursor para paginacion"),
|
|
80
|
+
},
|
|
81
|
+
outputSchema: paginatedOutput(bankTransactionItemOutput),
|
|
82
|
+
}, async ({ accountId, from, to, status, category, limit, offset, after }) => withToolLogging("list_transactions", async () => {
|
|
83
|
+
const result = await client.listTransactions({ accountId, from, to, status, category, limit, offset, after });
|
|
84
|
+
return {
|
|
85
|
+
content: [listContent(formatPaginatedResponse("transactions", result))],
|
|
86
|
+
structuredContent: result,
|
|
87
|
+
};
|
|
88
|
+
}));
|
|
89
|
+
// -- categorize_transaction --
|
|
90
|
+
server.registerTool("categorize_transaction", {
|
|
91
|
+
title: "Categorize Transaction",
|
|
92
|
+
description: "Apply a category to a bank transaction for manual classification. " +
|
|
93
|
+
"Categories map to expense categories for tax deduction tracking. " +
|
|
94
|
+
"Example: id='tx_abc', category='supplies', notes='Office paper Q1' " +
|
|
95
|
+
"/ Asigna una categoria a un movimiento bancario. " +
|
|
96
|
+
"Las categorias se mapean a categorias de gastos para el control de deducciones fiscales.",
|
|
97
|
+
annotations: UPDATE_ANNOTATIONS,
|
|
98
|
+
inputSchema: {
|
|
99
|
+
id: z.string().describe("Transaction ID / ID del movimiento"),
|
|
100
|
+
category: z.string().describe("Category slug (e.g. 'supplies', 'travel', 'software') / Categoria"),
|
|
101
|
+
notes: z.string().optional().describe("Optional notes for this classification / Notas opcionales"),
|
|
102
|
+
},
|
|
103
|
+
outputSchema: bankTransactionItemOutput,
|
|
104
|
+
}, async ({ id, category, notes }) => withToolLogging("categorize_transaction", async () => {
|
|
105
|
+
const result = await client.categorizeTransaction(id, { category, notes });
|
|
106
|
+
return {
|
|
107
|
+
content: [mutateContent(formatRecord("Transaction categorized", result))],
|
|
108
|
+
structuredContent: result,
|
|
109
|
+
};
|
|
110
|
+
}));
|
|
111
|
+
// -- match_transaction_to_invoice --
|
|
112
|
+
server.registerTool("match_transaction_to_invoice", {
|
|
113
|
+
title: "Match Transaction to Invoice",
|
|
114
|
+
description: "TRUST AREA — RECONCILIATION. Link a bank transaction to an invoice or expense document. " +
|
|
115
|
+
"This affects fiscal reconciliation records. Requires confirm=true to proceed. " +
|
|
116
|
+
"Idempotent: re-matching to same document is a no-op. " +
|
|
117
|
+
"Example: transactionId='tx_abc', documentId='inv_xyz', documentType='invoice', confirm=true " +
|
|
118
|
+
"/ AREA DE CONFIANZA — CONCILIACION. Vincula un movimiento bancario a una factura o gasto. " +
|
|
119
|
+
"Afecta registros de conciliacion fiscal. Requiere confirm=true para ejecutar.",
|
|
120
|
+
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
121
|
+
inputSchema: {
|
|
122
|
+
transactionId: z.string().describe("Bank transaction ID / ID del movimiento bancario"),
|
|
123
|
+
documentId: z.string().describe("Invoice or expense ID to link / ID de la factura o gasto a vincular"),
|
|
124
|
+
documentType: z
|
|
125
|
+
.enum(["invoice", "expense"])
|
|
126
|
+
.describe("Type of document being matched / Tipo de documento"),
|
|
127
|
+
confirm: z
|
|
128
|
+
.boolean()
|
|
129
|
+
.describe("Must be true to confirm fiscal reconciliation / Debe ser true para confirmar conciliacion fiscal"),
|
|
130
|
+
notes: z.string().optional().describe("Optional reconciliation notes / Notas de conciliacion opcionales"),
|
|
131
|
+
},
|
|
132
|
+
outputSchema: bankTransactionItemOutput,
|
|
133
|
+
}, async ({ transactionId, documentId, documentType, confirm, notes }) => withToolLogging("match_transaction_to_invoice", async () => {
|
|
134
|
+
if (!confirm) {
|
|
135
|
+
return {
|
|
136
|
+
content: [
|
|
137
|
+
{
|
|
138
|
+
type: "text",
|
|
139
|
+
text: "Error: confirm=true is required to perform fiscal reconciliation. " +
|
|
140
|
+
"This action links a bank transaction to a fiscal document and cannot be undone easily. " +
|
|
141
|
+
"Set confirm=true when you are certain about the match. / " +
|
|
142
|
+
"Se requiere confirm=true para realizar la conciliacion fiscal.",
|
|
143
|
+
},
|
|
144
|
+
],
|
|
145
|
+
isError: true,
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
const result = await client.matchTransactionToDocument(transactionId, { documentId, documentType, notes });
|
|
149
|
+
return {
|
|
150
|
+
content: [mutateContent(formatRecord("Transaction matched", result))],
|
|
151
|
+
structuredContent: result,
|
|
152
|
+
};
|
|
153
|
+
}));
|
|
154
|
+
}
|
|
155
|
+
//# sourceMappingURL=banking.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"banking.js","sourceRoot":"","sources":["../../src/tools/banking.ts"],"names":[],"mappings":"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"}
|