@fluentcommerce/fluent-mcp-extn 0.7.0 → 0.7.2

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,9 +1,9 @@
1
1
  /**
2
- * Workflow management tools: workflow.upload, workflow.diff, workflow.simulate
2
+ * Workflow management tools: workflow_upload, workflow_diff, workflow_simulate
3
3
  *
4
4
  * Closes the deploy loop — agents can analyze, modify, and deploy
5
- * workflow JSON without falling back to CLI.
6
- * workflow.simulate adds lightweight static prediction for reasoning about
5
+ * workflow JSON via the Fluent REST API (PUT).
6
+ * workflow_simulate adds lightweight static prediction for reasoning about
7
7
  * event outcomes without live execution.
8
8
  */
9
9
  import { z } from "zod";
@@ -97,8 +97,8 @@ export const WorkflowSimulateInputSchema = z.object({
97
97
  // ---------------------------------------------------------------------------
98
98
  export const WORKFLOW_TOOL_DEFINITIONS = [
99
99
  {
100
- name: "workflow.get",
101
- description: "Fetch a workflow by entity type+subtype. Returns statuses, rulesets, rules, triggers. Use outputFile to save large JSON to disk. Works even when workflow.list returns 401.",
100
+ name: "workflow_get",
101
+ description: "Fetch a workflow by entity type+subtype. Returns statuses, rulesets, rules, triggers. Use outputFile to save large JSON to disk. Works even when workflow_list returns 401.",
102
102
  annotations: {
103
103
  title: "Get Workflow",
104
104
  readOnlyHint: true,
@@ -108,8 +108,8 @@ export const WORKFLOW_TOOL_DEFINITIONS = [
108
108
  },
109
109
  },
110
110
  {
111
- name: "workflow.list",
112
- description: "List all workflows for a retailer. Use outputDir to download all as JSON files. May return 401 on restricted accounts — use workflow.get instead.",
111
+ name: "workflow_list",
112
+ description: "List all workflows for a retailer. Use outputDir to download all as JSON files. May return 401 on restricted accounts — use workflow_get instead.",
113
113
  annotations: {
114
114
  title: "List Workflows",
115
115
  readOnlyHint: true,
@@ -119,8 +119,8 @@ export const WORKFLOW_TOOL_DEFINITIONS = [
119
119
  },
120
120
  },
121
121
  {
122
- name: "workflow.upload",
123
- description: "Deploy a workflow JSON to the Fluent environment. Validates structure before upload. Use dryRun=true to validate without deploying. Returns new version number.",
122
+ name: "workflow_upload",
123
+ description: "Deploy a workflow JSON to the Fluent environment via REST API (PUT). Validates structure before upload. Use dryRun=true to validate without deploying. Idempotent deploying the same JSON twice does not create duplicate versions. WARNING: Does NOT update the CLI workflowlog — subsequent `fluent workflow download` may see stale data.",
124
124
  annotations: {
125
125
  title: "Upload Workflow",
126
126
  readOnlyHint: false,
@@ -130,7 +130,7 @@ export const WORKFLOW_TOOL_DEFINITIONS = [
130
130
  },
131
131
  },
132
132
  {
133
- name: "workflow.diff",
133
+ name: "workflow_diff",
134
134
  description: "Compare two workflow JSONs locally. Shows ruleset/status/trigger changes with risk assessment. Formats: summary, detailed, mermaid.",
135
135
  annotations: {
136
136
  title: "Diff Workflows",
@@ -141,7 +141,7 @@ export const WORKFLOW_TOOL_DEFINITIONS = [
141
141
  },
142
142
  },
143
143
  {
144
- name: "workflow.simulate",
144
+ name: "workflow_simulate",
145
145
  description: "Static prediction of event outcomes from workflow JSON (no API call). Finds matching rulesets, predicts state transitions, follow-on events, and webhooks. Cannot evaluate runtime conditions or custom rule logic.",
146
146
  annotations: {
147
147
  title: "Simulate Workflow",
@@ -397,7 +397,7 @@ function computeWorkflowDiff(base, target) {
397
397
  }
398
398
  function requireWorkflowClient(ctx) {
399
399
  if (!ctx.client) {
400
- throw new ToolError("CONFIG_ERROR", "SDK client is not available. Run config.validate and fix auth/base URL.");
400
+ throw new ToolError("CONFIG_ERROR", "SDK client is not available. Run config_validate and fix auth/base URL.");
401
401
  }
402
402
  return ctx.client;
403
403
  }
@@ -618,8 +618,8 @@ function summarizeWorkflow(wf) {
618
618
  ...(customRuleRulesets.length > 0 ? { customRuleRulesets } : {}),
619
619
  },
620
620
  _hints: [
621
- "Use workflow.simulate to predict event outcomes for any status.",
622
- "Use workflow.diff to compare versions before uploading.",
621
+ "Use workflow_simulate to predict event outcomes for any status.",
622
+ "Use workflow_diff to compare versions before uploading.",
623
623
  ...(webhookRulesets.length > 0
624
624
  ? [`${webhookRulesets.length} ruleset(s) trigger webhooks — check settings for endpoint config.`]
625
625
  : []),
@@ -637,7 +637,8 @@ function writeWorkflowFile(filePath, workflow) {
637
637
  return Buffer.byteLength(fileContent, "utf-8");
638
638
  }
639
639
  /**
640
- * Handle workflow.upload tool call.
640
+ * Handle workflow_upload tool call.
641
+ * Deploys via REST API (PUT /api/v4.1/workflow/{retailerId}).
641
642
  */
642
643
  export async function handleWorkflowUpload(args, ctx) {
643
644
  const parsed = WorkflowUploadInputSchema.parse(args);
@@ -645,7 +646,7 @@ export async function handleWorkflowUpload(args, ctx) {
645
646
  // Resolve retailer ID
646
647
  const retailerId = parsed.retailerId ?? ctx.config.retailerId;
647
648
  if (!retailerId) {
648
- throw new ToolError("VALIDATION_ERROR", "retailerId is required for workflow upload. Set FLUENT_RETAILER_ID or pass retailerId.");
649
+ throw new ToolError("VALIDATION_ERROR", "retailerId is required for workflow_upload. Set FLUENT_RETAILER_ID or pass retailerId.");
649
650
  }
650
651
  const preflight = await buildWorkflowUploadPreflight(wf, ctx, retailerId);
651
652
  // Validate if requested
@@ -684,23 +685,13 @@ export async function handleWorkflowUpload(args, ctx) {
684
685
  ...preflight,
685
686
  };
686
687
  }
687
- // Upload via REST API POST /api/v4.1/workflow/{retailerId}
688
- // This is the same endpoint the Fluent CLI uses.
689
- // NOTE: For production deployments, prefer `fluent module install` via CLI
690
- // which bundles workflows with settings, rules, and data in a versioned module.
691
- const client = requireWorkflowClient(ctx);
692
- // FluentClientAdapter may expose request() for custom REST endpoints
693
- const clientAny = client;
694
- if (typeof clientAny.request !== "function") {
695
- throw new ToolError("CONFIG_ERROR", "SDK client does not expose request() method — cannot call REST workflow upload API. " +
696
- "Use the Fluent CLI instead: fluent workflow merge <file> <name> -p <profile> -r <retailer>");
688
+ // Deploy via REST API (PUT)
689
+ const workflowName = wf.name ?? "";
690
+ if (!workflowName) {
691
+ throw new ToolError("VALIDATION_ERROR", "Workflow JSON must include a 'name' field (e.g. 'ORDER::HD').");
697
692
  }
698
- const requestFn = clientAny.request;
699
- const response = await requestFn(`/api/v4.1/workflow/${retailerId}`, {
700
- method: "POST",
701
- headers: { "Content-Type": "application/json" },
702
- body: wf,
703
- });
693
+ const client = requireWorkflowClient(ctx);
694
+ await client.uploadWorkflow(retailerId, wf);
704
695
  if (ctx.cache) {
705
696
  await ctx.cache.invalidate(`workflow:get:${retailerId}:${wf.name}:*`);
706
697
  await ctx.cache.invalidate(buildWorkflowListCacheKey(retailerId));
@@ -708,20 +699,19 @@ export async function handleWorkflowUpload(args, ctx) {
708
699
  return {
709
700
  ok: true,
710
701
  uploaded: true,
711
- workflowName: wf.name,
702
+ workflowName,
712
703
  retailerId,
713
- response,
704
+ deployMethod: "rest-put",
714
705
  ...preflight,
715
706
  _hints: [
716
- "REST/MCP uploads do NOT update the CLI workflowlog cache. Run 'fluent workflowlog delete' if you later use CLI workflow commands.",
717
- "Use workflow.diff to compare old vs new before uploading.",
718
- "Use workflow.simulate to verify event outcomes after uploading.",
719
- "For production deployments, prefer 'fluent module install' via CLI for versioned, bundled deployments.",
707
+ "Deployed via REST API (PUT). The CLI workflowlog is NOT updated — run `fluent workflowlog delete` then redeploy via CLI if you need CLI consistency.",
708
+ "Use workflow_diff to compare old vs new before uploading.",
709
+ "Use workflow_simulate to verify event outcomes after uploading.",
720
710
  ],
721
711
  };
722
712
  }
723
713
  /**
724
- * Handle workflow.diff tool call.
714
+ * Handle workflow_diff tool call.
725
715
  * Pure computation — no API calls.
726
716
  */
727
717
  export async function handleWorkflowDiff(args, _ctx) {
@@ -873,7 +863,7 @@ function simulateWorkflow(wf, currentStatus, eventName, entityType, entitySubtyp
873
863
  return matches;
874
864
  }
875
865
  /**
876
- * Handle workflow.simulate tool call.
866
+ * Handle workflow_simulate tool call.
877
867
  * Pure computation — no API calls.
878
868
  */
879
869
  export async function handleWorkflowSimulate(args, _ctx) {
@@ -891,7 +881,7 @@ export async function handleWorkflowSimulate(args, _ctx) {
891
881
  if (hasCustomRules) {
892
882
  limitations.push(`${allCustomRules.length} custom rule(s) found whose behavior cannot be predicted statically: ${allCustomRules.join(", ")}.`);
893
883
  }
894
- limitations.push("Use workflow.transitions for AUTHORITATIVE live validation of available actions.");
884
+ limitations.push("Use workflow_transitions for AUTHORITATIVE live validation of available actions.");
895
885
  return {
896
886
  ok: true,
897
887
  workflowName: wf.name ?? "unknown",
@@ -927,7 +917,7 @@ export async function handleWorkflowSimulate(args, _ctx) {
927
917
  };
928
918
  }
929
919
  /**
930
- * Handle workflow.get tool call.
920
+ * Handle workflow_get tool call.
931
921
  * Fetches a specific workflow by entityType::entitySubtype via REST API.
932
922
  */
933
923
  export async function handleWorkflowGet(args, ctx) {
@@ -1018,7 +1008,7 @@ export async function handleWorkflowGet(args, ctx) {
1018
1008
  };
1019
1009
  }
1020
1010
  /**
1021
- * Handle workflow.list tool call.
1011
+ * Handle workflow_list tool call.
1022
1012
  * Lists all workflows for a retailer via REST API.
1023
1013
  */
1024
1014
  export async function handleWorkflowList(args, ctx) {
@@ -1147,7 +1137,7 @@ export async function handleWorkflowList(args, ctx) {
1147
1137
  workflows: latest,
1148
1138
  ...(cacheMeta ? { _cache: cacheMeta } : {}),
1149
1139
  note: workflows.length === 0
1150
- ? "No workflows found. The list endpoint may return 401 on some accounts — try workflow.get with a specific entityType and entitySubtype instead."
1140
+ ? "No workflows found. The list endpoint may return 401 on some accounts — try workflow_get with a specific entityType and entitySubtype instead."
1151
1141
  : undefined,
1152
1142
  };
1153
1143
  }
@@ -9,7 +9,7 @@ real Fluent API operations.
9
9
  |--------|------|---------|
10
10
  | `e2e-smoke.ts` | E2E | Full MCP smoke cycle: tool discovery, config, health, events, GraphQL |
11
11
  | `e2e-negative.ts` | E2E | Validation error and malformed input handling |
12
- | `e2e-profile-test.mjs` | E2E | Quick FLUENT_PROFILE integration check |
12
+ | `e2e-profile-test_mjs` | E2E | Quick FLUENT_PROFILE integration check |
13
13
  | `e2e-full-order.ts` | E2E | Single order lifecycle: create, validate, fulfil, ship, deliver |
14
14
  | `e2e-full-multi.ts` | E2E | ORDER::MULTI lifecycle with discovery and fulfilment event sequence |
15
15
  | `e2e-agentic.ts` | E2E | All 11 agentic tools: entity CRUD, workflow, settings, environment |
@@ -26,16 +26,16 @@ All scripts require a built server (`npm run build`) and valid Fluent credential
26
26
  - `npm run build`
27
27
  - `npm test`
28
28
  - **Level 2: MCP runtime check** (server starts, tools load)
29
- - `config.validate`
30
- - `health.ping`
31
- - `connection.test`
29
+ - `config_validate`
30
+ - `health_ping`
31
+ - `connection_test`
32
32
  - **Level 3: Fluent API smoke** (real API calls)
33
- - `event.send` dry-run and real send
34
- - `event.get` on sent event ID
35
- - `graphql.query`
36
- - `graphql.queryAll` (pagination timeout + aggregation)
37
- - optional batch flow (`batch.create` -> `batch.send` -> `batch.status`)
38
- - optional webhook verification (`webhook.validate` with `rawBody`)
33
+ - `event_send` dry-run and real send
34
+ - `event_get` on sent event ID
35
+ - `graphql_query`
36
+ - `graphql_queryAll` (pagination timeout + aggregation)
37
+ - optional batch flow (`batch_create` -> `batch_send` -> `batch_status`)
38
+ - optional webhook verification (`webhook_validate` with `rawBody`)
39
39
 
40
40
  ## 2) Prerequisites
41
41
 
@@ -148,9 +148,9 @@ only when non-skipped steps fail.
148
148
 
149
149
  Full MCP client smoke cycle that exercises the core tool chain end to end.
150
150
 
151
- **What it tests:** tool discovery, `config.validate`, `health.ping`, `event.build`,
152
- `event.send` (dry-run and real), `graphql.query`, `graphql.queryAll`, order lookup,
153
- `event.get` by ID.
151
+ **What it tests:** tool discovery, `config_validate`, `health_ping`, `event_build`,
152
+ `event_send` (dry-run and real), `graphql_query`, `graphql_queryAll`, order lookup,
153
+ `event_get` by ID.
154
154
 
155
155
  **How to run:**
156
156
 
@@ -171,11 +171,11 @@ npm run e2e:smoke -- --skip-real-send
171
171
  Validates that the server returns correct error envelopes for invalid inputs.
172
172
 
173
173
  **What it tests:**
174
- - `event.send` with missing required `entityRef` field
175
- - `graphql.query` with malformed GraphQL syntax
176
- - `event.get` with a nonexistent event ID
177
- - `graphql.introspect` with a nonexistent mutation name
178
- - `webhook.validate` with an invalid signature and public key
174
+ - `event_send` with missing required `entityRef` field
175
+ - `graphql_query` with malformed GraphQL syntax
176
+ - `event_get` with a nonexistent event ID
177
+ - `graphql_introspect` with a nonexistent mutation name
178
+ - `webhook_validate` with an invalid signature and public key
179
179
 
180
180
  Each test case asserts: `ok: false`, standard error envelope shape
181
181
  (`code` + `message` + `retryable`), and expected error code where applicable
@@ -193,7 +193,7 @@ npx tsx scripts/e2e-negative.ts --profile YOUR_PROFILE --retailer YOUR_RETAILER
193
193
 
194
194
  ---
195
195
 
196
- ### `e2e-profile-test.mjs`
196
+ ### `e2e-profile-test_mjs`
197
197
 
198
198
  Minimal FLUENT_PROFILE integration check. Loads config, creates SDK client, and
199
199
  runs four quick API calls to verify profile-based auth works end to end.
@@ -208,7 +208,7 @@ runs four quick API calls to verify profile-based auth works end to end.
208
208
  **How to run:**
209
209
 
210
210
  ```bash
211
- FLUENT_PROFILE=YOUR_PROFILE FLUENT_PROFILE_RETAILER=YOUR_RETAILER node scripts/e2e-profile-test.mjs
211
+ FLUENT_PROFILE=YOUR_PROFILE FLUENT_PROFILE_RETAILER=YOUR_RETAILER node scripts/e2e-profile-test_mjs
212
212
  ```
213
213
 
214
214
  **Environment:** requires `FLUENT_PROFILE` and optionally `FLUENT_PROFILE_RETAILER`
@@ -255,7 +255,7 @@ MULTI order type workflow and includes workflow transition discovery.
255
255
  **What it tests:**
256
256
  1. Config validation
257
257
  2. Discovery: retailer, locations, catalogues, products, customers, settings
258
- 3. `workflow.transitions` for ORDER::MULTI at ON_VALIDATION status
258
+ 3. `workflow_transitions` for ORDER::MULTI at ON_VALIDATION status
259
259
  4. `createOrder` mutation with MULTI type
260
260
  5. `ConfirmValidation` event
261
261
  6. Fulfilment creation verification
@@ -269,7 +269,7 @@ MULTI order type workflow and includes workflow transition discovery.
269
269
  npx tsx scripts/e2e-full-multi.ts
270
270
  ```
271
271
 
272
- **Environment:** defaults to `FLUENT_BASE_URL=https://<account>.test.api.fluentretail.com`
272
+ **Environment:** defaults to `FLUENT_BASE_URL=https://<account>.test_api.fluentretail.com`
273
273
  and `FLUENT_RETAILER_ID=2`. Override with env vars. Requires OAuth or profile
274
274
  credentials.
275
275
 
@@ -282,16 +282,16 @@ credentials.
282
282
  Comprehensive smoke test for all 11 agentic tools against a live environment.
283
283
 
284
284
  **What it tests:**
285
- - `environment.discover` (retailer + locations, catalogues)
286
- - `environment.validate` (auth, retailer, locations checks)
287
- - `entity.create` (dryRun validation, required field rejection, live creation)
288
- - `entity.get` (by ID, by ref, nonexistent ref)
289
- - `entity.update` (attribute update)
290
- - `test.assert` (status match, status mismatch)
291
- - `setting.upsert` (create new, update existing with previous value)
292
- - `workflow.diff` (summary format, mermaid format)
293
- - `workflow.simulate` (status matching, custom rule confidence, no-match)
294
- - `workflow.upload` (dryRun structure validation)
285
+ - `environment_discover` (retailer + locations, catalogues)
286
+ - `environment_validate` (auth, retailer, locations checks)
287
+ - `entity_create` (dryRun validation, required field rejection, live creation)
288
+ - `entity_get` (by ID, by ref, nonexistent ref)
289
+ - `entity_update` (attribute update)
290
+ - `test_assert` (status match, status mismatch)
291
+ - `setting_upsert` (create new, update existing with previous value)
292
+ - `workflow_diff` (summary format, mermaid format)
293
+ - `workflow_simulate` (status matching, custom rule confidence, no-match)
294
+ - `workflow_upload` (dryRun structure validation)
295
295
 
296
296
  **How to run:**
297
297
 
@@ -312,10 +312,10 @@ Proves that response shaping (auto-summarization) works correctly on real API
312
312
  responses.
313
313
 
314
314
  **What it proves:**
315
- 1. `event.flowInspect` compact response stays within budget (50k chars)
316
- 2. `event.flowInspect` full mode (`compact: false`) gets auto-summarized, not truncated
317
- 3. `plugin.list` (unfiltered, 500+ rules) gets shaped when large
318
- 4. `event.list` (500 events) gets shaped when large
315
+ 1. `event_flowInspect` compact response stays within budget (50k chars)
316
+ 2. `event_flowInspect` full mode (`compact: false`) gets auto-summarized, not truncated
317
+ 3. `plugin_list` (unfiltered, 500+ rules) gets shaped when large
318
+ 4. `event_list` (500 events) gets shaped when large
319
319
  5. `_responseMeta` appears with accurate stats (originalChars, shapedChars, reductionPercent)
320
320
  6. No `_truncated` markers anywhere (replaced by `_summarized`)
321
321
 
@@ -333,9 +333,9 @@ budget threshold.
333
333
 
334
334
  ### `run-flow-inspect.ts`
335
335
 
336
- Advanced FlowInspect forensics runner. Calls `event.flowInspect`, then performs
336
+ Advanced FlowInspect forensics runner. Calls `event_flowInspect`, then performs
337
337
  local analysis: risk scoring, finding extraction, evidence ranking, and optional
338
- per-event drilldowns via `event.get`.
338
+ per-event drilldowns via `event_get`.
339
339
 
340
340
  **Outputs:**
341
341
  - Raw JSON: full flowInspect response
@@ -440,7 +440,7 @@ npx tsx scripts/check-event-status.ts --event-name ConfirmValidation --entity-re
440
440
 
441
441
  Run these tools in order from the assistant:
442
442
 
443
- ### Step 1: `config.validate`
443
+ ### Step 1: `config_validate`
444
444
 
445
445
  Request:
446
446
 
@@ -454,7 +454,7 @@ Expected:
454
454
  - `validation.isReadyForApiCalls: true`
455
455
  - no blocking errors
456
456
 
457
- ### Step 2: `health.ping`
457
+ ### Step 2: `health_ping`
458
458
 
459
459
  Request:
460
460
 
@@ -468,7 +468,7 @@ Expected:
468
468
  - `sdkClient: "connected"` (or equivalent ready status)
469
469
  - config summary present without secret values
470
470
 
471
- ### Step 3: `connection.test`
471
+ ### Step 3: `connection_test`
472
472
 
473
473
  Request:
474
474
 
@@ -482,7 +482,7 @@ Expected:
482
482
  - `details` includes user, retailer, and location info
483
483
  - confirms end-to-end GraphQL connectivity
484
484
 
485
- ### Step 4: `event.build`
485
+ ### Step 4: `event_build`
486
486
 
487
487
  Request:
488
488
 
@@ -504,7 +504,7 @@ Expected:
504
504
  - complete event payload returned
505
505
  - defaults applied (`rootEntityType`, `source`, `type`)
506
506
 
507
- ### Step 5: `event.send` dry-run
507
+ ### Step 5: `event_send` dry-run
508
508
 
509
509
  Request:
510
510
 
@@ -524,7 +524,7 @@ Expected:
524
524
  - `dryRun: true`
525
525
  - no API call made
526
526
 
527
- ### Step 6: `event.send` real call
527
+ ### Step 6: `event_send` real call
528
528
 
529
529
  Request:
530
530
 
@@ -553,7 +553,7 @@ Expected:
553
553
 
554
554
  If this fails, investigate before resubmitting to avoid duplicate side effects.
555
555
 
556
- ### Step 7: `graphql.query` verification
556
+ ### Step 7: `graphql_query` verification
557
557
 
558
558
  Use a query valid for your schema. Example shape:
559
559
 
@@ -573,7 +573,7 @@ Expected:
573
573
 
574
574
  > Note: exact query fields differ by tenant schema/version.
575
575
 
576
- ### Step 8: `graphql.queryAll` verification
576
+ ### Step 8: `graphql_queryAll` verification
577
577
 
578
578
  Validate auto-pagination and run-level timeout behavior:
579
579
 
@@ -591,9 +591,9 @@ Expected:
591
591
  - `response.extensions.autoPagination` present
592
592
  - `pagination.totalPages` / `pagination.totalRecords` present in tool response
593
593
 
594
- ### Step 9: `event.get` verification
594
+ ### Step 9: `event_get` verification
595
595
 
596
- Use an event ID from successful `event.send` (or resolve ID via `event.list`).
596
+ Use an event ID from successful `event_send` (or resolve ID via `event_list`).
597
597
 
598
598
  ```json
599
599
  {
@@ -607,7 +607,7 @@ Expected:
607
607
  - event payload returned from Event API
608
608
  - event payload includes expected `name`, `context.entityRef`, and retailer
609
609
 
610
- If `event.send` response does not contain `id`, resolve it first with `event.list`:
610
+ If `event_send` response does not contain `id`, resolve it first with `event_list`:
611
611
 
612
612
  ```json
613
613
  {
@@ -619,7 +619,7 @@ If `event.send` response does not contain `id`, resolve it first with `event.lis
619
619
  }
620
620
  ```
621
621
 
622
- ### Step 10 (optional): `graphql.introspect`
622
+ ### Step 10 (optional): `graphql_introspect`
623
623
 
624
624
  Verify schema introspection access:
625
625
 
@@ -659,7 +659,7 @@ Expected:
659
659
 
660
660
  ## 8) Optional batch E2E
661
661
 
662
- ### `batch.create`
662
+ ### `batch_create`
663
663
 
664
664
  ```json
665
665
  {
@@ -669,7 +669,7 @@ Expected:
669
669
  }
670
670
  ```
671
671
 
672
- ### `batch.send`
672
+ ### `batch_send`
673
673
 
674
674
  ```json
675
675
  {
@@ -690,7 +690,7 @@ Expected:
690
690
  }
691
691
  ```
692
692
 
693
- ### `batch.status`
693
+ ### `batch_status`
694
694
 
695
695
  ```json
696
696
  {
@@ -700,7 +700,7 @@ Expected:
700
700
 
701
701
  ## 9) Failure triage quick map
702
702
 
703
- - `CONFIG_ERROR`: missing env values -> run `config.validate`
703
+ - `CONFIG_ERROR`: missing env values -> run `config_validate`
704
704
  - `AUTH_ERROR`: invalid creds/token -> verify OAuth or `TOKEN_COMMAND`
705
705
  - `VALIDATION_ERROR`: invalid input shape -> fix request payload
706
706
  - `TIMEOUT_ERROR` / `NETWORK_ERROR`: tune timeout/retry; verify connectivity
@@ -712,11 +712,11 @@ Mark E2E successful only when:
712
712
 
713
713
  - local build/test passed
714
714
  - config/health/connection tools are green
715
- - at least one real `event.send` succeeded
716
- - at least one `event.get` succeeded
717
- - at least one real `graphql.query` succeeded
718
- - at least one `graphql.queryAll` run succeeded
719
- - (optional) `graphql.introspect` schema access confirmed
715
+ - at least one real `event_send` succeeded
716
+ - at least one `event_get` succeeded
717
+ - at least one real `graphql_query` succeeded
718
+ - at least one `graphql_queryAll` run succeeded
719
+ - (optional) `graphql_introspect` schema access confirmed
720
720
  - (optional) batch cycle completed
721
721
 
722
722
  ## 11) CI-triggered smoke (GitHub Actions)
@@ -54,14 +54,14 @@ Copy `fluent-mcp-extn/docs/HANDOVER_VSCODE_MCP_JSON.example.json` to `.vscode/mc
54
54
 
55
55
  6) Verify in Copilot chat (agent mode), run:
56
56
 
57
- 1. `config.validate`
58
- 2. `health.ping`
59
- 3. `graphql.query` with `query { __typename }`
57
+ 1. `config_validate`
58
+ 2. `health_ping`
59
+ 3. `graphql_query` with `query { __typename }`
60
60
 
61
61
  Expected minimum:
62
62
 
63
- - `config.validate` returns `ok: true`
64
- - `health.ping` returns `status: "ok"`
63
+ - `config_validate` returns `ok: true`
64
+ - `health_ping` returns `status: "ok"`
65
65
  - GraphQL test returns data without auth/config errors
66
66
 
67
67
  If these pass, local setup is complete.
@@ -70,7 +70,7 @@ Operational behavior to know:
70
70
 
71
71
  - read operations use retry/backoff for transient failures
72
72
  - non-idempotent write operations do not auto-retry
73
- - `graphql.query` disables retries automatically when the request is a mutation
73
+ - `graphql_query` disables retries automatically when the request is a mutation
74
74
 
75
75
  ### Updating after code changes
76
76
 
@@ -120,7 +120,7 @@ This configuration uses `type: "local"` and explicitly allowlists tools.
120
120
 
121
121
  - trigger an agent task in the repository
122
122
  - open session logs and confirm MCP server start step succeeds
123
- - confirm tools are discovered (for example `config.validate`, `graphql.query`)
123
+ - confirm tools are discovered (for example `config_validate`, `graphql_query`)
124
124
 
125
125
  ### Updating after code changes
126
126
 
@@ -128,7 +128,7 @@ The `copilot-setup-steps.yml` workflow runs `npm ci && npm run build` automatica
128
128
 
129
129
  ## Synchronous fulfilment options support
130
130
 
131
- `graphql.query` supports live checkout-style synchronous fulfilment options calls, for example:
131
+ `graphql_query` supports live checkout-style synchronous fulfilment options calls, for example:
132
132
 
133
133
  - `createFulfilmentOption(..., executionMode: AWAIT_ORCHESTRATION)`
134
134
 
@@ -148,7 +148,7 @@ Important runtime requirement:
148
148
  - `Workflow [FULFILMENT_OPTIONS::<type>] not found`
149
149
  - deploy matching fulfilment options workflow for the selected retailer/type
150
150
  - webhook signature mismatch
151
- - provide exact `rawBody` to `webhook.validate` (signature checks are byte-sensitive)
151
+ - provide exact `rawBody` to `webhook_validate` (signature checks are byte-sensitive)
152
152
 
153
153
  ## Security notes
154
154
 
@@ -5,18 +5,18 @@
5
5
  "command": "node",
6
6
  "args": ["fluent-mcp-extn/dist/index.js"],
7
7
  "tools": [
8
- "config.validate",
9
- "health.ping",
10
- "event.build",
11
- "event.send",
12
- "event.get",
13
- "event.list",
14
- "graphql.query",
15
- "batch.create",
16
- "batch.send",
17
- "batch.status",
18
- "batch.batchStatus",
19
- "batch.results"
8
+ "config_validate",
9
+ "health_ping",
10
+ "event_build",
11
+ "event_send",
12
+ "event_get",
13
+ "event_list",
14
+ "graphql_query",
15
+ "batch_create",
16
+ "batch_send",
17
+ "batch_status",
18
+ "batch_batchStatus",
19
+ "batch_results"
20
20
  ],
21
21
  "env": {
22
22
  "FLUENT_BASE_URL": "COPILOT_MCP_FLUENT_BASE_URL",