@frihet/mcp-server 1.16.2 → 1.16.4
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 +1 -1
- package/dist/openai-profile.js +1 -1
- package/package.json +7 -4
- package/scripts/postinstall.js +30 -8
- package/dist/__tests__/audit-server-version.test.d.ts +0 -13
- package/dist/__tests__/audit-server-version.test.d.ts.map +0 -1
- package/dist/__tests__/audit-server-version.test.js +0 -96
- package/dist/__tests__/audit-server-version.test.js.map +0 -1
- package/dist/__tests__/banking-client-contract.test.d.ts +0 -20
- package/dist/__tests__/banking-client-contract.test.d.ts.map +0 -1
- package/dist/__tests__/banking-client-contract.test.js +0 -133
- package/dist/__tests__/banking-client-contract.test.js.map +0 -1
- package/dist/__tests__/banking-tools.test.d.ts +0 -18
- package/dist/__tests__/banking-tools.test.d.ts.map +0 -1
- package/dist/__tests__/banking-tools.test.js +0 -252
- package/dist/__tests__/banking-tools.test.js.map +0 -1
- package/dist/__tests__/contract.test.d.ts +0 -33
- package/dist/__tests__/contract.test.d.ts.map +0 -1
- package/dist/__tests__/contract.test.js +0 -208
- package/dist/__tests__/contract.test.js.map +0 -1
- package/dist/__tests__/d4b-hr-payroll-onboarding-tools.test.d.ts +0 -13
- package/dist/__tests__/d4b-hr-payroll-onboarding-tools.test.d.ts.map +0 -1
- package/dist/__tests__/d4b-hr-payroll-onboarding-tools.test.js +0 -420
- package/dist/__tests__/d4b-hr-payroll-onboarding-tools.test.js.map +0 -1
- package/dist/__tests__/demo-mode.test.d.ts +0 -11
- package/dist/__tests__/demo-mode.test.d.ts.map +0 -1
- package/dist/__tests__/demo-mode.test.js +0 -119
- package/dist/__tests__/demo-mode.test.js.map +0 -1
- package/dist/__tests__/einvoice-day4-tools.test.d.ts +0 -16
- package/dist/__tests__/einvoice-day4-tools.test.d.ts.map +0 -1
- package/dist/__tests__/einvoice-day4-tools.test.js +0 -421
- package/dist/__tests__/einvoice-day4-tools.test.js.map +0 -1
- package/dist/__tests__/einvoice-integration.test.d.ts +0 -24
- package/dist/__tests__/einvoice-integration.test.d.ts.map +0 -1
- package/dist/__tests__/einvoice-integration.test.js +0 -142
- package/dist/__tests__/einvoice-integration.test.js.map +0 -1
- package/dist/__tests__/einvoice-tools.test.d.ts +0 -16
- package/dist/__tests__/einvoice-tools.test.d.ts.map +0 -1
- package/dist/__tests__/einvoice-tools.test.js +0 -411
- package/dist/__tests__/einvoice-tools.test.js.map +0 -1
- package/dist/__tests__/fiscal-tools.test.d.ts +0 -21
- package/dist/__tests__/fiscal-tools.test.d.ts.map +0 -1
- package/dist/__tests__/fiscal-tools.test.js +0 -271
- package/dist/__tests__/fiscal-tools.test.js.map +0 -1
- package/dist/__tests__/get-envelope-unwrap-regression.test.d.ts +0 -27
- package/dist/__tests__/get-envelope-unwrap-regression.test.d.ts.map +0 -1
- package/dist/__tests__/get-envelope-unwrap-regression.test.js +0 -223
- package/dist/__tests__/get-envelope-unwrap-regression.test.js.map +0 -1
- package/dist/__tests__/intelligence-duplicate-invoice.test.d.ts +0 -14
- package/dist/__tests__/intelligence-duplicate-invoice.test.d.ts.map +0 -1
- package/dist/__tests__/intelligence-duplicate-invoice.test.js +0 -108
- package/dist/__tests__/intelligence-duplicate-invoice.test.js.map +0 -1
- package/dist/__tests__/kitchen-tools.test.d.ts +0 -18
- package/dist/__tests__/kitchen-tools.test.d.ts.map +0 -1
- package/dist/__tests__/kitchen-tools.test.js +0 -399
- package/dist/__tests__/kitchen-tools.test.js.map +0 -1
- package/dist/__tests__/mutation-unwrap-and-schema-regression.test.d.ts +0 -30
- package/dist/__tests__/mutation-unwrap-and-schema-regression.test.d.ts.map +0 -1
- package/dist/__tests__/mutation-unwrap-and-schema-regression.test.js +0 -164
- package/dist/__tests__/mutation-unwrap-and-schema-regression.test.js.map +0 -1
- package/dist/__tests__/observability-redaction.test.d.ts +0 -13
- package/dist/__tests__/observability-redaction.test.d.ts.map +0 -1
- package/dist/__tests__/observability-redaction.test.js +0 -94
- package/dist/__tests__/observability-redaction.test.js.map +0 -1
- package/dist/__tests__/openai-grouped-compose.test.d.ts +0 -26
- package/dist/__tests__/openai-grouped-compose.test.d.ts.map +0 -1
- package/dist/__tests__/openai-grouped-compose.test.js +0 -245
- package/dist/__tests__/openai-grouped-compose.test.js.map +0 -1
- package/dist/__tests__/openai-profile.test.d.ts +0 -10
- package/dist/__tests__/openai-profile.test.d.ts.map +0 -1
- package/dist/__tests__/openai-profile.test.js +0 -168
- package/dist/__tests__/openai-profile.test.js.map +0 -1
- package/dist/__tests__/pagination-cursor-param.test.d.ts +0 -27
- package/dist/__tests__/pagination-cursor-param.test.d.ts.map +0 -1
- package/dist/__tests__/pagination-cursor-param.test.js +0 -96
- package/dist/__tests__/pagination-cursor-param.test.js.map +0 -1
- package/dist/__tests__/pos-tools.test.d.ts +0 -16
- package/dist/__tests__/pos-tools.test.d.ts.map +0 -1
- package/dist/__tests__/pos-tools.test.js +0 -244
- package/dist/__tests__/pos-tools.test.js.map +0 -1
- package/dist/__tests__/recurring-tools.test.d.ts +0 -23
- package/dist/__tests__/recurring-tools.test.d.ts.map +0 -1
- package/dist/__tests__/recurring-tools.test.js +0 -352
- package/dist/__tests__/recurring-tools.test.js.map +0 -1
- package/dist/__tests__/schema-envelope-guard.test.d.ts +0 -18
- package/dist/__tests__/schema-envelope-guard.test.d.ts.map +0 -1
- package/dist/__tests__/schema-envelope-guard.test.js +0 -56
- package/dist/__tests__/schema-envelope-guard.test.js.map +0 -1
- package/dist/__tests__/stay-tools.test.d.ts +0 -17
- package/dist/__tests__/stay-tools.test.d.ts.map +0 -1
- package/dist/__tests__/stay-tools.test.js +0 -259
- package/dist/__tests__/stay-tools.test.js.map +0 -1
- package/dist/__tests__/team-tools.test.d.ts +0 -18
- package/dist/__tests__/team-tools.test.d.ts.map +0 -1
- package/dist/__tests__/team-tools.test.js +0 -228
- package/dist/__tests__/team-tools.test.js.map +0 -1
- package/dist/__tests__/time-tools.test.d.ts +0 -19
- package/dist/__tests__/time-tools.test.d.ts.map +0 -1
- package/dist/__tests__/time-tools.test.js +0 -286
- package/dist/__tests__/time-tools.test.js.map +0 -1
- package/dist/__tests__/tool-exposure.test.d.ts +0 -11
- package/dist/__tests__/tool-exposure.test.d.ts.map +0 -1
- package/dist/__tests__/tool-exposure.test.js +0 -264
- package/dist/__tests__/tool-exposure.test.js.map +0 -1
- package/dist/client-interface.d.ts.map +0 -1
- package/dist/client-interface.js.map +0 -1
- package/dist/client.d.ts.map +0 -1
- package/dist/client.js.map +0 -1
- package/dist/demo-client.d.ts.map +0 -1
- package/dist/demo-client.js.map +0 -1
- package/dist/demo-fixtures.d.ts.map +0 -1
- package/dist/demo-fixtures.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/logger.d.ts.map +0 -1
- package/dist/logger.js.map +0 -1
- package/dist/metrics.d.ts.map +0 -1
- package/dist/metrics.js.map +0 -1
- package/dist/observability.d.ts.map +0 -1
- package/dist/observability.js.map +0 -1
- package/dist/openai-profile.d.ts.map +0 -1
- package/dist/openai-profile.js.map +0 -1
- package/dist/prompts/register-all.d.ts.map +0 -1
- package/dist/prompts/register-all.js.map +0 -1
- package/dist/redaction.d.ts.map +0 -1
- package/dist/redaction.js.map +0 -1
- package/dist/resources/register-all.d.ts.map +0 -1
- package/dist/resources/register-all.js.map +0 -1
- package/dist/tool-exposure.d.ts.map +0 -1
- package/dist/tool-exposure.js.map +0 -1
- package/dist/tools/accountingClose.d.ts.map +0 -1
- package/dist/tools/accountingClose.js.map +0 -1
- package/dist/tools/audit_gl.d.ts.map +0 -1
- package/dist/tools/audit_gl.js.map +0 -1
- package/dist/tools/backend-availability.d.ts.map +0 -1
- package/dist/tools/backend-availability.js.map +0 -1
- package/dist/tools/bank_rules.d.ts.map +0 -1
- package/dist/tools/bank_rules.js.map +0 -1
- package/dist/tools/banking.d.ts.map +0 -1
- package/dist/tools/banking.js.map +0 -1
- package/dist/tools/clients.d.ts.map +0 -1
- package/dist/tools/clients.js.map +0 -1
- package/dist/tools/crm.d.ts.map +0 -1
- package/dist/tools/crm.js.map +0 -1
- package/dist/tools/deposits.d.ts.map +0 -1
- package/dist/tools/deposits.js.map +0 -1
- package/dist/tools/einvoice.d.ts.map +0 -1
- package/dist/tools/einvoice.js.map +0 -1
- package/dist/tools/expenses.d.ts.map +0 -1
- package/dist/tools/expenses.js.map +0 -1
- package/dist/tools/fiscal.d.ts.map +0 -1
- package/dist/tools/fiscal.js.map +0 -1
- package/dist/tools/gestoria.d.ts.map +0 -1
- package/dist/tools/gestoria.js.map +0 -1
- package/dist/tools/hr.d.ts.map +0 -1
- package/dist/tools/hr.js.map +0 -1
- package/dist/tools/igic.d.ts.map +0 -1
- package/dist/tools/igic.js.map +0 -1
- package/dist/tools/impuesto_sociedades.d.ts.map +0 -1
- package/dist/tools/impuesto_sociedades.js.map +0 -1
- package/dist/tools/intelligence.d.ts.map +0 -1
- package/dist/tools/intelligence.js.map +0 -1
- package/dist/tools/invoices.d.ts.map +0 -1
- package/dist/tools/invoices.js.map +0 -1
- package/dist/tools/kitchen.d.ts.map +0 -1
- package/dist/tools/kitchen.js.map +0 -1
- package/dist/tools/onboard_vies.d.ts.map +0 -1
- package/dist/tools/onboard_vies.js.map +0 -1
- package/dist/tools/onboarding.d.ts.map +0 -1
- package/dist/tools/onboarding.js.map +0 -1
- package/dist/tools/payroll.d.ts.map +0 -1
- package/dist/tools/payroll.js.map +0 -1
- package/dist/tools/permissions.d.ts.map +0 -1
- package/dist/tools/permissions.js.map +0 -1
- package/dist/tools/portal_domain.d.ts.map +0 -1
- package/dist/tools/portal_domain.js.map +0 -1
- package/dist/tools/pos.d.ts.map +0 -1
- package/dist/tools/pos.js.map +0 -1
- package/dist/tools/products.d.ts.map +0 -1
- package/dist/tools/products.js.map +0 -1
- package/dist/tools/quotes.d.ts.map +0 -1
- package/dist/tools/quotes.js.map +0 -1
- package/dist/tools/recurring.d.ts.map +0 -1
- package/dist/tools/recurring.js.map +0 -1
- package/dist/tools/register-all.d.ts.map +0 -1
- package/dist/tools/register-all.js.map +0 -1
- package/dist/tools/shared.d.ts.map +0 -1
- package/dist/tools/shared.js.map +0 -1
- package/dist/tools/stay.d.ts.map +0 -1
- package/dist/tools/stay.js.map +0 -1
- package/dist/tools/team.d.ts.map +0 -1
- package/dist/tools/team.js.map +0 -1
- package/dist/tools/time.d.ts.map +0 -1
- package/dist/tools/time.js.map +0 -1
- package/dist/tools/vendors.d.ts.map +0 -1
- package/dist/tools/vendors.js.map +0 -1
- package/dist/tools/webhooks.d.ts.map +0 -1
- package/dist/tools/webhooks.js.map +0 -1
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js.map +0 -1
- package/scripts/audit-mcp-refs.mjs +0 -402
- package/scripts/no-public-leak.sh +0 -60
- package/scripts/test-openai-grouped-compose.mjs +0 -173
|
@@ -1,168 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Tests for the OpenAI-safe MCP profile.
|
|
3
|
-
*
|
|
4
|
-
* The public ChatGPT app intentionally exposes a narrower tool surface than
|
|
5
|
-
* the full MCP server. This prevents regulated or sensitive workflows added
|
|
6
|
-
* to the general MCP server from becoming part of the OpenAI submission by
|
|
7
|
-
* accident.
|
|
8
|
-
*/
|
|
9
|
-
import { describe, test } from "node:test";
|
|
10
|
-
import assert from "node:assert/strict";
|
|
11
|
-
import { applyOpenAIProfile } from "../openai-profile.js";
|
|
12
|
-
import { SENSITIVE_FIELD_NAMES } from "../redaction.js";
|
|
13
|
-
import { registerAllTools } from "../tools/register-all.js";
|
|
14
|
-
import { registerAllPrompts } from "../prompts/register-all.js";
|
|
15
|
-
import { registerAllResources } from "../resources/register-all.js";
|
|
16
|
-
class StubMcpServer {
|
|
17
|
-
tools = new Map();
|
|
18
|
-
prompts = [];
|
|
19
|
-
resources = [];
|
|
20
|
-
registerTool(name, config, handler) {
|
|
21
|
-
this.tools.set(name, { name, config, handler });
|
|
22
|
-
}
|
|
23
|
-
registerPrompt(name) {
|
|
24
|
-
this.prompts.push(name);
|
|
25
|
-
}
|
|
26
|
-
registerResource(name) {
|
|
27
|
-
this.resources.push(name);
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
function makeClient() {
|
|
31
|
-
return new Proxy({}, {
|
|
32
|
-
get: (_target, prop) => async (input) => {
|
|
33
|
-
if (prop === "createClient") {
|
|
34
|
-
return {
|
|
35
|
-
id: "cli_openai",
|
|
36
|
-
name: "OpenAI Test Corp",
|
|
37
|
-
email: "test@example.com",
|
|
38
|
-
taxId: "B12345678",
|
|
39
|
-
secret: "should-not-leak",
|
|
40
|
-
};
|
|
41
|
-
}
|
|
42
|
-
return {
|
|
43
|
-
data: [],
|
|
44
|
-
total: 0,
|
|
45
|
-
limit: 10,
|
|
46
|
-
offset: 0,
|
|
47
|
-
input,
|
|
48
|
-
};
|
|
49
|
-
},
|
|
50
|
-
});
|
|
51
|
-
}
|
|
52
|
-
function makeOpenAIServer() {
|
|
53
|
-
const server = new StubMcpServer();
|
|
54
|
-
applyOpenAIProfile(server);
|
|
55
|
-
registerAllTools(server, makeClient());
|
|
56
|
-
registerAllResources(server);
|
|
57
|
-
registerAllPrompts(server);
|
|
58
|
-
return server;
|
|
59
|
-
}
|
|
60
|
-
describe("OpenAI profile", () => {
|
|
61
|
-
test("exposes exactly the reviewed 53-tool surface", () => {
|
|
62
|
-
const server = makeOpenAIServer();
|
|
63
|
-
assert.equal(server.tools.size, 53);
|
|
64
|
-
assert.equal(server.prompts.length, 0);
|
|
65
|
-
assert.equal(server.resources.length, 0);
|
|
66
|
-
for (const hiddenTool of [
|
|
67
|
-
"get_quarterly_taxes",
|
|
68
|
-
"get_invoice_einvoice",
|
|
69
|
-
"send_einvoice",
|
|
70
|
-
"validate_einvoice_xml",
|
|
71
|
-
"frihet_tax_id_vies_lookup",
|
|
72
|
-
"create_reservation",
|
|
73
|
-
"payroll_export",
|
|
74
|
-
"invite_team_member",
|
|
75
|
-
]) {
|
|
76
|
-
assert.equal(server.tools.has(hiddenTool), false, `${hiddenTool} must not be exposed in OpenAI mode`);
|
|
77
|
-
}
|
|
78
|
-
});
|
|
79
|
-
test("keeps only reviewed open-world tools marked openWorldHint=true", () => {
|
|
80
|
-
const server = makeOpenAIServer();
|
|
81
|
-
const openWorldTools = [...server.tools.values()]
|
|
82
|
-
.filter((tool) => tool.config.annotations?.["openWorldHint"] === true)
|
|
83
|
-
.map((tool) => tool.name)
|
|
84
|
-
.sort();
|
|
85
|
-
assert.deepEqual(openWorldTools, [
|
|
86
|
-
"create_webhook",
|
|
87
|
-
"send_invoice",
|
|
88
|
-
"send_quote",
|
|
89
|
-
"update_webhook",
|
|
90
|
-
]);
|
|
91
|
-
});
|
|
92
|
-
test("removes restricted input fields from OpenAI-visible schemas", () => {
|
|
93
|
-
const server = makeOpenAIServer();
|
|
94
|
-
for (const name of ["create_client", "update_client", "create_vendor", "update_vendor"]) {
|
|
95
|
-
const tool = server.tools.get(name);
|
|
96
|
-
assert.ok(tool, `${name} should be visible`);
|
|
97
|
-
assert.equal("taxId" in (tool.config.inputSchema ?? {}), false);
|
|
98
|
-
}
|
|
99
|
-
for (const name of ["send_invoice", "send_quote"]) {
|
|
100
|
-
const tool = server.tools.get(name);
|
|
101
|
-
assert.ok(tool, `${name} should be visible`);
|
|
102
|
-
assert.equal("to" in (tool.config.inputSchema ?? {}), false);
|
|
103
|
-
}
|
|
104
|
-
for (const name of ["create_webhook", "update_webhook"]) {
|
|
105
|
-
const tool = server.tools.get(name);
|
|
106
|
-
assert.ok(tool, `${name} should be visible`);
|
|
107
|
-
assert.equal("secret" in (tool.config.inputSchema ?? {}), false);
|
|
108
|
-
}
|
|
109
|
-
});
|
|
110
|
-
test("every reviewed tool states an explicit openWorldHint rationale", () => {
|
|
111
|
-
const server = makeOpenAIServer();
|
|
112
|
-
for (const tool of server.tools.values()) {
|
|
113
|
-
// OpenAI review: openWorldHint must be explicit (not null) AND justified per tool.
|
|
114
|
-
assert.equal(typeof tool.config.annotations?.["openWorldHint"], "boolean", `${tool.name} must have an explicit boolean openWorldHint`);
|
|
115
|
-
assert.ok(tool.config.description.includes("openWorldHint"), `${tool.name} description must state an openWorldHint rationale`);
|
|
116
|
-
}
|
|
117
|
-
// Closed-world read tool carries the closed-world rationale.
|
|
118
|
-
assert.match(server.tools.get("list_invoices").config.description, /openWorldHint: false/);
|
|
119
|
-
// Open-world tool keeps its bespoke true rationale (not double-appended).
|
|
120
|
-
const sendInvoiceDesc = server.tools.get("send_invoice").config.description;
|
|
121
|
-
assert.match(sendInvoiceDesc, /openWorldHint: true/);
|
|
122
|
-
assert.doesNotMatch(sendInvoiceDesc, /openWorldHint: false/);
|
|
123
|
-
});
|
|
124
|
-
test("redacts restricted output fields from structured content and text", async () => {
|
|
125
|
-
const server = makeOpenAIServer();
|
|
126
|
-
const tool = server.tools.get("create_client");
|
|
127
|
-
assert.ok(tool, "create_client should be visible");
|
|
128
|
-
const result = await tool.handler({ name: "OpenAI Test Corp" });
|
|
129
|
-
const serialized = JSON.stringify(result);
|
|
130
|
-
assert.equal(serialized.includes("taxId"), false);
|
|
131
|
-
assert.equal(serialized.includes("B12345678"), false);
|
|
132
|
-
assert.equal(serialized.includes("secret"), false);
|
|
133
|
-
assert.equal(serialized.includes("should-not-leak"), false);
|
|
134
|
-
});
|
|
135
|
-
test("no reviewed tool DECLARES a sensitive field in its outputSchema", () => {
|
|
136
|
-
const server = makeOpenAIServer();
|
|
137
|
-
// Recursively collect every object key declared by a Zod output schema.
|
|
138
|
-
const collectKeys = (schema, acc) => {
|
|
139
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
140
|
-
const def = schema?._def;
|
|
141
|
-
const typeName = def?.typeName;
|
|
142
|
-
if (typeName === "ZodObject") {
|
|
143
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
144
|
-
for (const [key, value] of Object.entries(schema.shape)) {
|
|
145
|
-
acc.add(key);
|
|
146
|
-
collectKeys(value, acc);
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
else if (typeName === "ZodArray") {
|
|
150
|
-
collectKeys(def.type, acc);
|
|
151
|
-
}
|
|
152
|
-
else if (typeName === "ZodOptional" || typeName === "ZodNullable") {
|
|
153
|
-
collectKeys(def.innerType, acc);
|
|
154
|
-
}
|
|
155
|
-
return acc;
|
|
156
|
-
};
|
|
157
|
-
for (const tool of server.tools.values()) {
|
|
158
|
-
const out = tool.config.outputSchema;
|
|
159
|
-
if (!out)
|
|
160
|
-
continue;
|
|
161
|
-
const keys = collectKeys(out, new Set());
|
|
162
|
-
for (const field of SENSITIVE_FIELD_NAMES) {
|
|
163
|
-
assert.equal(keys.has(field), false, `${tool.name} outputSchema must not declare sensitive field "${field}"`);
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
});
|
|
167
|
-
});
|
|
168
|
-
//# sourceMappingURL=openai-profile.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"openai-profile.test.js","sourceRoot":"","sources":["../../src/__tests__/openai-profile.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Pagination cursor wire-param contract.
|
|
3
|
-
*
|
|
4
|
-
* Bug (verified live): the client built the cursor-pagination query as
|
|
5
|
-
* `after: params?.after`, but the ERP backend reads `req.query.cursor`
|
|
6
|
-
* (functions/src/publicApi.ts:6472 in Frihet-ERP) and returns `nextCursor`.
|
|
7
|
-
* The cursor token therefore never reached the backend, every "next page"
|
|
8
|
-
* request fell back to offset=0, and cursor-based pagination looped on
|
|
9
|
-
* page 1 forever.
|
|
10
|
-
*
|
|
11
|
-
* Current state (post-fix): `after` remains the caller-facing param name on
|
|
12
|
-
* every public list/search method below — tools/*.ts and other callers keep
|
|
13
|
-
* passing `{ after }` unchanged, it's a naming alias only. The wire query
|
|
14
|
-
* key actually sent to the backend is `cursor` (see the doc comment atop
|
|
15
|
-
* `FrihetClient` in src/client.ts); `after` itself is never sent.
|
|
16
|
-
*
|
|
17
|
-
* This spins up a local node:http server (acting as the ERP backend), points
|
|
18
|
-
* a REAL FrihetClient at it, and asserts — for EVERY paginated public method
|
|
19
|
-
* that accepts `after` (the 16 call sites in src/client.ts where the wire
|
|
20
|
-
* query builder has `cursor: params?.after`) — that the captured query
|
|
21
|
-
* string contains `cursor=<token>` and NOT `after=<token>` when a pagination
|
|
22
|
-
* token is passed.
|
|
23
|
-
*
|
|
24
|
-
* Run: npm test (after build)
|
|
25
|
-
*/
|
|
26
|
-
export {};
|
|
27
|
-
//# sourceMappingURL=pagination-cursor-param.test.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"pagination-cursor-param.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/pagination-cursor-param.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG"}
|
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Pagination cursor wire-param contract.
|
|
3
|
-
*
|
|
4
|
-
* Bug (verified live): the client built the cursor-pagination query as
|
|
5
|
-
* `after: params?.after`, but the ERP backend reads `req.query.cursor`
|
|
6
|
-
* (functions/src/publicApi.ts:6472 in Frihet-ERP) and returns `nextCursor`.
|
|
7
|
-
* The cursor token therefore never reached the backend, every "next page"
|
|
8
|
-
* request fell back to offset=0, and cursor-based pagination looped on
|
|
9
|
-
* page 1 forever.
|
|
10
|
-
*
|
|
11
|
-
* Current state (post-fix): `after` remains the caller-facing param name on
|
|
12
|
-
* every public list/search method below — tools/*.ts and other callers keep
|
|
13
|
-
* passing `{ after }` unchanged, it's a naming alias only. The wire query
|
|
14
|
-
* key actually sent to the backend is `cursor` (see the doc comment atop
|
|
15
|
-
* `FrihetClient` in src/client.ts); `after` itself is never sent.
|
|
16
|
-
*
|
|
17
|
-
* This spins up a local node:http server (acting as the ERP backend), points
|
|
18
|
-
* a REAL FrihetClient at it, and asserts — for EVERY paginated public method
|
|
19
|
-
* that accepts `after` (the 16 call sites in src/client.ts where the wire
|
|
20
|
-
* query builder has `cursor: params?.after`) — that the captured query
|
|
21
|
-
* string contains `cursor=<token>` and NOT `after=<token>` when a pagination
|
|
22
|
-
* token is passed.
|
|
23
|
-
*
|
|
24
|
-
* Run: npm test (after build)
|
|
25
|
-
*/
|
|
26
|
-
import { test, describe, before, after } from "node:test";
|
|
27
|
-
import assert from "node:assert/strict";
|
|
28
|
-
import { createServer } from "node:http";
|
|
29
|
-
import { FrihetClient } from "../client.js";
|
|
30
|
-
const captured = [];
|
|
31
|
-
let server;
|
|
32
|
-
let baseUrl;
|
|
33
|
-
before(async () => {
|
|
34
|
-
server = createServer((req, res) => {
|
|
35
|
-
const url = new URL(req.url ?? "/", "http://localhost");
|
|
36
|
-
captured.push({
|
|
37
|
-
method: req.method ?? "",
|
|
38
|
-
path: url.pathname,
|
|
39
|
-
query: url.searchParams,
|
|
40
|
-
});
|
|
41
|
-
res.setHeader("Content-Type", "application/json");
|
|
42
|
-
res.end(JSON.stringify({ data: [], total: 0, limit: 20, offset: 0 }));
|
|
43
|
-
});
|
|
44
|
-
await new Promise((resolve) => server.listen(0, "127.0.0.1", resolve));
|
|
45
|
-
const { port } = server.address();
|
|
46
|
-
baseUrl = `http://127.0.0.1:${port}`;
|
|
47
|
-
});
|
|
48
|
-
after(async () => {
|
|
49
|
-
await new Promise((resolve) => server.close(() => resolve()));
|
|
50
|
-
});
|
|
51
|
-
function makeClient() {
|
|
52
|
-
return new FrihetClient("fri_test_key", baseUrl);
|
|
53
|
-
}
|
|
54
|
-
function lastRequest() {
|
|
55
|
-
return captured[captured.length - 1];
|
|
56
|
-
}
|
|
57
|
-
const CURSOR_TOKEN = "eyJpZCI6Imludl8xMjMifQ"; // opaque base64url-ish token, matches backend shape
|
|
58
|
-
/**
|
|
59
|
-
* Every public FrihetClient method whose wire-query builder in src/client.ts
|
|
60
|
-
* sends `cursor: params?.after` — i.e. every method that accepts a
|
|
61
|
-
* caller-facing `after` pagination token. Verified via
|
|
62
|
-
* `grep -n "cursor: params?.after" src/client.ts` (16 call sites as of the
|
|
63
|
-
* `cursor` rename in PR #71). Each entry drives the real method with
|
|
64
|
-
* `{ after: CURSOR_TOKEN }` the same way a real caller (or tools/*.ts) would.
|
|
65
|
-
* Add new paginated methods here as they ship so coverage stays exhaustive.
|
|
66
|
-
*/
|
|
67
|
-
const PAGINATED_ENDPOINTS = [
|
|
68
|
-
{ method: "listInvoices", invoke: (c) => c.listInvoices({ after: CURSOR_TOKEN, limit: 20 }) },
|
|
69
|
-
{ method: "searchInvoices", invoke: (c) => c.searchInvoices("acme", { after: CURSOR_TOKEN }) },
|
|
70
|
-
{ method: "listExpenses", invoke: (c) => c.listExpenses({ after: CURSOR_TOKEN }) },
|
|
71
|
-
{ method: "listClients", invoke: (c) => c.listClients({ after: CURSOR_TOKEN }) },
|
|
72
|
-
{ method: "listProducts", invoke: (c) => c.listProducts({ after: CURSOR_TOKEN }) },
|
|
73
|
-
{ method: "listQuotes", invoke: (c) => c.listQuotes({ after: CURSOR_TOKEN }) },
|
|
74
|
-
{ method: "listVendors", invoke: (c) => c.listVendors({ after: CURSOR_TOKEN }) },
|
|
75
|
-
{ method: "listDeposits", invoke: (c) => c.listDeposits({ after: CURSOR_TOKEN }) },
|
|
76
|
-
{ method: "listReservations", invoke: (c) => c.listReservations({ after: CURSOR_TOKEN }) },
|
|
77
|
-
{ method: "listProperties", invoke: (c) => c.listProperties({ after: CURSOR_TOKEN }) },
|
|
78
|
-
{ method: "listSales", invoke: (c) => c.listSales({ after: CURSOR_TOKEN }) },
|
|
79
|
-
{ method: "listKitchenTickets", invoke: (c) => c.listKitchenTickets({ after: CURSOR_TOKEN }) },
|
|
80
|
-
{ method: "listMenuItems", invoke: (c) => c.listMenuItems({ after: CURSOR_TOKEN }) },
|
|
81
|
-
{ method: "listTransactions", invoke: (c) => c.listTransactions({ after: CURSOR_TOKEN }) },
|
|
82
|
-
{ method: "listTimeEntries", invoke: (c) => c.listTimeEntries({ after: CURSOR_TOKEN }) },
|
|
83
|
-
{ method: "listLeaves", invoke: (c) => c.listLeaves({ after: CURSOR_TOKEN }) },
|
|
84
|
-
];
|
|
85
|
-
describe("Pagination cursor wire param — every list/search method must send `cursor`, not `after`", () => {
|
|
86
|
-
for (const { method, invoke } of PAGINATED_ENDPOINTS) {
|
|
87
|
-
test(`${method}({ after: token }) → query string has cursor=token, no after param`, async () => {
|
|
88
|
-
const client = makeClient();
|
|
89
|
-
await invoke(client);
|
|
90
|
-
const req = lastRequest();
|
|
91
|
-
assert.equal(req.query.get("cursor"), CURSOR_TOKEN, `${method}: backend reads req.query.cursor — token must land there`);
|
|
92
|
-
assert.equal(req.query.get("after"), null, `${method}: the \`after\` param is not read by the backend and must not be sent`);
|
|
93
|
-
});
|
|
94
|
-
}
|
|
95
|
-
});
|
|
96
|
-
//# sourceMappingURL=pagination-cursor-param.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"pagination-cursor-param.test.js","sourceRoot":"","sources":["../../src/__tests__/pagination-cursor-param.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Tests for POS MCP tools — Wave 5 (4 tools).
|
|
3
|
-
*
|
|
4
|
-
* Uses Node.js built-in test runner (node:test + node:assert).
|
|
5
|
-
* Run: npm test (after build)
|
|
6
|
-
*
|
|
7
|
-
* Coverage:
|
|
8
|
-
* 1. Tool registration — all 4 tools registered on McpServer
|
|
9
|
-
* 2. list_terminals — success path + structuredContent shape
|
|
10
|
-
* 3. get_sale — success path + structuredContent shape
|
|
11
|
-
* 4. list_sales — success path + structuredContent shape
|
|
12
|
-
* 5. refund_sale — confirm=false blocked, confirm=true succeeds
|
|
13
|
-
* 6. API error path — 404 propagated through handleToolError
|
|
14
|
-
*/
|
|
15
|
-
export {};
|
|
16
|
-
//# sourceMappingURL=pos-tools.test.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"pos-tools.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/pos-tools.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG"}
|
|
@@ -1,244 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Tests for POS MCP tools — Wave 5 (4 tools).
|
|
3
|
-
*
|
|
4
|
-
* Uses Node.js built-in test runner (node:test + node:assert).
|
|
5
|
-
* Run: npm test (after build)
|
|
6
|
-
*
|
|
7
|
-
* Coverage:
|
|
8
|
-
* 1. Tool registration — all 4 tools registered on McpServer
|
|
9
|
-
* 2. list_terminals — success path + structuredContent shape
|
|
10
|
-
* 3. get_sale — success path + structuredContent shape
|
|
11
|
-
* 4. list_sales — success path + structuredContent shape
|
|
12
|
-
* 5. refund_sale — confirm=false blocked, confirm=true succeeds
|
|
13
|
-
* 6. API error path — 404 propagated through handleToolError
|
|
14
|
-
*/
|
|
15
|
-
import { test, describe, beforeEach } from "node:test";
|
|
16
|
-
import assert from "node:assert/strict";
|
|
17
|
-
class StubMcpServer {
|
|
18
|
-
tools = new Map();
|
|
19
|
-
registerTool(name, config, handler) {
|
|
20
|
-
this.tools.set(name, { name, config, handler });
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
// ── Client stubs ─────────────────────────────────────────────────────────────
|
|
24
|
-
const MOCK_TERMINAL = {
|
|
25
|
-
id: "term_001",
|
|
26
|
-
label: "Front Desk",
|
|
27
|
-
deviceType: "bbpos_wisepos_e",
|
|
28
|
-
locationId: "loc_tenerife",
|
|
29
|
-
status: "online",
|
|
30
|
-
stripeReaderId: "tmr_xxxx",
|
|
31
|
-
createdAt: "2026-01-01T00:00:00Z",
|
|
32
|
-
updatedAt: "2026-01-01T00:00:00Z",
|
|
33
|
-
};
|
|
34
|
-
const MOCK_TERMINALS_LIST = {
|
|
35
|
-
data: [MOCK_TERMINAL],
|
|
36
|
-
total: 1,
|
|
37
|
-
limit: 20,
|
|
38
|
-
offset: 0,
|
|
39
|
-
};
|
|
40
|
-
const MOCK_SALE = {
|
|
41
|
-
id: "sale_abc123",
|
|
42
|
-
terminalId: "term_001",
|
|
43
|
-
status: "succeeded",
|
|
44
|
-
amountCents: 4200,
|
|
45
|
-
currency: "EUR",
|
|
46
|
-
paymentMethod: "card_present",
|
|
47
|
-
items: [
|
|
48
|
-
{ description: "Menu del dia", quantity: 2, unitPriceCents: 1200 },
|
|
49
|
-
{ description: "Agua", quantity: 2, unitPriceCents: 150 },
|
|
50
|
-
],
|
|
51
|
-
refundedAmountCents: 0,
|
|
52
|
-
createdAt: "2026-05-10T12:30:00Z",
|
|
53
|
-
updatedAt: "2026-05-10T12:30:00Z",
|
|
54
|
-
};
|
|
55
|
-
const MOCK_SALES_LIST = {
|
|
56
|
-
data: [MOCK_SALE],
|
|
57
|
-
total: 1,
|
|
58
|
-
limit: 20,
|
|
59
|
-
offset: 0,
|
|
60
|
-
};
|
|
61
|
-
const MOCK_REFUND = {
|
|
62
|
-
id: "ref_xyz789",
|
|
63
|
-
saleId: "sale_abc123",
|
|
64
|
-
status: "succeeded",
|
|
65
|
-
amountCents: 4200,
|
|
66
|
-
currency: "EUR",
|
|
67
|
-
reason: "requested_by_customer",
|
|
68
|
-
createdAt: "2026-05-10T13:00:00Z",
|
|
69
|
-
};
|
|
70
|
-
function makeSuccessClient() {
|
|
71
|
-
return {
|
|
72
|
-
listTerminals: async () => MOCK_TERMINALS_LIST,
|
|
73
|
-
getSale: async (_id) => MOCK_SALE,
|
|
74
|
-
listSales: async () => MOCK_SALES_LIST,
|
|
75
|
-
refundSale: async (_id, _data) => MOCK_REFUND,
|
|
76
|
-
};
|
|
77
|
-
}
|
|
78
|
-
function make404Client() {
|
|
79
|
-
const notFound = () => {
|
|
80
|
-
const err = Object.assign(new Error("Not Found"), { statusCode: 404, errorCode: "not_found" });
|
|
81
|
-
return Promise.reject(err);
|
|
82
|
-
};
|
|
83
|
-
return {
|
|
84
|
-
listTerminals: notFound,
|
|
85
|
-
getSale: notFound,
|
|
86
|
-
listSales: notFound,
|
|
87
|
-
refundSale: notFound,
|
|
88
|
-
};
|
|
89
|
-
}
|
|
90
|
-
// ── Helper ───────────────────────────────────────────────────────────────────
|
|
91
|
-
async function makeServer(clientFn) {
|
|
92
|
-
const server = new StubMcpServer();
|
|
93
|
-
const { registerPosTools } = await import("../tools/pos.js");
|
|
94
|
-
registerPosTools(server, clientFn());
|
|
95
|
-
return server;
|
|
96
|
-
}
|
|
97
|
-
// ── Registration tests ───────────────────────────────────────────────────────
|
|
98
|
-
describe("POS Tools — Registration", () => {
|
|
99
|
-
let server;
|
|
100
|
-
beforeEach(async () => {
|
|
101
|
-
server = await makeServer(makeSuccessClient);
|
|
102
|
-
});
|
|
103
|
-
test("registers exactly 4 POS tools", () => {
|
|
104
|
-
assert.equal(server.tools.size, 4);
|
|
105
|
-
});
|
|
106
|
-
test("registers list_terminals", () => {
|
|
107
|
-
assert.ok(server.tools.has("list_terminals"), "list_terminals not registered");
|
|
108
|
-
});
|
|
109
|
-
test("registers get_sale", () => {
|
|
110
|
-
assert.ok(server.tools.has("get_sale"), "get_sale not registered");
|
|
111
|
-
});
|
|
112
|
-
test("registers list_sales", () => {
|
|
113
|
-
assert.ok(server.tools.has("list_sales"), "list_sales not registered");
|
|
114
|
-
});
|
|
115
|
-
test("registers refund_sale", () => {
|
|
116
|
-
assert.ok(server.tools.has("refund_sale"), "refund_sale not registered");
|
|
117
|
-
});
|
|
118
|
-
});
|
|
119
|
-
// ── list_terminals ───────────────────────────────────────────────────────────
|
|
120
|
-
describe("list_terminals — success path", () => {
|
|
121
|
-
test("returns structuredContent with data array", async () => {
|
|
122
|
-
const server = await makeServer(makeSuccessClient);
|
|
123
|
-
const tool = server.tools.get("list_terminals");
|
|
124
|
-
const result = await tool.handler({});
|
|
125
|
-
assert.ok(!result.isError);
|
|
126
|
-
const sc = result.structuredContent;
|
|
127
|
-
assert.ok(Array.isArray(sc["data"]));
|
|
128
|
-
assert.equal(sc["data"].length, 1);
|
|
129
|
-
assert.equal(sc["total"], 1);
|
|
130
|
-
});
|
|
131
|
-
test("first terminal has expected fields", async () => {
|
|
132
|
-
const server = await makeServer(makeSuccessClient);
|
|
133
|
-
const tool = server.tools.get("list_terminals");
|
|
134
|
-
const result = await tool.handler({});
|
|
135
|
-
const first = result.structuredContent["data"][0];
|
|
136
|
-
assert.equal(first["id"], "term_001");
|
|
137
|
-
assert.equal(first["label"], "Front Desk");
|
|
138
|
-
assert.equal(first["status"], "online");
|
|
139
|
-
assert.equal(first["deviceType"], "bbpos_wisepos_e");
|
|
140
|
-
});
|
|
141
|
-
test("content block has type text", async () => {
|
|
142
|
-
const server = await makeServer(makeSuccessClient);
|
|
143
|
-
const tool = server.tools.get("list_terminals");
|
|
144
|
-
const result = await tool.handler({});
|
|
145
|
-
assert.equal(result.content[0].type, "text");
|
|
146
|
-
assert.ok(result.content[0].text.includes("terminals"));
|
|
147
|
-
});
|
|
148
|
-
});
|
|
149
|
-
// ── get_sale ─────────────────────────────────────────────────────────────────
|
|
150
|
-
describe("get_sale — success path", () => {
|
|
151
|
-
test("returns sale by ID", async () => {
|
|
152
|
-
const server = await makeServer(makeSuccessClient);
|
|
153
|
-
const tool = server.tools.get("get_sale");
|
|
154
|
-
const result = await tool.handler({ id: "sale_abc123" });
|
|
155
|
-
assert.ok(!result.isError);
|
|
156
|
-
const sc = result.structuredContent;
|
|
157
|
-
assert.equal(sc["id"], "sale_abc123");
|
|
158
|
-
assert.equal(sc["status"], "succeeded");
|
|
159
|
-
assert.equal(sc["amountCents"], 4200);
|
|
160
|
-
assert.equal(sc["currency"], "EUR");
|
|
161
|
-
});
|
|
162
|
-
test("items array present", async () => {
|
|
163
|
-
const server = await makeServer(makeSuccessClient);
|
|
164
|
-
const tool = server.tools.get("get_sale");
|
|
165
|
-
const result = await tool.handler({ id: "sale_abc123" });
|
|
166
|
-
const sc = result.structuredContent;
|
|
167
|
-
assert.ok(Array.isArray(sc["items"]));
|
|
168
|
-
assert.equal(sc["items"].length, 2);
|
|
169
|
-
});
|
|
170
|
-
test("404 error propagates as isError=true", async () => {
|
|
171
|
-
const server = await makeServer(make404Client);
|
|
172
|
-
const tool = server.tools.get("get_sale");
|
|
173
|
-
const result = await tool.handler({ id: "sale_missing" });
|
|
174
|
-
assert.ok(result.isError, "should be an error on 404");
|
|
175
|
-
assert.ok(result.content[0].text.includes("Error:"));
|
|
176
|
-
});
|
|
177
|
-
});
|
|
178
|
-
// ── list_sales ───────────────────────────────────────────────────────────────
|
|
179
|
-
describe("list_sales — success path", () => {
|
|
180
|
-
test("returns sales list with total", async () => {
|
|
181
|
-
const server = await makeServer(makeSuccessClient);
|
|
182
|
-
const tool = server.tools.get("list_sales");
|
|
183
|
-
const result = await tool.handler({});
|
|
184
|
-
assert.ok(!result.isError);
|
|
185
|
-
const sc = result.structuredContent;
|
|
186
|
-
assert.ok(Array.isArray(sc["data"]));
|
|
187
|
-
assert.equal(sc["total"], 1);
|
|
188
|
-
});
|
|
189
|
-
test("filters accepted without error", async () => {
|
|
190
|
-
const server = await makeServer(makeSuccessClient);
|
|
191
|
-
const tool = server.tools.get("list_sales");
|
|
192
|
-
const result = await tool.handler({
|
|
193
|
-
terminalId: "term_001",
|
|
194
|
-
status: "succeeded",
|
|
195
|
-
from: "2026-05-01",
|
|
196
|
-
to: "2026-05-31",
|
|
197
|
-
limit: 10,
|
|
198
|
-
offset: 0,
|
|
199
|
-
});
|
|
200
|
-
assert.ok(!result.isError);
|
|
201
|
-
});
|
|
202
|
-
});
|
|
203
|
-
// ── refund_sale ──────────────────────────────────────────────────────────────
|
|
204
|
-
describe("refund_sale — Trust Area confirmation gate", () => {
|
|
205
|
-
test("confirm=false returns isError=true without calling API", async () => {
|
|
206
|
-
const server = await makeServer(makeSuccessClient);
|
|
207
|
-
const tool = server.tools.get("refund_sale");
|
|
208
|
-
const result = await tool.handler({ id: "sale_abc123", confirm: false });
|
|
209
|
-
assert.ok(result.isError, "should be an error when confirm=false");
|
|
210
|
-
assert.ok(result.content[0].text.includes("confirm=true"), "error message should mention confirm=true requirement");
|
|
211
|
-
});
|
|
212
|
-
test("confirm=true proceeds and returns refund data", async () => {
|
|
213
|
-
const server = await makeServer(makeSuccessClient);
|
|
214
|
-
const tool = server.tools.get("refund_sale");
|
|
215
|
-
const result = await tool.handler({
|
|
216
|
-
id: "sale_abc123",
|
|
217
|
-
confirm: true,
|
|
218
|
-
reason: "requested_by_customer",
|
|
219
|
-
});
|
|
220
|
-
assert.ok(!result.isError, "should succeed with confirm=true");
|
|
221
|
-
const sc = result.structuredContent;
|
|
222
|
-
assert.equal(sc["saleId"], "sale_abc123");
|
|
223
|
-
assert.equal(sc["status"], "succeeded");
|
|
224
|
-
assert.equal(sc["amountCents"], 4200);
|
|
225
|
-
});
|
|
226
|
-
test("partial refund with amountCents", async () => {
|
|
227
|
-
const server = await makeServer(makeSuccessClient);
|
|
228
|
-
const tool = server.tools.get("refund_sale");
|
|
229
|
-
const result = await tool.handler({
|
|
230
|
-
id: "sale_abc123",
|
|
231
|
-
confirm: true,
|
|
232
|
-
amountCents: 1200,
|
|
233
|
-
reason: "duplicate",
|
|
234
|
-
});
|
|
235
|
-
assert.ok(!result.isError, "partial refund should succeed");
|
|
236
|
-
});
|
|
237
|
-
test("404 on refund propagates as isError=true", async () => {
|
|
238
|
-
const server = await makeServer(make404Client);
|
|
239
|
-
const tool = server.tools.get("refund_sale");
|
|
240
|
-
const result = await tool.handler({ id: "sale_gone", confirm: true });
|
|
241
|
-
assert.ok(result.isError, "should be an error on 404");
|
|
242
|
-
});
|
|
243
|
-
});
|
|
244
|
-
//# sourceMappingURL=pos-tools.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"pos-tools.test.js","sourceRoot":"","sources":["../../src/__tests__/pos-tools.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Tests for Recurring Invoice MCP tools — Wave Mature 3 (8 tools: 2 original + 6 new).
|
|
3
|
-
*
|
|
4
|
-
* Uses Node.js built-in test runner (node:test + node:assert).
|
|
5
|
-
* Run: npm test (after build)
|
|
6
|
-
*
|
|
7
|
-
* Coverage:
|
|
8
|
-
* 1. Tool registration — all 8 recurring tools registered
|
|
9
|
-
* 2. list_recurring_invoices — success path + structuredContent shape
|
|
10
|
-
* 3. list_recurring_invoices — status filter accepted
|
|
11
|
-
* 4. get_recurring_invoice — success path
|
|
12
|
-
* 5. create_recurring_invoice — success path
|
|
13
|
-
* 6. update_recurring_invoice — success path + partial update
|
|
14
|
-
* 7. pause_recurring_invoice — success path
|
|
15
|
-
* 8. resume_recurring_invoice — success path
|
|
16
|
-
* 9. delete_recurring_invoice — confirm=false gate
|
|
17
|
-
* 10. delete_recurring_invoice — confirm=true success path
|
|
18
|
-
* 11. run_recurring_now — success path (default draftOnly=true)
|
|
19
|
-
* 12. run_recurring_now — draftOnly=false passes through
|
|
20
|
-
* 13. API error — 404 propagated as isError=true
|
|
21
|
-
*/
|
|
22
|
-
export {};
|
|
23
|
-
//# sourceMappingURL=recurring-tools.test.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"recurring-tools.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/recurring-tools.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG"}
|