@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/README.md +176 -174
- package/dist/batch-tools.js +21 -21
- package/dist/cache-tools.js +5 -5
- package/dist/config.js +1 -1
- package/dist/entity-tools.js +16 -16
- package/dist/environment-tools.js +10 -10
- package/dist/event-tools.js +45 -28
- package/dist/fluent-client.js +20 -0
- package/dist/graphql-query-tools.js +73 -17
- package/dist/graphql-schema-tools.js +14 -14
- package/dist/metrics-tools.js +87 -40
- package/dist/profile-registry.js +2 -2
- package/dist/response-shaper.js +1 -1
- package/dist/settings-tools.js +62 -26
- package/dist/test-tools.js +4 -4
- package/dist/tools.js +153 -148
- package/dist/workflow-tools.js +34 -44
- package/docs/E2E_TESTING.md +59 -59
- package/docs/HANDOVER_GITHUB_COPILOT.md +9 -9
- package/docs/HANDOVER_GITHUB_REPO_MCP_CONFIG.example.json +12 -12
- package/docs/RUNBOOK.md +38 -38
- package/docs/TOOL_REFERENCE.md +296 -296
- package/package.json +1 -1
package/dist/workflow-tools.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Workflow management tools:
|
|
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
|
|
6
|
-
*
|
|
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: "
|
|
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
|
|
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: "
|
|
112
|
-
description: "List all workflows for a retailer. Use outputDir to download all as JSON files. May return 401 on restricted accounts — use
|
|
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: "
|
|
123
|
-
description: "Deploy a workflow JSON to the Fluent environment. Validates structure before upload. Use dryRun=true to validate without deploying.
|
|
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: "
|
|
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: "
|
|
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
|
|
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
|
|
622
|
-
"Use
|
|
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
|
|
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
|
|
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
|
-
//
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
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
|
|
699
|
-
|
|
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
|
|
702
|
+
workflowName,
|
|
712
703
|
retailerId,
|
|
713
|
-
|
|
704
|
+
deployMethod: "rest-put",
|
|
714
705
|
...preflight,
|
|
715
706
|
_hints: [
|
|
716
|
-
"
|
|
717
|
-
"Use
|
|
718
|
-
"Use
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
}
|
package/docs/E2E_TESTING.md
CHANGED
|
@@ -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-
|
|
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
|
-
- `
|
|
30
|
-
- `
|
|
31
|
-
- `
|
|
29
|
+
- `config_validate`
|
|
30
|
+
- `health_ping`
|
|
31
|
+
- `connection_test`
|
|
32
32
|
- **Level 3: Fluent API smoke** (real API calls)
|
|
33
|
-
- `
|
|
34
|
-
- `
|
|
35
|
-
- `
|
|
36
|
-
- `
|
|
37
|
-
- optional batch flow (`
|
|
38
|
-
- optional webhook verification (`
|
|
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, `
|
|
152
|
-
`
|
|
153
|
-
`
|
|
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
|
-
- `
|
|
175
|
-
- `
|
|
176
|
-
- `
|
|
177
|
-
- `
|
|
178
|
-
- `
|
|
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-
|
|
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-
|
|
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. `
|
|
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>.
|
|
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
|
-
- `
|
|
286
|
-
- `
|
|
287
|
-
- `
|
|
288
|
-
- `
|
|
289
|
-
- `
|
|
290
|
-
- `
|
|
291
|
-
- `
|
|
292
|
-
- `
|
|
293
|
-
- `
|
|
294
|
-
- `
|
|
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. `
|
|
316
|
-
2. `
|
|
317
|
-
3. `
|
|
318
|
-
4. `
|
|
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 `
|
|
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 `
|
|
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: `
|
|
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: `
|
|
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: `
|
|
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: `
|
|
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: `
|
|
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: `
|
|
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: `
|
|
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: `
|
|
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: `
|
|
594
|
+
### Step 9: `event_get` verification
|
|
595
595
|
|
|
596
|
-
Use an event ID from successful `
|
|
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 `
|
|
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): `
|
|
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
|
-
### `
|
|
662
|
+
### `batch_create`
|
|
663
663
|
|
|
664
664
|
```json
|
|
665
665
|
{
|
|
@@ -669,7 +669,7 @@ Expected:
|
|
|
669
669
|
}
|
|
670
670
|
```
|
|
671
671
|
|
|
672
|
-
### `
|
|
672
|
+
### `batch_send`
|
|
673
673
|
|
|
674
674
|
```json
|
|
675
675
|
{
|
|
@@ -690,7 +690,7 @@ Expected:
|
|
|
690
690
|
}
|
|
691
691
|
```
|
|
692
692
|
|
|
693
|
-
### `
|
|
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 `
|
|
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 `
|
|
716
|
-
- at least one `
|
|
717
|
-
- at least one real `
|
|
718
|
-
- at least one `
|
|
719
|
-
- (optional) `
|
|
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. `
|
|
58
|
-
2. `
|
|
59
|
-
3. `
|
|
57
|
+
1. `config_validate`
|
|
58
|
+
2. `health_ping`
|
|
59
|
+
3. `graphql_query` with `query { __typename }`
|
|
60
60
|
|
|
61
61
|
Expected minimum:
|
|
62
62
|
|
|
63
|
-
- `
|
|
64
|
-
- `
|
|
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
|
-
- `
|
|
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 `
|
|
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
|
-
`
|
|
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 `
|
|
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
|
-
"
|
|
9
|
-
"
|
|
10
|
-
"
|
|
11
|
-
"
|
|
12
|
-
"
|
|
13
|
-
"
|
|
14
|
-
"
|
|
15
|
-
"
|
|
16
|
-
"
|
|
17
|
-
"
|
|
18
|
-
"
|
|
19
|
-
"
|
|
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",
|