@lexq/cli 0.1.59 → 0.2.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.
@@ -1,18 +1,19 @@
1
1
  // src/mcp/tools/status.ts
2
+ import { z } from "zod";
2
3
  function registerStatusTools(server, callApi) {
3
4
  server.registerTool(
4
5
  "lexq_whoami",
5
6
  {
6
7
  title: "Who Am I",
7
8
  description: "Show current authentication info (tenant ID, user ID, role).",
8
- inputSchema: {}
9
+ inputSchema: z.object({})
9
10
  },
10
11
  async () => callApi("GET", "whoami")
11
12
  );
12
13
  }
13
14
 
14
15
  // src/mcp/tools/groups.ts
15
- import { z } from "zod";
16
+ import { z as z2 } from "zod";
16
17
 
17
18
  // src/types/enums.ts
18
19
  var ValueType = ["STRING", "NUMBER", "BOOLEAN", "LIST_STRING", "LIST_NUMBER"];
@@ -39,7 +40,7 @@ function registerGroupTools(server, callApi) {
39
40
  {
40
41
  title: "List Policy Groups",
41
42
  description: "List all policy groups (tenant-wide, priority ASC).",
42
- inputSchema: {}
43
+ inputSchema: z2.object({})
43
44
  },
44
45
  async () => callApi("GET", "policy-groups")
45
46
  );
@@ -48,9 +49,9 @@ function registerGroupTools(server, callApi) {
48
49
  {
49
50
  title: "Get Policy Group",
50
51
  description: "Get a single policy group by ID.",
51
- inputSchema: {
52
- groupId: z.string().uuid().describe("Policy group ID")
53
- }
52
+ inputSchema: z2.object({
53
+ groupId: z2.string().uuid().describe("Policy group ID")
54
+ })
54
55
  },
55
56
  async ({ groupId }) => callApi("GET", `policy-groups/${groupId}`)
56
57
  );
