@frihet/mcp-server 1.13.1 → 1.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/README.md +8 -8
  2. package/dist/__tests__/audit-server-version.test.d.ts +13 -0
  3. package/dist/__tests__/audit-server-version.test.d.ts.map +1 -0
  4. package/dist/__tests__/audit-server-version.test.js +96 -0
  5. package/dist/__tests__/audit-server-version.test.js.map +1 -0
  6. package/dist/__tests__/kitchen-tools.test.d.ts +18 -0
  7. package/dist/__tests__/kitchen-tools.test.d.ts.map +1 -0
  8. package/dist/__tests__/kitchen-tools.test.js +399 -0
  9. package/dist/__tests__/kitchen-tools.test.js.map +1 -0
  10. package/dist/__tests__/openai-grouped-compose.test.d.ts +26 -0
  11. package/dist/__tests__/openai-grouped-compose.test.d.ts.map +1 -0
  12. package/dist/__tests__/openai-grouped-compose.test.js +240 -0
  13. package/dist/__tests__/openai-grouped-compose.test.js.map +1 -0
  14. package/dist/__tests__/tool-exposure.test.js +10 -10
  15. package/dist/client-interface.d.ts +20 -0
  16. package/dist/client-interface.d.ts.map +1 -1
  17. package/dist/client.d.ts +20 -0
  18. package/dist/client.d.ts.map +1 -1
  19. package/dist/client.js +33 -0
  20. package/dist/client.js.map +1 -1
  21. package/dist/index.js +31 -20
  22. package/dist/index.js.map +1 -1
  23. package/dist/openai-profile.d.ts +16 -0
  24. package/dist/openai-profile.d.ts.map +1 -1
  25. package/dist/openai-profile.js +16 -0
  26. package/dist/openai-profile.js.map +1 -1
  27. package/dist/tool-exposure.d.ts +20 -1
  28. package/dist/tool-exposure.d.ts.map +1 -1
  29. package/dist/tool-exposure.js +52 -4
  30. package/dist/tool-exposure.js.map +1 -1
  31. package/dist/tools/kitchen.d.ts +14 -0
  32. package/dist/tools/kitchen.d.ts.map +1 -0
  33. package/dist/tools/kitchen.js +256 -0
  34. package/dist/tools/kitchen.js.map +1 -0
  35. package/dist/tools/register-all.d.ts.map +1 -1
  36. package/dist/tools/register-all.js +2 -0
  37. package/dist/tools/register-all.js.map +1 -1
  38. package/dist/tools/shared.d.ts +40 -0
  39. package/dist/tools/shared.d.ts.map +1 -1
  40. package/dist/tools/shared.js +41 -0
  41. package/dist/tools/shared.js.map +1 -1
  42. package/package.json +3 -3
  43. package/scripts/audit-mcp-refs.mjs +71 -1
  44. package/scripts/test-openai-grouped-compose.mjs +173 -0
package/README.md CHANGED
@@ -17,7 +17,7 @@
17
17
  <a href="https://smithery.ai/server/frihet/frihet-mcp"><img src="https://smithery.ai/badge/frihet/frihet-mcp" alt="Smithery installs"></a>
18
18
  <a href="https://registry.modelcontextprotocol.io/?q=io.frihet"><img src="https://img.shields.io/badge/MCP_Registry-io.frihet%2Ferp-4A90D9?style=flat&logo=anthropic&logoColor=white" alt="MCP Registry"></a>
19
19
  <a href="https://github.com/Frihet-io/frihet-mcp/blob/main/LICENSE"><img src="https://img.shields.io/badge/license-MIT-18181b?style=flat&labelColor=09090b" alt="license"></a>
20
- <img src="https://img.shields.io/badge/tools-151-18181b?style=flat&labelColor=09090b" alt="151 tools">
20
+ <img src="https://img.shields.io/badge/tools-157-18181b?style=flat&labelColor=09090b" alt="157 tools">
21
21
  <img src="https://img.shields.io/badge/node-%3E%3D18-18181b?style=flat&labelColor=09090b" alt="node >=18">
22
22
  <a href="https://www.typescriptlang.org/"><img src="https://img.shields.io/badge/TypeScript-18181b?style=flat&labelColor=09090b" alt="TypeScript"></a>
23
23
  </p>
