@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,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Onboarding tools for the Frihet MCP server — D4-B megasprint (2 tools).
|
|
3
|
+
*
|
|
4
|
+
* Tools:
|
|
5
|
+
* 1. onboarding_status — current workspace onboarding state (completed/pending steps)
|
|
6
|
+
* 2. onboarding_persona_set — set workspace persona (autonomo/empresa/agencia/gestoria)
|
|
7
|
+
*
|
|
8
|
+
* REST surface: /v1/onboarding/status, /v1/onboarding/persona
|
|
9
|
+
*
|
|
10
|
+
* Persona drives module visibility + default chart-of-accounts + onboarding checklist.
|
|
11
|
+
* Persona can only be set once during onboarding; later changes require workspace admin.
|
|
12
|
+
*
|
|
13
|
+
* NOTE: ERP backend endpoints land in parallel D4-A wave. 404s propagate as isError
|
|
14
|
+
* until backend ships.
|
|
15
|
+
*/
|
|
16
|
+
import { z } from "zod/v4";
|
|
17
|
+
import { withToolLogging, formatRecord, getContent, mutateContent, READ_ONLY_ANNOTATIONS, UPDATE_ANNOTATIONS, onboardingStatusOutput, onboardingPersonaResultOutput, } from "./shared.js";
|
|
18
|
+
export function registerOnboardingTools(server, client) {
|
|
19
|
+
// -- onboarding_status --
|
|
20
|
+
server.registerTool("onboarding_status", {
|
|
21
|
+
title: "Onboarding Status",
|
|
22
|
+
description: "Return the current workspace onboarding state — persona, completed steps, pending steps, " +
|
|
23
|
+
"percent complete. Useful to drive in-app guidance, sales follow-up triggers, " +
|
|
24
|
+
"and partner program tracking. " +
|
|
25
|
+
"/ Devuelve el estado actual del onboarding del workspace (persona, pasos completados/pendientes).",
|
|
26
|
+
annotations: READ_ONLY_ANNOTATIONS,
|
|
27
|
+
inputSchema: {},
|
|
28
|
+
outputSchema: onboardingStatusOutput,
|
|
29
|
+
}, async () => withToolLogging("onboarding_status", async () => {
|
|
30
|
+
const result = await client.getOnboardingStatus();
|
|
31
|
+
return {
|
|
32
|
+
content: [getContent(formatRecord("Onboarding status", result))],
|
|
33
|
+
structuredContent: result,
|
|
34
|
+
};
|
|
35
|
+
}));
|
|
36
|
+
// -- onboarding_persona_set --
|
|
37
|
+
server.registerTool("onboarding_persona_set", {
|
|
38
|
+
title: "Set Onboarding Persona",
|
|
39
|
+
description: "Set the workspace persona. Drives module visibility, default chart-of-accounts, " +
|
|
40
|
+
"and onboarding checklist. Personas:\n" +
|
|
41
|
+
" - 'autonomo' — self-employed (autonomo Spain)\n" +
|
|
42
|
+
" - 'empresa' — small/medium business\n" +
|
|
43
|
+
" - 'agencia' — agency / consultancy\n" +
|
|
44
|
+
" - 'gestoria' — accounting firm (manages multiple client workspaces)\n" +
|
|
45
|
+
"\n" +
|
|
46
|
+
"Idempotent: setting the same persona again is a no-op. " +
|
|
47
|
+
"/ Define la persona del workspace. Determina modulos visibles, plan contable y checklist.",
|
|
48
|
+
annotations: UPDATE_ANNOTATIONS,
|
|
49
|
+
inputSchema: {
|
|
50
|
+
persona: z
|
|
51
|
+
.enum(["autonomo", "empresa", "agencia", "gestoria"])
|
|
52
|
+
.describe("Workspace persona / Persona del workspace"),
|
|
53
|
+
},
|
|
54
|
+
outputSchema: onboardingPersonaResultOutput,
|
|
55
|
+
}, async ({ persona }) => withToolLogging("onboarding_persona_set", async () => {
|
|
56
|
+
const result = await client.setOnboardingPersona({ persona });
|
|
57
|
+
return {
|
|
58
|
+
content: [mutateContent(formatRecord("Persona set", result))],
|
|
59
|
+
structuredContent: result,
|
|
60
|
+
};
|
|
61
|
+
}));
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=onboarding.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"onboarding.js","sourceRoot":"","sources":["../../src/tools/onboarding.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAGH,OAAO,EAAE,CAAC,EAAE,MAAM,QAAQ,CAAC;AAE3B,OAAO,EACL,eAAe,EACf,YAAY,EACZ,UAAU,EACV,aAAa,EACb,qBAAqB,EACrB,kBAAkB,EAClB,sBAAsB,EACtB,6BAA6B,GAC9B,MAAM,aAAa,CAAC;AAErB,MAAM,UAAU,uBAAuB,CAAC,MAAiB,EAAE,MAAqB;IAC9E,0BAA0B;IAE1B,MAAM,CAAC,YAAY,CACjB,mBAAmB,EACnB;QACE,KAAK,EAAE,mBAAmB;QAC1B,WAAW,EACT,2FAA2F;YAC3F,+EAA+E;YAC/E,gCAAgC;YAChC,mGAAmG;QACrG,WAAW,EAAE,qBAAqB;QAClC,WAAW,EAAE,EAAE;QACf,YAAY,EAAE,sBAAsB;KACrC,EACD,KAAK,IAAI,EAAE,CAAC,eAAe,CAAC,mBAAmB,EAAE,KAAK,IAAI,EAAE;QAC1D,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,mBAAmB,EAAE,CAAC;QAClD,OAAO;YACL,OAAO,EAAE,CAAC,UAAU,CAAC,YAAY,CAAC,mBAAmB,EAAE,MAAM,CAAC,CAAC,CAAC;YAChE,iBAAiB,EAAE,MAA4C;SAChE,CAAC;IACJ,CAAC,CAAC,CACH,CAAC;IAEF,+BAA+B;IAE/B,MAAM,CAAC,YAAY,CACjB,wBAAwB,EACxB;QACE,KAAK,EAAE,wBAAwB;QAC/B,WAAW,EACT,kFAAkF;YAClF,uCAAuC;YACvC,mDAAmD;YACnD,0CAA0C;YAC1C,yCAAyC;YACzC,yEAAyE;YACzE,IAAI;YACJ,yDAAyD;YACzD,2FAA2F;QAC7F,WAAW,EAAE,kBAAkB;QAC/B,WAAW,EAAE;YACX,OAAO,EAAE,CAAC;iBACP,IAAI,CAAC,CAAC,UAAU,EAAE,SAAS,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC;iBACpD,QAAQ,CAAC,2CAA2C,CAAC;SACzD;QACD,YAAY,EAAE,6BAA6B;KAC5C,EACD,KAAK,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,eAAe,CAAC,wBAAwB,EAAE,KAAK,IAAI,EAAE;QAC1E,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,oBAAoB,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC;QAC9D,OAAO;YACL,OAAO,EAAE,CAAC,aAAa,CAAC,YAAY,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC,CAAC;YAC7D,iBAAiB,EAAE,MAA4C;SAChE,CAAC;IACJ,CAAC,CAAC,CACH,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Payroll preparation tools for the Frihet MCP server — D4-B megasprint (2 tools).
|
|
3
|
+
*
|
|
4
|
+
* Tools:
|
|
5
|
+
* 1. payroll_export — export payroll for a month in gestoria format (A3, Contasol, Sage, Holded, Siltra)
|
|
6
|
+
* 2. payroll_checklist — list employees with status (ready / missing_data / blocked) for a month
|
|
7
|
+
*
|
|
8
|
+
* REST surface: /v1/payroll/prep/export, /v1/payroll/prep/employees
|
|
9
|
+
*
|
|
10
|
+
* Frihet does NOT process payroll. It exports to gestoria-compatible formats so
|
|
11
|
+
* the asesoria handles SS/IRPF/contracts. Output formats track the most common
|
|
12
|
+
* Spanish payroll software clusters.
|
|
13
|
+
*
|
|
14
|
+
* NOTE: ERP backend endpoints land in parallel D4-A wave. 404s propagate as isError
|
|
15
|
+
* until backend ships. TODO: confirm A3 columns + SILTRA file extension.
|
|
16
|
+
*/
|
|
17
|
+
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
18
|
+
import type { IFrihetClient } from "../client-interface.js";
|
|
19
|
+
export declare function registerPayrollTools(server: McpServer, client: IFrihetClient): void;
|
|
20
|
+
//# sourceMappingURL=payroll.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"payroll.d.ts","sourceRoot":"","sources":["../../src/tools/payroll.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;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,CAkEnF"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Payroll preparation tools for the Frihet MCP server — D4-B megasprint (2 tools).
|
|
3
|
+
*
|
|
4
|
+
* Tools:
|
|
5
|
+
* 1. payroll_export — export payroll for a month in gestoria format (A3, Contasol, Sage, Holded, Siltra)
|
|
6
|
+
* 2. payroll_checklist — list employees with status (ready / missing_data / blocked) for a month
|
|
7
|
+
*
|
|
8
|
+
* REST surface: /v1/payroll/prep/export, /v1/payroll/prep/employees
|
|
9
|
+
*
|
|
10
|
+
* Frihet does NOT process payroll. It exports to gestoria-compatible formats so
|
|
11
|
+
* the asesoria handles SS/IRPF/contracts. Output formats track the most common
|
|
12
|
+
* Spanish payroll software clusters.
|
|
13
|
+
*
|
|
14
|
+
* NOTE: ERP backend endpoints land in parallel D4-A wave. 404s propagate as isError
|
|
15
|
+
* until backend ships. TODO: confirm A3 columns + SILTRA file extension.
|
|
16
|
+
*/
|
|
17
|
+
import { z } from "zod/v4";
|
|
18
|
+
import { withToolLogging, formatRecord, getContent, READ_ONLY_ANNOTATIONS, payrollExportOutput, payrollChecklistOutput, } from "./shared.js";
|
|
19
|
+
export function registerPayrollTools(server, client) {
|
|
20
|
+
// -- payroll_export --
|
|
21
|
+
server.registerTool("payroll_export", {
|
|
22
|
+
title: "Export Payroll (Gestoria Format)",
|
|
23
|
+
description: "Export payroll data for a month in gestoria-compatible format. " +
|
|
24
|
+
"Supported formats:\n" +
|
|
25
|
+
" - 'a3' — Wolters Kluwer A3 (CSV with Spanish payroll columns)\n" +
|
|
26
|
+
" - 'contasol' — Sage Contasol\n" +
|
|
27
|
+
" - 'sage' — Sage 50/200\n" +
|
|
28
|
+
" - 'holded' — Holded import format\n" +
|
|
29
|
+
" - 'siltra' — SILTRA Seguridad Social XML\n" +
|
|
30
|
+
"\n" +
|
|
31
|
+
"Frihet does NOT calculate payroll — it exports staged data for the gestoria. " +
|
|
32
|
+
"Month format: 'YYYY-MM'. " +
|
|
33
|
+
"/ Exporta datos de nominas en formato compatible con gestoria. Mes en formato 'YYYY-MM'.",
|
|
34
|
+
annotations: READ_ONLY_ANNOTATIONS,
|
|
35
|
+
inputSchema: {
|
|
36
|
+
format: z
|
|
37
|
+
.enum(["a3", "contasol", "sage", "holded", "siltra"])
|
|
38
|
+
.describe("Gestoria payroll software format / Formato del software de gestoria"),
|
|
39
|
+
month: z.string().regex(/^\d{4}-\d{2}$/).describe("Month in 'YYYY-MM' format / Mes formato 'YYYY-MM'"),
|
|
40
|
+
},
|
|
41
|
+
outputSchema: payrollExportOutput,
|
|
42
|
+
}, async ({ format, month }) => withToolLogging("payroll_export", async () => {
|
|
43
|
+
const result = await client.exportPayroll({ format, month });
|
|
44
|
+
return {
|
|
45
|
+
content: [getContent(formatRecord("Payroll export", result))],
|
|
46
|
+
structuredContent: result,
|
|
47
|
+
};
|
|
48
|
+
}));
|
|
49
|
+
// -- payroll_checklist --
|
|
50
|
+
server.registerTool("payroll_checklist", {
|
|
51
|
+
title: "Payroll Readiness Checklist",
|
|
52
|
+
description: "List all employees for a given month with their payroll readiness status. " +
|
|
53
|
+
"Status values:\n" +
|
|
54
|
+
" - 'ready' — all required data present, ready to export\n" +
|
|
55
|
+
" - 'missing_data' — some required fields missing (see missingFields[])\n" +
|
|
56
|
+
" - 'blocked' — manually blocked or data inconsistency detected\n" +
|
|
57
|
+
"\n" +
|
|
58
|
+
"Use BEFORE payroll_export to identify gaps. Month format: 'YYYY-MM'. " +
|
|
59
|
+
"/ Lista empleados con estado de preparacion para nomina. Usar antes de payroll_export.",
|
|
60
|
+
annotations: READ_ONLY_ANNOTATIONS,
|
|
61
|
+
inputSchema: {
|
|
62
|
+
month: z.string().regex(/^\d{4}-\d{2}$/).describe("Month in 'YYYY-MM' format / Mes formato 'YYYY-MM'"),
|
|
63
|
+
},
|
|
64
|
+
outputSchema: payrollChecklistOutput,
|
|
65
|
+
}, async ({ month }) => withToolLogging("payroll_checklist", async () => {
|
|
66
|
+
const result = await client.getPayrollChecklist({ month });
|
|
67
|
+
return {
|
|
68
|
+
content: [getContent(formatRecord("Payroll checklist", result))],
|
|
69
|
+
structuredContent: result,
|
|
70
|
+
};
|
|
71
|
+
}));
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=payroll.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"payroll.js","sourceRoot":"","sources":["../../src/tools/payroll.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAGH,OAAO,EAAE,CAAC,EAAE,MAAM,QAAQ,CAAC;AAE3B,OAAO,EACL,eAAe,EACf,YAAY,EACZ,UAAU,EACV,qBAAqB,EACrB,mBAAmB,EACnB,sBAAsB,GACvB,MAAM,aAAa,CAAC;AAErB,MAAM,UAAU,oBAAoB,CAAC,MAAiB,EAAE,MAAqB;IAC3E,uBAAuB;IAEvB,MAAM,CAAC,YAAY,CACjB,gBAAgB,EAChB;QACE,KAAK,EAAE,kCAAkC;QACzC,WAAW,EACT,iEAAiE;YACjE,sBAAsB;YACtB,yEAAyE;YACzE,kCAAkC;YAClC,gCAAgC;YAChC,yCAAyC;YACzC,gDAAgD;YAChD,IAAI;YACJ,+EAA+E;YAC/E,2BAA2B;YAC3B,0FAA0F;QAC5F,WAAW,EAAE,qBAAqB;QAClC,WAAW,EAAE;YACX,MAAM,EAAE,CAAC;iBACN,IAAI,CAAC,CAAC,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC;iBACpD,QAAQ,CAAC,qEAAqE,CAAC;YAClF,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC,QAAQ,CAAC,mDAAmD,CAAC;SACvG;QACD,YAAY,EAAE,mBAAmB;KAClC,EACD,KAAK,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,eAAe,CAAC,gBAAgB,EAAE,KAAK,IAAI,EAAE;QACxE,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;QAC7D,OAAO;YACL,OAAO,EAAE,CAAC,UAAU,CAAC,YAAY,CAAC,gBAAgB,EAAE,MAAM,CAAC,CAAC,CAAC;YAC7D,iBAAiB,EAAE,MAA4C;SAChE,CAAC;IACJ,CAAC,CAAC,CACH,CAAC;IAEF,0BAA0B;IAE1B,MAAM,CAAC,YAAY,CACjB,mBAAmB,EACnB;QACE,KAAK,EAAE,6BAA6B;QACpC,WAAW,EACT,4EAA4E;YAC5E,kBAAkB;YAClB,oEAAoE;YACpE,4EAA4E;YAC5E,yEAAyE;YACzE,IAAI;YACJ,uEAAuE;YACvE,wFAAwF;QAC1F,WAAW,EAAE,qBAAqB;QAClC,WAAW,EAAE;YACX,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC,QAAQ,CAAC,mDAAmD,CAAC;SACvG;QACD,YAAY,EAAE,sBAAsB;KACrC,EACD,KAAK,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,eAAe,CAAC,mBAAmB,EAAE,KAAK,IAAI,EAAE;QACnE,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,mBAAmB,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;QAC3D,OAAO;YACL,OAAO,EAAE,CAAC,UAAU,CAAC,YAAY,CAAC,mBAAmB,EAAE,MAAM,CAAC,CAAC,CAAC;YAChE,iBAAiB,EAAE,MAA4C;SAChE,CAAC;IACJ,CAAC,CAAC,CACH,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Permissions tools for the Frihet MCP server — D4-B megasprint (2 tools).
|
|
3
|
+
*
|
|
4
|
+
* Tools:
|
|
5
|
+
* 1. permissions_matrix — full role/permission matrix for the workspace
|
|
6
|
+
* 2. permissions_me — caller's own role + permissions
|
|
7
|
+
*
|
|
8
|
+
* REST surface: /v1/permissions/matrix, /v1/permissions/me
|
|
9
|
+
*
|
|
10
|
+
* Permissions are derived from role + workspace overrides. Tools are read-only —
|
|
11
|
+
* mutating roles is done via team_invite / team_role_update (existing).
|
|
12
|
+
*
|
|
13
|
+
* NOTE: ERP backend endpoints land in parallel D4-A wave. 404s propagate as isError
|
|
14
|
+
* until backend ships.
|
|
15
|
+
*/
|
|
16
|
+
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
17
|
+
import type { IFrihetClient } from "../client-interface.js";
|
|
18
|
+
export declare function registerPermissionsTools(server: McpServer, client: IFrihetClient): void;
|
|
19
|
+
//# sourceMappingURL=permissions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"permissions.d.ts","sourceRoot":"","sources":["../../src/tools/permissions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAU5D,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,aAAa,GAAG,IAAI,CA+CvF"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Permissions tools for the Frihet MCP server — D4-B megasprint (2 tools).
|
|
3
|
+
*
|
|
4
|
+
* Tools:
|
|
5
|
+
* 1. permissions_matrix — full role/permission matrix for the workspace
|
|
6
|
+
* 2. permissions_me — caller's own role + permissions
|
|
7
|
+
*
|
|
8
|
+
* REST surface: /v1/permissions/matrix, /v1/permissions/me
|
|
9
|
+
*
|
|
10
|
+
* Permissions are derived from role + workspace overrides. Tools are read-only —
|
|
11
|
+
* mutating roles is done via team_invite / team_role_update (existing).
|
|
12
|
+
*
|
|
13
|
+
* NOTE: ERP backend endpoints land in parallel D4-A wave. 404s propagate as isError
|
|
14
|
+
* until backend ships.
|
|
15
|
+
*/
|
|
16
|
+
import { withToolLogging, formatRecord, getContent, READ_ONLY_ANNOTATIONS, permissionsMatrixOutput, permissionsMeOutput, } from "./shared.js";
|
|
17
|
+
export function registerPermissionsTools(server, client) {
|
|
18
|
+
// -- permissions_matrix --
|
|
19
|
+
server.registerTool("permissions_matrix", {
|
|
20
|
+
title: "Permissions Matrix",
|
|
21
|
+
description: "Return the full role-to-permission matrix for the workspace. " +
|
|
22
|
+
"Lists every role with the permissions it grants and every protected resource. " +
|
|
23
|
+
"Useful for security audits, role design, and compliance reporting. " +
|
|
24
|
+
"/ Devuelve la matriz completa de roles y permisos del workspace.",
|
|
25
|
+
annotations: READ_ONLY_ANNOTATIONS,
|
|
26
|
+
inputSchema: {},
|
|
27
|
+
outputSchema: permissionsMatrixOutput,
|
|
28
|
+
}, async () => withToolLogging("permissions_matrix", async () => {
|
|
29
|
+
const result = await client.getPermissionsMatrix();
|
|
30
|
+
return {
|
|
31
|
+
content: [getContent(formatRecord("Permissions matrix", result))],
|
|
32
|
+
structuredContent: result,
|
|
33
|
+
};
|
|
34
|
+
}));
|
|
35
|
+
// -- permissions_me --
|
|
36
|
+
server.registerTool("permissions_me", {
|
|
37
|
+
title: "My Permissions",
|
|
38
|
+
description: "Return the caller's effective role + permissions in the current workspace. " +
|
|
39
|
+
"Useful for client-side UI gating, debugging access errors, and capability discovery. " +
|
|
40
|
+
"/ Devuelve el rol efectivo y los permisos del llamante en el workspace actual.",
|
|
41
|
+
annotations: READ_ONLY_ANNOTATIONS,
|
|
42
|
+
inputSchema: {},
|
|
43
|
+
outputSchema: permissionsMeOutput,
|
|
44
|
+
}, async () => withToolLogging("permissions_me", async () => {
|
|
45
|
+
const result = await client.getMyPermissions();
|
|
46
|
+
return {
|
|
47
|
+
content: [getContent(formatRecord("My permissions", result))],
|
|
48
|
+
structuredContent: result,
|
|
49
|
+
};
|
|
50
|
+
}));
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=permissions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"permissions.js","sourceRoot":"","sources":["../../src/tools/permissions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAIH,OAAO,EACL,eAAe,EACf,YAAY,EACZ,UAAU,EACV,qBAAqB,EACrB,uBAAuB,EACvB,mBAAmB,GACpB,MAAM,aAAa,CAAC;AAErB,MAAM,UAAU,wBAAwB,CAAC,MAAiB,EAAE,MAAqB;IAC/E,2BAA2B;IAE3B,MAAM,CAAC,YAAY,CACjB,oBAAoB,EACpB;QACE,KAAK,EAAE,oBAAoB;QAC3B,WAAW,EACT,+DAA+D;YAC/D,gFAAgF;YAChF,qEAAqE;YACrE,kEAAkE;QACpE,WAAW,EAAE,qBAAqB;QAClC,WAAW,EAAE,EAAE;QACf,YAAY,EAAE,uBAAuB;KACtC,EACD,KAAK,IAAI,EAAE,CAAC,eAAe,CAAC,oBAAoB,EAAE,KAAK,IAAI,EAAE;QAC3D,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,oBAAoB,EAAE,CAAC;QACnD,OAAO;YACL,OAAO,EAAE,CAAC,UAAU,CAAC,YAAY,CAAC,oBAAoB,EAAE,MAAM,CAAC,CAAC,CAAC;YACjE,iBAAiB,EAAE,MAA4C;SAChE,CAAC;IACJ,CAAC,CAAC,CACH,CAAC;IAEF,uBAAuB;IAEvB,MAAM,CAAC,YAAY,CACjB,gBAAgB,EAChB;QACE,KAAK,EAAE,gBAAgB;QACvB,WAAW,EACT,6EAA6E;YAC7E,uFAAuF;YACvF,gFAAgF;QAClF,WAAW,EAAE,qBAAqB;QAClC,WAAW,EAAE,EAAE;QACf,YAAY,EAAE,mBAAmB;KAClC,EACD,KAAK,IAAI,EAAE,CAAC,eAAe,CAAC,gBAAgB,EAAE,KAAK,IAAI,EAAE;QACvD,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,gBAAgB,EAAE,CAAC;QAC/C,OAAO;YACL,OAAO,EAAE,CAAC,UAAU,CAAC,YAAY,CAAC,gBAAgB,EAAE,MAAM,CAAC,CAAC,CAAC;YAC7D,iBAAiB,EAAE,MAA4C;SAChE,CAAC;IACJ,CAAC,CAAC,CACH,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* White-label portal domain tools for the Frihet MCP server — Day 1 Megasprint (3 tools).
|
|
3
|
+
*
|
|
4
|
+
* Tools:
|
|
5
|
+
* 1. frihet_portal_domain_add — add a custom domain to the client portal
|
|
6
|
+
* 2. frihet_portal_domain_verify — verify DNS propagation for a custom domain
|
|
7
|
+
* 3. frihet_portal_domain_remove — remove a custom portal domain
|
|
8
|
+
*
|
|
9
|
+
* REST surface: /v1/portal/domain/* proxies Firebase callables:
|
|
10
|
+
* addCustomPortalDomain, verifyCustomPortalDomain, removeCustomPortalDomain (eu-west1)
|
|
11
|
+
*
|
|
12
|
+
* Backend status (post-Day 1 Megasprint, May 2026):
|
|
13
|
+
* Frihet-ERP PR #397 — White-label portal domain 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 registerPortalDomainTools(server: McpServer, client: IFrihetClient): void;
|
|
19
|
+
//# sourceMappingURL=portal_domain.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"portal_domain.d.ts","sourceRoot":"","sources":["../../src/tools/portal_domain.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEzE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAW5D,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,aAAa,GAAG,IAAI,CA0FxF"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* White-label portal domain tools for the Frihet MCP server — Day 1 Megasprint (3 tools).
|
|
3
|
+
*
|
|
4
|
+
* Tools:
|
|
5
|
+
* 1. frihet_portal_domain_add — add a custom domain to the client portal
|
|
6
|
+
* 2. frihet_portal_domain_verify — verify DNS propagation for a custom domain
|
|
7
|
+
* 3. frihet_portal_domain_remove — remove a custom portal domain
|
|
8
|
+
*
|
|
9
|
+
* REST surface: /v1/portal/domain/* proxies Firebase callables:
|
|
10
|
+
* addCustomPortalDomain, verifyCustomPortalDomain, removeCustomPortalDomain (eu-west1)
|
|
11
|
+
*
|
|
12
|
+
* Backend status (post-Day 1 Megasprint, May 2026):
|
|
13
|
+
* Frihet-ERP PR #397 — White-label portal domain 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, CREATE_ANNOTATIONS, DELETE_ANNOTATIONS, } from "./shared.js";
|
|
18
|
+
export function registerPortalDomainTools(server, client) {
|
|
19
|
+
// -- frihet_portal_domain_add ---------------------------------------------
|
|
20
|
+
server.registerTool("frihet_portal_domain_add", {
|
|
21
|
+
title: "Add Custom Portal Domain",
|
|
22
|
+
description: "Add a custom domain to the Frihet client portal for white-label branding. " +
|
|
23
|
+
"Returns DNS records (CNAME) that must be configured at the registrar before verification. " +
|
|
24
|
+
"Example: domain='portal.miempresa.com'. " +
|
|
25
|
+
"/ Agrega un dominio personalizado al portal de clientes Frihet para marca blanca. " +
|
|
26
|
+
"Devuelve los registros DNS (CNAME) que deben configurarse en el registrador antes de verificar.",
|
|
27
|
+
annotations: CREATE_ANNOTATIONS,
|
|
28
|
+
inputSchema: {
|
|
29
|
+
domain: z.string().describe("Custom domain to add (e.g. 'portal.miempresa.com') / Dominio personalizado (ej. 'portal.miempresa.com')"),
|
|
30
|
+
workspaceId: z.string().optional().describe("Target workspace ID (defaults to caller's workspace) / ID del workspace destino"),
|
|
31
|
+
},
|
|
32
|
+
}, async ({ domain, workspaceId }) => withToolLogging("frihet_portal_domain_add", async () => {
|
|
33
|
+
const result = await client.addCustomPortalDomain({ domain, workspaceId });
|
|
34
|
+
return {
|
|
35
|
+
content: [
|
|
36
|
+
mutateContent(formatRecord(`Custom portal domain added: ${domain}`, result) +
|
|
37
|
+
"\n\nNext step: Configure the returned CNAME record at your DNS registrar, then call frihet_portal_domain_verify." +
|
|
38
|
+
"\nSiguiente paso: Configura el registro CNAME en tu registrador DNS, luego llama a frihet_portal_domain_verify."),
|
|
39
|
+
],
|
|
40
|
+
structuredContent: result,
|
|
41
|
+
};
|
|
42
|
+
}));
|
|
43
|
+
// -- frihet_portal_domain_verify ------------------------------------------
|
|
44
|
+
server.registerTool("frihet_portal_domain_verify", {
|
|
45
|
+
title: "Verify Custom Portal Domain",
|
|
46
|
+
description: "Verify DNS propagation for a custom portal domain added via frihet_portal_domain_add. " +
|
|
47
|
+
"Returns verification status (pending/verified/failed) and any DNS errors. " +
|
|
48
|
+
"DNS propagation can take up to 48 hours — retry if status is 'pending'. " +
|
|
49
|
+
"Example: domain='portal.miempresa.com'. " +
|
|
50
|
+
"/ Verifica la propagacion DNS de un dominio de portal personalizado. " +
|
|
51
|
+
"Devuelve estado (pending/verified/failed). La propagacion puede tardar hasta 48h.",
|
|
52
|
+
annotations: READ_ONLY_ANNOTATIONS,
|
|
53
|
+
inputSchema: {
|
|
54
|
+
domain: z.string().describe("Custom domain to verify / Dominio personalizado a verificar"),
|
|
55
|
+
},
|
|
56
|
+
}, async ({ domain }) => withToolLogging("frihet_portal_domain_verify", async () => {
|
|
57
|
+
const result = await client.verifyCustomPortalDomain({ domain });
|
|
58
|
+
return {
|
|
59
|
+
content: [getContent(formatRecord(`Domain verification status: ${domain}`, result))],
|
|
60
|
+
structuredContent: result,
|
|
61
|
+
};
|
|
62
|
+
}));
|
|
63
|
+
// -- frihet_portal_domain_remove ------------------------------------------
|
|
64
|
+
server.registerTool("frihet_portal_domain_remove", {
|
|
65
|
+
title: "Remove Custom Portal Domain",
|
|
66
|
+
description: "Remove a custom domain from the Frihet client portal. " +
|
|
67
|
+
"The portal will revert to the default Frihet subdomain. " +
|
|
68
|
+
"Example: domain='portal.miempresa.com'. " +
|
|
69
|
+
"/ Elimina un dominio personalizado del portal de clientes Frihet. " +
|
|
70
|
+
"El portal volverá al subdominio predeterminado de Frihet.",
|
|
71
|
+
annotations: DELETE_ANNOTATIONS,
|
|
72
|
+
inputSchema: {
|
|
73
|
+
domain: z.string().describe("Custom domain to remove / Dominio personalizado a eliminar"),
|
|
74
|
+
},
|
|
75
|
+
}, async ({ domain }) => withToolLogging("frihet_portal_domain_remove", async () => {
|
|
76
|
+
const result = await client.removeCustomPortalDomain({ domain });
|
|
77
|
+
return {
|
|
78
|
+
content: [
|
|
79
|
+
mutateContent(formatRecord(`Custom portal domain removed: ${domain}`, result)),
|
|
80
|
+
],
|
|
81
|
+
structuredContent: result,
|
|
82
|
+
};
|
|
83
|
+
}));
|
|
84
|
+
}
|
|
85
|
+
//# sourceMappingURL=portal_domain.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"portal_domain.js","sourceRoot":"","sources":["../../src/tools/portal_domain.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* POS (Point of Sale) tools for the Frihet MCP server.
|
|
3
|
+
*
|
|
4
|
+
* Wave 5 — 4 tools for point-of-sale management:
|
|
5
|
+
* list_terminals, get_sale, list_sales, refund_sale
|
|
6
|
+
*
|
|
7
|
+
* ERP backend endpoints land separately (Frihet-ERP S2 sprint).
|
|
8
|
+
* Tools target /v1/pos/terminals and /v1/pos/sales.
|
|
9
|
+
*
|
|
10
|
+
* Trust Area: refund_sale requires explicit confirmation (destructive).
|
|
11
|
+
*/
|
|
12
|
+
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
13
|
+
import type { IFrihetClient } from "../client-interface.js";
|
|
14
|
+
export declare function registerPosTools(server: McpServer, client: IFrihetClient): void;
|
|
15
|
+
//# sourceMappingURL=pos.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pos.d.ts","sourceRoot":"","sources":["../../src/tools/pos.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEzE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAe5D,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,aAAa,GAAG,IAAI,CAiL/E"}
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* POS (Point of Sale) tools for the Frihet MCP server.
|
|
3
|
+
*
|
|
4
|
+
* Wave 5 — 4 tools for point-of-sale management:
|
|
5
|
+
* list_terminals, get_sale, list_sales, refund_sale
|
|
6
|
+
*
|
|
7
|
+
* ERP backend endpoints land separately (Frihet-ERP S2 sprint).
|
|
8
|
+
* Tools target /v1/pos/terminals and /v1/pos/sales.
|
|
9
|
+
*
|
|
10
|
+
* Trust Area: refund_sale requires explicit confirmation (destructive).
|
|
11
|
+
*/
|
|
12
|
+
import { z } from "zod/v4";
|
|
13
|
+
import { withToolLogging, formatPaginatedResponse, formatRecord, listContent, getContent, mutateContent, READ_ONLY_ANNOTATIONS, DELETE_ANNOTATIONS, paginatedOutput, posTerminalItemOutput, posSaleItemOutput, } from "./shared.js";
|
|
14
|
+
export function registerPosTools(server, client) {
|
|
15
|
+
// -- list_terminals --
|
|
16
|
+
server.registerTool("list_terminals", {
|
|
17
|
+
title: "List POS Terminals",
|
|
18
|
+
description: "List all configured POS terminals (Stripe Terminal readers) for the workspace. " +
|
|
19
|
+
"Returns terminal label, device type, location, and connection status. " +
|
|
20
|
+
"/ Lista todos los terminales de punto de venta (lectores Stripe Terminal). " +
|
|
21
|
+
"Devuelve etiqueta, tipo de dispositivo, ubicacion y estado de conexion.",
|
|
22
|
+
annotations: READ_ONLY_ANNOTATIONS,
|
|
23
|
+
inputSchema: {
|
|
24
|
+
locationId: z
|
|
25
|
+
.string()
|
|
26
|
+
.optional()
|
|
27
|
+
.describe("Filter by location ID / Filtrar por ubicacion"),
|
|
28
|
+
limit: z.number().int().min(1).max(100).optional().describe("Max results (1-100)"),
|
|
29
|
+
offset: z.number().int().min(0).optional().describe("Offset / Desplazamiento"),
|
|
30
|
+
},
|
|
31
|
+
outputSchema: paginatedOutput(posTerminalItemOutput),
|
|
32
|
+
}, async (args) => withToolLogging("list_terminals", async () => {
|
|
33
|
+
const result = await client.listTerminals(args);
|
|
34
|
+
return {
|
|
35
|
+
content: [listContent(formatPaginatedResponse("terminals", result))],
|
|
36
|
+
structuredContent: result,
|
|
37
|
+
};
|
|
38
|
+
}));
|
|
39
|
+
// -- get_sale --
|
|
40
|
+
server.registerTool("get_sale", {
|
|
41
|
+
title: "Get POS Sale",
|
|
42
|
+
description: "Get a single POS sale by ID. Returns full sale details: terminal, items, " +
|
|
43
|
+
"payment method, amounts, and status. " +
|
|
44
|
+
"/ Obtiene una venta POS por ID. Devuelve todos los detalles: terminal, " +
|
|
45
|
+
"articulos, metodo de pago, importes y estado.",
|
|
46
|
+
annotations: READ_ONLY_ANNOTATIONS,
|
|
47
|
+
inputSchema: {
|
|
48
|
+
id: z.string().describe("Sale ID / ID de venta"),
|
|
49
|
+
},
|
|
50
|
+
outputSchema: posSaleItemOutput,
|
|
51
|
+
}, async ({ id }) => withToolLogging("get_sale", async () => {
|
|
52
|
+
const result = await client.getSale(id);
|
|
53
|
+
return {
|
|
54
|
+
content: [getContent(formatRecord("Sale", result))],
|
|
55
|
+
structuredContent: result,
|
|
56
|
+
};
|
|
57
|
+
}));
|
|
58
|
+
// -- list_sales --
|
|
59
|
+
server.registerTool("list_sales", {
|
|
60
|
+
title: "List POS Sales",
|
|
61
|
+
description: "List POS sales with optional filters by date range, terminal, or status. " +
|
|
62
|
+
"/ Lista las ventas POS con filtros opcionales por fecha, terminal o estado.",
|
|
63
|
+
annotations: READ_ONLY_ANNOTATIONS,
|
|
64
|
+
inputSchema: {
|
|
65
|
+
terminalId: z
|
|
66
|
+
.string()
|
|
67
|
+
.optional()
|
|
68
|
+
.describe("Filter by terminal ID / Filtrar por terminal"),
|
|
69
|
+
status: z
|
|
70
|
+
.enum(["succeeded", "pending", "cancelled", "refunded", "partially_refunded"])
|
|
71
|
+
.optional()
|
|
72
|
+
.describe("Filter by sale status / Filtrar por estado"),
|
|
73
|
+
from: z
|
|
74
|
+
.string()
|
|
75
|
+
.optional()
|
|
76
|
+
.describe("Start date YYYY-MM-DD / Fecha de inicio"),
|
|
77
|
+
to: z
|
|
78
|
+
.string()
|
|
79
|
+
.optional()
|
|
80
|
+
.describe("End date YYYY-MM-DD / Fecha de fin"),
|
|
81
|
+
limit: z.number().int().min(1).max(100).optional().describe("Max results (1-100)"),
|
|
82
|
+
offset: z.number().int().min(0).optional().describe("Offset / Desplazamiento"),
|
|
83
|
+
after: z
|
|
84
|
+
.string()
|
|
85
|
+
.optional()
|
|
86
|
+
.describe("Cursor for cursor-based pagination / Cursor de paginacion"),
|
|
87
|
+
},
|
|
88
|
+
outputSchema: paginatedOutput(posSaleItemOutput),
|
|
89
|
+
}, async (args) => withToolLogging("list_sales", async () => {
|
|
90
|
+
const result = await client.listSales(args);
|
|
91
|
+
return {
|
|
92
|
+
content: [listContent(formatPaginatedResponse("sales", result))],
|
|
93
|
+
structuredContent: result,
|
|
94
|
+
};
|
|
95
|
+
}));
|
|
96
|
+
// -- refund_sale --
|
|
97
|
+
// Trust Area: destructive action. Requires explicit `confirm: true` flag.
|
|
98
|
+
server.registerTool("refund_sale", {
|
|
99
|
+
title: "Refund POS Sale",
|
|
100
|
+
description: "Refund a POS sale in full or partially. This action is irreversible — " +
|
|
101
|
+
"the customer will receive a refund to their original payment method. " +
|
|
102
|
+
"You MUST pass confirm=true to proceed. Optionally specify amountCents for " +
|
|
103
|
+
"a partial refund (defaults to full refund). " +
|
|
104
|
+
"/ Reembolsa una venta POS total o parcialmente. Accion irreversible. " +
|
|
105
|
+
"Debes pasar confirm=true. Pasa amountCents para reembolso parcial.",
|
|
106
|
+
annotations: DELETE_ANNOTATIONS,
|
|
107
|
+
inputSchema: {
|
|
108
|
+
id: z.string().describe("Sale ID to refund / ID de venta a reembolsar"),
|
|
109
|
+
confirm: z
|
|
110
|
+
.boolean()
|
|
111
|
+
.describe("Must be true to proceed. Safety gate for destructive action. " +
|
|
112
|
+
"/ Debe ser true para continuar. Confirmacion obligatoria."),
|
|
113
|
+
amountCents: z
|
|
114
|
+
.number()
|
|
115
|
+
.int()
|
|
116
|
+
.positive()
|
|
117
|
+
.optional()
|
|
118
|
+
.describe("Partial refund amount in cents. Omit for full refund. " +
|
|
119
|
+
"/ Importe parcial en centimos. Omitir para reembolso completo."),
|
|
120
|
+
reason: z
|
|
121
|
+
.enum(["duplicate", "fraudulent", "requested_by_customer", "other"])
|
|
122
|
+
.optional()
|
|
123
|
+
.describe("Refund reason / Motivo del reembolso"),
|
|
124
|
+
},
|
|
125
|
+
outputSchema: z.object({
|
|
126
|
+
id: z.string(),
|
|
127
|
+
saleId: z.string(),
|
|
128
|
+
status: z.enum(["succeeded", "pending", "failed"]),
|
|
129
|
+
amountCents: z.number().int().nonnegative(),
|
|
130
|
+
currency: z.string(),
|
|
131
|
+
reason: z.string().optional(),
|
|
132
|
+
createdAt: z.string(),
|
|
133
|
+
}).passthrough(),
|
|
134
|
+
}, async ({ id, confirm, amountCents, reason }) => withToolLogging("refund_sale", async () => {
|
|
135
|
+
if (!confirm) {
|
|
136
|
+
return {
|
|
137
|
+
content: [
|
|
138
|
+
{
|
|
139
|
+
type: "text",
|
|
140
|
+
text: "Error: refund_sale requires confirm=true to proceed. " +
|
|
141
|
+
"This action is irreversible — the customer will receive a refund. " +
|
|
142
|
+
"/ Se requiere confirm=true. Esta accion es irreversible.",
|
|
143
|
+
annotations: { audience: ["user"], priority: 1.0 },
|
|
144
|
+
},
|
|
145
|
+
],
|
|
146
|
+
isError: true,
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
const result = await client.refundSale(id, { amountCents, reason });
|
|
150
|
+
return {
|
|
151
|
+
content: [mutateContent(formatRecord("Refund created", result))],
|
|
152
|
+
structuredContent: result,
|
|
153
|
+
};
|
|
154
|
+
}));
|
|
155
|
+
}
|
|
156
|
+
//# sourceMappingURL=pos.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pos.js","sourceRoot":"","sources":["../../src/tools/pos.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Recurring invoice tools for the Frihet MCP server — Wave Mature 3 (7 tools).
|
|
3
|
+
*
|
|
4
|
+
* Tools:
|
|
5
|
+
* 1. list_recurring_invoices — list recurring invoice templates
|
|
6
|
+
* 2. get_recurring_invoice — get single recurring template by ID
|
|
7
|
+
* 3. create_recurring_invoice — create a new recurring invoice template
|
|
8
|
+
* 4. update_recurring_invoice — update template fields (PATCH semantics)
|
|
9
|
+
* 5. pause_recurring_invoice — pause an active recurring template
|
|
10
|
+
* 6. resume_recurring_invoice — resume a paused recurring template
|
|
11
|
+
* 7. delete_recurring_invoice — permanently delete a recurring template (Trust Area)
|
|
12
|
+
* 8. run_recurring_now — manually trigger generation of next instance from template
|
|
13
|
+
*
|
|
14
|
+
* REST surface: /v1/recurring/invoices
|
|
15
|
+
*
|
|
16
|
+
* Backend: /v1/recurring/* endpoints live as of Wave 4-A (Frihet-ERP functions/src/publicApi.ts).
|
|
17
|
+
*/
|
|
18
|
+
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
19
|
+
import type { IFrihetClient } from "../client-interface.js";
|
|
20
|
+
export declare function registerRecurringTools(server: McpServer, client: IFrihetClient): void;
|
|
21
|
+
//# sourceMappingURL=recurring.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recurring.d.ts","sourceRoot":"","sources":["../../src/tools/recurring.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEzE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAkB5D,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,aAAa,GAAG,IAAI,CAsRrF"}
|