@@ -59,18 +60,18 @@ function registerGroupTools(server, callApi) {
59
60
  {
60
61
  title: "Create Policy Group",
61
62
  description: "Create a new policy group. Requires name. Priority is auto-assigned (appended last, tenant-wide); use lexq_groups_reorder to change order. Optionally set conflict resolution, activation group, and description. Policy groups that share an activationGroup form a cluster and must share the same activationMode / activationStrategy / executionLimit; executionLimit is how many of those groups run, not how many rules.",
62
- inputSchema: {
63
- name: z.string().describe("Group name (unique among non-ARCHIVED)"),
64
- description: z.string().optional().describe("Group description"),
65
- activationMode: z.enum(ConflictResolutionMode).optional().describe("Conflict resolution mode"),
66
- activationStrategy: z.enum(ConflictResolutionStrategy).optional().describe("Ranking used to pick the winning groups when mode is EXCLUSIVE or MAX_N"),
67
- executionLimit: z.number().int().min(1).optional().describe(
63
+ inputSchema: z2.object({
64
+ name: z2.string().describe("Group name (unique among non-ARCHIVED)"),
65
+ description: z2.string().optional().describe("Group description"),
66
+ activationMode: z2.enum(ConflictResolutionMode).optional().describe("Conflict resolution mode"),
67
+ activationStrategy: z2.enum(ConflictResolutionStrategy).optional().describe("Ranking used to pick the winning groups when mode is EXCLUSIVE or MAX_N"),
68
+ executionLimit: z2.number().int().min(1).optional().describe(
68
69
  "How many policy groups sharing this activationGroup may run (required when mode is MAX_N). Counts groups, not rules: every rule of a winning group runs."
69
70
  ),
70
- activationGroup: z.string().optional().describe(
71
+ activationGroup: z2.string().optional().describe(
71
72
  "Activation group (Execution Group) cluster key. Policy groups sharing this key compete, and group priority picks the winners."
72
73
  )
73
- }
74
+ })
74
75
  },
75
76
  async (args) => {
76
77
  const body = {
@@ -89,20 +90,20 @@ function registerGroupTools(server, callApi) {
89
90
  {
90
91
  title: "Update Policy Group",
91
92
  description: "Update a policy group. Only provided fields are updated; omitted fields remain unchanged.",
92
- inputSchema: {
93
- groupId: z.string().uuid().describe("Policy group ID"),
94
- name: z.string().optional().describe("New name"),
95
- description: z.string().optional().describe("New description"),
96
- status: z.enum(["ACTIVE", "DISABLED"]).optional().describe("Status (DISABLED = emergency stop)"),
97
- activationGroup: z.string().optional().describe(
93
+ inputSchema: z2.object({
94
+ groupId: z2.string().uuid().describe("Policy group ID"),
95
+ name: z2.string().optional().describe("New name"),
96
+ description: z2.string().optional().describe("New description"),
97
+ status: z2.enum(["ACTIVE", "DISABLED"]).optional().describe("Status (DISABLED = emergency stop)"),
98
+ activationGroup: z2.string().optional().describe(
98
99
  "Activation group (Execution Group) cluster key. Policy groups sharing this key compete, and group priority picks the winners."
99
100
  ),
100
- activationMode: z.enum(ConflictResolutionMode).optional().describe("Conflict resolution mode"),
101
- activationStrategy: z.enum(ConflictResolutionStrategy).optional().describe("Ranking used to pick the winning groups"),
102
- executionLimit: z.number().int().min(1).optional().describe(
101
+ activationMode: z2.enum(ConflictResolutionMode).optional().describe("Conflict resolution mode"),
102
+ activationStrategy: z2.enum(ConflictResolutionStrategy).optional().describe("Ranking used to pick the winning groups"),
103
+ executionLimit: z2.number().int().min(1).optional().describe(
103
104
  "How many policy groups sharing this activationGroup may run. Counts groups, not rules."
104
105
  )
105
- }
106
+ })
106
107
  },
107
108
  async ({ groupId, ...body }) => callApi("PUT", `policy-groups/${groupId}`, { body })
108
109
  );
@@ -111,9 +112,9 @@ function registerGroupTools(server, callApi) {
111
112
  {
112
113
  title: "Delete Policy Group",
113
114
  description: "Archive a policy group. Only non-live groups can be deleted. This is irreversible.",
114
- inputSchema: {
115
- groupId: z.string().uuid().describe("Policy group ID")
116
- }
115
+ inputSchema: z2.object({
116
+ groupId: z2.string().uuid().describe("Policy group ID")
117
+ })
117
118
  },
118
119
  async ({ groupId }) => callApi("DELETE", `policy-groups/${groupId}`)
119
120
  );
@@ -122,9 +123,9 @@ function registerGroupTools(server, callApi) {
122
123
  {
123
124
  title: "Reorder Policy Groups",
124
125
  description: "Reorder policy groups by priority. Priority is tenant-wide and flat (1...N continuous); array index 0 = priority 1 (highest precedence). activationGroup is not affected \u2014 this only changes priority.",
125
- inputSchema: {
126
- groupIds: z.array(z.string().uuid()).describe("Group IDs in desired priority order (index 0 = priority 1)")
127
- }
126
+ inputSchema: z2.object({
127
+ groupIds: z2.array(z2.string().uuid()).describe("Group IDs in desired priority order (index 0 = priority 1)")
128
+ })
128
129
  },
129
130
  async ({ groupIds }) => {
130
131
  const groups = groupIds.map((groupId, index) => ({
@@ -139,11 +140,11 @@ function registerGroupTools(server, callApi) {
139
140
  {
140
141
  title: "Start A/B Test",
141
142
  description: "Start an A/B test on a policy group. Requires a challenger version ID and traffic rate. The split is computed from context.trafficKey on each execution request; requests that omit it never reach the challenger and the test stays at 0%.",
142
- inputSchema: {
143
- groupId: z.string().uuid().describe("Policy group ID"),
144
- testVersionId: z.string().uuid().describe("Challenger version ID to test"),
145
- trafficRate: z.number().int().min(1).max(99).describe("Traffic percentage routed to challenger (1-99)")
146
- }
143
+ inputSchema: z2.object({
144
+ groupId: z2.string().uuid().describe("Policy group ID"),
145
+ testVersionId: z2.string().uuid().describe("Challenger version ID to test"),
146
+ trafficRate: z2.number().int().min(1).max(99).describe("Traffic percentage routed to challenger (1-99)")
147
+ })
147
148
  },
148
149
  async ({ groupId, ...body }) => callApi("POST", `policy-groups/${groupId}/ab-test`, { body })
149
150
  );
@@ -152,9 +153,9 @@ function registerGroupTools(server, callApi) {
152
153
  {
153
154
  title: "Stop A/B Test",
154
155
  description: "Stop a running A/B test. All traffic is restored to the control (current) version.",
155
- inputSchema: {
156
- groupId: z.string().uuid().describe("Policy group ID")
157
- }
156
+ inputSchema: z2.object({
157
+ groupId: z2.string().uuid().describe("Policy group ID")
158
+ })
158
159
  },
159
160
  async ({ groupId }) => callApi("DELETE", `policy-groups/${groupId}/ab-test`)
160
161
  );
@@ -163,17 +164,17 @@ function registerGroupTools(server, callApi) {
163
164
  {
164
165
  title: "Adjust A/B Test",
165
166
  description: "Adjust traffic rate of a running A/B test.",
166
- inputSchema: {
167
- groupId: z.string().uuid().describe("Policy group ID"),
168
- trafficRate: z.number().int().min(1).max(99).describe("New traffic percentage for challenger (1-99)")
169
- }
167
+ inputSchema: z2.object({
168
+ groupId: z2.string().uuid().describe("Policy group ID"),
169
+ trafficRate: z2.number().int().min(1).max(99).describe("New traffic percentage for challenger (1-99)")
170
+ })
170
171
  },
171
172
  async ({ groupId, ...body }) => callApi("PATCH", `policy-groups/${groupId}/ab-test/traffic-rate`, { body })
172
173
  );
173
174
  }
174
175
 
175
176
  // src/mcp/tools/versions.ts
176
- import { z as z2 } from "zod";
177
+ import { z as z3 } from "zod";
177
178
 
178
179
  // src/lib/config.ts
179
180
  import { existsSync, mkdirSync, readFileSync, writeFileSync, unlinkSync } from "fs";
@@ -238,11 +239,11 @@ function registerVersionTools(server, callApi) {
238
239
  {
239
240
  title: "List Policy Versions",
240
241
  description: "List all versions of a policy group.",
241
- inputSchema: {
242
- groupId: z2.string().uuid().describe("Policy group ID"),
243
- page: z2.number().int().min(0).default(0).describe("Page number"),
244
- size: z2.number().int().min(1).max(100).default(20).describe("Page size")
245
- }
242
+ inputSchema: z3.object({
243
+ groupId: z3.string().uuid().describe("Policy group ID"),
244
+ page: z3.number().int().min(0).default(0).describe("Page number"),
245
+ size: z3.number().int().min(1).max(100).default(20).describe("Page size")
246
+ })
246
247
  },
247
248
  async ({ groupId, page, size }) => callApi("GET", `policy-groups/${groupId}/versions`, {
248
249
  params: paginationParams(page, size)
@@ -253,10 +254,10 @@ function registerVersionTools(server, callApi) {
253
254
  {
254
255
  title: "Get Policy Version",
255
256
  description: "Get a single version by ID, including its rules and fact requirements.",
256
- inputSchema: {
257
- groupId: z2.string().uuid().describe("Policy group ID"),
258
- versionId: z2.string().uuid().describe("Version ID")
259
- }
257
+ inputSchema: z3.object({
258
+ groupId: z3.string().uuid().describe("Policy group ID"),
259
+ versionId: z3.string().uuid().describe("Version ID")
260
+ })
260
261
  },
261
262
  async ({ groupId, versionId }) => callApi("GET", `policy-groups/${groupId}/versions/${versionId}`)
262
263
  );
@@ -265,12 +266,12 @@ function registerVersionTools(server, callApi) {
265
266
  {
266
267
  title: "Create Policy Version",
267
268
  description: "Create a new DRAFT version in a policy group. Optionally provide a commit message and effective date range.",
268
- inputSchema: {
269
- groupId: z2.string().uuid().describe("Policy group ID"),
270
- commitMessage: z2.string().optional().describe("Commit message describing this version"),
271
- effectiveFrom: z2.string().optional().describe("Effective start date (ISO 8601)"),
272
- effectiveTo: z2.string().optional().describe("Effective end date (ISO 8601)")
273
- }
269
+ inputSchema: z3.object({
270
+ groupId: z3.string().uuid().describe("Policy group ID"),
271
+ commitMessage: z3.string().optional().describe("Commit message describing this version"),
272
+ effectiveFrom: z3.string().optional().describe("Effective start date (ISO 8601)"),
273
+ effectiveTo: z3.string().optional().describe("Effective end date (ISO 8601)")
274
+ })
274
275
  },
275
276
  async ({ groupId, ...body }) => callApi("POST", `policy-groups/${groupId}/versions`, { body })
276
277
  );
@@ -279,13 +280,13 @@ function registerVersionTools(server, callApi) {
279
280
  {
280
281
  title: "Update Policy Version",
281
282
  description: "Update a DRAFT version. Only DRAFT versions can be modified. Only provided fields are changed.",
282
- inputSchema: {
283
- groupId: z2.string().uuid().describe("Policy group ID"),
284
- versionId: z2.string().uuid().describe("Version ID"),
285
- commitMessage: z2.string().optional().describe("New commit message"),
286
- effectiveFrom: z2.string().optional().describe("New effective start date"),
287
- effectiveTo: z2.string().optional().describe("New effective end date")
288
- }
283
+ inputSchema: z3.object({
284
+ groupId: z3.string().uuid().describe("Policy group ID"),
285
+ versionId: z3.string().uuid().describe("Version ID"),
286
+ commitMessage: z3.string().optional().describe("New commit message"),
287
+ effectiveFrom: z3.string().optional().describe("New effective start date"),
288
+ effectiveTo: z3.string().optional().describe("New effective end date")
289
+ })
289
290
  },
290
291
  async ({ groupId, versionId, ...body }) => callApi("PUT", `policy-groups/${groupId}/versions/${versionId}`, { body })
291
292
  );
@@ -294,10 +295,10 @@ function registerVersionTools(server, callApi) {
294
295
  {
295
296
  title: "Delete Policy Version",
296
297
  description: "Delete a DRAFT version. Only DRAFT versions can be deleted.",
297
- inputSchema: {
298
- groupId: z2.string().uuid().describe("Policy group ID"),
299
- versionId: z2.string().uuid().describe("Version ID")
300
- }
298
+ inputSchema: z3.object({
299
+ groupId: z3.string().uuid().describe("Policy group ID"),
300
+ versionId: z3.string().uuid().describe("Version ID")
301
+ })
301
302
  },
302
303
  async ({ groupId, versionId }) => callApi("DELETE", `policy-groups/${groupId}/versions/${versionId}`)
303
304
  );
@@ -306,10 +307,10 @@ function registerVersionTools(server, callApi) {
306
307
  {
307
308
  title: "Clone Policy Version",
308
309
  description: "Clone an existing version to create a new DRAFT. Useful when the source version is already published.",
309
- inputSchema: {
310
- groupId: z2.string().uuid().describe("Policy group ID"),
311
- versionId: z2.string().uuid().describe("Source version ID to clone")
312
- }
310
+ inputSchema: z3.object({
311
+ groupId: z3.string().uuid().describe("Policy group ID"),
312
+ versionId: z3.string().uuid().describe("Source version ID to clone")
313
+ })
313
314
  },
314
315
  async ({ groupId, versionId }) => {
315
316
  return callApi("POST", `policy-groups/${groupId}/versions/${versionId}/clone`, {
@@ -331,7 +332,7 @@ var MIN_COHORT_SIZE = 3;
331
332
  var PROFILE_DEFAULT_WINDOW_HOURS = 24;
332
333
 
333
334
  // src/mcp/tools/rules.ts
334
- import { z as z3 } from "zod";
335
+ import { z as z4 } from "zod";
335
336
  import dedent from "dedent";
336
337
  function registerRuleTools(server, callApi) {
337
338
  server.registerTool(
@@ -339,10 +340,10 @@ function registerRuleTools(server, callApi) {
339
340
  {
340
341
  title: "List Rules",
341
342
  description: "List all rules in a version (priority ASC). Returns summary with conditionSummary and actionSummary.",
342
- inputSchema: {
343
- groupId: z3.string().uuid().describe("Policy group ID"),
344
- versionId: z3.string().uuid().describe("Version ID")
345
- }
343
+ inputSchema: z4.object({
344
+ groupId: z4.string().uuid().describe("Policy group ID"),
345
+ versionId: z4.string().uuid().describe("Version ID")
346
+ })
346
347
  },
347
348
  async ({ groupId, versionId }) => callApi("GET", `policy-groups/${groupId}/versions/${versionId}/rules`)
348
349
  );
@@ -351,11 +352,11 @@ function registerRuleTools(server, callApi) {
351
352
  {
352
353
  title: "Get Rule Detail",
353
354
  description: "Get full rule detail including condition tree and action definitions.",
354
- inputSchema: {
355
- groupId: z3.string().uuid().describe("Policy group ID"),
356
- versionId: z3.string().uuid().describe("Version ID"),
357
- ruleId: z3.string().uuid().describe("Rule ID")
358
- }
355
+ inputSchema: z4.object({
356
+ groupId: z4.string().uuid().describe("Policy group ID"),
357
+ versionId: z4.string().uuid().describe("Version ID"),
358
+ ruleId: z4.string().uuid().describe("Rule ID")
359
+ })
359
360
  },
360
361
  async ({ groupId, versionId, ruleId }) => callApi("GET", `policy-groups/${groupId}/versions/${versionId}/rules/${ruleId}`)
361
362
  );
@@ -424,13 +425,13 @@ function registerRuleTools(server, callApi) {
424
425
 
425
426
  RoundingOption (optional, MUTATE_FACT only): { scale: integer (0..${MAX_ROUNDING_SCALE}), mode?: "HALF_UP"|"HALF_DOWN"|"HALF_EVEN"|"FLOOR"|"CEILING"|"DOWN"|"UP" } mode defaults to HALF_UP. When omitted, calculator output is preserved at full precision (lossless).
426
427
  `,
427
- inputSchema: {
428
- groupId: z3.string().uuid().describe("Policy group ID"),
429
- versionId: z3.string().uuid().describe("Version ID"),
430
- rule: z3.string().describe(
428
+ inputSchema: z4.object({
429
+ groupId: z4.string().uuid().describe("Policy group ID"),
430
+ versionId: z4.string().uuid().describe("Version ID"),
431
+ rule: z4.string().describe(
431
432
  "JSON string of CreateRuleRequest: { name, condition, actions, mutexGroup?, mutexMode?, mutexStrategy?, mutexLimit?, isEnabled? }"
432
433
  )
433
- }
434
+ })
434
435
  },
435
436
  async ({ groupId, versionId, rule }) => {
436
437
  const body = parseJson(rule);
@@ -442,14 +443,14 @@ function registerRuleTools(server, callApi) {
442
443
  {
443
444
  title: "Update Rule",
444
445
  description: "Update an existing rule in a DRAFT version. Only provided fields are changed.",
445
- inputSchema: {
446
- groupId: z3.string().uuid().describe("Policy group ID"),
447
- versionId: z3.string().uuid().describe("Version ID"),
448
- ruleId: z3.string().uuid().describe("Rule ID"),
449
- rule: z3.string().describe(
446
+ inputSchema: z4.object({
447
+ groupId: z4.string().uuid().describe("Policy group ID"),
448
+ versionId: z4.string().uuid().describe("Version ID"),
449
+ ruleId: z4.string().uuid().describe("Rule ID"),
450
+ rule: z4.string().describe(
450
451
  "JSON string of UpdateRuleRequest: { name?, condition?, actions?, mutexGroup?, mutexMode?, mutexStrategy?, mutexLimit?, isEnabled? }"
451
452
  )
452
- }
453
+ })
453
454
  },
454
455
  async ({ groupId, versionId, ruleId, rule }) => {
455
456
  const body = parseJson(rule);
@@ -463,12 +464,12 @@ function registerRuleTools(server, callApi) {
463
464
  {
464
465
  title: "Delete Rule",
465
466
  description: "Delete a rule from a DRAFT version.",
466
- inputSchema: {
467
- groupId: z3.string().uuid().describe("Policy group ID"),
468
- versionId: z3.string().uuid().describe("Version ID"),
469
- ruleId: z3.string().uuid().describe("Rule ID"),
470
- force: z3.boolean().default(false).describe("Skip confirmation (for the last rule in a version)")
471
- }
467
+ inputSchema: z4.object({
468
+ groupId: z4.string().uuid().describe("Policy group ID"),
469
+ versionId: z4.string().uuid().describe("Version ID"),
470
+ ruleId: z4.string().uuid().describe("Rule ID"),
471
+ force: z4.boolean().default(false).describe("Skip confirmation (for the last rule in a version)")
472
+ })
472
473
  },
473
474
  async ({ groupId, versionId, ruleId, force }) => {
474
475
  const params = {};
@@ -483,11 +484,11 @@ function registerRuleTools(server, callApi) {
483
484
  {
484
485
  title: "Reorder Rules",
485
486
  description: "Reorder rules by specifying rule IDs in desired order. Priorities are assigned 1...N (1-based, continuous); array index 0 = priority 1 (highest precedence).",
486
- inputSchema: {
487
- groupId: z3.string().uuid().describe("Policy group ID"),
488
- versionId: z3.string().uuid().describe("Version ID"),
489
- ruleIds: z3.array(z3.string().uuid()).describe("Rule IDs in desired priority order")
490
- }
487
+ inputSchema: z4.object({
488
+ groupId: z4.string().uuid().describe("Policy group ID"),
489
+ versionId: z4.string().uuid().describe("Version ID"),
490
+ ruleIds: z4.array(z4.string().uuid()).describe("Rule IDs in desired priority order")
491
+ })
491
492
  },
492
493
  async ({ groupId, versionId, ruleIds }) => {
493
494
  const rules = ruleIds.map((ruleId, index) => ({
@@ -504,12 +505,12 @@ function registerRuleTools(server, callApi) {
504
505
  {
505
506
  title: "Toggle Rule",
506
507
  description: "Enable or disable a rule without deleting it.",
507
- inputSchema: {
508
- groupId: z3.string().uuid().describe("Policy group ID"),
509
- versionId: z3.string().uuid().describe("Version ID"),
510
- ruleId: z3.string().uuid().describe("Rule ID"),
511
- isEnabled: z3.boolean().describe("true to enable, false to disable")
512
- }
508
+ inputSchema: z4.object({
509
+ groupId: z4.string().uuid().describe("Policy group ID"),
510
+ versionId: z4.string().uuid().describe("Version ID"),
511
+ ruleId: z4.string().uuid().describe("Rule ID"),
512
+ isEnabled: z4.boolean().describe("true to enable, false to disable")
513
+ })
513
514
  },
514
515
  async ({ groupId, versionId, ruleId, isEnabled }) => callApi("PATCH", `policy-groups/${groupId}/versions/${versionId}/rules/${ruleId}/enabled`, {
515
516
  body: { isEnabled }
@@ -518,7 +519,7 @@ function registerRuleTools(server, callApi) {
518
519
  }
519
520
 
520
521
  // src/mcp/tools/facts.ts
521
- import { z as z4 } from "zod";
522
+ import { z as z5 } from "zod";
522
523
 
523
524
  // src/types/facts.ts
524
525
  var FACT_KEY_PATTERN = /^[a-zA-Z][a-zA-Z0-9_]*$/;
@@ -535,11 +536,11 @@ function registerFactTools(server, callApi) {
535
536
  {
536
537
  title: "List Fact Definitions",
537
538
  description: "List all fact definitions (input variable schema). Shows key, type, required, and PII status. Always check this before creating rules.",
538
- inputSchema: {
539
- page: z4.number().int().min(0).default(0).describe("Page number"),
540
- size: z4.number().int().min(1).max(100).default(20).describe("Page size"),
541
- keyword: z4.string().optional().describe("Search keyword")
542
- }
539
+ inputSchema: z5.object({
540
+ page: z5.number().int().min(0).default(0).describe("Page number"),
541
+ size: z5.number().int().min(1).max(100).default(20).describe("Page size"),
542
+ keyword: z5.string().optional().describe("Search keyword")
543
+ })
543
544
  },
544
545
  async ({ page, size, keyword }) => {
545
546
  const params = paginationParams(page, size);
@@ -552,16 +553,16 @@ function registerFactTools(server, callApi) {
552
553
  {
553
554
  title: "Create Fact Definition",
554
555
  description: "Register a new input variable. Key starts with a letter, then letters, numbers, and underscores (e.g. paymentAmount). Casing is not enforced. Types: STRING, NUMBER, BOOLEAN, LIST_STRING, LIST_NUMBER.",
555
- inputSchema: {
556
- key: z4.string().regex(FACT_KEY_PATTERN).describe("Variable key. Any casing; must start with a letter."),
557
- name: z4.string().describe("Display name"),
558
- type: z4.enum(VALUE_TYPES).describe("Value type"),
559
- description: z4.string().optional().describe("Description"),
560
- isRequired: z4.boolean().default(false).describe("Whether this fact is required for rule evaluation"),
561
- isPii: z4.boolean().default(false).describe(
556
+ inputSchema: z5.object({
557
+ key: z5.string().regex(FACT_KEY_PATTERN).describe("Variable key. Any casing; must start with a letter."),
558
+ name: z5.string().describe("Display name"),
559
+ type: z5.enum(VALUE_TYPES).describe("Value type"),
560
+ description: z5.string().optional().describe("Description"),
561
+ isRequired: z5.boolean().default(false).describe("Whether this fact is required for rule evaluation"),
562
+ isPii: z5.boolean().default(false).describe(
562
563
  "Mark as PII \u2014 masked on every read surface, revealable only in the console (audited)"
563
564
  )
564
- }
565
+ })
565
566
  },
566
567
  async (args) => callApi("POST", "schema/facts", { body: args })
567
568
  );
@@ -570,16 +571,16 @@ function registerFactTools(server, callApi) {
570
571
  {
571
572
  title: "Update Fact Definition",
572
573
  description: "Update a fact definition. The key is immutable. The type can change only while no rule references the fact; if any does, the call fails with FD-007 and reports the count. Only the fields you send are changed. System facts accept name, description, and PII only.",
573
- inputSchema: {
574
- factId: z4.string().uuid().describe("Fact definition ID"),
575
- name: z4.string().optional().describe("Display name"),
576
- description: z4.string().optional().describe("Description"),
577
- type: z4.enum(VALUE_TYPES).optional().describe(
574
+ inputSchema: z5.object({
575
+ factId: z5.string().uuid().describe("Fact definition ID"),
576
+ name: z5.string().optional().describe("Display name"),
577
+ description: z5.string().optional().describe("Description"),
578
+ type: z5.enum(VALUE_TYPES).optional().describe(
578
579
  "Value type. Omit to leave it unchanged. Changing it fails with FD-007 while any rule references the fact."
579
580
  ),
580
- isRequired: z4.boolean().optional().describe("Required flag"),
581
- isPii: z4.boolean().optional().describe("PII flag \u2014 enables/disables masking (changeable even on system facts)")
582
- }
581
+ isRequired: z5.boolean().optional().describe("Required flag"),
582
+ isPii: z5.boolean().optional().describe("PII flag \u2014 enables/disables masking (changeable even on system facts)")
583
+ })
583
584
  },
584
585
  async ({ factId, ...body }) => callApi("PUT", `schema/facts/${factId}`, { body })
585
586
  );
@@ -588,9 +589,9 @@ function registerFactTools(server, callApi) {
588
589
  {
589
590
  title: "Delete Fact Definition",
590
591
  description: "Delete a fact definition. System facts cannot be deleted. Neither can a fact that any rule references: that call fails with FD-006 and reports the count. Remove the references first.",
591
- inputSchema: {
592
- factId: z4.string().uuid().describe("Fact definition ID")
593
- }
592
+ inputSchema: z5.object({
593
+ factId: z5.string().uuid().describe("Fact definition ID")
594
+ })
594
595
  },
595
596
  async ({ factId }) => callApi("DELETE", `schema/facts/${factId}`)
596
597
  );
@@ -599,7 +600,7 @@ function registerFactTools(server, callApi) {
599
600
  {
600
601
  title: "Get Action Runtime Fact Metadata",
601
602
  description: "Retrieve runtime fact requirements per Action type. For each Action, shows which input facts must be present in the execution payload \u2014 e.g. MUTATE_FACT always requires its targetVar fact, plus refVar when one is specified. The factRequired flag describes the FACT, not the parameter: refVar is an optional parameter, but if you specify it the named fact must exist. A required fact absent at runtime throws \u2014 the engine never defaults to 0. Facts are supplied as input or written by a prior action in the same rule; only SET_FACT creates a fact from nothing. Static data, safe to cache in-session.",
602
- inputSchema: {}
603
+ inputSchema: z5.object({})
603
604
  },
604
605
  async () => callApi("GET", "schema/action-metadata")
605
606
  );
@@ -608,10 +609,10 @@ function registerFactTools(server, callApi) {
608
609
  {
609
610
  title: "List Unregistered Facts",
610
611
  description: "List facts referenced by a version's rules but not yet defined (read-only \u2014 does not block publish/deploy, INV-4). Version-wide: covers every rule in the version. Each entry carries the inferred type, suggested name, and where it is referenced (condition/action). Register them with lexq_facts_create to enable type validation and the dry-run requirements analyzer.",
611
- inputSchema: {
612
- groupId: z4.string().uuid().describe("Policy group ID"),
613
- versionId: z4.string().uuid().describe("Version ID")
614
- }
612
+ inputSchema: z5.object({
613
+ groupId: z5.string().uuid().describe("Policy group ID"),
614
+ versionId: z5.string().uuid().describe("Version ID")
615
+ })
615
616
  },
616
617
  async ({ groupId, versionId }) => callApi("GET", `policy-groups/${groupId}/versions/${versionId}/unregistered-facts`)
617
618
  );
@@ -620,10 +621,10 @@ function registerFactTools(server, callApi) {
620
621
  {
621
622
  title: "Export Fact Catalog",
622
623
  description: "Export the fact catalog. The two formats carry different things: CSV is the catalog as it stands, system facts included, for reading in a spreadsheet; JSON matches the shape that batch create accepts, so it can be fed straight back in, which is why it leaves out the fields that endpoint does not take. Returns the file contents as text.",
623
- inputSchema: {
624
- format: z4.enum(EXPORT_FORMATS).default("csv").describe("Export format"),
625
- keyword: z4.string().optional().describe("Filter by key or name")
626
- }
624
+ inputSchema: z5.object({
625
+ format: z5.enum(EXPORT_FORMATS).default("csv").describe("Export format"),
626
+ keyword: z5.string().optional().describe("Filter by key or name")
627
+ })
627
628
  },
628
629
  async ({ format, keyword }) => callApi("GET", "schema/facts/export", {
629
630
  params: keyword ? { format, keyword } : { format }
@@ -632,18 +633,18 @@ function registerFactTools(server, callApi) {
632
633
  }
633
634
 
634
635
  // src/mcp/tools/deploy.ts
635
- import { z as z5 } from "zod";
636
+ import { z as z6 } from "zod";
636
637
  function registerDeployTools(server, callApi) {
637
638
  server.registerTool(
638
639
  "lexq_deploy_publish",
639
640
  {
640
641
  title: "Publish Version",
641
642
  description: "Publish a DRAFT version (DRAFT \u2192 ACTIVE). Locks the version from further edits. Must have at least one rule. Undefined facts referenced by rules do not block publishing (INV-4); call lexq_facts_unregistered first to review them.",
642
- inputSchema: {
643
- groupId: z5.string().uuid().describe("Policy group ID"),
644
- versionId: z5.string().uuid().describe("Version ID to publish"),
645
- memo: z5.string().min(1).describe("Publish memo (required)")
646
- }
643
+ inputSchema: z6.object({
644
+ groupId: z6.string().uuid().describe("Policy group ID"),
645
+ versionId: z6.string().uuid().describe("Version ID to publish"),
646
+ memo: z6.string().min(1).describe("Publish memo (required)")
647
+ })
647
648
  },
648
649
  async ({ groupId, versionId, memo }) => callApi("POST", `policy-groups/${groupId}/versions/${versionId}/publish`, { body: { memo } })
649
650
  );
@@ -652,11 +653,11 @@ function registerDeployTools(server, callApi) {
652
653
  {
653
654
  title: "Deploy to Live",
654
655
  description: "Deploy an ACTIVE (published) version to live traffic. Takes effect immediately. Versions whose effective start date has not arrived are rejected (P-037) \u2014 use lexq_deploy_schedule for those. Undefined facts do not block deployment (INV-4); use lexq_facts_unregistered to review what the version references but has not defined.",
655
- inputSchema: {
656
- groupId: z5.string().uuid().describe("Policy group ID"),
657
- versionId: z5.string().uuid().describe("Version ID to deploy"),
658
- memo: z5.string().min(1).describe("Deployment memo (required)")
659
- }
656
+ inputSchema: z6.object({
657
+ groupId: z6.string().uuid().describe("Policy group ID"),
658
+ versionId: z6.string().uuid().describe("Version ID to deploy"),
659
+ memo: z6.string().min(1).describe("Deployment memo (required)")
660
+ })
660
661
  },
661
662
  async ({ groupId, versionId, memo }) => callApi("POST", `policy-groups/${groupId}/deploy`, {
662
663
  body: { versionId, memo }
@@ -667,10 +668,10 @@ function registerDeployTools(server, callApi) {
667
668
  {
668
669
  title: "Rollback Deployment",
669
670
  description: "Rollback to the previous deployed version. Only available if there is a previous version.",
670
- inputSchema: {
671
- groupId: z5.string().uuid().describe("Policy group ID"),
672
- memo: z5.string().min(1).describe("Rollback reason (required)")
673
- }
671
+ inputSchema: z6.object({
672
+ groupId: z6.string().uuid().describe("Policy group ID"),
673
+ memo: z6.string().min(1).describe("Rollback reason (required)")
674
+ })
674
675
  },
675
676
  async ({ groupId, memo }) => callApi("POST", `policy-groups/${groupId}/rollback`, {
676
677
  body: { memo }
@@ -681,10 +682,10 @@ function registerDeployTools(server, callApi) {
681
682
  {
682
683
  title: "Undeploy",
683
684
  description: "Remove the live version from traffic. The version stays ACTIVE but no longer serves requests.",
684
- inputSchema: {
685
- groupId: z5.string().uuid().describe("Policy group ID"),
686
- memo: z5.string().min(1).describe("Undeploy reason (required)")
687
- }
685
+ inputSchema: z6.object({
686
+ groupId: z6.string().uuid().describe("Policy group ID"),
687
+ memo: z6.string().min(1).describe("Undeploy reason (required)")
688
+ })
688
689
  },
689
690
  async ({ groupId, memo }) => callApi("POST", `policy-groups/${groupId}/undeploy`, {
690
691
  body: { memo }
@@ -695,11 +696,11 @@ function registerDeployTools(server, callApi) {
695
696
  {
696
697
  title: "Schedule Deployment",
697
698
  description: "Schedule an ACTIVE version with a future effective start date to auto-deploy at that time (Scheduled Deployment). One pending schedule per group; manual deploy/rollback/undeploy, starting an A/B test, or archiving the group cancels it. The snapshot hash is sealed at scheduling and re-verified at execution (fail-closed).",
698
- inputSchema: {
699
- groupId: z5.string().uuid().describe("Policy group ID"),
700
- versionId: z5.string().uuid().describe("ACTIVE version ID with a future effective start date"),
701
- memo: z5.string().min(1).describe("Schedule memo (required)")
702
- }
699
+ inputSchema: z6.object({
700
+ groupId: z6.string().uuid().describe("Policy group ID"),
701
+ versionId: z6.string().uuid().describe("ACTIVE version ID with a future effective start date"),
702
+ memo: z6.string().min(1).describe("Schedule memo (required)")
703
+ })
703
704
  },
704
705
  async ({ groupId, versionId, memo }) => callApi("POST", `policy-groups/${groupId}/schedule`, {
705
706
  body: { versionId, memo }
@@ -710,9 +711,9 @@ function registerDeployTools(server, callApi) {
710
711
  {
711
712
  title: "Cancel Scheduled Deployment",
712
713
  description: "Cancel the pending scheduled deployment for a group. The version itself is not affected. Fails with P-039 if no pending schedule exists.",
713
- inputSchema: {
714
- groupId: z5.string().uuid().describe("Policy group ID")
715
- }
714
+ inputSchema: z6.object({
715
+ groupId: z6.string().uuid().describe("Policy group ID")
716
+ })
716
717
  },
717
718
  async ({ groupId }) => callApi("DELETE", `policy-groups/${groupId}/schedule`)
718
719
  );
@@ -721,10 +722,10 @@ function registerDeployTools(server, callApi) {
721
722
  {
722
723
  title: "List Scheduled Deployments",
723
724
  description: "List scheduled deployments across all groups (all statuses: PENDING, EXECUTED, CANCELED, FAILED), newest first.",
724
- inputSchema: {
725
- page: z5.number().int().min(0).default(0).describe("Page number"),
726
- size: z5.number().int().min(1).max(100).default(20).describe("Page size")
727
- }
725
+ inputSchema: z6.object({
726
+ page: z6.number().int().min(0).default(0).describe("Page number"),
727
+ size: z6.number().int().min(1).max(100).default(20).describe("Page size")
728
+ })
728
729
  },
729
730
  async ({ page, size }) => callApi("GET", "policy-groups/schedules", { params: paginationParams(page, size) })
730
731
  );
@@ -733,14 +734,14 @@ function registerDeployTools(server, callApi) {
733
734
  {
734
735
  title: "Deployment History",
735
736
  description: "List deployment history across all groups.",
736
- inputSchema: {
737
- page: z5.number().int().min(0).default(0).describe("Page number"),
738
- size: z5.number().int().min(1).max(100).default(20).describe("Page size"),
739
- groupId: z5.string().uuid().optional().describe("Filter by group ID"),
740
- types: z5.string().optional().describe("Filter by deployment types (comma-separated: DEPLOY,ROLLBACK,UNDEPLOY)"),
741
- startDate: z5.string().optional().describe("Start date (yyyy-MM-dd)"),
742
- endDate: z5.string().optional().describe("End date (yyyy-MM-dd)")
743
- }
737
+ inputSchema: z6.object({
738
+ page: z6.number().int().min(0).default(0).describe("Page number"),
739
+ size: z6.number().int().min(1).max(100).default(20).describe("Page size"),
740
+ groupId: z6.string().uuid().optional().describe("Filter by group ID"),
741
+ types: z6.string().optional().describe("Filter by deployment types (comma-separated: DEPLOY,ROLLBACK,UNDEPLOY)"),
742
+ startDate: z6.string().optional().describe("Start date (yyyy-MM-dd)"),
743
+ endDate: z6.string().optional().describe("End date (yyyy-MM-dd)")
744
+ })
744
745
  },
745
746
  async ({ page, size, groupId, types, startDate, endDate }) => {
746
747
  const params = paginationParams(page, size);
@@ -756,9 +757,9 @@ function registerDeployTools(server, callApi) {
756
757
  {
757
758
  title: "Deployment Detail",
758
759
  description: "Get detailed info about a specific deployment including snapshot hash and integrity check.",
759
- inputSchema: {
760
- deploymentId: z5.string().uuid().describe("Deployment ID")
761
- }
760
+ inputSchema: z6.object({
761
+ deploymentId: z6.string().uuid().describe("Deployment ID")
762
+ })
762
763
  },
763
764
  async ({ deploymentId }) => callApi("GET", `deployments/${deploymentId}`)
764
765
  );
@@ -767,7 +768,7 @@ function registerDeployTools(server, callApi) {
767
768
  {
768
769
  title: "Deployment Overview",
769
770
  description: "Show current deployment status of all groups \u2014 which version is live, last deployment type, and deployer.",
770
- inputSchema: {}
771
+ inputSchema: z6.object({})
771
772
  },
772
773
  async () => callApi("GET", "deployments/overview")
773
774
  );
@@ -776,9 +777,9 @@ function registerDeployTools(server, callApi) {
776
777
  {
777
778
  title: "List Deployable Versions",
778
779
  description: "List ACTIVE (published) versions that can be deployed for a group. Use this to find which versions are available before calling deploy live.",
779
- inputSchema: {
780
- groupId: z5.string().uuid().describe("Policy group ID")
781
- }
780
+ inputSchema: z6.object({
781
+ groupId: z6.string().uuid().describe("Policy group ID")
782
+ })
782
783
  },
783
784
  async ({ groupId }) => callApi("GET", `deployments/groups/${groupId}/deployable-versions`)
784
785
  );
@@ -787,10 +788,10 @@ function registerDeployTools(server, callApi) {
787
788
  {
788
789
  title: "Deployment Diff",
789
790
  description: "Compare rule snapshots between two versions. Shows added, removed, and modified rules. Useful for reviewing changes before deploying a new version.",
790
- inputSchema: {
791
- baseVersionId: z5.string().uuid().describe("Base version ID (typically the current live)"),
792
- targetVersionId: z5.string().uuid().describe("Target version ID (the one you want to deploy)")
793
- }
791
+ inputSchema: z6.object({
792
+ baseVersionId: z6.string().uuid().describe("Base version ID (typically the current live)"),
793
+ targetVersionId: z6.string().uuid().describe("Target version ID (the one you want to deploy)")
794
+ })
794
795
  },
795
796
  async ({ baseVersionId, targetVersionId }) => callApi("GET", "deployments/diff", {
796
797
  params: { baseVersionId, targetVersionId }
@@ -799,7 +800,7 @@ function registerDeployTools(server, callApi) {
799
800
  }
800
801
 
801
802
  // src/mcp/tools/analytics.ts
802
- import { z as z6 } from "zod";
803
+ import { z as z7 } from "zod";
803
804
  import dedent2 from "dedent";
804
805
  function registerAnalyticsTools(server, callApi) {
805
806
  server.registerTool(
@@ -818,11 +819,11 @@ function registerAnalyticsTools(server, callApi) {
818
819
 
819
820
  Example input: { "facts": { "paymentAmount": 100000, "customerTier": "VIP" } }
820
821
  Always dry-run before publishing to validate rule behavior.`,
821
- inputSchema: {
822
- versionId: z6.string().uuid().describe("Policy version ID to test against"),
823
- facts: z6.string().describe('JSON string of facts object, e.g. {"paymentAmount":100000}'),
824
- includeDebugInfo: z6.boolean().default(true).describe("Include execution and decision traces")
825
- }
822
+ inputSchema: z7.object({
823
+ versionId: z7.string().uuid().describe("Policy version ID to test against"),
824
+ facts: z7.string().describe('JSON string of facts object, e.g. {"paymentAmount":100000}'),
825
+ includeDebugInfo: z7.boolean().default(true).describe("Include execution and decision traces")
826
+ })
826
827
  },
827
828
  async ({ versionId, facts, includeDebugInfo }) => {
828
829
  const parsedFacts = parseJson(facts);
@@ -842,11 +843,11 @@ function registerAnalyticsTools(server, callApi) {
842
843
  resultA / resultB — full DryRunResponse for each version
843
844
  diff.mutatedDiff — changes in mutatedFacts between A and B (key → {before, after})
844
845
  diff.generatedDiff — changes in generatedVariables between A and B`,
845
- inputSchema: {
846
- versionIdA: z6.string().uuid().describe("Baseline version ID"),
847
- versionIdB: z6.string().uuid().describe("Candidate version ID"),
848
- facts: z6.string().describe("JSON string of facts object")
849
- }
846
+ inputSchema: z7.object({
847
+ versionIdA: z7.string().uuid().describe("Baseline version ID"),
848
+ versionIdB: z7.string().uuid().describe("Candidate version ID"),
849
+ facts: z7.string().describe("JSON string of facts object")
850
+ })
850
851
  },
851
852
  async ({ versionIdA, versionIdB, facts }) => {
852
853
  const parsedFacts = parseJson(facts);
@@ -860,10 +861,10 @@ function registerAnalyticsTools(server, callApi) {
860
861
  {
861
862
  title: "Analyze Requirements",
862
863
  description: "Analyze which input facts a version requires. Returns required keys, types, and an example request body.",
863
- inputSchema: {
864
- groupId: z6.string().uuid().describe("Policy group ID"),
865
- versionId: z6.string().uuid().describe("Version ID")
866
- }
864
+ inputSchema: z7.object({
865
+ groupId: z7.string().uuid().describe("Policy group ID"),
866
+ versionId: z7.string().uuid().describe("Version ID")
867
+ })
867
868
  },
868
869
  async ({ groupId, versionId }) => callApi("GET", `analytics/groups/${groupId}/versions/${versionId}/requirements`)
869
870
  );
@@ -899,9 +900,9 @@ function registerAnalyticsTools(server, callApi) {
899
900
  "options": { "baselinePolicyVersionId": "<uuid>", "includeRuleStats": true }
900
901
  }
901
902
  `,
902
- inputSchema: {
903
- body: z6.string().describe("JSON string of SimulationRequest")
904
- }
903
+ inputSchema: z7.object({
904
+ body: z7.string().describe("JSON string of SimulationRequest")
905
+ })
905
906
  },
906
907
  async ({ body }) => {
907
908
  const parsed = parseJson(body);
@@ -913,9 +914,9 @@ function registerAnalyticsTools(server, callApi) {
913
914
  {
914
915
  title: "Simulation Status",
915
916
  description: "Get simulation status and results. Poll until status is COMPLETED or FAILED.",
916
- inputSchema: {
917
- simulationId: z6.string().uuid().describe("Simulation ID")
918
- }
917
+ inputSchema: z7.object({
918
+ simulationId: z7.string().uuid().describe("Simulation ID")
919
+ })
919
920
  },
920
921
  async ({ simulationId }) => callApi("GET", `analytics/simulations/${simulationId}`)
921
922
  );
@@ -924,13 +925,13 @@ function registerAnalyticsTools(server, callApi) {
924
925
  {
925
926
  title: "List Simulations",
926
927
  description: "List simulation history with optional filters.",
927
- inputSchema: {
928
- page: z6.number().int().min(0).default(0).describe("Page number"),
929
- size: z6.number().int().min(1).max(100).default(20).describe("Page size"),
930
- status: z6.enum(["PENDING", "RUNNING", "COMPLETED", "FAILED", "CANCELED"]).optional().describe("Filter by status"),
931
- from: z6.string().optional().describe("Start date (yyyy-MM-dd)"),
932
- to: z6.string().optional().describe("End date (yyyy-MM-dd)")
933
- }
928
+ inputSchema: z7.object({
929
+ page: z7.number().int().min(0).default(0).describe("Page number"),
930
+ size: z7.number().int().min(1).max(100).default(20).describe("Page size"),
931
+ status: z7.enum(["PENDING", "RUNNING", "COMPLETED", "FAILED", "CANCELED"]).optional().describe("Filter by status"),
932
+ from: z7.string().optional().describe("Start date (yyyy-MM-dd)"),
933
+ to: z7.string().optional().describe("End date (yyyy-MM-dd)")
934
+ })
934
935
  },
935
936
  async ({ page, size, status, from, to }) => {
936
937
  const params = paginationParams(page, size);
@@ -945,9 +946,9 @@ function registerAnalyticsTools(server, callApi) {
945
946
  {
946
947
  title: "Cancel Simulation",
947
948
  description: "Cancel a running or pending simulation.",
948
- inputSchema: {
949
- simulationId: z6.string().uuid().describe("Simulation ID")
950
- }
949
+ inputSchema: z7.object({
950
+ simulationId: z7.string().uuid().describe("Simulation ID")
951
+ })
951
952
  },
952
953
  async ({ simulationId }) => callApi("DELETE", `analytics/simulations/${simulationId}`)
953
954
  );
@@ -956,10 +957,10 @@ function registerAnalyticsTools(server, callApi) {
956
957
  {
957
958
  title: "Export Simulation",
958
959
  description: "Export simulation results as JSON or CSV. Returns the raw data.",
959
- inputSchema: {
960
- simulationId: z6.string().uuid().describe("Simulation ID"),
961
- format: z6.enum(EXPORT_FORMATS).default("json").describe("Export format")
962
- }
960
+ inputSchema: z7.object({
961
+ simulationId: z7.string().uuid().describe("Simulation ID"),
962
+ format: z7.enum(EXPORT_FORMATS).default("json").describe("Export format")
963
+ })
963
964
  },
964
965
  async ({ simulationId, format }) => callApi("GET", `analytics/simulations/${simulationId}/export`, {
965
966
  params: { format }
@@ -983,10 +984,10 @@ function registerAnalyticsTools(server, callApi) {
983
984
 
984
985
  JSON example: [{"userId":"user_001","paymentAmount":150000}, {"userId":"user_002","paymentAmount":50000}]
985
986
  `,
986
- inputSchema: {
987
- content: z6.string().describe("CSV or JSON content as string"),
988
- filename: z6.string().default("dataset.csv").describe("Filename with extension (.csv or .json)")
989
- }
987
+ inputSchema: z7.object({
988
+ content: z7.string().describe("CSV or JSON content as string"),
989
+ filename: z7.string().default("dataset.csv").describe("Filename with extension (.csv or .json)")
990
+ })
990
991
  },
991
992
  async ({ content, filename }) => {
992
993
  const result = await callApi("POST", "analytics/datasets/upload", {
@@ -1013,11 +1014,11 @@ function registerAnalyticsTools(server, callApi) {
1013
1014
  {
1014
1015
  title: "Download Dataset Template",
1015
1016
  description: "Generate a sample CSV or JSON template based on the required facts of a version. Use this to understand the expected data format before uploading a dataset.",
1016
- inputSchema: {
1017
- groupId: z6.string().uuid().describe("Policy group ID"),
1018
- versionId: z6.string().uuid().describe("Version ID"),
1019
- format: z6.enum(EXPORT_FORMATS).default("csv").describe("Template format")
1020
- }
1017
+ inputSchema: z7.object({
1018
+ groupId: z7.string().uuid().describe("Policy group ID"),
1019
+ versionId: z7.string().uuid().describe("Version ID"),
1020
+ format: z7.enum(EXPORT_FORMATS).default("csv").describe("Template format")
1021
+ })
1021
1022
  },
1022
1023
  async ({ groupId, versionId, format }) => callApi("GET", `analytics/groups/${groupId}/versions/${versionId}/dataset-template`, {
1023
1024
  params: { format }
@@ -1026,7 +1027,7 @@ function registerAnalyticsTools(server, callApi) {
1026
1027
  }
1027
1028
 
1028
1029
  // src/mcp/tools/profile.ts
1029
- import { z as z7 } from "zod";
1030
+ import { z as z8 } from "zod";
1030
1031
  var RELATIVE_THRESHOLD = `flagged = p50 \u2265 ${SLOW_MULTIPLIER}\xD7 median of per-rule p50s within the group; absolute thresholds are intentionally not supported.`;
1031
1032
  function profileParams(opts) {
1032
1033
  const params = {};
@@ -1042,15 +1043,15 @@ function registerProfileTools(server, callApi) {
1042
1043
  {
1043
1044
  title: "Group Latency Profile",
1044
1045
  description: "Per-rule latency profile of a policy group over a time window: group TOTAL distribution split by cache state (HIT = compiled ruleset cache hit, MISS = deep-load + compile), a per-rule CONDITION/ACTION percentile table, and slow-rule flags. " + RELATIVE_THRESHOLD + ` Every percentile is accompanied by its sample count n; a percentile is withheld (null) unless n\xD7(1\u2212q) \u2265 ${TAIL_MIN_OBS} (p50 needs n \u2265 6, p95 n \u2265 60, p99 n \u2265 300 \u2014 display gate, separate from the n \u2265 ${MIN_SAMPLES} judgment gate). Baselines report INSUFFICIENT_COHORT when fewer than ${MIN_COHORT_SIZE} rules qualify. Rule detail comes from a deterministic ${PROFILE_SAMPLE_PERMILLE / 10}% sample of calls; TOTAL is recorded for every call. Defaults: last ${PROFILE_DEFAULT_WINDOW_HOURS}h, live version, cacheState HIT.`,
1045
- inputSchema: {
1046
- groupId: z7.string().uuid().describe("Policy group ID"),
1047
- versionId: z7.string().uuid().optional().describe("Version to inspect (default: live version)"),
1048
- from: z7.string().optional().describe(
1046
+ inputSchema: z8.object({
1047
+ groupId: z8.string().uuid().describe("Policy group ID"),
1048
+ versionId: z8.string().uuid().optional().describe("Version to inspect (default: live version)"),
1049
+ from: z8.string().optional().describe(
1049
1050
  `Window start, ISO-8601 instant (e.g. 2026-07-01T00:00:00Z). Default: ${PROFILE_DEFAULT_WINDOW_HOURS}h ago`
1050
1051
  ),
1051
- to: z7.string().optional().describe("Window end, ISO-8601 instant. Default: now"),
1052
- cacheState: z7.enum(["HIT", "MISS"]).optional().describe("Cache dimension for the rule table and judgment (default: HIT)")
1053
- }
1052
+ to: z8.string().optional().describe("Window end, ISO-8601 instant. Default: now"),
1053
+ cacheState: z8.enum(["HIT", "MISS"]).optional().describe("Cache dimension for the rule table and judgment (default: HIT)")
1054
+ })
1054
1055
  },
1055
1056
  async ({ groupId, versionId, from, to, cacheState }) => callApi("GET", `policy-groups/${groupId}/profile`, {
1056
1057
  params: profileParams({ versionId, from, to, cacheState })
@@ -1061,15 +1062,15 @@ function registerProfileTools(server, callApi) {
1061
1062
  {
1062
1063
  title: "Rule Latency Detail",
1063
1064
  description: `Single-rule latency detail: merged phase \xD7 cacheState distributions plus a per-window time series (${LATENCY_WINDOW_MILLIS / 1e3}s windows). Missing windows are genuine gaps \u2014 never interpolated. Series points carry each window's own values; percentiles in merged distributions are withheld (null) unless n\xD7(1\u2212q) \u2265 ${TAIL_MIN_OBS} (p50 n \u2265 6, p95 n \u2265 60, p99 n \u2265 300). ` + RELATIVE_THRESHOLD,
1064
- inputSchema: {
1065
- groupId: z7.string().uuid().describe("Policy group ID"),
1066
- ruleId: z7.string().uuid().describe("Rule ID (from lexq_profile_overview)"),
1067
- versionId: z7.string().uuid().optional().describe("Version to inspect (default: live version)"),
1068
- from: z7.string().optional().describe(
1065
+ inputSchema: z8.object({
1066
+ groupId: z8.string().uuid().describe("Policy group ID"),
1067
+ ruleId: z8.string().uuid().describe("Rule ID (from lexq_profile_overview)"),
1068
+ versionId: z8.string().uuid().optional().describe("Version to inspect (default: live version)"),
1069
+ from: z8.string().optional().describe(
1069
1070
  `Window start, ISO-8601 instant. Default: ${PROFILE_DEFAULT_WINDOW_HOURS}h ago`
1070
1071
  ),
1071
- to: z7.string().optional().describe("Window end, ISO-8601 instant. Default: now")
1072
- }
1072
+ to: z8.string().optional().describe("Window end, ISO-8601 instant. Default: now")
1073
+ })
1073
1074
  },
1074
1075
  async ({ groupId, ruleId, versionId, from, to }) => callApi("GET", `policy-groups/${groupId}/profile/rules/${ruleId}`, {
1075
1076
  params: profileParams({ versionId, from, to })
@@ -1078,17 +1079,17 @@ function registerProfileTools(server, callApi) {
1078
1079
  }
1079
1080
 
1080
1081
  // src/mcp/tools/replay.ts
1081
- import { z as z8 } from "zod";
1082
+ import { z as z9 } from "zod";
1082
1083
  function registerReplayTools(server, callApi) {
1083
1084
  server.registerTool(
1084
1085
  "lexq_replay_decision",
1085
1086
  {
1086
1087
  title: "Replay a Decision",
1087
1088
  description: "Re-evaluate a past execution (traceId) against a candidate version and return the decision diff (decisionChanged, effect changes, fired rules) plus a determinism verdict. Synchronous and free of charge (TPS throttle only). A replay sends no webhook, notification, or event: rule actions produce no outward effects.",
1088
- inputSchema: {
1089
- traceId: z8.string().describe("Trace ID of the past execution to replay"),
1090
- candidateVersionId: z8.string().uuid().describe("Version to re-evaluate against")
1091
- }
1089
+ inputSchema: z9.object({
1090
+ traceId: z9.string().describe("Trace ID of the past execution to replay"),
1091
+ candidateVersionId: z9.string().uuid().describe("Version to re-evaluate against")
1092
+ })
1092
1093
  },
1093
1094
  async ({ traceId, candidateVersionId }) => callApi("POST", "replay/decisions", { body: { traceId, candidateVersionId } })
1094
1095
  );
@@ -1097,14 +1098,14 @@ function registerReplayTools(server, callApi) {
1097
1098
  {
1098
1099
  title: "Start Window Replay (Blast Radius)",
1099
1100
  description: "Submit an async job that replays a date window of past executions against a candidate version and measures the blast radius (how many decisions change). Billed per replayed record (REPLAY metric); VIEWER role cannot submit. Poll with lexq_replay_status.",
1100
- inputSchema: {
1101
- candidateVersionId: z8.string().uuid().describe("Version to re-evaluate against"),
1102
- from: z8.string().describe("Window start date (yyyy-MM-dd)"),
1103
- to: z8.string().describe("Window end date (yyyy-MM-dd)"),
1104
- maxRecords: z8.number().int().min(1).optional().describe(
1101
+ inputSchema: z9.object({
1102
+ candidateVersionId: z9.string().uuid().describe("Version to re-evaluate against"),
1103
+ from: z9.string().describe("Window start date (yyyy-MM-dd)"),
1104
+ to: z9.string().describe("Window end date (yyyy-MM-dd)"),
1105
+ maxRecords: z9.number().int().min(1).optional().describe(
1105
1106
  `Sample cap (server default applies; hard cap ${REPLAY_WINDOW_MAX_RECORDS / 1e3}k)`
1106
1107
  )
1107
- }
1108
+ })
1108
1109
  },
1109
1110
  async ({ candidateVersionId, from, to, maxRecords }) => callApi("POST", "replay/jobs", { body: { candidateVersionId, from, to, maxRecords } })
1110
1111
  );
@@ -1113,9 +1114,9 @@ function registerReplayTools(server, callApi) {
1113
1114
  {
1114
1115
  title: "Get Replay Job Status",
1115
1116
  description: "Poll a window replay job. RUNNING shows progress 0\u2013100; COMPLETED fills summary and changedSamples; FAILED carries errorMessage. capped=true means the window exceeded the sample cap and only part was replayed.",
1116
- inputSchema: {
1117
- jobId: z8.string().describe("Replay job ID from lexq_replay_start")
1118
- }
1117
+ inputSchema: z9.object({
1118
+ jobId: z9.string().describe("Replay job ID from lexq_replay_start")
1119
+ })
1119
1120
  },
1120
1121
  async ({ jobId }) => callApi("GET", `replay/jobs/${jobId}`)
1121
1122
  );
@@ -1124,10 +1125,10 @@ function registerReplayTools(server, callApi) {
1124
1125
  {
1125
1126
  title: "List Replay Jobs",
1126
1127
  description: "List window replay job history (reverse-chronological). Lightweight items \u2014 use lexq_replay_status for summary and changed samples.",
1127
- inputSchema: {
1128
- page: z8.number().int().min(0).default(0).describe("Page number"),
1129
- size: z8.number().int().min(1).max(100).default(20).describe("Page size")
1130
- }
1128
+ inputSchema: z9.object({
1129
+ page: z9.number().int().min(0).default(0).describe("Page number"),
1130
+ size: z9.number().int().min(1).max(100).default(20).describe("Page size")
1131
+ })
1131
1132
  },
1132
1133
  async ({ page, size }) => callApi("GET", "replay/jobs", { params: paginationParams(page, size) })
1133
1134
  );
@@ -1136,9 +1137,9 @@ function registerReplayTools(server, callApi) {
1136
1137
  {
1137
1138
  title: "Cancel Replay Job",
1138
1139
  description: "Cooperatively cancel a PENDING or RUNNING window replay job. Other states are rejected. VIEWER role cannot cancel.",
1139
- inputSchema: {
1140
- jobId: z8.string().describe("Replay job ID")
1141
- }
1140
+ inputSchema: z9.object({
1141
+ jobId: z9.string().describe("Replay job ID")
1142
+ })
1142
1143
  },
1143
1144
  async ({ jobId }) => callApi("POST", `replay/jobs/${jobId}/cancel`)
1144
1145
  );
@@ -1147,33 +1148,33 @@ function registerReplayTools(server, callApi) {
1147
1148
  {
1148
1149
  title: "Export Replay Result",
1149
1150
  description: "Export a COMPLETED window replay job. A running job is rejected \u2014 a partial result reads as the whole thing on the receiving end. The two formats carry different things: CSV holds the effect blast radius, whose columns are fixed; JSON holds the changed samples and action parameters, which nest and whose keys differ per tenant. JSON is not a superset of CSV. Returns the file contents as text.",
1150
- inputSchema: {
1151
- jobId: z8.string().describe("Replay job ID"),
1152
- format: z8.enum(EXPORT_FORMATS).default("json").describe("Export format")
1153
- }
1151
+ inputSchema: z9.object({
1152
+ jobId: z9.string().describe("Replay job ID"),
1153
+ format: z9.enum(EXPORT_FORMATS).default("json").describe("Export format")
1154
+ })
1154
1155
  },
1155
1156
  async ({ jobId, format }) => callApi("GET", `replay/jobs/${jobId}/export`, { params: { format } })
1156
1157
  );
1157
1158
  }
1158
1159
 
1159
1160
  // src/mcp/tools/history.ts
1160
- import { z as z9 } from "zod";
1161
+ import { z as z10 } from "zod";
1161
1162
  function registerHistoryTools(server, callApi) {
1162
1163
  server.registerTool(
1163
1164
  "lexq_history_list",
1164
1165
  {
1165
1166
  title: "List Execution History",
1166
1167
  description: "List policy execution history. Shows trace ID, group, version, status, match result, and latency.",
1167
- inputSchema: {
1168
- page: z9.number().int().min(0).default(0).describe("Page number"),
1169
- size: z9.number().int().min(1).max(100).default(20).describe("Page size"),
1170
- traceId: z9.string().optional().describe("Filter by trace ID"),
1171
- groupId: z9.string().uuid().optional().describe("Filter by policy group"),
1172
- versionId: z9.string().uuid().optional().describe("Filter by version"),
1173
- status: z9.enum(["SUCCESS", "NO_MATCH", "ERROR", "TIMEOUT"]).optional().describe("Filter by execution status"),
1174
- startDate: z9.string().optional().describe("Start date (yyyy-MM-dd)"),
1175
- endDate: z9.string().optional().describe("End date (yyyy-MM-dd)")
1176
- }
1168
+ inputSchema: z10.object({
1169
+ page: z10.number().int().min(0).default(0).describe("Page number"),
1170
+ size: z10.number().int().min(1).max(100).default(20).describe("Page size"),
1171
+ traceId: z10.string().optional().describe("Filter by trace ID"),
1172
+ groupId: z10.string().uuid().optional().describe("Filter by policy group"),
1173
+ versionId: z10.string().uuid().optional().describe("Filter by version"),
1174
+ status: z10.enum(["SUCCESS", "NO_MATCH", "ERROR", "TIMEOUT"]).optional().describe("Filter by execution status"),
1175
+ startDate: z10.string().optional().describe("Start date (yyyy-MM-dd)"),
1176
+ endDate: z10.string().optional().describe("End date (yyyy-MM-dd)")
1177
+ })
1177
1178
  },
1178
1179
  async ({ page, size, traceId, groupId, versionId, status, startDate, endDate }) => {
1179
1180
  const params = paginationParams(page, size);
@@ -1191,9 +1192,9 @@ function registerHistoryTools(server, callApi) {
1191
1192
  {
1192
1193
  title: "Get Execution Detail",
1193
1194
  description: "Get full execution detail including inputFacts, mutatedFacts, generatedVariables, executionTraces, and decisionTraces.",
1194
- inputSchema: {
1195
- traceId: z9.string().describe("Trace ID from execution history")
1196
- }
1195
+ inputSchema: z10.object({
1196
+ traceId: z10.string().describe("Trace ID from execution history")
1197
+ })
1197
1198
  },
1198
1199
  async ({ traceId }) => callApi("GET", `execution/history/${traceId}`)
1199
1200
  );
@@ -1202,11 +1203,11 @@ function registerHistoryTools(server, callApi) {
1202
1203
  {
1203
1204
  title: "Execution Statistics",
1204
1205
  description: "Get execution KPIs: total executions, success/failure counts, success rate, and average latency.",
1205
- inputSchema: {
1206
- groupId: z9.string().uuid().optional().describe("Filter by policy group"),
1207
- startDate: z9.string().optional().describe("Start date (yyyy-MM-dd)"),
1208
- endDate: z9.string().optional().describe("End date (yyyy-MM-dd)")
1209
- }
1206
+ inputSchema: z10.object({
1207
+ groupId: z10.string().uuid().optional().describe("Filter by policy group"),
1208
+ startDate: z10.string().optional().describe("Start date (yyyy-MM-dd)"),
1209
+ endDate: z10.string().optional().describe("End date (yyyy-MM-dd)")
1210
+ })
1210
1211
  },
1211
1212
  async ({ groupId, startDate, endDate }) => {
1212
1213
  const params = {};
@@ -1219,16 +1220,16 @@ function registerHistoryTools(server, callApi) {
1219
1220
  }
1220
1221
 
1221
1222
  // src/mcp/tools/provenance.ts
1222
- import { z as z10 } from "zod";
1223
+ import { z as z11 } from "zod";
1223
1224
  function registerProvenanceTools(server, callApi) {
1224
1225
  server.registerTool(
1225
1226
  "lexq_provenance_get",
1226
1227
  {
1227
1228
  title: "Get Decision Provenance",
1228
1229
  description: "Get the lineage of a single decision: what was decided, deterministic why per rule, input facts (PII facts are masked as \u2022\u2022\u2022\u2022\u2022\u2022 with maskedKeys listing them \u2014 values are revealable only in the console, audited), the authored/published/deployed responsibility chain, and the rule snapshot fingerprint.",
1229
- inputSchema: {
1230
- traceId: z10.string().describe("Trace ID of the execution")
1231
- }
1230
+ inputSchema: z11.object({
1231
+ traceId: z11.string().describe("Trace ID of the execution")
1232
+ })
1232
1233
  },
1233
1234
  async ({ traceId }) => callApi("GET", `provenance/${traceId}`)
1234
1235
  );
@@ -1237,15 +1238,15 @@ function registerProvenanceTools(server, callApi) {
1237
1238
  {
1238
1239
  title: "List PII Reveal Audits",
1239
1240
  description: "List the PII reveal audit ledger \u2014 who revealed which fact of which trace, and when. Metadata only; revealed values are never stored or returned. Use for monthly access-log inspection and SIEM collection.",
1240
- inputSchema: {
1241
- page: z10.number().int().min(0).default(0).describe("Page number"),
1242
- size: z10.number().int().min(1).max(100).default(20).describe("Page size"),
1243
- traceId: z10.string().optional().describe("Filter by trace ID (exact match)"),
1244
- revealedBy: z10.string().optional().describe("Filter by operator ID (exact match)"),
1245
- factKey: z10.string().optional().describe("Filter by fact key (partial match, case-insensitive)"),
1246
- startDate: z10.string().optional().describe("Start date (yyyy-MM-dd)"),
1247
- endDate: z10.string().optional().describe("End date (yyyy-MM-dd)")
1248
- }
1241
+ inputSchema: z11.object({
1242
+ page: z11.number().int().min(0).default(0).describe("Page number"),
1243
+ size: z11.number().int().min(1).max(100).default(20).describe("Page size"),
1244
+ traceId: z11.string().optional().describe("Filter by trace ID (exact match)"),
1245
+ revealedBy: z11.string().optional().describe("Filter by operator ID (exact match)"),
1246
+ factKey: z11.string().optional().describe("Filter by fact key (partial match, case-insensitive)"),
1247
+ startDate: z11.string().optional().describe("Start date (yyyy-MM-dd)"),
1248
+ endDate: z11.string().optional().describe("End date (yyyy-MM-dd)")
1249
+ })
1249
1250
  },
1250
1251
  async ({ page, size, traceId, revealedBy, factKey, startDate, endDate }) => {
1251
1252
  const params = paginationParams(page, size);
@@ -1260,22 +1261,22 @@ function registerProvenanceTools(server, callApi) {
1260
1261
  }
1261
1262
 
1262
1263
  // src/mcp/tools/logs.ts
1263
- import { z as z11 } from "zod";
1264
+ import { z as z12 } from "zod";
1264
1265
  function registerLogTools(server, callApi) {
1265
1266
  server.registerTool(
1266
1267
  "lexq_logs_list",
1267
1268
  {
1268
1269
  title: "List Failure Logs",
1269
1270
  description: "List system failure logs from background tasks (platform event webhooks, scheduled deployments).",
1270
- inputSchema: {
1271
- page: z11.number().int().min(0).default(0).describe("Page number"),
1272
- size: z11.number().int().min(1).max(100).default(20).describe("Page size"),
1273
- taskType: z11.enum(TaskType).optional().describe("Task type"),
1274
- status: z11.enum(FailureStatus).optional().describe("Log status"),
1275
- keyword: z11.string().optional().describe("Search in refId, refSubId, errorMessage"),
1276
- startDate: z11.string().optional().describe("Start date (yyyy-MM-dd)"),
1277
- endDate: z11.string().optional().describe("End date (yyyy-MM-dd)")
1278
- }
1271
+ inputSchema: z12.object({
1272
+ page: z12.number().int().min(0).default(0).describe("Page number"),
1273
+ size: z12.number().int().min(1).max(100).default(20).describe("Page size"),
1274
+ taskType: z12.enum(TaskType).optional().describe("Task type"),
1275
+ status: z12.enum(FailureStatus).optional().describe("Log status"),
1276
+ keyword: z12.string().optional().describe("Search in refId, refSubId, errorMessage"),
1277
+ startDate: z12.string().optional().describe("Start date (yyyy-MM-dd)"),
1278
+ endDate: z12.string().optional().describe("End date (yyyy-MM-dd)")
1279
+ })
1279
1280
  },
1280
1281
  async ({ page, size, taskType, status, keyword, startDate, endDate }) => {
1281
1282
  const params = paginationParams(page, size);
@@ -1292,9 +1293,9 @@ function registerLogTools(server, callApi) {
1292
1293
  {
1293
1294
  title: "Get Failure Log",
1294
1295
  description: "Get failure log detail by ID.",
1295
- inputSchema: {
1296
- logId: z11.string().uuid().describe("Failure log ID")
1297
- }
1296
+ inputSchema: z12.object({
1297
+ logId: z12.string().uuid().describe("Failure log ID")
1298
+ })
1298
1299
  },
1299
1300
  async ({ logId }) => callApi("GET", `failure-logs/${logId}`)
1300
1301
  );
@@ -1303,10 +1304,10 @@ function registerLogTools(server, callApi) {
1303
1304
  {
1304
1305
  title: "Process Failure Log",
1305
1306
  description: "Process a single failure log: RESOLVE (mark as manually fixed) or IGNORE (skip intentionally).",
1306
- inputSchema: {
1307
- logId: z11.string().uuid().describe("Failure log ID"),
1308
- action: z11.enum(FailureAction).describe("Action to take")
1309
- }
1307
+ inputSchema: z12.object({
1308
+ logId: z12.string().uuid().describe("Failure log ID"),
1309
+ action: z12.enum(FailureAction).describe("Action to take")
1310
+ })
1310
1311
  },
1311
1312
  async ({ logId, action }) => callApi("POST", `failure-logs/${logId}/actions`, {
1312
1313
  params: { action }
@@ -1317,10 +1318,10 @@ function registerLogTools(server, callApi) {
1317
1318
  {
1318
1319
  title: "Bulk Process Failure Logs",
1319
1320
  description: "Process multiple failure logs at once. Provide an array of log IDs and the action.",
1320
- inputSchema: {
1321
- logIds: z11.array(z11.string().uuid()).describe("Array of failure log IDs"),
1322
- action: z11.enum(FailureAction).describe("Action to apply to all logs")
1323
- }
1321
+ inputSchema: z12.object({
1322
+ logIds: z12.array(z12.string().uuid()).describe("Array of failure log IDs"),
1323
+ action: z12.enum(FailureAction).describe("Action to apply to all logs")
1324
+ })
1324
1325
  },
1325
1326
  async ({ logIds, action }) => callApi("POST", "failure-logs/bulk-actions", {
1326
1327
  body: { logIds, action }
@@ -1329,17 +1330,17 @@ function registerLogTools(server, callApi) {
1329
1330
  }
1330
1331
 
1331
1332
  // src/mcp/tools/webhook-subscriptions.ts
1332
- import { z as z12 } from "zod";
1333
+ import { z as z13 } from "zod";
1333
1334
  function registerWebhookSubscriptionTools(server, callApi) {
1334
1335
  server.registerTool(
1335
1336
  "lexq_webhook_subscriptions_list",
1336
1337
  {
1337
1338
  title: "List Webhook Subscriptions",
1338
1339
  description: "List platform event webhook subscriptions. These receive deployment lifecycle notifications (publish, deploy, rollback, undeploy).",
1339
- inputSchema: {
1340
- page: z12.number().int().min(0).default(0).describe("Page number"),
1341
- size: z12.number().int().min(1).max(100).default(20).describe("Page size")
1342
- }
1340
+ inputSchema: z13.object({
1341
+ page: z13.number().int().min(0).default(0).describe("Page number"),
1342
+ size: z13.number().int().min(1).max(100).default(20).describe("Page size")
1343
+ })
1343
1344
  },
1344
1345
  async ({ page, size }) => {
1345
1346
  const params = paginationParams(page, size);
@@ -1351,9 +1352,9 @@ function registerWebhookSubscriptionTools(server, callApi) {
1351
1352
  {
1352
1353
  title: "Get Webhook Subscription",
1353
1354
  description: "Get webhook subscription detail by ID.",
1354
- inputSchema: {
1355
- id: z12.string().uuid().describe("Webhook subscription ID")
1356
- }
1355
+ inputSchema: z13.object({
1356
+ id: z13.string().uuid().describe("Webhook subscription ID")
1357
+ })
1357
1358
  },
1358
1359
  async ({ id }) => callApi("GET", `webhook-subscriptions/${id}`)
1359
1360
  );
@@ -1362,15 +1363,15 @@ function registerWebhookSubscriptionTools(server, callApi) {
1362
1363
  {
1363
1364
  title: "Save Webhook Subscription",
1364
1365
  description: 'Create or update a webhook subscription. Omit id to create, provide id to update. Events: VERSION_PUBLISHED, DEPLOYED, ROLLED_BACK, UNDEPLOYED. Formats: GENERIC (full JSON), SLACK ({"text": "..."}).',
1365
- inputSchema: {
1366
- id: z12.string().uuid().optional().describe("Subscription ID (omit to create, provide to update)"),
1367
- name: z12.string().min(1).describe("Subscription name (unique per tenant)"),
1368
- webhookUrl: z12.string().url().describe("Webhook endpoint URL"),
1369
- subscribedEvents: z12.array(z12.enum(PlatformEventType)).min(1).describe("Events to subscribe to"),
1370
- payloadFormat: z12.enum(WebhookPayloadFormat).optional().default("GENERIC").describe("Payload format"),
1371
- secret: z12.string().optional().describe("HMAC-SHA256 signing secret"),
1372
- isActive: z12.boolean().optional().default(true).describe("Whether the subscription is active")
1373
- }
1366
+ inputSchema: z13.object({
1367
+ id: z13.string().uuid().optional().describe("Subscription ID (omit to create, provide to update)"),
1368
+ name: z13.string().min(1).describe("Subscription name (unique per tenant)"),
1369
+ webhookUrl: z13.string().url().describe("Webhook endpoint URL"),
1370
+ subscribedEvents: z13.array(z13.enum(PlatformEventType)).min(1).describe("Events to subscribe to"),
1371
+ payloadFormat: z13.enum(WebhookPayloadFormat).optional().default("GENERIC").describe("Payload format"),
1372
+ secret: z13.string().optional().describe("HMAC-SHA256 signing secret"),
1373
+ isActive: z13.boolean().optional().default(true).describe("Whether the subscription is active")
1374
+ })
1374
1375
  },
1375
1376
  async ({ ...body }) => callApi("POST", "webhook-subscriptions", { body })
1376
1377
  );
@@ -1379,9 +1380,9 @@ function registerWebhookSubscriptionTools(server, callApi) {
1379
1380
  {
1380
1381
  title: "Delete Webhook Subscription",
1381
1382
  description: "Delete a webhook subscription by ID.",
1382
- inputSchema: {
1383
- id: z12.string().uuid().describe("Webhook subscription ID")
1384
- }
1383
+ inputSchema: z13.object({
1384
+ id: z13.string().uuid().describe("Webhook subscription ID")
1385
+ })
1385
1386
  },
1386
1387
  async ({ id }) => callApi("DELETE", `webhook-subscriptions/${id}`)
1387
1388
  );
@@ -1390,23 +1391,23 @@ function registerWebhookSubscriptionTools(server, callApi) {
1390
1391
  {
1391
1392
  title: "Test Webhook Subscription",
1392
1393
  description: "Send a test event to verify webhook connectivity. Returns the HTTP status code and success/failure message.",
1393
- inputSchema: {
1394
- id: z12.string().uuid().describe("Webhook subscription ID")
1395
- }
1394
+ inputSchema: z13.object({
1395
+ id: z13.string().uuid().describe("Webhook subscription ID")
1396
+ })
1396
1397
  },
1397
1398
  async ({ id }) => callApi("POST", `webhook-subscriptions/${id}/test`)
1398
1399
  );
1399
1400
  }
1400
1401
 
1401
1402
  // src/mcp/tools/domain-templates.ts
1402
- import { z as z13 } from "zod";
1403
+ import { z as z14 } from "zod";
1403
1404
  function registerDomainTemplateTools(server, callApi) {
1404
1405
  server.registerTool(
1405
1406
  "lexq_domain_templates_list",
1406
1407
  {
1407
1408
  title: "List Domain Templates",
1408
1409
  description: "List all domain templates. A domain template is a curated, industry-specific starter pack of fact definitions and sample rules (e.g. ECOMMERCE). Each entry reports its key, status (ACTIVE or COMING_SOON), and a summary of what it provisions. Call this before preview or apply to discover which templates can currently be applied.",
1409
- inputSchema: {}
1410
+ inputSchema: z14.object({})
1410
1411
  },
1411
1412
  async () => callApi("GET", "domain-templates")
1412
1413
  );
@@ -1415,11 +1416,11 @@ function registerDomainTemplateTools(server, callApi) {
1415
1416
  {
1416
1417
  title: "Preview Domain Template",
1417
1418
  description: "Preview exactly what a domain template will provision before applying it: the fact definitions it registers, the sample rules it creates, and an apply plan. This is a read-only dry run \u2014 nothing is created. Only ACTIVE templates can be previewed.",
1418
- inputSchema: {
1419
- template: z13.string().describe(
1419
+ inputSchema: z14.object({
1420
+ template: z14.string().describe(
1420
1421
  "Domain template key (e.g. ECOMMERCE). Use lexq_domain_templates_list to see available keys \u2014 currently only ECOMMERCE is ACTIVE."
1421
1422
  )
1422
- }
1423
+ })
1423
1424
  },
1424
1425
  async ({ template }) => callApi("GET", `domain-templates/${template}/preview`)
1425
1426
  );
@@ -1428,12 +1429,12 @@ function registerDomainTemplateTools(server, callApi) {
1428
1429
  {
1429
1430
  title: "Apply Domain Template",
1430
1431
  description: "Apply a domain template to the current tenant. Creates the template's fact definitions and a new policy group pre-populated with its sample rules as a DRAFT version. Existing facts are skipped \u2014 apply is additive and never overwrites existing schema. Run lexq_domain_templates_preview first to review what will be created. Only ACTIVE templates can be applied.",
1431
- inputSchema: {
1432
- template: z13.string().describe("Domain template key to apply (e.g. ECOMMERCE)."),
1433
- customName: z13.string().optional().describe(
1432
+ inputSchema: z14.object({
1433
+ template: z14.string().describe("Domain template key to apply (e.g. ECOMMERCE)."),
1434
+ customName: z14.string().optional().describe(
1434
1435
  "Optional custom name for the policy group that gets created. If omitted, the template's default name is used."
1435
1436
  )
1436
- }
1437
+ })
1437
1438
  },
1438
1439
  async ({ template, customName }) => {
1439
1440
  const body = {};