@fluentcommerce/fluent-mcp-extn 0.7.0 → 0.7.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/tools.js CHANGED
@@ -209,7 +209,7 @@ const SettingListedInputSchema = {
209
209
  additionalProperties: false,
210
210
  };
211
211
  const WORKFLOW_LISTED_SCHEMAS = {
212
- "workflow.upload": {
212
+ "workflow_upload": {
213
213
  type: "object",
214
214
  properties: {
215
215
  workflow: {
@@ -234,7 +234,7 @@ const WORKFLOW_LISTED_SCHEMAS = {
234
234
  required: ["workflow"],
235
235
  additionalProperties: false,
236
236
  },
237
- "workflow.diff": {
237
+ "workflow_diff": {
238
238
  type: "object",
239
239
  properties: {
240
240
  base: {
@@ -255,7 +255,7 @@ const WORKFLOW_LISTED_SCHEMAS = {
255
255
  required: ["base", "target"],
256
256
  additionalProperties: false,
257
257
  },
258
- "workflow.simulate": {
258
+ "workflow_simulate": {
259
259
  type: "object",
260
260
  properties: {
261
261
  workflow: {
@@ -284,8 +284,8 @@ const WORKFLOW_LISTED_SCHEMAS = {
284
284
  },
285
285
  };
286
286
  const SETTING_LISTED_SCHEMAS = {
287
- "setting.upsert": SettingListedInputSchema,
288
- "setting.bulkUpsert": {
287
+ "setting_upsert": SettingListedInputSchema,
288
+ "setting_bulkUpsert": {
289
289
  type: "object",
290
290
  properties: {
291
291
  settings: {
@@ -303,152 +303,152 @@ const SETTING_LISTED_SCHEMAS = {
303
303
  export const TOOL_CATALOG = [
304
304
  // ---- config & health (no API) ------------------------------------------
305
305
  {
306
- name: "config.validate",
306
+ name: "config_validate",
307
307
  description: "Run first: validates auth/base URL/retailer configuration and reports readiness for API tools.",
308
308
  schema: z.object({}),
309
309
  annotations: { title: "Validate Configuration", readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
310
310
  },
311
311
  {
312
- name: "health.ping",
312
+ name: "health_ping",
313
313
  description: "Quick diagnostics: confirms SDK adapter connection and config readiness when calls fail.",
314
314
  schema: z.object({}),
315
315
  annotations: { title: "Health Ping", readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true },
316
316
  },
317
317
  {
318
- name: "time.resolveWindow",
318
+ name: "time_resolveWindow",
319
319
  description: "Resolve natural-language, shorthand, or datemath time phrases like 'last month', '1h30m', 'now-7d/d', or 'now-7d to now' into exact ISO from/to timestamps. Returns candidates instead of guessing when the phrase is ambiguous.",
320
320
  schema: ResolveTimeWindowInputSchema,
321
321
  annotations: { title: "Resolve Time Window", readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
322
322
  },
323
323
  // ---- event tools (from event-tools module) -----------------------------
324
324
  ...fromModule(EVENT_TOOL_DEFINITIONS, {
325
- "event.build": EventBuildInputSchema,
326
- "event.send": EventPublishInputSchema,
327
- "event.get": EventGetInputSchema,
328
- "event.list": EventListInputSchema,
329
- "event.flowInspect": EventFlowInspectInputSchema,
325
+ "event_build": EventBuildInputSchema,
326
+ "event_send": EventPublishInputSchema,
327
+ "event_get": EventGetInputSchema,
328
+ "event_list": EventListInputSchema,
329
+ "event_flowInspect": EventFlowInspectInputSchema,
330
330
  }),
331
331
  // ---- metrics tools (from metrics-tools module) -------------------------
332
332
  ...fromModule(METRICS_TOOL_DEFINITIONS, {
333
- "metrics.query": MetricsQueryInputSchema,
334
- "metrics.topEvents": MetricsTopEventsInputSchema,
335
- "metrics.healthCheck": MetricsHealthCheckInputSchema,
336
- "metrics.sloReport": MetricsSloReportInputSchema,
337
- "metrics.labelCatalog": MetricsLabelCatalogInputSchema,
338
- "metrics.metricCatalog": MetricsMetricCatalogInputSchema,
339
- "metrics.planQuery": MetricsPlanQueryInputSchema,
340
- "metrics.snapshot": MetricsSnapshotInputSchema,
341
- "metrics.compare": MetricsCompareInputSchema,
342
- "metrics.mutationAudit": MetricsMutationAuditInputSchema,
333
+ "metrics_query": MetricsQueryInputSchema,
334
+ "metrics_topEvents": MetricsTopEventsInputSchema,
335
+ "metrics_healthCheck": MetricsHealthCheckInputSchema,
336
+ "metrics_sloReport": MetricsSloReportInputSchema,
337
+ "metrics_labelCatalog": MetricsLabelCatalogInputSchema,
338
+ "metrics_metricCatalog": MetricsMetricCatalogInputSchema,
339
+ "metrics_planQuery": MetricsPlanQueryInputSchema,
340
+ "metrics_snapshot": MetricsSnapshotInputSchema,
341
+ "metrics_compare": MetricsCompareInputSchema,
342
+ "metrics_mutationAudit": MetricsMutationAuditInputSchema,
343
343
  }),
344
- // ---- workflow.transitions & plugin.list (inline) -----------------------
344
+ // ---- workflow_transitions & plugin_list (inline) -----------------------
345
345
  {
346
- name: "workflow.transitions",
346
+ name: "workflow_transitions",
347
347
  description: [
348
348
  "Query available user actions (transitions) via POST /api/v4.1/transition.",
349
349
  "Requires flexType (e.g. ORDER::HD) — auto-derived from type+subtype when omitted.",
350
- "Returns per-trigger summary of event names, required attributes, _attributeTemplate (ready for event.send), _predictions with target status + action classification + multi-step lookahead, and _recommended safest next action. Auto-fetches workflow when not cached.",
350
+ "Returns per-trigger summary of event names, required attributes, _attributeTemplate (ready for event_send), _predictions with target status + action classification + multi-step lookahead, and _recommended safest next action. Auto-fetches workflow when not cached.",
351
351
  ].join("\n"),
352
352
  schema: TransitionActionsInputSchema,
353
353
  annotations: { title: "Query Transitions", readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true },
354
354
  },
355
355
  {
356
- name: "plugin.list",
356
+ name: "plugin_list",
357
357
  description: "List registered orchestration rules with metadata. Optional name filter. Use keysOnly=true for lightweight key+count response.",
358
358
  schema: PluginListInputSchema,
359
359
  annotations: { title: "List Plugins", readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true },
360
360
  },
361
- // ---- graphql query tools (from graphql-query-tools module) -------------
361
+ // ---- graphql_query tools (from graphql_query-tools module) -------------
362
362
  ...fromModule(GRAPHQL_QUERY_TOOL_DEFINITIONS, {
363
- "graphql.query": GraphQLQueryInputSchema,
364
- "graphql.queryAll": GraphQLQueryAllInputSchema,
365
- "graphql.batchMutate": GraphQLBatchMutateInputSchema,
366
- "graphql.introspect": GraphQLIntrospectInputSchema,
363
+ "graphql_query": GraphQLQueryInputSchema,
364
+ "graphql_queryAll": GraphQLQueryAllInputSchema,
365
+ "graphql_batchMutate": GraphQLBatchMutateInputSchema,
366
+ "graphql_introspect": GraphQLIntrospectInputSchema,
367
367
  }),
368
368
  // ---- batch tools (from batch-tools module) -----------------------------
369
369
  ...fromModule(BATCH_TOOL_DEFINITIONS, {
370
- "batch.create": BatchCreateInputSchema,
371
- "batch.send": BatchSendInputSchema,
372
- "batch.status": BatchStatusInputSchema,
373
- "batch.batchStatus": BatchGetBatchStatusInputSchema,
374
- "batch.results": BatchResultsInputSchema,
375
- "batch.describePayload": BatchDescribePayloadInputSchema,
370
+ "batch_create": BatchCreateInputSchema,
371
+ "batch_send": BatchSendInputSchema,
372
+ "batch_status": BatchStatusInputSchema,
373
+ "batch_batchStatus": BatchGetBatchStatusInputSchema,
374
+ "batch_results": BatchResultsInputSchema,
375
+ "batch_describePayload": BatchDescribePayloadInputSchema,
376
376
  }),
377
377
  // ---- connection & webhook (inline) -------------------------------------
378
378
  {
379
- name: "connection.test",
379
+ name: "connection_test",
380
380
  description: "End-to-end connectivity test. Authenticates and executes a 'me' query.",
381
381
  schema: z.object({}),
382
382
  annotations: { title: "Test Connection", readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true },
383
383
  },
384
384
  {
385
- name: "webhook.validate",
385
+ name: "webhook_validate",
386
386
  description: "Validate a webhook payload. Optionally verify signature with public key.",
387
387
  schema: WebhookValidateInputSchema,
388
388
  annotations: { title: "Validate Webhook", readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
389
389
  },
390
390
  // ---- connection management (multi-profile) --------------------------------
391
391
  {
392
- name: "connection.list",
392
+ name: "connection_list",
393
393
  description: "List all loaded profiles with connection status, auth strategy, and which is the default.",
394
394
  schema: z.object({}),
395
395
  annotations: { title: "List Connections", readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
396
396
  },
397
397
  {
398
- name: "connection.add",
398
+ name: "connection_add",
399
399
  description: "Register an additional connection from a CLI profile or explicit credentials.",
400
400
  schema: ConnectionAddInputSchema,
401
401
  annotations: { title: "Add Connection", readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: false },
402
402
  },
403
403
  {
404
- name: "connection.remove",
404
+ name: "connection_remove",
405
405
  description: "Remove a previously loaded profile. Cannot remove the current default profile.",
406
406
  schema: ConnectionRemoveInputSchema,
407
407
  annotations: { title: "Remove Connection", readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: false },
408
408
  },
409
409
  {
410
- name: "connection.switch",
410
+ name: "connection_switch",
411
411
  description: "Switch the default profile. Subsequent tool calls without an explicit profile parameter will use this profile.",
412
412
  schema: ConnectionSwitchInputSchema,
413
413
  annotations: { title: "Switch Default Connection", readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: false },
414
414
  },
415
415
  // ---- sub-module tools (entity, workflow, setting, environment, test, graphql schema, cache) --
416
416
  ...fromModule(ENTITY_TOOL_DEFINITIONS, {
417
- "entity.create": EntityCreateInputSchema,
418
- "entity.update": EntityUpdateInputSchema,
419
- "entity.get": EntityGetInputSchema,
420
- "entity.planCreate": EntityPlanCreateInputSchema,
421
- "entity.planUpdate": EntityPlanUpdateInputSchema,
417
+ "entity_create": EntityCreateInputSchema,
418
+ "entity_update": EntityUpdateInputSchema,
419
+ "entity_get": EntityGetInputSchema,
420
+ "entity_planCreate": EntityPlanCreateInputSchema,
421
+ "entity_planUpdate": EntityPlanUpdateInputSchema,
422
422
  }),
423
423
  ...fromModule(WORKFLOW_TOOL_DEFINITIONS, {
424
- "workflow.get": WorkflowGetInputSchema,
425
- "workflow.list": WorkflowListInputSchema,
426
- "workflow.upload": WorkflowUploadInputSchema,
427
- "workflow.diff": WorkflowDiffInputSchema,
428
- "workflow.simulate": WorkflowSimulateInputSchema,
424
+ "workflow_get": WorkflowGetInputSchema,
425
+ "workflow_list": WorkflowListInputSchema,
426
+ "workflow_upload": WorkflowUploadInputSchema,
427
+ "workflow_diff": WorkflowDiffInputSchema,
428
+ "workflow_simulate": WorkflowSimulateInputSchema,
429
429
  }, WORKFLOW_LISTED_SCHEMAS),
430
430
  ...fromModule(SETTING_TOOL_DEFINITIONS, {
431
- "setting.get": SettingGetInputSchema,
432
- "setting.upsert": SettingUpsertInputSchema,
433
- "setting.bulkUpsert": SettingBulkUpsertInputSchema,
431
+ "setting_get": SettingGetInputSchema,
432
+ "setting_upsert": SettingUpsertInputSchema,
433
+ "setting_bulkUpsert": SettingBulkUpsertInputSchema,
434
434
  }, SETTING_LISTED_SCHEMAS),
435
435
  ...fromModule(ENVIRONMENT_TOOL_DEFINITIONS, {
436
- "environment.discover": EnvironmentDiscoverInputSchema,
437
- "environment.validate": EnvironmentValidateInputSchema,
436
+ "environment_discover": EnvironmentDiscoverInputSchema,
437
+ "environment_validate": EnvironmentValidateInputSchema,
438
438
  }),
439
439
  ...fromModule(TEST_TOOL_DEFINITIONS, {
440
- "test.assert": TestAssertInputSchema,
440
+ "test_assert": TestAssertInputSchema,
441
441
  }),
442
442
  ...fromModule(GRAPHQL_SCHEMA_TOOL_DEFINITIONS, {
443
- "graphql.listRoots": ListRootsInputSchema,
444
- "graphql.planOperation": PlanOperationInputSchema,
445
- "graphql.buildQuery": BuildQueryInputSchema,
446
- "graphql.validate": ValidateInputSchema,
447
- "graphql.generateFull": GenerateFullInputSchema,
443
+ "graphql_listRoots": ListRootsInputSchema,
444
+ "graphql_planOperation": PlanOperationInputSchema,
445
+ "graphql_buildQuery": BuildQueryInputSchema,
446
+ "graphql_validate": ValidateInputSchema,
447
+ "graphql_generateFull": GenerateFullInputSchema,
448
448
  }),
449
449
  ...fromModule(CACHE_TOOL_DEFINITIONS, {
450
- "cache.status": CacheStatusInputSchema,
451
- "cache.clear": CacheClearInputSchema,
450
+ "cache_status": CacheStatusInputSchema,
451
+ "cache_clear": CacheClearInputSchema,
452
452
  }),
453
453
  ];
454
454
  // ---------------------------------------------------------------------------
@@ -707,14 +707,14 @@ export function buildActionPredictions(analysis, workflow) {
707
707
  }
708
708
  }
709
709
  if (!workflow) {
710
- hints.push("Call workflow.get with this entity type+subtype to enable status predictions and action classification.");
710
+ hints.push("Call workflow_get with this entity type+subtype to enable status predictions and action classification.");
711
711
  }
712
712
  if (Object.keys(_attributeTemplate).length > 0) {
713
- hints.push("Use _attributeTemplate values as the 'attributes' parameter in event.send or event.build.");
713
+ hints.push("Use _attributeTemplate values as the 'attributes' parameter in event_send or event_build.");
714
714
  }
715
715
  const terminalActions = predictions.filter((p) => p.classification === "terminal");
716
716
  if (terminalActions.length > 0) {
717
- hints.push(`Terminal actions (no further workflow transitions): ${terminalActions.map((a) => a.eventName).join(", ")}. Use with caution.`);
717
+ hints.push(`Terminal actions (no further workflow_transitions): ${terminalActions.map((a) => a.eventName).join(", ")}. Use with caution.`);
718
718
  }
719
719
  const progressionActions = predictions.filter((p) => p.classification === "progression");
720
720
  if (progressionActions.length > 0 && progressionActions.length < predictions.length) {
@@ -830,7 +830,7 @@ export function getFilteredCatalog(filterOverride) {
830
830
  if (prefixes.length === 0)
831
831
  return TOOL_CATALOG;
832
832
  return TOOL_CATALOG.filter((t) => {
833
- const category = t.name.split(".")[0].toLowerCase();
833
+ const category = t.name.split("_")[0].toLowerCase();
834
834
  return prefixes.includes(category);
835
835
  });
836
836
  }
@@ -867,28 +867,28 @@ function json(payload, isError = false, budget) {
867
867
  }
868
868
  function requireClient(ctx) {
869
869
  if (!ctx.client) {
870
- throw new ToolError("CONFIG_ERROR", "SDK client is not available. Run config.validate and fix auth/base URL.");
870
+ throw new ToolError("CONFIG_ERROR", "SDK client is not available. Run config_validate and fix auth/base URL.");
871
871
  }
872
872
  return ctx.client;
873
873
  }
874
874
  /** Tools where selecting a profile has no effect. */
875
875
  const PROFILE_IRRELEVANT_TOOLS = new Set([
876
- "time.resolveWindow",
877
- "webhook.validate",
878
- "connection.list",
879
- "connection.add",
880
- "connection.remove",
881
- "connection.switch",
876
+ "time_resolveWindow",
877
+ "webhook_validate",
878
+ "connection_list",
879
+ "connection_add",
880
+ "connection_remove",
881
+ "connection_switch",
882
882
  ]);
883
883
  /**
884
884
  * Tools that should follow the selected profile's config/cache but do not need
885
885
  * an SDK client to do their work.
886
886
  */
887
887
  const PROFILE_CONFIG_ONLY_TOOLS = new Set([
888
- "config.validate",
889
- "cache.status",
890
- "cache.clear",
891
- "event.build",
888
+ "config_validate",
889
+ "cache_status",
890
+ "cache_clear",
891
+ "event_build",
892
892
  ]);
893
893
  const MCP_TOOL_INPUT_SCHEMA = z.object({}).passthrough().default({});
894
894
  function getLowLevelServer(server) {
@@ -977,7 +977,7 @@ export function getListedInputSchema(tool, registry) {
977
977
  const props = (normalized.properties ?? {});
978
978
  props.profile = {
979
979
  type: "string",
980
- description: `Target profile (see connection.list). Default: ${registry.defaultName}`,
980
+ description: `Target profile (see connection_list). Default: ${registry.defaultName}`,
981
981
  };
982
982
  normalized.properties = props;
983
983
  }
@@ -1077,14 +1077,14 @@ async function handleToolCall(toolName, args, ctx) {
1077
1077
  }
1078
1078
  async function dispatchToolCall(toolName, args, ctx) {
1079
1079
  // ------- cache tools (no API) ----------------------------------------
1080
- if (toolName === "cache.status") {
1080
+ if (toolName === "cache_status") {
1081
1081
  return json(handleCacheStatus(args, ctx.cache), false, ctx.responseBudget);
1082
1082
  }
1083
- if (toolName === "cache.clear") {
1083
+ if (toolName === "cache_clear") {
1084
1084
  return json(handleCacheClear(args, ctx.cache), false, ctx.responseBudget);
1085
1085
  }
1086
1086
  // ------- config & health (no API) ------------------------------------
1087
- if (toolName === "config.validate") {
1087
+ if (toolName === "config_validate") {
1088
1088
  const validation = validateConfig(ctx.config);
1089
1089
  return json({
1090
1090
  ok: true,
@@ -1093,7 +1093,7 @@ async function dispatchToolCall(toolName, args, ctx) {
1093
1093
  config: toSafeConfigSummary(ctx.config),
1094
1094
  });
1095
1095
  }
1096
- if (toolName === "health.ping") {
1096
+ if (toolName === "health_ping") {
1097
1097
  const validation = validateConfig(ctx.config);
1098
1098
  return json({
1099
1099
  ok: true,
@@ -1104,11 +1104,11 @@ async function dispatchToolCall(toolName, args, ctx) {
1104
1104
  config: toSafeConfigSummary(ctx.config),
1105
1105
  });
1106
1106
  }
1107
- if (toolName === "time.resolveWindow") {
1107
+ if (toolName === "time_resolveWindow") {
1108
1108
  return json(handleResolveTimeWindow(args), false, ctx.responseBudget);
1109
1109
  }
1110
1110
  // ------- connection management (multi-profile) -----------------------
1111
- if (toolName === "connection.list") {
1111
+ if (toolName === "connection_list") {
1112
1112
  if (!ctx.registry) {
1113
1113
  return json({
1114
1114
  ok: true,
@@ -1124,7 +1124,7 @@ async function dispatchToolCall(toolName, args, ctx) {
1124
1124
  }
1125
1125
  return json({ ok: true, profiles: ctx.registry.list() });
1126
1126
  }
1127
- if (toolName === "connection.add") {
1127
+ if (toolName === "connection_add") {
1128
1128
  const parsed = ConnectionAddInputSchema.parse(args);
1129
1129
  if (!ctx.registry) {
1130
1130
  return json(toToolFailure(new ToolError("CONFIG_ERROR", "Multi-profile not enabled. Set FLUENT_ADDITIONAL_PROFILES or start with a FLUENT_PROFILE to enable the registry.")), true);
@@ -1136,7 +1136,7 @@ async function dispatchToolCall(toolName, args, ctx) {
1136
1136
  ctx.registry.add(name, params);
1137
1137
  return json({ ok: true, message: `Profile "${parsed.name}" registered (lazy init on first use).`, profiles: ctx.registry.list() });
1138
1138
  }
1139
- if (toolName === "connection.remove") {
1139
+ if (toolName === "connection_remove") {
1140
1140
  const parsed = ConnectionRemoveInputSchema.parse(args);
1141
1141
  if (!ctx.registry) {
1142
1142
  return json(toToolFailure(new ToolError("CONFIG_ERROR", "Multi-profile not enabled.")), true);
@@ -1144,7 +1144,7 @@ async function dispatchToolCall(toolName, args, ctx) {
1144
1144
  ctx.registry.remove(parsed.name);
1145
1145
  return json({ ok: true, message: `Profile "${parsed.name}" removed.`, profiles: ctx.registry.list() });
1146
1146
  }
1147
- if (toolName === "connection.switch") {
1147
+ if (toolName === "connection_switch") {
1148
1148
  const parsed = ConnectionSwitchInputSchema.parse(args);
1149
1149
  if (!ctx.registry) {
1150
1150
  return json(toToolFailure(new ToolError("CONFIG_ERROR", "Multi-profile not enabled.")), true);
@@ -1158,54 +1158,54 @@ async function dispatchToolCall(toolName, args, ctx) {
1158
1158
  return json({ ok: true, message: `Default profile switched to "${parsed.name}".`, profiles: ctx.registry.list() });
1159
1159
  }
1160
1160
  // ------- event tools (delegated to event-tools module) ---------------
1161
- if (toolName === "event.build") {
1161
+ if (toolName === "event_build") {
1162
1162
  return json(await handleEventBuild(args, ctx), false, ctx.responseBudget);
1163
1163
  }
1164
- if (toolName === "event.send") {
1164
+ if (toolName === "event_send") {
1165
1165
  return json(await handleEventSend(args, ctx), false, ctx.responseBudget);
1166
1166
  }
1167
- if (toolName === "event.get") {
1167
+ if (toolName === "event_get") {
1168
1168
  return json(await handleEventGet(args, ctx), false, ctx.responseBudget);
1169
1169
  }
1170
- if (toolName === "event.list") {
1170
+ if (toolName === "event_list") {
1171
1171
  return json(await handleEventList(args, ctx), false, ctx.responseBudget);
1172
1172
  }
1173
- if (toolName === "event.flowInspect") {
1173
+ if (toolName === "event_flowInspect") {
1174
1174
  return json(await handleEventFlowInspect(args, ctx), false, ctx.responseBudget);
1175
1175
  }
1176
1176
  // ------- metrics tools (delegated to metrics-tools module) -----------
1177
- if (toolName === "metrics.query") {
1177
+ if (toolName === "metrics_query") {
1178
1178
  return json(await handleMetricsQuery(args, ctx), false, ctx.responseBudget);
1179
1179
  }
1180
- if (toolName === "metrics.healthCheck") {
1180
+ if (toolName === "metrics_healthCheck") {
1181
1181
  return json(await handleMetricsHealthCheck(args, ctx), false, ctx.responseBudget);
1182
1182
  }
1183
- if (toolName === "metrics.sloReport") {
1183
+ if (toolName === "metrics_sloReport") {
1184
1184
  return json(await handleMetricsSloReport(args, ctx), false, ctx.responseBudget);
1185
1185
  }
1186
- if (toolName === "metrics.labelCatalog") {
1186
+ if (toolName === "metrics_labelCatalog") {
1187
1187
  return json(await handleMetricsLabelCatalog(args, ctx), false, ctx.responseBudget);
1188
1188
  }
1189
- if (toolName === "metrics.metricCatalog") {
1189
+ if (toolName === "metrics_metricCatalog") {
1190
1190
  return json(await handleMetricsMetricCatalog(args, ctx), false, ctx.responseBudget);
1191
1191
  }
1192
- if (toolName === "metrics.planQuery") {
1192
+ if (toolName === "metrics_planQuery") {
1193
1193
  return json(await handleMetricsPlanQuery(args), false, ctx.responseBudget);
1194
1194
  }
1195
- if (toolName === "metrics.topEvents") {
1195
+ if (toolName === "metrics_topEvents") {
1196
1196
  return json(await handleMetricsTopEvents(args, ctx), false, ctx.responseBudget);
1197
1197
  }
1198
- if (toolName === "metrics.snapshot") {
1198
+ if (toolName === "metrics_snapshot") {
1199
1199
  return json(await handleMetricsSnapshot(args, ctx), false, ctx.responseBudget);
1200
1200
  }
1201
- if (toolName === "metrics.compare") {
1201
+ if (toolName === "metrics_compare") {
1202
1202
  return json(await handleMetricsCompare(args, ctx), false, ctx.responseBudget);
1203
1203
  }
1204
- if (toolName === "metrics.mutationAudit") {
1204
+ if (toolName === "metrics_mutationAudit") {
1205
1205
  return json(await handleMetricsMutationAudit(args, ctx), false, ctx.responseBudget);
1206
1206
  }
1207
- // ------- workflow.transitions (inline) --------------------------------
1208
- if (toolName === "workflow.transitions") {
1207
+ // ------- workflow_transitions (inline) --------------------------------
1208
+ if (toolName === "workflow_transitions") {
1209
1209
  const parsed = TransitionActionsInputSchema.parse(args);
1210
1210
  const client = requireClient(ctx);
1211
1211
  const payload = resolveTransitionRequest(parsed, ctx.config.retailerId);
@@ -1273,8 +1273,8 @@ async function dispatchToolCall(toolName, args, ctx) {
1273
1273
  ],
1274
1274
  }, false, ctx.responseBudget);
1275
1275
  }
1276
- // ------- plugin.list (inline) ----------------------------------------
1277
- if (toolName === "plugin.list") {
1276
+ // ------- plugin_list (inline) ----------------------------------------
1277
+ if (toolName === "plugin_list") {
1278
1278
  const client = requireClient(ctx);
1279
1279
  const parsed = PluginListInputSchema.parse(args);
1280
1280
  let rawPlugins = null;
@@ -1321,40 +1321,40 @@ async function dispatchToolCall(toolName, args, ctx) {
1321
1321
  ...(cacheMeta ? { _cache: cacheMeta } : {}),
1322
1322
  }, false, ctx.responseBudget);
1323
1323
  }
1324
- // ------- graphql query tools (delegated to graphql-query-tools module) --
1325
- if (toolName === "graphql.query") {
1324
+ // ------- graphql_query tools (delegated to graphql_query-tools module) --
1325
+ if (toolName === "graphql_query") {
1326
1326
  return json(await handleGraphQLQuery(args, ctx), false, ctx.responseBudget);
1327
1327
  }
1328
- if (toolName === "graphql.queryAll") {
1328
+ if (toolName === "graphql_queryAll") {
1329
1329
  return json(await handleGraphQLQueryAll(args, ctx), false, ctx.responseBudget);
1330
1330
  }
1331
- if (toolName === "graphql.batchMutate") {
1331
+ if (toolName === "graphql_batchMutate") {
1332
1332
  return json(await handleGraphQLBatchMutate(args, ctx), false, ctx.responseBudget);
1333
1333
  }
1334
- if (toolName === "graphql.introspect") {
1334
+ if (toolName === "graphql_introspect") {
1335
1335
  return json(await handleGraphQLIntrospect(args, ctx), false, ctx.responseBudget);
1336
1336
  }
1337
1337
  // ------- batch tools (delegated to batch-tools module) ---------------
1338
- if (toolName === "batch.create") {
1338
+ if (toolName === "batch_create") {
1339
1339
  return json(await handleBatchCreate(args, ctx), false, ctx.responseBudget);
1340
1340
  }
1341
- if (toolName === "batch.send") {
1341
+ if (toolName === "batch_send") {
1342
1342
  return json(await handleBatchSend(args, ctx), false, ctx.responseBudget);
1343
1343
  }
1344
- if (toolName === "batch.status") {
1344
+ if (toolName === "batch_status") {
1345
1345
  return json(await handleBatchStatus(args, ctx), false, ctx.responseBudget);
1346
1346
  }
1347
- if (toolName === "batch.batchStatus") {
1347
+ if (toolName === "batch_batchStatus") {
1348
1348
  return json(await handleBatchBatchStatus(args, ctx), false, ctx.responseBudget);
1349
1349
  }
1350
- if (toolName === "batch.results") {
1350
+ if (toolName === "batch_results") {
1351
1351
  return json(await handleBatchResults(args, ctx), false, ctx.responseBudget);
1352
1352
  }
1353
- if (toolName === "batch.describePayload") {
1353
+ if (toolName === "batch_describePayload") {
1354
1354
  return json(await handleBatchDescribePayload(args, ctx), false, ctx.responseBudget);
1355
1355
  }
1356
- // ------- connection.test (inline) ------------------------------------
1357
- if (toolName === "connection.test") {
1356
+ // ------- connection_test (inline) ------------------------------------
1357
+ if (toolName === "connection_test") {
1358
1358
  const client = requireClient(ctx);
1359
1359
  const tester = new FluentConnectionTester(client.asGraphQLCapable(), {
1360
1360
  retailerId: ctx.config.retailerId ?? "unknown",
@@ -1369,8 +1369,8 @@ async function dispatchToolCall(toolName, args, ctx) {
1369
1369
  : { error: result.error }),
1370
1370
  });
1371
1371
  }
1372
- // ------- webhook.validate (inline) -----------------------------------
1373
- if (toolName === "webhook.validate") {
1372
+ // ------- webhook_validate (inline) -----------------------------------
1373
+ if (toolName === "webhook_validate") {
1374
1374
  const parsed = WebhookValidateInputSchema.parse(args);
1375
1375
  const payload = parsed.payload;
1376
1376
  // Basic field validation
@@ -1474,72 +1474,72 @@ async function dispatchToolCall(toolName, args, ctx) {
1474
1474
  });
1475
1475
  }
1476
1476
  // ------- entity tools (delegated to entity-tools module) -------------
1477
- if (toolName === "entity.create") {
1477
+ if (toolName === "entity_create") {
1478
1478
  return json(await handleEntityCreate(args, ctx), false, ctx.responseBudget);
1479
1479
  }
1480
- if (toolName === "entity.update") {
1480
+ if (toolName === "entity_update") {
1481
1481
  return json(await handleEntityUpdate(args, ctx), false, ctx.responseBudget);
1482
1482
  }
1483
- if (toolName === "entity.get") {
1483
+ if (toolName === "entity_get") {
1484
1484
  return json(await handleEntityGet(args, ctx), false, ctx.responseBudget);
1485
1485
  }
1486
- if (toolName === "entity.planCreate") {
1486
+ if (toolName === "entity_planCreate") {
1487
1487
  return json(handleEntityPlanCreate(args, ctx), false, ctx.responseBudget);
1488
1488
  }
1489
- if (toolName === "entity.planUpdate") {
1489
+ if (toolName === "entity_planUpdate") {
1490
1490
  return json(handleEntityPlanUpdate(args, ctx), false, ctx.responseBudget);
1491
1491
  }
1492
1492
  // ------- workflow tools (delegated to workflow-tools module) ----------
1493
- if (toolName === "workflow.get") {
1493
+ if (toolName === "workflow_get") {
1494
1494
  return json(await handleWorkflowGet(args, ctx), false, ctx.responseBudget);
1495
1495
  }
1496
- if (toolName === "workflow.list") {
1496
+ if (toolName === "workflow_list") {
1497
1497
  return json(await handleWorkflowList(args, ctx), false, ctx.responseBudget);
1498
1498
  }
1499
- if (toolName === "workflow.upload") {
1499
+ if (toolName === "workflow_upload") {
1500
1500
  return json(await handleWorkflowUpload(args, ctx), false, ctx.responseBudget);
1501
1501
  }
1502
- if (toolName === "workflow.diff") {
1502
+ if (toolName === "workflow_diff") {
1503
1503
  return json(await handleWorkflowDiff(args, ctx), false, ctx.responseBudget);
1504
1504
  }
1505
- if (toolName === "workflow.simulate") {
1505
+ if (toolName === "workflow_simulate") {
1506
1506
  return json(await handleWorkflowSimulate(args, ctx), false, ctx.responseBudget);
1507
1507
  }
1508
1508
  // ------- setting tools (delegated to settings-tools module) ----------
1509
- if (toolName === "setting.get") {
1509
+ if (toolName === "setting_get") {
1510
1510
  return json(await handleSettingGet(args, ctx), false, ctx.responseBudget);
1511
1511
  }
1512
- if (toolName === "setting.upsert") {
1512
+ if (toolName === "setting_upsert") {
1513
1513
  return json(await handleSettingUpsert(args, ctx), false, ctx.responseBudget);
1514
1514
  }
1515
- if (toolName === "setting.bulkUpsert") {
1515
+ if (toolName === "setting_bulkUpsert") {
1516
1516
  return json(await handleSettingBulkUpsert(args, ctx), false, ctx.responseBudget);
1517
1517
  }
1518
1518
  // ------- environment tools (delegated to environment-tools module) ---
1519
- if (toolName === "environment.discover") {
1519
+ if (toolName === "environment_discover") {
1520
1520
  return json(await handleEnvironmentDiscover(args, ctx), false, ctx.responseBudget);
1521
1521
  }
1522
- if (toolName === "environment.validate") {
1522
+ if (toolName === "environment_validate") {
1523
1523
  return json(await handleEnvironmentValidate(args, ctx), false, ctx.responseBudget);
1524
1524
  }
1525
1525
  // ------- test tools (delegated to test-tools module) -----------------
1526
- if (toolName === "test.assert") {
1526
+ if (toolName === "test_assert") {
1527
1527
  return json(await handleTestAssert(args, ctx), false, ctx.responseBudget);
1528
1528
  }
1529
1529
  // ------- graphql schema tools (delegated to graphql-schema-tools module) --
1530
- if (toolName === "graphql.listRoots") {
1530
+ if (toolName === "graphql_listRoots") {
1531
1531
  return json(await handleListRoots(args, ctx), false, ctx.responseBudget);
1532
1532
  }
1533
- if (toolName === "graphql.planOperation") {
1533
+ if (toolName === "graphql_planOperation") {
1534
1534
  return json(await handlePlanOperation(args, ctx), false, ctx.responseBudget);
1535
1535
  }
1536
- if (toolName === "graphql.buildQuery") {
1536
+ if (toolName === "graphql_buildQuery") {
1537
1537
  return json(await handleBuildQuery(args, ctx), false, ctx.responseBudget);
1538
1538
  }
1539
- if (toolName === "graphql.validate") {
1539
+ if (toolName === "graphql_validate") {
1540
1540
  return json(await handleValidate(args, ctx), false, ctx.responseBudget);
1541
1541
  }
1542
- if (toolName === "graphql.generateFull") {
1542
+ if (toolName === "graphql_generateFull") {
1543
1543
  return json(await handleGenerateFull(args, ctx), false, ctx.responseBudget);
1544
1544
  }
1545
1545
  throw new ToolError("VALIDATION_ERROR", `Unknown tool: ${toolName}`);
@@ -1564,5 +1564,10 @@ export function registerToolHandlers(server, ctx) {
1564
1564
  ...(tool.annotations ? { annotations: tool.annotations } : {}),
1565
1565
  })),
1566
1566
  }));
1567
- lowLevelServer.setRequestHandler(CallToolRequestSchema, async (request) => handleToolCall(request.params.name, request.params.arguments ?? {}, ctx));
1567
+ lowLevelServer.setRequestHandler(CallToolRequestSchema, async (request) => {
1568
+ // Normalize dot-notation names for backward compatibility with lenient clients
1569
+ // that still send "health.ping" instead of "health_ping".
1570
+ const toolName = request.params.name.replace(/\./g, "_");
1571
+ return handleToolCall(toolName, request.params.arguments ?? {}, ctx);
1572
+ });
1568
1573
  }