@@ -39,7 +39,7 @@
39
39
  | **ChatGPT Apps** | Coming soon | [chatgpt.com](https://chatgpt.com) |
40
40
  | **Anthropic Claude Directory** | Coming soon | [claude.ai/settings/connectors](https://claude.ai/settings/connectors) |
41
41
 
42
- > **Tool count:** npm `latest` (1.13.1) ships all 151 tools, same as the remote endpoint (`mcp.frihet.io`).
42
+ > **Tool count:** npm `latest` (1.14.0) ships all 157 tools, same as the remote endpoint (`mcp.frihet.io`).
43
43
 
44
44
  ---
45
45
 
@@ -52,9 +52,9 @@ You: "Create an invoice for TechStart SL, 40 hours of consulting at 75 EUR/h
52
52
  Claude: Done. Invoice INV-2026-089 created. Total: 3,000.00 EUR + 21% IVA = 3,630.00 EUR.
53
53
  ```
54
54
 
55
- 151 tools. 11 resources. 10 prompts. Structured output on every tool. Zero boilerplate.
55
+ 157 tools. 11 resources. 10 prompts. Structured output on every tool. Zero boilerplate.
56
56
 
57
- <!-- v1.12.0-beta.1 — D4-B megasprint: HR (9), payroll (2), onboarding (2), permissions (2), period close (3), webhook test (1) = +19 = 151 tools total -->
57
+ <!-- v1.12.0-beta.1 — D4-B megasprint: HR (9), payroll (2), onboarding (2), permissions (2), period close (3), webhook test (1) = +19 = 157 tools total -->
58
58
 
59
59
  ---
60
60
 
@@ -182,7 +182,7 @@ Talk to your ERP. These are real prompts, not marketing copy.
182
182
 
183
183
  ## What to expect
184
184
 
185
- This MCP is a **structured data interface** -- you describe what you want in natural language, and the AI creates, queries, or modifies business records in Frihet. All 151 tools are CRUD operations over the REST API.
185
+ This MCP is a **structured data interface** -- you describe what you want in natural language, and the AI creates, queries, or modifies business records in Frihet. All 157 tools are CRUD operations over the REST API.
186
186
 
187
187
  **Works great:**
188
188
 
@@ -209,7 +209,7 @@ If you need to digitize paper invoices or receipts, extract the data first (e.g.
209
209
 
210
210
  ---
211
211
 
212
- ## Tools (151)
212
+ ## Tools (157)
213
213
 
214
214
  ### Invoices (12)
215
215
 
@@ -545,7 +545,7 @@ If you need to digitize paper invoices or receipts, extract the data first (e.g.
545
545
  | `period_close` | Close an accounting period (gestor/admin only — TRUST AREA) |
546
546
  | `period_reopen` | Reopen a closed period with a mandatory reason (TRUST AREA) |
547
547
 
548
- All 151 tools return **structured output** via `outputSchema` -- typed JSON, not raw text. List tools return paginated results (`{ data, total, limit, offset }`).
548
+ All 157 tools return **structured output** via `outputSchema` -- typed JSON, not raw text. List tools return paginated results (`{ data, total, limit, offset }`).
549
549
 
550
550
  ---
551
551
 
@@ -768,7 +768,7 @@ npm run build # must pass before submitting
768
768
 
769
769
  | Package | What it is |
770
770
  |---------|-----------|
771
- | [`@frihet/mcp-server`](https://www.npmjs.com/package/@frihet/mcp-server) | This MCP server (151 tools, 11 resources, 10 prompts) |
771
+ | [`@frihet/mcp-server`](https://www.npmjs.com/package/@frihet/mcp-server) | This MCP server (157 tools, 11 resources, 10 prompts) |
772
772
  | [`@frihet/sdk`](https://github.com/Frihet-io/frihet-sdk) | TypeScript SDK (`frihet.invoices.create()`) |
773
773
  | [`frihet`](https://www.npmjs.com/package/frihet) | CLI (`frihet invoices list --status overdue`) |
774
774
  | [`n8n-nodes-frihet`](https://www.npmjs.com/package/n8n-nodes-frihet) | n8n community node for workflow automation |
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Tests for the server.json version gate in scripts/audit-mcp-refs.mjs.
3
+ *
4
+ * Regression guard: server.json carries the package version as BARE JSON values
5
+ * (root `.version` and `.packages[0].version`). The audit's generic line-scan
6
+ * version check requires an MCP marker on the same line, which never matched
7
+ * those bare `"version": "x.y.z"` lines — so a desynced server.json passed the
8
+ * publish gate silently and caused a Registry 400 "duplicate version" in
9
+ * release 1.13.1. The `checkServerJsonVersion` helper closes that gap; these
10
+ * tests prove it FAILS on drift and PASSES when synced.
11
+ */
12
+ export {};
13
+ //# sourceMappingURL=audit-server-version.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audit-server-version.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/audit-server-version.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG"}
@@ -0,0 +1,96 @@
1
+ /**
2
+ * Tests for the server.json version gate in scripts/audit-mcp-refs.mjs.
3
+ *
4
+ * Regression guard: server.json carries the package version as BARE JSON values
5
+ * (root `.version` and `.packages[0].version`). The audit's generic line-scan
6
+ * version check requires an MCP marker on the same line, which never matched
7
+ * those bare `"version": "x.y.z"` lines — so a desynced server.json passed the
8
+ * publish gate silently and caused a Registry 400 "duplicate version" in
9
+ * release 1.13.1. The `checkServerJsonVersion` helper closes that gap; these
10
+ * tests prove it FAILS on drift and PASSES when synced.
11
+ */
12
+ import { describe, test } from "node:test";
13
+ import assert from "node:assert/strict";
14
+ import { readFileSync, writeFileSync, mkdtempSync, rmSync } from "node:fs";
15
+ import { tmpdir } from "node:os";
16
+ import { join, resolve } from "node:path";
17
+ import { fileURLToPath, pathToFileURL } from "node:url";
18
+ // dist/__tests__/ → repo root is ../../ ; scripts + server.json live at root.
19
+ const HERE = resolve(fileURLToPath(import.meta.url), "..");
20
+ const REPO_ROOT = resolve(HERE, "..", "..");
21
+ const SERVER_JSON_PATH = join(REPO_ROOT, "server.json");
22
+ const PKG_PATH = join(REPO_ROOT, "package.json");
23
+ // Import the pure helper from the audit script. The script is import-safe:
24
+ // its CLI body is guarded by an `if (isMain)` check, so importing it does not
25
+ // run the audit or call process.exit.
26
+ const auditScriptUrl = pathToFileURL(resolve(REPO_ROOT, "scripts", "audit-mcp-refs.mjs")).href;
27
+ const auditMod = await import(auditScriptUrl);
28
+ const checkServerJsonVersion = auditMod.checkServerJsonVersion;
29
+ const SOT_VERSION = JSON.parse(readFileSync(PKG_PATH, "utf8")).version;
30
+ describe("server.json version gate", () => {
31
+ test("exports a checkServerJsonVersion helper", () => {
32
+ assert.equal(typeof checkServerJsonVersion, "function");
33
+ });
34
+ test("real server.json is in sync with package.json (no drift)", () => {
35
+ const serverJson = JSON.parse(readFileSync(SERVER_JSON_PATH, "utf8"));
36
+ const drifts = checkServerJsonVersion(serverJson, SOT_VERSION);
37
+ assert.deepEqual(drifts, [], `server.json must match SoT ${SOT_VERSION} — drift: ${JSON.stringify(drifts)}`);
38
+ });
39
+ test("reports STALE when root .version drifts", () => {
40
+ const serverJson = JSON.parse(readFileSync(SERVER_JSON_PATH, "utf8"));
41
+ serverJson.version = "9.9.9";
42
+ const drifts = checkServerJsonVersion(serverJson, SOT_VERSION);
43
+ assert.equal(drifts.length, 1, "exactly one drift expected");
44
+ assert.equal(drifts[0].jsonPath, ".version");
45
+ assert.equal(drifts[0].found, "9.9.9");
46
+ assert.equal(drifts[0].expected, SOT_VERSION);
47
+ });
48
+ test("reports STALE when .packages[0].version drifts", () => {
49
+ const serverJson = JSON.parse(readFileSync(SERVER_JSON_PATH, "utf8"));
50
+ serverJson.packages[0].version = "0.0.1";
51
+ const drifts = checkServerJsonVersion(serverJson, SOT_VERSION);
52
+ assert.equal(drifts.length, 1);
53
+ assert.equal(drifts[0].jsonPath, ".packages[0].version");
54
+ assert.equal(drifts[0].found, "0.0.1");
55
+ });
56
+ test("reports BOTH fields when both drift", () => {
57
+ const serverJson = JSON.parse(readFileSync(SERVER_JSON_PATH, "utf8"));
58
+ serverJson.version = "2.0.0";
59
+ serverJson.packages[0].version = "2.0.0";
60
+ const drifts = checkServerJsonVersion(serverJson, SOT_VERSION);
61
+ assert.equal(drifts.length, 2);
62
+ assert.deepEqual(drifts.map((d) => d.jsonPath).sort(), [".packages[0].version", ".version"]);
63
+ });
64
+ test("treats a missing version field as drift (not a silent pass)", () => {
65
+ const serverJson = JSON.parse(readFileSync(SERVER_JSON_PATH, "utf8"));
66
+ delete serverJson.version;
67
+ const drifts = checkServerJsonVersion(serverJson, SOT_VERSION);
68
+ assert.equal(drifts.length, 1);
69
+ assert.equal(drifts[0].jsonPath, ".version");
70
+ assert.equal(drifts[0].found, undefined);
71
+ });
72
+ // End-to-end proof the gate fires on a real desynced file, written to a temp
73
+ // copy so the repo's server.json is never mutated. We reproduce the exact
74
+ // helper-driven check the CLI runs, then confirm the synced copy is clean.
75
+ test("temp-file round trip: desync fails, sync passes", () => {
76
+ const dir = mkdtempSync(join(tmpdir(), "frihet-serverjson-"));
77
+ try {
78
+ const original = readFileSync(SERVER_JSON_PATH, "utf8");
79
+ const tmpFile = join(dir, "server.json");
80
+ // Desync the temp copy.
81
+ const desynced = JSON.parse(original);
82
+ desynced.version = "0.0.0-stale";
83
+ writeFileSync(tmpFile, JSON.stringify(desynced, null, 2) + "\n");
84
+ const staleDrifts = checkServerJsonVersion(JSON.parse(readFileSync(tmpFile, "utf8")), SOT_VERSION);
85
+ assert.ok(staleDrifts.length > 0, "desynced temp file must report STALE");
86
+ // Re-sync and confirm clean.
87
+ writeFileSync(tmpFile, original);
88
+ const cleanDrifts = checkServerJsonVersion(JSON.parse(readFileSync(tmpFile, "utf8")), SOT_VERSION);
89
+ assert.deepEqual(cleanDrifts, [], "synced temp file must pass");
90
+ }
91
+ finally {
92
+ rmSync(dir, { recursive: true, force: true });
93
+ }
94
+ });
95
+ });
96
+ //# sourceMappingURL=audit-server-version.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audit-server-version.test.js","sourceRoot":"","sources":["../../src/__tests__/audit-server-version.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Tests for Kitchen MCP tools — Wave 6 (6 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 6 tools registered on McpServer
9
+ * 2. list_kitchen_tickets — success path + structuredContent shape
10
+ * 3. get_kitchen_ticket — success path + structuredContent shape
11
+ * 4. update_kitchen_ticket — success path + structuredContent shape
12
+ * 5. list_kitchen_stations — success path + structuredContent shape
13
+ * 6. list_menu_items — success path + structuredContent shape
14
+ * 7. kitchen_flow_summary — success path + bottleneck detection
15
+ * 8. API error path — 404 propagated through handleToolError
16
+ */
17
+ export {};
18
+ //# sourceMappingURL=kitchen-tools.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"kitchen-tools.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/kitchen-tools.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG"}
@@ -0,0 +1,399 @@
1
+ /**
2
+ * Tests for Kitchen MCP tools — Wave 6 (6 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 6 tools registered on McpServer
9
+ * 2. list_kitchen_tickets — success path + structuredContent shape
10
+ * 3. get_kitchen_ticket — success path + structuredContent shape
11
+ * 4. update_kitchen_ticket — success path + structuredContent shape
12
+ * 5. list_kitchen_stations — success path + structuredContent shape
13
+ * 6. list_menu_items — success path + structuredContent shape
14
+ * 7. kitchen_flow_summary — success path + bottleneck detection
15
+ * 8. API error path — 404 propagated through handleToolError
16
+ */
17
+ import { test, describe, beforeEach } from "node:test";
18
+ import assert from "node:assert/strict";
19
+ class StubMcpServer {
20
+ tools = new Map();
21
+ registerTool(name, config, handler) {
22
+ this.tools.set(name, { name, config, handler });
23
+ }
24
+ }
25
+ // ── Fixtures ─────────────────────────────────────────────────────────────────
26
+ const MOCK_TICKET = {
27
+ id: "tkt_001",
28
+ stationId: "sta_grill",
29
+ status: "preparing",
30
+ tableRef: "T4",
31
+ items: [
32
+ { id: "ti_001", menuItemId: "mi_burger", name: "Burger", quantity: 2, notes: "no onions", status: "preparing" },
33
+ ],
34
+ createdAt: "2026-06-15T12:00:00Z",
35
+ updatedAt: "2026-06-15T12:01:00Z",
36
+ };
37
+ const MOCK_TICKET_2 = {
38
+ id: "tkt_002",
39
+ stationId: "sta_grill",
40
+ status: "queued",
41
+ tableRef: "T5",
42
+ items: [
43
+ { id: "ti_002", menuItemId: "mi_fries", name: "Fries", quantity: 1, notes: "", status: "queued" },
44
+ ],
45
+ createdAt: "2026-06-15T12:02:00Z",
46
+ updatedAt: "2026-06-15T12:02:00Z",
47
+ };
48
+ const MOCK_TICKET_3 = {
49
+ id: "tkt_003",
50
+ stationId: "sta_bar",
51
+ status: "ready",
52
+ tableRef: "T2",
53
+ items: [
54
+ { id: "ti_003", menuItemId: "mi_mojito", name: "Mojito", quantity: 3, notes: "", status: "ready" },
55
+ ],
56
+ createdAt: "2026-06-15T12:05:00Z",
57
+ updatedAt: "2026-06-15T12:06:00Z",
58
+ };
59
+ const MOCK_TICKETS_LIST = {
60
+ data: [MOCK_TICKET, MOCK_TICKET_2, MOCK_TICKET_3],
61
+ total: 3,
62
+ limit: 100,
63
+ offset: 0,
64
+ };
65
+ const MOCK_STATION = {
66
+ id: "sta_grill",
67
+ name: "Grill",
68
+ isActive: true,
69
+ createdAt: "2026-01-01T00:00:00Z",
70
+ updatedAt: "2026-01-01T00:00:00Z",
71
+ };
72
+ const MOCK_STATION_2 = {
73
+ id: "sta_bar",
74
+ name: "Bar",
75
+ isActive: true,
76
+ createdAt: "2026-01-01T00:00:00Z",
77
+ updatedAt: "2026-01-01T00:00:00Z",
78
+ };
79
+ const MOCK_STATIONS_LIST = {
80
+ data: [MOCK_STATION, MOCK_STATION_2],
81
+ total: 2,
82
+ limit: 100,
83
+ offset: 0,
84
+ };
85
+ const MOCK_MENU_ITEM = {
86
+ id: "mi_burger",
87
+ name: "Burger",
88
+ description: "Classic beef burger",
89
+ priceCents: 1200,
90
+ category: "Main",
91
+ isActive: true,
92
+ createdAt: "2026-01-01T00:00:00Z",
93
+ updatedAt: "2026-01-01T00:00:00Z",
94
+ };
95
+ const MOCK_MENU_ITEMS_LIST = {
96
+ data: [MOCK_MENU_ITEM],
97
+ total: 1,
98
+ limit: 20,
99
+ offset: 0,
100
+ };
101
+ const MOCK_UPDATED_TICKET = { ...MOCK_TICKET, status: "ready" };
102
+ // ── Client stubs ─────────────────────────────────────────────────────────────
103
+ function makeSuccessClient() {
104
+ return {
105
+ listKitchenTickets: async () => MOCK_TICKETS_LIST,
106
+ getKitchenTicket: async (_id) => MOCK_TICKET,
107
+ updateKitchenTicket: async (_id, _data) => MOCK_UPDATED_TICKET,
108
+ listKitchenStations: async () => MOCK_STATIONS_LIST,
109
+ listMenuItems: async () => MOCK_MENU_ITEMS_LIST,
110
+ };
111
+ }
112
+ function make404Client() {
113
+ const notFound = () => {
114
+ const err = Object.assign(new Error("Not Found"), { statusCode: 404, errorCode: "not_found" });
115
+ return Promise.reject(err);
116
+ };
117
+ return {
118
+ listKitchenTickets: notFound,
119
+ getKitchenTicket: notFound,
120
+ updateKitchenTicket: notFound,
121
+ listKitchenStations: notFound,
122
+ listMenuItems: notFound,
123
+ };
124
+ }
125
+ // ── Helper ───────────────────────────────────────────────────────────────────
126
+ async function makeServer(clientFn) {
127
+ const server = new StubMcpServer();
128
+ const { registerKitchenTools } = await import("../tools/kitchen.js");
129
+ registerKitchenTools(server, clientFn());
130
+ return server;
131
+ }
132
+ // ── Registration tests ───────────────────────────────────────────────────────
133
+ describe("Kitchen Tools — Registration", () => {
134
+ let server;
135
+ beforeEach(async () => {
136
+ server = await makeServer(makeSuccessClient);
137
+ });
138
+ test("registers exactly 6 kitchen tools", () => {
139
+ assert.equal(server.tools.size, 6);
140
+ });
141
+ test("registers list_kitchen_tickets", () => {
142
+ assert.ok(server.tools.has("list_kitchen_tickets"), "list_kitchen_tickets not registered");
143
+ });
144
+ test("registers get_kitchen_ticket", () => {
145
+ assert.ok(server.tools.has("get_kitchen_ticket"), "get_kitchen_ticket not registered");
146
+ });
147
+ test("registers update_kitchen_ticket", () => {
148
+ assert.ok(server.tools.has("update_kitchen_ticket"), "update_kitchen_ticket not registered");
149
+ });
150
+ test("registers list_kitchen_stations", () => {
151
+ assert.ok(server.tools.has("list_kitchen_stations"), "list_kitchen_stations not registered");
152
+ });
153
+ test("registers list_menu_items", () => {
154
+ assert.ok(server.tools.has("list_menu_items"), "list_menu_items not registered");
155
+ });
156
+ test("registers kitchen_flow_summary", () => {
157
+ assert.ok(server.tools.has("kitchen_flow_summary"), "kitchen_flow_summary not registered");
158
+ });
159
+ });
160
+ // ── Output schemas ────────────────────────────────────────────────────────────
161
+ describe("Kitchen Tools — Output schemas", () => {
162
+ test("all tools have an outputSchema", async () => {
163
+ const server = await makeServer(makeSuccessClient);
164
+ const expected = [
165
+ "list_kitchen_tickets",
166
+ "get_kitchen_ticket",
167
+ "update_kitchen_ticket",
168
+ "list_kitchen_stations",
169
+ "list_menu_items",
170
+ "kitchen_flow_summary",
171
+ ];
172
+ for (const name of expected) {
173
+ const tool = server.tools.get(name);
174
+ assert.ok(tool.config.outputSchema, `${name} must have outputSchema`);
175
+ }
176
+ });
177
+ });
178
+ // ── list_kitchen_tickets ──────────────────────────────────────────────────────
179
+ describe("list_kitchen_tickets — success path", () => {
180
+ test("returns structuredContent with data array", async () => {
181
+ const server = await makeServer(makeSuccessClient);
182
+ const tool = server.tools.get("list_kitchen_tickets");
183
+ const result = await tool.handler({ limit: 100, offset: 0 });
184
+ assert.ok(!result.isError, "should not be an error");
185
+ assert.ok(result.structuredContent, "structuredContent missing");
186
+ const sc = result.structuredContent;
187
+ assert.ok(Array.isArray(sc["data"]), "data should be an array");
188
+ assert.equal(sc["data"].length, 3);
189
+ assert.equal(sc["total"], 3);
190
+ });
191
+ test("first ticket has expected fields", async () => {
192
+ const server = await makeServer(makeSuccessClient);
193
+ const tool = server.tools.get("list_kitchen_tickets");
194
+ const result = await tool.handler({});
195
+ const sc = result.structuredContent;
196
+ const first = sc["data"][0];
197
+ assert.equal(first["id"], "tkt_001");
198
+ assert.equal(first["status"], "preparing");
199
+ assert.equal(first["stationId"], "sta_grill");
200
+ assert.equal(first["tableRef"], "T4");
201
+ });
202
+ test("content block has type text and mentions tickets", async () => {
203
+ const server = await makeServer(makeSuccessClient);
204
+ const tool = server.tools.get("list_kitchen_tickets");
205
+ const result = await tool.handler({});
206
+ assert.ok(Array.isArray(result.content));
207
+ assert.equal(result.content[0].type, "text");
208
+ assert.ok(result.content[0].text.includes("kitchen tickets"));
209
+ });
210
+ test("404 error propagates as isError=true", async () => {
211
+ const server = await makeServer(make404Client);
212
+ const tool = server.tools.get("list_kitchen_tickets");
213
+ const result = await tool.handler({});
214
+ assert.ok(result.isError, "should be an error on 404");
215
+ assert.ok(result.content[0].text.includes("Error:"));
216
+ });
217
+ });
218
+ // ── get_kitchen_ticket ────────────────────────────────────────────────────────
219
+ describe("get_kitchen_ticket — success path", () => {
220
+ test("returns single ticket by ID", async () => {
221
+ const server = await makeServer(makeSuccessClient);
222
+ const tool = server.tools.get("get_kitchen_ticket");
223
+ const result = await tool.handler({ id: "tkt_001" });
224
+ assert.ok(!result.isError);
225
+ const sc = result.structuredContent;
226
+ assert.equal(sc["id"], "tkt_001");
227
+ assert.equal(sc["status"], "preparing");
228
+ assert.equal(sc["stationId"], "sta_grill");
229
+ });
230
+ test("404 error propagates as isError=true", async () => {
231
+ const server = await makeServer(make404Client);
232
+ const tool = server.tools.get("get_kitchen_ticket");
233
+ const result = await tool.handler({ id: "tkt_missing" });
234
+ assert.ok(result.isError, "should be an error on 404");
235
+ assert.ok(result.content[0].text.includes("Error:"));
236
+ });
237
+ });
238
+ // ── update_kitchen_ticket ─────────────────────────────────────────────────────
239
+ describe("update_kitchen_ticket — success path", () => {
240
+ test("returns updated ticket with new status", async () => {
241
+ const server = await makeServer(makeSuccessClient);
242
+ const tool = server.tools.get("update_kitchen_ticket");
243
+ const result = await tool.handler({ id: "tkt_001", status: "ready" });
244
+ assert.ok(!result.isError);
245
+ const sc = result.structuredContent;
246
+ assert.equal(sc["id"], "tkt_001");
247
+ assert.equal(sc["status"], "ready");
248
+ });
249
+ test("content block is a mutate-type annotated text", async () => {
250
+ const server = await makeServer(makeSuccessClient);
251
+ const tool = server.tools.get("update_kitchen_ticket");
252
+ const result = await tool.handler({ id: "tkt_001", status: "ready" });
253
+ assert.equal(result.content[0].type, "text");
254
+ assert.ok(result.content[0].text.includes("Kitchen ticket updated"));
255
+ });
256
+ test("calls client.updateKitchenTicket with correct args", async () => {
257
+ let calledId;
258
+ let calledData;
259
+ const client = {
260
+ updateKitchenTicket: async (id, data) => {
261
+ calledId = id;
262
+ calledData = data;
263
+ return MOCK_UPDATED_TICKET;
264
+ },
265
+ };
266
+ const server = new StubMcpServer();
267
+ const { registerKitchenTools } = await import("../tools/kitchen.js");
268
+ registerKitchenTools(server, client);
269
+ await server.tools.get("update_kitchen_ticket").handler({ id: "tkt_001", status: "ready", stationId: "sta_bar" });
270
+ assert.equal(calledId, "tkt_001");
271
+ assert.equal(calledData?.["status"], "ready");
272
+ assert.equal(calledData?.["stationId"], "sta_bar");
273
+ });
274
+ });
275
+ // ── list_kitchen_stations ─────────────────────────────────────────────────────
276
+ describe("list_kitchen_stations — success path", () => {
277
+ test("returns stations list with total", async () => {
278
+ const server = await makeServer(makeSuccessClient);
279
+ const tool = server.tools.get("list_kitchen_stations");
280
+ const result = await tool.handler({});
281
+ assert.ok(!result.isError);
282
+ const sc = result.structuredContent;
283
+ assert.ok(Array.isArray(sc["data"]));
284
+ assert.equal(sc["total"], 2);
285
+ });
286
+ test("first station has expected fields", async () => {
287
+ const server = await makeServer(makeSuccessClient);
288
+ const tool = server.tools.get("list_kitchen_stations");
289
+ const result = await tool.handler({});
290
+ const first = result.structuredContent["data"][0];
291
+ assert.equal(first["id"], "sta_grill");
292
+ assert.equal(first["name"], "Grill");
293
+ assert.equal(first["isActive"], true);
294
+ });
295
+ });
296
+ // ── list_menu_items ───────────────────────────────────────────────────────────
297
+ describe("list_menu_items — success path", () => {
298
+ test("returns menu items list with total", async () => {
299
+ const server = await makeServer(makeSuccessClient);
300
+ const tool = server.tools.get("list_menu_items");
301
+ const result = await tool.handler({});
302
+ assert.ok(!result.isError);
303
+ const sc = result.structuredContent;
304
+ assert.ok(Array.isArray(sc["data"]));
305
+ assert.equal(sc["total"], 1);
306
+ });
307
+ test("first menu item has expected fields", async () => {
308
+ const server = await makeServer(makeSuccessClient);
309
+ const tool = server.tools.get("list_menu_items");
310
+ const result = await tool.handler({ isActive: true });
311
+ const first = result.structuredContent["data"][0];
312
+ assert.equal(first["id"], "mi_burger");
313
+ assert.equal(first["name"], "Burger");
314
+ assert.equal(first["priceCents"], 1200);
315
+ assert.equal(first["category"], "Main");
316
+ assert.equal(first["isActive"], true);
317
+ });
318
+ });
319
+ // ── kitchen_flow_summary ──────────────────────────────────────────────────────
320
+ describe("kitchen_flow_summary — success path", () => {
321
+ test("returns summary with stations array and totalOpenTickets", async () => {
322
+ const server = await makeServer(makeSuccessClient);
323
+ const tool = server.tools.get("kitchen_flow_summary");
324
+ const result = await tool.handler({});
325
+ assert.ok(!result.isError, "should not be an error");
326
+ const sc = result.structuredContent;
327
+ assert.ok(Array.isArray(sc["stations"]), "stations must be an array");
328
+ assert.ok(typeof sc["totalOpenTickets"] === "number", "totalOpenTickets must be a number");
329
+ assert.ok(typeof sc["generatedAt"] === "string", "generatedAt must be a string");
330
+ });
331
+ test("counts open tickets per station (2 grill, 1 bar — served/cancelled excluded)", async () => {
332
+ // MOCK_TICKETS_LIST has tkt_001 (grill/preparing), tkt_002 (grill/queued), tkt_003 (bar/ready)
333
+ // All are open (none served or cancelled)
334
+ const server = await makeServer(makeSuccessClient);
335
+ const tool = server.tools.get("kitchen_flow_summary");
336
+ const result = await tool.handler({});
337
+ const sc = result.structuredContent;
338
+ const stations = sc["stations"];
339
+ assert.equal(sc["totalOpenTickets"], 3);
340
+ const grill = stations.find((s) => s["stationId"] === "sta_grill");
341
+ const bar = stations.find((s) => s["stationId"] === "sta_bar");
342
+ assert.ok(grill, "grill station should be present");
343
+ assert.ok(bar, "bar station should be present");
344
+ assert.equal(grill["openTickets"], 2);
345
+ assert.equal(bar["openTickets"], 1);
346
+ });
347
+ test("flags grill as bottleneck (2 open tickets > bar 1)", async () => {
348
+ const server = await makeServer(makeSuccessClient);
349
+ const tool = server.tools.get("kitchen_flow_summary");
350
+ const result = await tool.handler({});
351
+ const sc = result.structuredContent;
352
+ assert.equal(sc["bottleneckStationId"], "sta_grill");
353
+ const stations = sc["stations"];
354
+ const grill = stations.find((s) => s["stationId"] === "sta_grill");
355
+ const bar = stations.find((s) => s["stationId"] === "sta_bar");
356
+ assert.equal(grill["isBottleneck"], true);
357
+ assert.equal(bar["isBottleneck"], false);
358
+ });
359
+ test("excludes served and cancelled tickets from counts", async () => {
360
+ const servedTicket = { ...MOCK_TICKET, id: "tkt_served", stationId: "sta_grill", status: "served" };
361
+ const cancelledTicket = { ...MOCK_TICKET, id: "tkt_cancelled", stationId: "sta_bar", status: "cancelled" };
362
+ const client = {
363
+ listKitchenTickets: async () => ({
364
+ data: [MOCK_TICKET, servedTicket, cancelledTicket],
365
+ total: 3,
366
+ limit: 100,
367
+ offset: 0,
368
+ }),
369
+ listKitchenStations: async () => MOCK_STATIONS_LIST,
370
+ };
371
+ const server = new StubMcpServer();
372
+ const { registerKitchenTools } = await import("../tools/kitchen.js");
373
+ registerKitchenTools(server, client);
374
+ const result = await server.tools.get("kitchen_flow_summary").handler({});
375
+ const sc = result.structuredContent;
376
+ // Only tkt_001 (grill/preparing) is open
377
+ assert.equal(sc["totalOpenTickets"], 1);
378
+ const stations = sc["stations"];
379
+ const grill = stations.find((s) => s["stationId"] === "sta_grill");
380
+ const bar = stations.find((s) => s["stationId"] === "sta_bar");
381
+ assert.equal(grill["openTickets"], 1);
382
+ assert.equal(bar["openTickets"], 0);
383
+ });
384
+ test("content block mentions summary", async () => {
385
+ const server = await makeServer(makeSuccessClient);
386
+ const tool = server.tools.get("kitchen_flow_summary");
387
+ const result = await tool.handler({});
388
+ assert.ok(Array.isArray(result.content));
389
+ assert.equal(result.content[0].type, "text");
390
+ assert.ok(result.content[0].text.includes("Kitchen flow summary"));
391
+ });
392
+ test("404 error propagates as isError=true", async () => {
393
+ const server = await makeServer(make404Client);
394
+ const tool = server.tools.get("kitchen_flow_summary");
395
+ const result = await tool.handler({});
396
+ assert.ok(result.isError, "should be an error on 404");
397
+ });
398
+ });
399
+ //# sourceMappingURL=kitchen-tools.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"kitchen-tools.test.js","sourceRoot":"","sources":["../../src/__tests__/kitchen-tools.test.ts"],"names":[],"mappings":"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"}