@frihet/mcp-server 1.13.1 → 1.14.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.
Files changed (58) 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__/banking-client-contract.test.d.ts +20 -0
  7. package/dist/__tests__/banking-client-contract.test.d.ts.map +1 -0
  8. package/dist/__tests__/banking-client-contract.test.js +133 -0
  9. package/dist/__tests__/banking-client-contract.test.js.map +1 -0
  10. package/dist/__tests__/einvoice-day4-tools.test.js +84 -0
  11. package/dist/__tests__/einvoice-day4-tools.test.js.map +1 -1
  12. package/dist/__tests__/kitchen-tools.test.d.ts +18 -0
  13. package/dist/__tests__/kitchen-tools.test.d.ts.map +1 -0
  14. package/dist/__tests__/kitchen-tools.test.js +399 -0
  15. package/dist/__tests__/kitchen-tools.test.js.map +1 -0
  16. package/dist/__tests__/openai-grouped-compose.test.d.ts +26 -0
  17. package/dist/__tests__/openai-grouped-compose.test.d.ts.map +1 -0
  18. package/dist/__tests__/openai-grouped-compose.test.js +240 -0
  19. package/dist/__tests__/openai-grouped-compose.test.js.map +1 -0
  20. package/dist/__tests__/tool-exposure.test.js +10 -10
  21. package/dist/client-interface.d.ts +20 -0
  22. package/dist/client-interface.d.ts.map +1 -1
  23. package/dist/client.d.ts +20 -0
  24. package/dist/client.d.ts.map +1 -1
  25. package/dist/client.js +36 -1
  26. package/dist/client.js.map +1 -1
  27. package/dist/index.js +31 -20
  28. package/dist/index.js.map +1 -1
  29. package/dist/openai-profile.d.ts +16 -0
  30. package/dist/openai-profile.d.ts.map +1 -1
  31. package/dist/openai-profile.js +16 -0
  32. package/dist/openai-profile.js.map +1 -1
  33. package/dist/tool-exposure.d.ts +20 -1
  34. package/dist/tool-exposure.d.ts.map +1 -1
  35. package/dist/tool-exposure.js +52 -4
  36. package/dist/tool-exposure.js.map +1 -1
  37. package/dist/tools/banking.d.ts +4 -2
  38. package/dist/tools/banking.d.ts.map +1 -1
  39. package/dist/tools/banking.js +4 -2
  40. package/dist/tools/banking.js.map +1 -1
  41. package/dist/tools/einvoice.d.ts +12 -4
  42. package/dist/tools/einvoice.d.ts.map +1 -1
  43. package/dist/tools/einvoice.js +24 -6
  44. package/dist/tools/einvoice.js.map +1 -1
  45. package/dist/tools/kitchen.d.ts +14 -0
  46. package/dist/tools/kitchen.d.ts.map +1 -0
  47. package/dist/tools/kitchen.js +256 -0
  48. package/dist/tools/kitchen.js.map +1 -0
  49. package/dist/tools/register-all.d.ts.map +1 -1
  50. package/dist/tools/register-all.js +2 -0
  51. package/dist/tools/register-all.js.map +1 -1
  52. package/dist/tools/shared.d.ts +40 -0
  53. package/dist/tools/shared.d.ts.map +1 -1
  54. package/dist/tools/shared.js +41 -0
  55. package/dist/tools/shared.js.map +1 -1
  56. package/package.json +3 -3
  57. package/scripts/audit-mcp-refs.mjs +71 -1
  58. package/scripts/test-openai-grouped-compose.mjs +173 -0
@@ -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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"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Tests for the OpenAI × grouped tool-exposure COMPOSITION.
3
+ *
4
+ * openai-mcp.frihet.io now runs BOTH profiles: the OpenAI-safe profile
5
+ * (53 reviewed tools, redaction, openWorldHint justification) AND the grouped
6
+ * progressive-disclosure profile (terse descriptions + 3 discovery meta-tools).
7
+ *
8
+ * This is the Trust-Area-critical surface that the ChatGPT app review covers, so
9
+ * the three invariants below are asserted explicitly:
10
+ *
11
+ * (1) The 3 grouped meta-tools (search_tools, describe_tool, list_tool_groups)
12
+ * are PRESENT in OpenAI mode — they register against the real server and
13
+ * bypass the OpenAI allow-list gate. Live surface = 53 + 3 = 56 tools.
14
+ * (2) Every one of the 53 reviewed tools has a COLLAPSED (terse) description
15
+ * AND still carries the per-tool openWorldHint rationale marker that OpenAI
16
+ * app review requires.
17
+ * (3) The grouped catalog (what search_tools / describe_tool / list_tool_groups
18
+ * surface) contains ONLY the 53 reviewed tools — a tool outside the reviewed
19
+ * set is never returned by search_tools and is rejected by describe_tool.
20
+ *
21
+ * Composition order under test mirrors the worker/stdio init wiring:
22
+ * applyToolExposureProfile(server, { allowlist }) FIRST (innermost),
23
+ * applyOpenAIProfile(server) SECOND (outermost).
24
+ */
25
+ export {};
26
+ //# sourceMappingURL=openai-grouped-compose.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openai-grouped-compose.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/openai-grouped-compose.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG"}