@fluentcommerce/fluent-mcp-extn 0.2.0 → 0.3.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.
package/README.md CHANGED
@@ -1,804 +1,924 @@
1
- # @fluentcommerce/fluent-mcp-extn
2
-
3
- > **Alpha** — This package is under active development. APIs, tool signatures, and configuration may change between releases without notice. Use in non-production environments and pin to a specific version if stability matters.
4
-
5
- MCP ([Model Context Protocol](https://modelcontextprotocol.io)) extension server for [Fluent Commerce](https://fluentcommerce.com).
6
-
7
- Exposes event dispatch, transition actions, GraphQL operations, Prometheus metrics queries, batch ingestion, webhook validation, entity lifecycle management, workflow management, settings management, environment discovery, and test automation as MCP tools — powered by [`@fluentcommerce/fc-connect-sdk`](https://www.npmjs.com/package/@fluentcommerce/fc-connect-sdk).
8
-
9
- **What this does:** This server runs as a background process inside your AI coding assistant (Claude Code, Cursor, VS Code Copilot, Windsurf, etc.). It gives the AI direct, authenticated access to Fluent Commerce APIs — so the AI can query orders, send events, inspect workflows, check metrics, and run diagnostics on your behalf, using natural language.
10
-
11
- ## Table of Contents
12
-
13
- - [End-User Setup Checklist (First 15 Minutes)](#end-user-setup-checklist-first-15-minutes)
14
- - [MCP Config File Locations](#mcp-config-file-locations)
15
- - [Why This Extension](#why-this-extension)
16
- - [Quick Start](#quick-start)
17
- - [End-to-End Validation](#end-to-end-validation)
18
- - [Compatibility](#compatibility)
19
- - [Requirements](#requirements)
20
- - [Install](#install)
21
- - [Configuration](#configuration)
22
- - [Tools (36)](#tools-36)
23
- - [Error Handling](#error-handling)
24
- - [Support Scripts (Debugging and Validation)](#support-scripts-debugging-and-validation)
25
- - [Troubleshooting](#troubleshooting)
26
- - [Development Workflow](#development-workflow)
27
- - [Workspace Integration](#workspace-integration)
28
- - [Companion Packages](#companion-packages)
29
- - [NPM Publish Checklist (Maintainers)](#npm-publish-checklist-maintainers)
30
- - [License](#license)
31
-
32
- ## End-User Setup Checklist (First 15 Minutes)
33
-
34
- Follow this exact order for the smoothest first run:
35
-
36
- 1. Confirm prerequisites:
37
- - `node -v` (must be `>=20`)
38
- - if using profile auth: `fluent profile list`
39
- 2. Add one `fluent-mcp-extn` server entry in your workspace MCP config (see [MCP Config File Locations](#mcp-config-file-locations)).
40
- 3. Prefer **Option A (profile auth)** first for local usage, because it avoids copying secrets into `.mcp.json`.
41
- 4. Restart your IDE/agent session so MCP servers reload.
42
- 5. Run these tools in order:
43
- - `config.validate`
44
- - `health.ping`
45
- - `connection.test`
46
- 6. Run a safe event validation:
47
- - `event.build`
48
- - `event.send` with `dryRun: true`
49
- 7. Only then run `event.send` with `dryRun: false` when you are ready for a real event.
50
-
51
- If any step fails, jump to [Troubleshooting](#troubleshooting).
52
-
53
- ## MCP Config File Locations
54
-
55
- | Client | Recommended MCP config file |
56
- |---|---|
57
- | Claude Code | `.mcp.json` (workspace root) |
58
- | Cursor | `.mcp.json` (workspace root) or `.cursor/mcp.json` |
59
- | VS Code Copilot | `.vscode/mcp.json` |
60
- | GitHub Copilot Agent | Repository MCP settings |
61
- | Windsurf | Workspace/app MCP settings |
62
-
63
- ## Why This Extension
64
-
65
- The official `fluent mcp server` (bundled with Fluent CLI) covers core GraphQL and workflow operations. This extension adds capabilities typically needed for implementation and diagnostics:
66
-
67
- | Capability | Official MCP | This Extension |
68
- |---|:---:|:---:|
69
- | Event dispatch (`event.build` / `event.send` / `event.list` / `event.get`) | | Yes |
70
- | Event runtime forensics (`event.flowInspect`) | | Yes |
71
- | Workflow transitions (`workflow.transitions`) | | Yes |
72
- | Auto-paginated GraphQL (`graphql.queryAll`) | | Yes |
73
- | Batch mutations (`graphql.batchMutate`) | | Yes |
74
- | Batch ingestion (`batch.*`) | | Yes |
75
- | Prometheus metrics (`metrics.query`) | | Yes |
76
- | Metrics health assessment (`metrics.healthCheck`) | | Yes |
77
- | Managed SLO snapshot (`metrics.sloReport`) | | Yes |
78
- | Metric label discovery (`metrics.labelCatalog`) | | Yes |
79
- | Event analytics rankings (`metrics.topEvents`) | | Yes |
80
- | Webhook signature validation | | Yes |
81
- | Schema introspection (`graphql.introspect`) | | Yes |
82
- | Multi-strategy auth (profile, OAuth, token command, static token) | | Yes |
83
- | Entity CRUD (`entity.create` / `entity.update` / `entity.get`) | | Yes |
84
- | Workflow management (`workflow.upload` / `workflow.diff` / `workflow.simulate`) | | Yes |
85
- | Settings management (`setting.upsert` / `setting.bulkUpsert`) | | Yes |
86
- | Environment snapshot (`environment.discover` / `environment.validate`) | | Yes |
87
- | Test assertions with polling (`test.assert`) | | Yes |
88
-
89
- Best practice: run both the official MCP server and this extension together.
90
-
91
- ## Quick Start
92
-
93
- ### 1. Add MCP server entry
94
-
95
- Add to your project's `.mcp.json` (merge with existing servers, don't overwrite). Pick one of the options below.
96
-
97
- #### Option A: Fluent CLI Profile (recommended)
98
-
99
- Reuses your existing Fluent CLI profile — no credentials in `.mcp.json`:
100
-
101
- ```json
102
- {
103
- "mcpServers": {
104
- "fluent-mcp-extn": {
105
- "type": "stdio",
106
- "command": "npx",
107
- "args": ["@fluentcommerce/fluent-mcp-extn"],
108
- "env": {
109
- "FLUENT_PROFILE": "YOUR_PROFILE",
110
- "FLUENT_PROFILE_RETAILER": "YOUR_RETAILER_REF"
111
- }
112
- }
113
- }
114
- }
115
- ```
116
-
117
- Use retailer **ref** in `FLUENT_PROFILE_RETAILER` (for example `RETAILER_REF`), not retailer ID.
118
-
119
- Reads base URL, client ID/secret, username/password, and retailer ID from `~/.fluentcommerce/YOUR_PROFILE/`. Requires Fluent CLI to be installed with at least one profile configured (`fluent profile list`).
120
-
121
- #### Option B: Explicit OAuth credentials
122
-
123
- Pass all credentials directly in env vars:
124
-
125
- ```json
126
- {
127
- "mcpServers": {
128
- "fluent-mcp-extn": {
129
- "type": "stdio",
130
- "command": "npx",
131
- "args": ["@fluentcommerce/fluent-mcp-extn"],
132
- "env": {
133
- "FLUENT_BASE_URL": "https://YOUR_ACCOUNT.sandbox.api.fluentretail.com",
134
- "FLUENT_RETAILER_ID": "YOUR_RETAILER_ID",
135
- "FLUENT_CLIENT_ID": "YOUR_CLIENT_ID",
136
- "FLUENT_CLIENT_SECRET": "YOUR_CLIENT_SECRET",
137
- "FLUENT_USERNAME": "YOUR_USERNAME",
138
- "FLUENT_PASSWORD": "YOUR_PASSWORD"
139
- }
140
- }
141
- }
142
- }
143
- ```
144
-
145
- #### Option C: Profile + overrides (hybrid)
146
-
147
- Use a profile as the base, override specific values via env vars:
148
-
149
- ```json
150
- {
151
- "mcpServers": {
152
- "fluent-mcp-extn": {
153
- "type": "stdio",
154
- "command": "npx",
155
- "args": ["@fluentcommerce/fluent-mcp-extn"],
156
- "env": {
157
- "FLUENT_PROFILE": "YOUR_PROFILE",
158
- "FLUENT_PROFILE_RETAILER": "YOUR_RETAILER_REF",
159
- "FLUENT_RETAILER_ID": "YOUR_RETAILER_ID"
160
- }
161
- }
162
- }
163
- }
164
- ```
165
-
166
- Any explicit `FLUENT_*` env var overrides the value from the profile. Setting `FLUENT_BASE_URL` or OAuth env vars disables `createClientFromProfile` and falls back to standard OAuth (profile values still used as defaults for unset vars).
167
-
168
- #### Option D: Token command (vault / CI integration)
169
-
170
- For CI pipelines or environments where credentials come from a vault or external process:
171
-
172
- ```json
173
- {
174
- "mcpServers": {
175
- "fluent-mcp-extn": {
176
- "type": "stdio",
177
- "command": "npx",
178
- "args": ["@fluentcommerce/fluent-mcp-extn"],
179
- "env": {
180
- "FLUENT_BASE_URL": "https://YOUR_ACCOUNT.sandbox.api.fluentretail.com",
181
- "FLUENT_RETAILER_ID": "YOUR_RETAILER_ID",
182
- "TOKEN_COMMAND": "vault read -field=token secret/fluent/api",
183
- "TOKEN_COMMAND_TIMEOUT_MS": "10000"
184
- }
185
- }
186
- }
187
- }
188
- ```
189
-
190
- The command must print a valid bearer token to stdout. Token is cached for 55 minutes before re-executing the command.
191
-
192
- #### Option E: Static bearer token
193
-
194
- For quick testing with a pre-obtained token:
195
-
196
- ```json
197
- {
198
- "mcpServers": {
199
- "fluent-mcp-extn": {
200
- "type": "stdio",
201
- "command": "npx",
202
- "args": ["@fluentcommerce/fluent-mcp-extn"],
203
- "env": {
204
- "FLUENT_BASE_URL": "https://YOUR_ACCOUNT.sandbox.api.fluentretail.com",
205
- "FLUENT_RETAILER_ID": "YOUR_RETAILER_ID",
206
- "FLUENT_ACCESS_TOKEN": "YOUR_BEARER_TOKEN"
207
- }
208
- }
209
- }
210
- }
211
- ```
212
-
213
- No automatic refresh — the token will expire according to its original grant TTL.
214
-
215
- #### Auth priority order
216
-
217
- When multiple auth methods are configured, the first valid method wins:
218
-
219
- 1. **Profile** — `FLUENT_PROFILE` set → uses SDK `createClientFromProfile`
220
- 2. **OAuth**`FLUENT_CLIENT_ID` + `FLUENT_CLIENT_SECRET` SDK-native OAuth with automatic refresh
221
- 3. **Token command** — `TOKEN_COMMAND` → executes shell command, caches token for 55 min
222
- 4. **Static token** — `FLUENT_ACCESS_TOKEN` → no refresh, dev fallback only
223
-
224
- ### 2. Restart your IDE
225
-
226
- Restart so the MCP client picks up the new server.
227
-
228
- ### 3. Verify connection
229
-
230
- Run these tools in order to confirm everything works:
231
-
232
- 1. `config.validate` — should return `ok: true`
233
- 2. `health.ping` should return `ok: true`
234
- 3. `connection.test` — should return `ok: true` with your user/account details
235
-
236
- If any returns `ok: false`, see [Troubleshooting](#troubleshooting).
237
-
238
- ### 4. Try a real call
239
-
240
- ```
241
- event.build → build a payload (no API call)
242
- event.send with dryRun: true → validate without sending
243
- event.send with dryRun: false → send for real
244
- ```
245
-
246
- ### Automated setup via AI Skills
247
-
248
- If you use `@fluentcommerce/ai-skills`, it can generate `.mcp.json` for both servers:
249
-
250
- ```bash
251
- npx @fluentcommerce/ai-skills mcp-setup --profile YOUR_PROFILE
252
- npx @fluentcommerce/ai-skills mcp-setup --profile YOUR_PROFILE --profile-retailer YOUR_RETAILER_REF
253
- ```
254
-
255
- ## End-to-End Validation
256
-
257
- Run this sequence after setup to verify runtime + real API integration:
258
-
259
- ```bash
260
- cd fluent-mcp-extn
261
- npm install
262
- npm run build
263
- npm test
264
- npm run e2e:smoke -- --wizard
265
- npm run e2e:smoke -- --profile YOUR_PROFILE
266
- npm run e2e:smoke -- --profile YOUR_PROFILE --retailer YOUR_RETAILER_REF_OR_ID
267
- npm run e2e:smoke -- --profile YOUR_PROFILE --all-retailers
268
- ```
269
-
270
- What this smoke test validates:
271
-
272
- - tools are discoverable (`tools.list`)
273
- - config is valid (`config.validate`)
274
- - runtime starts cleanly (`health.ping`)
275
- - event payload build and dry-run send
276
- - GraphQL connectivity (`__typename` and order lookup)
277
- - real `event.send` on a candidate order
278
- - event retrieval via `event.get`
279
-
280
- Notes:
281
-
282
- - `--wizard` provides guided profile/account and retailer selection for interactive runs
283
- - `--wizard` requires an interactive terminal (TTY); in CI/non-interactive shells use explicit flags (`--profile <name> --retailer <id|ref>` or `--profile <name> --all-retailers`)
284
- - `--retailer` accepts retailer ID or retailer ref
285
- - `--all-retailers` requires `--profile` and runs one cycle per profile retailer file (`retailer.<ref>.json`), labeled as `retailer-<id>`
286
- - use `--skip-real-send` to avoid real event side effects
287
- - for profile-based setup, prefer retailer ref in `FLUENT_PROFILE_RETAILER`
288
- - in `--all-retailers` mode, retailers without a candidate order are reported as skipped (not failed)
289
- - with `--profile` only (no `--retailer` / `--all-retailers`), smoke may fall back to a retailer that has candidate orders for real-send validation; use `--retailer` for strict retailer scope
290
-
291
- ## Compatibility
292
-
293
- Works with any MCP client that supports stdio servers:
294
-
295
- | Client | MCP config location |
296
- |---|---|
297
- | Claude Code | `.mcp.json` (workspace root) |
298
- | Cursor | `.mcp.json` (workspace root) or `.cursor/mcp.json` |
299
- | VS Code Copilot | `.vscode/mcp.json` |
300
- | GitHub Copilot Agent | Repository MCP settings |
301
- | Windsurf | Workspace/app MCP settings |
302
-
303
- ## Requirements
304
-
305
- - Node.js 20+
306
- - Fluent CLI installed when using profile auth (`FLUENT_PROFILE`)
307
- - Fluent Commerce API credentials (see [Configuration](#configuration))
308
-
309
- ## Install
310
-
311
- ### From npm (recommended)
312
-
313
- No install needed `npx` runs it directly from the npm registry:
314
-
315
- ```bash
316
- npx @fluentcommerce/fluent-mcp-extn
317
- ```
318
-
319
- This starts the MCP stdio server process. In a plain terminal it appears idle because it is waiting for MCP JSON-RPC input from your IDE/agent.
320
-
321
- Or install as a project dependency:
322
-
323
- ```bash
324
- npm install @fluentcommerce/fluent-mcp-extn
325
- ```
326
-
327
- ### From source
328
-
329
- ```bash
330
- git clone https://bitbucket.org/fluentcommerce/fluent-mcp-extn.git
331
- cd fluent-mcp-extn
332
- npm install && npm run build
333
- ```
334
-
335
- Then use in `.mcp.json`:
336
-
337
- ```json
338
- {
339
- "command": "node",
340
- "args": ["path/to/fluent-mcp-extn/dist/index.js"]
341
- }
342
- ```
343
-
344
- ## Configuration
345
-
346
- All configuration is via environment variables in your `.mcp.json` `env` block. Never commit credentials to git.
347
-
348
- ### Required
349
-
350
- | Variable | Description |
351
- |---|---|
352
- | `FLUENT_BASE_URL` | Fluent Commerce API base URL |
353
-
354
- Plus at least one auth method below.
355
-
356
- ### Authentication (first valid method wins)
357
-
358
- #### 1. Fluent CLI profile (recommended for local development)
359
-
360
- | Variable | Required | Description |
361
- |---|---|---|
362
- | `FLUENT_PROFILE` | Yes | Fluent CLI profile name (`~/.fluentcommerce/<profile>`) |
363
- | `FLUENT_PROFILE_RETAILER` | No | Retailer **ref** (matches `retailer.<ref>.json`) |
364
- | `FLUENT_PROFILE_DIR` | No | Override profile base directory (defaults to `~/.fluentcommerce`) |
365
-
366
- `FLUENT_PROFILE_RETAILER` allows retailer-scoped user credential overrides from profile files.
367
-
368
- #### 2. OAuth
369
-
370
- | Variable | Required | Description |
371
- |---|---|---|
372
- | `FLUENT_CLIENT_ID` | Yes | OAuth client ID |
373
- | `FLUENT_CLIENT_SECRET` | Yes | OAuth client secret |
374
- | `FLUENT_USERNAME` | No | Username (for password grant) |
375
- | `FLUENT_PASSWORD` | No | Password (for password grant) |
376
-
377
- #### 3. Token command
378
-
379
- | Variable | Default | Description |
380
- |---|---|---|
381
- | `TOKEN_COMMAND` | — | Shell command that prints a bearer token to stdout |
382
- | `TOKEN_COMMAND_TIMEOUT_MS` | `10000` | Timeout for the command |
383
-
384
- #### 4. Static token
385
-
386
- | Variable | Description |
387
- |---|---|
388
- | `FLUENT_ACCESS_TOKEN` | Pre-obtained bearer token |
389
-
390
- ### Optional
391
-
392
- | Variable | Default | Description |
393
- |---|---|---|
394
- | `FLUENT_RETAILER_ID` | — | Default retailer for events and batch operations |
395
- | `FLUENT_ACCOUNT_ID` | — | Default account for events |
396
-
397
- ### Resilience Tuning
398
-
399
- | Variable | Default | Description |
400
- |---|---|---|
401
- | `FLUENT_REQUEST_TIMEOUT_MS` | `30000` | Request timeout |
402
- | `FLUENT_RETRY_ATTEMPTS` | `3` | Retry attempts for read operations |
403
- | `FLUENT_RETRY_INITIAL_DELAY_MS` | `300` | Initial backoff delay |
404
- | `FLUENT_RETRY_MAX_DELAY_MS` | `5000` | Max backoff delay |
405
- | `FLUENT_RETRY_FACTOR` | `2` | Backoff multiplier |
406
-
407
- ## Tools (36)
408
-
409
- ### Diagnostics
410
-
411
- | Tool | Description |
412
- |---|---|
413
- | `config.validate` | Validate auth and base URL configuration |
414
- | `health.ping` | Quick connectivity check |
415
- | `connection.test` | Full auth + GraphQL end-to-end test (returns user/account context) |
416
-
417
- ### Events
418
-
419
- | Tool | Description |
420
- |---|---|
421
- | `event.build` | Build event payload without sending (validation only) |
422
- | `event.send` | Build and send event (supports `dryRun: true`) |
423
- | `event.get` | Fetch a single event by ID |
424
- | `event.list` | List/filter events with pagination |
425
- | `event.flowInspect` | One-call root-entity flow forensics — works for ORDER/FULFILMENT/LOCATION/WAVE/PRODUCT and more |
426
-
427
- `event.flowInspect` supports any entity type. Pass `rootEntityType` when you want strict filtering; omit it to inspect by root ref only. Use `rootEntityId` when refs are reused and you need exact disambiguation.
428
-
429
- **Compact mode (default `compact: true`):** Returns a pre-analyzed summary (~2-3k tokens) with an `analysis` section containing anomaly findings, status flow, failed webhook endpoints, and slowest rulesets. Set `compact: false` for full raw data (~24k tokens).
430
-
431
- **Default-on flags:** `compact`, `includeAudit`, `includeExceptions`, `includeNoMatchDetails`, `includeEventDetails`, `includeScheduled`
432
-
433
- **Opt-in flags (default false):**
434
- - `includeRuleDetails` — per-rule execution trace with class name, props, and timing
435
- - `includeCustomLogs` — custom plugin log messages (LogCollection)
436
- - `includeSnapshots` — entity state snapshots at each processing point
437
- - `includeCrossEntity` — child entity events (FULFILMENT_CHOICE, FULFILMENT)
438
-
439
- **Example** compact forensics (recommended first call):
440
-
441
- ```json
442
- {
443
- "rootEntityRef": "ORD-001",
444
- "rootEntityType": "ORDER"
445
- }
446
- ```
447
-
448
- **Example** — full data with all sections:
449
-
450
- ```json
451
- {
452
- "rootEntityRef": "ORD-001",
453
- "rootEntityType": "ORDER",
454
- "compact": false,
455
- "includeRuleDetails": true,
456
- "includeCustomLogs": true,
457
- "includeSnapshots": true,
458
- "includeCrossEntity": true
459
- }
460
- ```
461
-
462
- **Example**lightweight (minimal output):
463
-
464
- ```json
465
- {
466
- "rootEntityRef": "ORD-001",
467
- "rootEntityType": "ORDER",
468
- "includeAudit": false,
469
- "includeEventDetails": false,
470
- "includeExceptions": false,
471
- "includeNoMatchDetails": false,
472
- "maxDrilldowns": 0
473
- }
474
- ```
475
-
476
- ### Local-First LLM Reduction (flowInspect)
477
-
478
- If `event.flowInspect` returns large JSON, run local analysis first and only send compact artifacts to an LLM:
479
-
480
- ```bash
481
- npx tsx scripts/run-flow-inspect.ts <ROOT_ENTITY_REF> --profile <PROFILE>
482
- ```
483
-
484
- This writes:
485
-
486
- - `EVENT_FLOW_INSPECT_<ref>.json` (raw)
487
- - `EVENT_FLOW_INSPECT_<ref>.summary.json` (local anomaly + metrics summary)
488
- - `EVENT_FLOW_INSPECT_<ref>.drilldown.json` (focused `event.get` extraction for top evidence IDs)
489
- - `EVENT_FLOW_INSPECT_<ref>.llm-packet.md` (small LLM handoff packet)
490
-
491
- Useful flags:
492
-
493
- - `--light` uses compact fetch mode for faster runs
494
- - `--root-type ...` and `--root-id ...` tighten entity matching
495
- - `--drilldown` / `--no-drilldown` toggle focused `event.get` enrichment
496
- - `--drilldown-limit` controls how many top evidence IDs get enriched
497
- - `--drilldown-classes webhook,mutation,sendEvent,mismatch,exception,scheduled,slow,status` limits enrichment to selected evidence classes
498
- - `--top-n`, `--evidence-limit`, `--truncate` control summary/packet compactness
499
- - `--no-llm-pack` skips markdown packet output
500
-
501
- ### Metrics
502
-
503
- | Tool | Description |
504
- |---|---|
505
- | `metrics.query` | Query Prometheus metrics using instant or range mode |
506
- | `metrics.healthCheck` | One-call anomaly check with Prometheus-first + Event API fallback |
507
- | `metrics.sloReport` | Managed-services SLO snapshot (rates + p95 latency + findings) |
508
- | `metrics.labelCatalog` | Discover supported metric labels from live series + known Fluent hints |
509
- | `metrics.topEvents` | Aggregate and rank top events by name/entity/status in a time window |
510
-
511
- ### Orchestration
512
-
513
- | Tool | Description |
514
- |---|---|
515
- | `workflow.transitions` | Query available user actions/transitions for provided triggers (`POST /api/v4.1/transition`) |
516
- | `plugin.list` | List all registered rules with metadata (`GET /orchestration/rest/v1/plugin`). Supports optional name filter. |
517
-
518
- **Example** — get actions for a ServicePoint manifest trigger:
519
-
520
- ```json
521
- {
522
- "triggers": [
523
- {
524
- "type": "MANIFEST",
525
- "subtype": "DEFAULT",
526
- "status": "PENDING",
527
- "module": "servicepoint",
528
- "flexType": "CARRIER::DEFAULT",
529
- "retailerId": "2"
530
- }
531
- ]
532
- }
533
- ```
534
-
535
- **Example** list all rules matching "SendEvent":
536
-
537
- ```json
538
- {
539
- "name": "SendEvent"
540
- }
541
- ```
542
-
543
- ### GraphQL
544
-
545
- | Tool | Description |
546
- |---|---|
547
- | `graphql.query` | Execute any query or mutation |
548
- | `graphql.queryAll` | Auto-paginated query follows cursors across all pages |
549
- | `graphql.batchMutate` | Execute up to 50 mutations in one request |
550
- | `graphql.introspect` | Inspect schema types, mutations, and input fields |
551
-
552
- **Example** — query orders:
553
-
554
- ```json
555
- {
556
- "query": "{ orders(first: 5) { edges { cursor node { id ref status } } pageInfo { hasNextPage } } }"
557
- }
558
- ```
559
-
560
- **Example** — auto-paginate all active orders:
561
-
562
- ```json
563
- {
564
- "query": "{ orders(first: 100, after: $cursor) { edges { cursor node { id ref status } } pageInfo { hasNextPage } } }",
565
- "variables": { "cursor": null },
566
- "maxRecords": 5000
567
- }
568
- ```
569
-
570
- **Example** — batch update 3 orders:
571
-
572
- ```json
573
- {
574
- "mutation": "updateOrder",
575
- "inputs": [
576
- { "id": "1", "status": "SHIPPED" },
577
- { "id": "2", "status": "SHIPPED" },
578
- { "id": "3", "status": "SHIPPED" }
579
- ],
580
- "returnFields": ["id", "ref", "status"]
581
- }
582
- ```
583
-
584
- ### Batch Ingestion
585
-
586
- | Tool | Description |
587
- |---|---|
588
- | `batch.create` | Create an ingestion job |
589
- | `batch.send` | Send records to a job |
590
- | `batch.status` | Check job status |
591
- | `batch.batchStatus` | Check a specific batch within a job |
592
- | `batch.results` | Get per-record outcomes |
593
-
594
- Typical flow: `batch.create` `batch.send` `batch.status` (poll) `batch.results`
595
-
596
- ### Webhook
597
-
598
- | Tool | Description |
599
- |---|---|
600
- | `webhook.validate` | Validate payload fields and optionally verify cryptographic signature |
601
-
602
- ### Entity Lifecycle
603
-
604
- | Tool | Description |
605
- |---|---|
606
- | `entity.create` | Type-safe entity creation with field validation, compound key encoding, and retailer auto-injection. Supports 12 entity types. |
607
- | `entity.update` | Status-aware entity updates with optional transition validation via `workflow.transitions` |
608
- | `entity.get` | Unified entity lookup by ID or ref with optional edge inclusion |
609
-
610
- **Supported types:** ORDER, FULFILMENT, LOCATION, NETWORK, CUSTOMER, PRODUCT, INVENTORY_POSITION, VIRTUAL_CATALOGUE, VIRTUAL_POSITION, CATEGORY, CARRIER, SETTING
611
-
612
- **Example** create a location:
613
-
614
- ```json
615
- {
616
- "entityType": "LOCATION",
617
- "data": {
618
- "ref": "LOC_WH_01",
619
- "type": "WAREHOUSE",
620
- "name": "Main Warehouse",
621
- "openingSchedule": { "allHours": true }
622
- },
623
- "dryRun": true
624
- }
625
- ```
626
-
627
- ### Workflow Management
628
-
629
- | Tool | Description |
630
- |---|---|
631
- | `workflow.upload` | Deploy workflow JSON via REST API with structure validation. For production, prefer `fluent module install` via CLI. |
632
- | `workflow.diff` | Compare two workflow definitions — returns added/removed/modified rulesets with risk assessment. Supports `summary`, `detailed`, and `mermaid` formats. |
633
- | `workflow.simulate` | Static analysis prediction of which rulesets would fire for a given status + event name. Does NOT execute Java rules or check runtime state — use `workflow.transitions` for authoritative live validation. |
634
-
635
- ### Settings Management
636
-
637
- | Tool | Description |
638
- |---|---|
639
- | `setting.upsert` | Create or update a setting with upsert semantics — queries existing by name + context + contextId first |
640
- | `setting.bulkUpsert` | Batch create/update up to 50 settings with per-setting error handling |
641
-
642
- **Contexts:** RETAILER, ACCOUNT, LOCATION, NETWORK, AGENT, CUSTOMER
643
-
644
- ### Environment
645
-
646
- | Tool | Description |
647
- |---|---|
648
- | `environment.discover` | Full environment snapshot retailer, locations, networks, catalogues, workflows, settings, modules, users. Each section is opt-in via `include` array. |
649
- | `environment.validate` | Pre-flight validation checks: auth, retailer, locations, inventory, workflows, settings, modules |
650
-
651
- ### Test Automation
652
-
653
- | Tool | Description |
654
- |---|---|
655
- | `test.assert` | Assert entity state matches expectations. Supports status, type, attribute, and edge assertions. Optional polling mode retries until pass or timeout. |
656
-
657
- **Example** — assert an order reached BOOKED with at least 1 fulfilment:
658
-
659
- ```json
660
- {
661
- "entityType": "ORDER",
662
- "ref": "HD-001",
663
- "assertions": {
664
- "status": "BOOKED",
665
- "edges": { "fulfilments": { "minCount": 1 } }
666
- },
667
- "poll": true,
668
- "timeoutMs": 60000
669
- }
670
- ```
671
-
672
- ## Error Handling
673
-
674
- All tools return a consistent envelope:
675
-
676
- **Success:**
677
-
678
- ```json
679
- {
680
- "ok": true,
681
- "response": { }
682
- }
683
- ```
684
-
685
- **Failure:**
686
-
687
- ```json
688
- {
689
- "ok": false,
690
- "error": {
691
- "code": "AUTH_ERROR",
692
- "message": "OAuth token request failed.",
693
- "retryable": false,
694
- "details": {}
695
- }
696
- }
697
- ```
698
-
699
- | Error Code | Meaning | Retryable |
700
- |---|---|---|
701
- | `CONFIG_ERROR` | Missing or invalid environment variables | No |
702
- | `AUTH_ERROR` | Authentication failed | No |
703
- | `VALIDATION_ERROR` | Invalid tool arguments | No |
704
- | `TIMEOUT_ERROR` | Request timed out | Yes |
705
- | `RATE_LIMIT` | API rate limit hit | Yes |
706
- | `UPSTREAM_UNAVAILABLE` | Fluent API unreachable | Yes |
707
- | `NETWORK_ERROR` | Network connectivity issue | Yes |
708
- | `SDK_ERROR` | Unexpected SDK error | Varies |
709
- | `UNKNOWN_ERROR` | Unclassified error | No |
710
-
711
- ## Support Scripts (Debugging and Validation)
712
-
713
- These scripts are useful during tenant validation, support, and failure triage:
714
-
715
- ```bash
716
- # Positive smoke test
717
- npm run e2e:smoke -- --profile YOUR_PROFILE --retailer YOUR_RETAILER_REF_OR_ID
718
-
719
- # Interactive smoke setup
720
- npm run e2e:smoke -- --wizard
721
-
722
- # Negative-path validation (bad payloads, schema failures, error envelopes)
723
- npx tsx scripts/e2e-negative.ts --profile YOUR_PROFILE --retailer YOUR_RETAILER_REF_OR_ID
724
-
725
- # Check status of specific events and filtered event lists
726
- npx tsx scripts/check-event-status.ts --profile YOUR_PROFILE --retailer YOUR_RETAILER_REF_OR_ID --event-id <EVENT_ID>
727
- ```
728
-
729
- Recommended operator flow:
730
-
731
- 1. Run positive smoke (`e2e:smoke`).
732
- 2. Run negative validation (`e2e-negative.ts`) to verify expected error handling.
733
- 3. Use `check-event-status.ts` to trace real event outcomes when diagnosing failures.
734
-
735
- ## Troubleshooting
736
-
737
- | Symptom | Likely Cause | Fix |
738
- |---|---|---|
739
- | `config.validate` fails | Missing or invalid env vars | Check `FLUENT_BASE_URL` and at least one complete auth method |
740
- | `FLUENT_PROFILE` auth fails | Profile/retailer ref mismatch or missing files | Verify `fluent profile list`, profile name, and `FLUENT_PROFILE_RETAILER` ref |
741
- | `AUTH_ERROR` on any tool | Bad credentials or expired token | Verify OAuth values or regenerate token |
742
- | `connection.test` fails | Network or URL mismatch | Verify API URL, check VPN/proxy, confirm tenant is reachable |
743
- | `event.send` succeeds but workflow doesn't trigger | Event name not mapped in workflow | Check workflow event handlers and ruleset conditions |
744
- | Server doesn't appear in MCP client | Config not reloaded | Restart IDE/client after editing `.mcp.json` |
745
- | Events sent to wrong tenant | Wrong `FLUENT_BASE_URL` | Confirm the API URL and retailer ID |
746
- | `RATE_LIMIT` errors | Too many requests | Reduce request frequency; retryable errors auto-retry up to `FLUENT_RETRY_ATTEMPTS` |
747
-
748
- ## Development Workflow
749
-
750
- For a step-by-step guide on using these MCP tools to add functionality and test end-to-end (scaffold rules, build modules, fire events, assert state transitions, debug failures), see the [Development Workflow Guide](../fluent-ai-skills/docs/DEV_WORKFLOW.md) in the companion `@fluentcommerce/ai-skills` package.
751
-
752
- ## Workspace Integration
753
-
754
- When used alongside `@fluentcommerce/ai-skills`, this extension server integrates with a workspace convention for managing source code, workflows, and analysis artifacts across multiple Fluent accounts:
755
-
756
- ```
757
- accounts/
758
- <PROFILE>/
759
- SOURCE/ # custom plugin repos and JAR files
760
- workflows/ # downloaded workflow JSONs (scoped by retailer)
761
- analysis/ # generated analysis artifacts
762
- ```
763
-
764
- Skills use this server's tools (`plugin.list`, `graphql.query`, `connection.test`, etc.) to:
765
- - Build a deployed rule inventory by cross-referencing live registered rules with local source
766
- - Validate connectivity during guided onboarding (`/fluent-connect`)
767
- - Run entity count discovery queries during workspace setup
768
- - Power end-to-end test flows with event dispatch and state assertions
769
-
770
- See the [Workspace Setup](https://www.npmjs.com/package/@fluentcommerce/ai-skills#workspace-setup) section in `@fluentcommerce/ai-skills` for the full directory layout, how to place source code and JAR files, and how the guided onboarding wizard works.
771
-
772
- ## Companion Packages
773
-
774
- | Package | Purpose |
775
- |---|---|
776
- | [`@fluentcommerce/ai-skills`](https://www.npmjs.com/package/@fluentcommerce/ai-skills) | Install Fluent domain skills across AI coding assistants |
777
- | Fluent CLI (`@fluentcommerce/cli`) | Official CLI and built-in MCP server |
778
-
779
- ## NPM Publish Checklist (Maintainers)
780
-
781
- Use this sequence before publishing:
782
-
783
- 1. Confirm version and metadata in `package.json`.
784
- 2. Build and test:
785
- - `npm run build`
786
- - `npm test`
787
- 3. Run smoke checks:
788
- - `npm run e2e:smoke -- --profile <PROFILE> --retailer <RETAILER>`
789
- - `npx tsx scripts/e2e-negative.ts --profile <PROFILE> --retailer <RETAILER>`
790
- 4. Validate package contents:
791
- - `npm pack`
792
- 5. Publish:
793
- - `npm publish --access public`
794
- 6. Post-publish sanity:
795
- - start via MCP client and run `config.validate`, `health.ping`, `connection.test`
796
-
797
- Notes:
798
-
799
- - `prepublishOnly` already enforces `npm run build && npm test`.
800
- - Keep credentials out of committed `.mcp.json` and docs examples.
801
-
802
- ## License
803
-
804
- [MIT](LICENSE)
1
+ # @fluentcommerce/fluent-mcp-extn
2
+
3
+ > **Alpha** — This package is under active development. APIs, tool signatures, and configuration may change between releases without notice. Use in non-production environments and pin to a specific version if stability matters.
4
+
5
+ MCP ([Model Context Protocol](https://modelcontextprotocol.io)) extension server for [Fluent Commerce](https://fluentcommerce.com).
6
+
7
+ Exposes event dispatch, transition actions, GraphQL operations, Prometheus metrics queries, batch ingestion, webhook validation, entity lifecycle management, workflow management, settings management, environment discovery, and test automation as MCP tools — powered by [`@fluentcommerce/fc-connect-sdk`](https://www.npmjs.com/package/@fluentcommerce/fc-connect-sdk).
8
+
9
+ **What this does:** This server runs as a background process inside your AI coding assistant (Claude Code, Cursor, VS Code Copilot, Windsurf, etc.). It gives the AI direct, authenticated access to Fluent Commerce APIs — so the AI can query orders, send events, inspect workflows, check metrics, and run diagnostics on your behalf, using natural language.
10
+
11
+ ## Table of Contents
12
+
13
+ - [End-User Setup Checklist (First 15 Minutes)](#end-user-setup-checklist-first-15-minutes)
14
+ - [MCP Config File Locations](#mcp-config-file-locations)
15
+ - [Why This Extension](#why-this-extension)
16
+ - [Quick Start](#quick-start)
17
+ - [End-to-End Validation](#end-to-end-validation)
18
+ - [Compatibility](#compatibility)
19
+ - [Requirements](#requirements)
20
+ - [Install](#install)
21
+ - [Configuration](#configuration)
22
+ - [Tools (39)](#tools-39)
23
+ - [Error Handling](#error-handling)
24
+ - [Support Scripts (Debugging and Validation)](#support-scripts-debugging-and-validation)
25
+ - [Troubleshooting](#troubleshooting)
26
+ - [Development Workflow](#development-workflow)
27
+ - [Workspace Integration](#workspace-integration)
28
+ - [Companion Packages](#companion-packages)
29
+ - [NPM Publish Checklist (Maintainers)](#npm-publish-checklist-maintainers)
30
+ - [License](#license)
31
+
32
+ ## End-User Setup Checklist (First 15 Minutes)
33
+
34
+ Follow this exact order for the smoothest first run:
35
+
36
+ 1. Confirm prerequisites:
37
+ - `node -v` (must be `>=20`)
38
+ - if using profile auth: `fluent profile list`
39
+ 2. Add one `fluent-mcp-extn` server entry in your workspace MCP config (see [MCP Config File Locations](#mcp-config-file-locations)).
40
+ 3. Prefer **Option A (profile auth)** first for local usage, because it avoids copying secrets into `.mcp.json`.
41
+ 4. Restart your IDE/agent session so MCP servers reload.
42
+ 5. Run these tools in order:
43
+ - `config.validate`
44
+ - `health.ping`
45
+ - `connection.test`
46
+ 6. Run a safe event validation:
47
+ - `event.build`
48
+ - `event.send` with `dryRun: true`
49
+ 7. Only then run `event.send` with `dryRun: false` when you are ready for a real event.
50
+
51
+ If any step fails, jump to [Troubleshooting](#troubleshooting).
52
+
53
+ ## MCP Config File Locations
54
+
55
+ | Client | Recommended MCP config file |
56
+ |---|---|
57
+ | Claude Code | `.mcp.json` (workspace root) |
58
+ | Cursor | `.mcp.json` (workspace root) or `.cursor/mcp.json` |
59
+ | VS Code Copilot | `.vscode/mcp.json` |
60
+ | GitHub Copilot Agent | Repository MCP settings |
61
+ | Windsurf | Workspace/app MCP settings |
62
+
63
+ ## Why This Extension
64
+
65
+ The official `fluent mcp server` (bundled with Fluent CLI) covers core GraphQL and workflow operations. This extension adds capabilities typically needed for implementation and diagnostics:
66
+
67
+ | Capability | Official MCP | This Extension |
68
+ |---|:---:|:---:|
69
+ | Event dispatch (`event.build` / `event.send` / `event.list` / `event.get`) | | Yes |
70
+ | Event runtime forensics (`event.flowInspect`) | | Yes |
71
+ | Workflow transitions (`workflow.transitions`) | | Yes |
72
+ | Auto-paginated GraphQL (`graphql.queryAll`) | | Yes |
73
+ | Batch mutations (`graphql.batchMutate`) | | Yes |
74
+ | Batch ingestion (`batch.*`) | | Yes |
75
+ | Prometheus metrics (`metrics.query`) | | Yes |
76
+ | Metrics health assessment (`metrics.healthCheck`) | | Yes |
77
+ | Managed SLO snapshot (`metrics.sloReport`) | | Yes |
78
+ | Metric label discovery (`metrics.labelCatalog`) | | Yes |
79
+ | Event analytics rankings (`metrics.topEvents`) | | Yes |
80
+ | Webhook signature validation | | Yes |
81
+ | Schema introspection (`graphql.introspect`) | | Yes |
82
+ | Multi-strategy auth (profile, OAuth, token command, static token) | | Yes |
83
+ | Entity CRUD (`entity.create` / `entity.update` / `entity.get`) | | Yes |
84
+ | Workflow management (`workflow.get` / `workflow.list` / `workflow.upload` / `workflow.diff` / `workflow.simulate`) | | Yes |
85
+ | Settings management (`setting.get` / `setting.upsert` / `setting.bulkUpsert`) | | Yes |
86
+ | Environment snapshot (`environment.discover` / `environment.validate`) | | Yes |
87
+ | Test assertions with polling (`test.assert`) | | Yes |
88
+
89
+ Best practice: run both the official MCP server and this extension together.
90
+
91
+ ## Quick Start
92
+
93
+ ### 1. Add MCP server entry
94
+
95
+ Add to your project's `.mcp.json` (merge with existing servers, don't overwrite). Pick one of the options below.
96
+
97
+ #### Option A: Fluent CLI Profile (recommended)
98
+
99
+ Reuses your existing Fluent CLI profile — no credentials in `.mcp.json`:
100
+
101
+ ```json
102
+ {
103
+ "mcpServers": {
104
+ "fluent-mcp-extn": {
105
+ "type": "stdio",
106
+ "command": "npx",
107
+ "args": ["@fluentcommerce/fluent-mcp-extn"],
108
+ "env": {
109
+ "FLUENT_PROFILE": "YOUR_PROFILE",
110
+ "FLUENT_PROFILE_RETAILER": "YOUR_RETAILER_REF"
111
+ }
112
+ }
113
+ }
114
+ }
115
+ ```
116
+
117
+ Use retailer **ref** in `FLUENT_PROFILE_RETAILER` (for example `RETAILER_REF`), not retailer ID.
118
+
119
+ Reads base URL, client ID/secret, username/password, and retailer ID from `~/.fluentcommerce/YOUR_PROFILE/`. Requires Fluent CLI to be installed with at least one profile configured (`fluent profile list`).
120
+
121
+ #### Option B: Explicit OAuth credentials
122
+
123
+ Set credentials as **shell environment variables** (never in `.mcp.json`):
124
+
125
+ ```bash
126
+ export FLUENT_CLIENT_ID=your-client-id
127
+ export FLUENT_CLIENT_SECRET=your-client-secret
128
+ export FLUENT_USERNAME=your-username
129
+ export FLUENT_PASSWORD=your-password
130
+ ```
131
+
132
+ Then in `.mcp.json`, only the non-sensitive connection details:
133
+
134
+ ```json
135
+ {
136
+ "mcpServers": {
137
+ "fluent-mcp-extn": {
138
+ "type": "stdio",
139
+ "command": "npx",
140
+ "args": ["@fluentcommerce/fluent-mcp-extn"],
141
+ "env": {
142
+ "FLUENT_BASE_URL": "https://YOUR_ACCOUNT.sandbox.api.fluentretail.com",
143
+ "FLUENT_RETAILER_ID": "YOUR_RETAILER_ID"
144
+ }
145
+ }
146
+ }
147
+ }
148
+ ```
149
+
150
+ The MCP server inherits all parent shell environment variables automatically.
151
+
152
+ #### Option C: Profile + overrides (hybrid)
153
+
154
+ Use a profile as the base, override specific values via env vars:
155
+
156
+ ```json
157
+ {
158
+ "mcpServers": {
159
+ "fluent-mcp-extn": {
160
+ "type": "stdio",
161
+ "command": "npx",
162
+ "args": ["@fluentcommerce/fluent-mcp-extn"],
163
+ "env": {
164
+ "FLUENT_PROFILE": "YOUR_PROFILE",
165
+ "FLUENT_PROFILE_RETAILER": "YOUR_RETAILER_REF",
166
+ "FLUENT_RETAILER_ID": "YOUR_RETAILER_ID"
167
+ }
168
+ }
169
+ }
170
+ }
171
+ ```
172
+
173
+ Any explicit `FLUENT_*` env var overrides the value from the profile. Setting `FLUENT_BASE_URL` or OAuth env vars disables `createClientFromProfile` and falls back to standard OAuth (profile values still used as defaults for unset vars).
174
+
175
+ #### Option D: Token command (vault / CI integration)
176
+
177
+ For CI pipelines or environments where credentials come from a vault or external process:
178
+
179
+ ```json
180
+ {
181
+ "mcpServers": {
182
+ "fluent-mcp-extn": {
183
+ "type": "stdio",
184
+ "command": "npx",
185
+ "args": ["@fluentcommerce/fluent-mcp-extn"],
186
+ "env": {
187
+ "FLUENT_BASE_URL": "https://YOUR_ACCOUNT.sandbox.api.fluentretail.com",
188
+ "FLUENT_RETAILER_ID": "YOUR_RETAILER_ID",
189
+ "TOKEN_COMMAND": "vault read -field=token secret/fluent/api",
190
+ "TOKEN_COMMAND_TIMEOUT_MS": "10000"
191
+ }
192
+ }
193
+ }
194
+ }
195
+ ```
196
+
197
+ The command must print a valid bearer token to stdout. Token is cached for 55 minutes before re-executing the command.
198
+
199
+ #### Option E: Static bearer token
200
+
201
+ For quick testing with a pre-obtained token:
202
+
203
+ ```json
204
+ {
205
+ "mcpServers": {
206
+ "fluent-mcp-extn": {
207
+ "type": "stdio",
208
+ "command": "npx",
209
+ "args": ["@fluentcommerce/fluent-mcp-extn"],
210
+ "env": {
211
+ "FLUENT_BASE_URL": "https://YOUR_ACCOUNT.sandbox.api.fluentretail.com",
212
+ "FLUENT_RETAILER_ID": "YOUR_RETAILER_ID",
213
+ "FLUENT_ACCESS_TOKEN": "YOUR_BEARER_TOKEN"
214
+ }
215
+ }
216
+ }
217
+ }
218
+ ```
219
+
220
+ No automatic refresh the token will expire according to its original grant TTL.
221
+
222
+ #### Auth priority order
223
+
224
+ When multiple auth methods are configured, the first valid method wins:
225
+
226
+ 1. **Profile** `FLUENT_PROFILE` set uses SDK `createClientFromProfile`
227
+ 2. **OAuth** — `FLUENT_CLIENT_ID` + `FLUENT_CLIENT_SECRET` → SDK-native OAuth with automatic refresh
228
+ 3. **Token command** — `TOKEN_COMMAND` → executes shell command, caches token for 55 min
229
+ 4. **Static token** — `FLUENT_ACCESS_TOKEN` → no refresh, dev fallback only
230
+
231
+ ### 2. Restart your IDE
232
+
233
+ Restart so the MCP client picks up the new server.
234
+
235
+ ### 3. Verify connection
236
+
237
+ Run these tools in order to confirm everything works:
238
+
239
+ 1. `config.validate` — should return `ok: true`
240
+ 2. `health.ping` — should return `ok: true`
241
+ 3. `connection.test` should return `ok: true` with your user/account details
242
+
243
+ If any returns `ok: false`, see [Troubleshooting](#troubleshooting).
244
+
245
+ ### 4. Try a real call
246
+
247
+ ```
248
+ event.build → build a payload (no API call)
249
+ event.send with dryRun: true → validate without sending
250
+ event.send with dryRun: false → send for real
251
+ ```
252
+
253
+ ### Automated setup via AI Skills (recommended)
254
+
255
+ If you use `@fluentcommerce/ai-skills`, a single command installs skills AND configures both MCP servers:
256
+
257
+ ```bash
258
+ # Install skills + configure .mcp.json + check prerequisites (one command)
259
+ npx @fluentcommerce/ai-skills install --profile YOUR_PROFILE --profile-retailer YOUR_RETAILER_REF
260
+
261
+ # Optional: pre-install this extension locally for faster MCP server startup
262
+ npx @fluentcommerce/ai-skills install --profile YOUR_PROFILE --install-mcp-extn
263
+ ```
264
+
265
+ Or configure MCP separately (if skills are already installed):
266
+
267
+ ```bash
268
+ npx @fluentcommerce/ai-skills mcp-setup --profile YOUR_PROFILE --profile-retailer YOUR_RETAILER_REF
269
+ ```
270
+
271
+ ## End-to-End Validation
272
+
273
+ Run this sequence after setup to verify runtime + real API integration:
274
+
275
+ ```bash
276
+ cd fluent-mcp-extn
277
+ npm install
278
+ npm run build
279
+ npm test
280
+ npm run e2e:smoke -- --wizard
281
+ npm run e2e:smoke -- --profile YOUR_PROFILE
282
+ npm run e2e:smoke -- --profile YOUR_PROFILE --retailer YOUR_RETAILER_REF_OR_ID
283
+ npm run e2e:smoke -- --profile YOUR_PROFILE --all-retailers
284
+ ```
285
+
286
+ What this smoke test validates:
287
+
288
+ - tools are discoverable (`tools.list`)
289
+ - config is valid (`config.validate`)
290
+ - runtime starts cleanly (`health.ping`)
291
+ - event payload build and dry-run send
292
+ - GraphQL connectivity (`__typename` and order lookup)
293
+ - real `event.send` on a candidate order
294
+ - event retrieval via `event.get`
295
+
296
+ Notes:
297
+
298
+ - `--wizard` provides guided profile/account and retailer selection for interactive runs
299
+ - `--wizard` requires an interactive terminal (TTY); in CI/non-interactive shells use explicit flags (`--profile <name> --retailer <id|ref>` or `--profile <name> --all-retailers`)
300
+ - `--retailer` accepts retailer ID or retailer ref
301
+ - `--all-retailers` requires `--profile` and runs one cycle per profile retailer file (`retailer.<ref>.json`), labeled as `retailer-<id>`
302
+ - use `--skip-real-send` to avoid real event side effects
303
+ - for profile-based setup, prefer retailer ref in `FLUENT_PROFILE_RETAILER`
304
+ - in `--all-retailers` mode, retailers without a candidate order are reported as skipped (not failed)
305
+ - with `--profile` only (no `--retailer` / `--all-retailers`), smoke may fall back to a retailer that has candidate orders for real-send validation; use `--retailer` for strict retailer scope
306
+
307
+ ## Compatibility
308
+
309
+ Works with any MCP client that supports stdio servers:
310
+
311
+ | Client | MCP config location |
312
+ |---|---|
313
+ | Claude Code | `.mcp.json` (workspace root) |
314
+ | Cursor | `.mcp.json` (workspace root) or `.cursor/mcp.json` |
315
+ | VS Code Copilot | `.vscode/mcp.json` |
316
+ | GitHub Copilot Agent | Repository MCP settings |
317
+ | Windsurf | Workspace/app MCP settings |
318
+
319
+ ## Requirements
320
+
321
+ - Node.js 20+
322
+ - Fluent CLI installed when using profile auth (`FLUENT_PROFILE`)
323
+ - Fluent Commerce API credentials (see [Configuration](#configuration))
324
+
325
+ ## Install
326
+
327
+ ### From npm (recommended)
328
+
329
+ No install needed — `npx` runs it directly from the npm registry:
330
+
331
+ ```bash
332
+ npx @fluentcommerce/fluent-mcp-extn
333
+ ```
334
+
335
+ This starts the MCP stdio server process. In a plain terminal it appears idle because it is waiting for MCP JSON-RPC input from your IDE/agent.
336
+
337
+ Or install as a project dependency:
338
+
339
+ ```bash
340
+ npm install @fluentcommerce/fluent-mcp-extn
341
+ ```
342
+
343
+ ### From source
344
+
345
+ ```bash
346
+ git clone https://bitbucket.org/fluentcommerce/fluent-mcp-extn.git
347
+ cd fluent-mcp-extn
348
+ npm install && npm run build
349
+ ```
350
+
351
+ Then use in `.mcp.json`:
352
+
353
+ ```json
354
+ {
355
+ "command": "node",
356
+ "args": ["path/to/fluent-mcp-extn/dist/index.js"]
357
+ }
358
+ ```
359
+
360
+ ## Configuration
361
+
362
+ All configuration is via environment variables in your `.mcp.json` `env` block. Never commit credentials to git.
363
+
364
+ ### Required
365
+
366
+ | Variable | Description |
367
+ |---|---|
368
+ | `FLUENT_BASE_URL` | Fluent Commerce API base URL |
369
+
370
+ Plus at least one auth method below.
371
+
372
+ ### Authentication (first valid method wins)
373
+
374
+ #### 1. Fluent CLI profile (recommended for local development)
375
+
376
+ | Variable | Required | Description |
377
+ |---|---|---|
378
+ | `FLUENT_PROFILE` | Yes | Fluent CLI profile name (`~/.fluentcommerce/<profile>`) |
379
+ | `FLUENT_PROFILE_RETAILER` | No | Retailer **ref** (matches `retailer.<ref>.json`) |
380
+ | `FLUENT_PROFILE_DIR` | No | Override profile base directory (defaults to `~/.fluentcommerce`) |
381
+
382
+ `FLUENT_PROFILE_RETAILER` allows retailer-scoped user credential overrides from profile files.
383
+
384
+ #### 2. OAuth
385
+
386
+ | Variable | Required | Description |
387
+ |---|---|---|
388
+ | `FLUENT_CLIENT_ID` | Yes | OAuth client ID |
389
+ | `FLUENT_CLIENT_SECRET` | Yes | OAuth client secret |
390
+ | `FLUENT_USERNAME` | No | Username (for password grant) |
391
+ | `FLUENT_PASSWORD` | No | Password (for password grant) |
392
+
393
+ > **Security:** These credentials must be set as shell environment variables, never in `.mcp.json`. MCP server processes inherit all parent shell env vars automatically. The `mcp-setup` command strips any secrets found in `.mcp.json` during re-runs.
394
+
395
+ #### 3. Token command
396
+
397
+ | Variable | Default | Description |
398
+ |---|---|---|
399
+ | `TOKEN_COMMAND` | | Shell command that prints a bearer token to stdout |
400
+ | `TOKEN_COMMAND_TIMEOUT_MS` | `10000` | Timeout for the command |
401
+
402
+ #### 4. Static token
403
+
404
+ | Variable | Description |
405
+ |---|---|
406
+ | `FLUENT_ACCESS_TOKEN` | Pre-obtained bearer token |
407
+
408
+ ### Optional
409
+
410
+ | Variable | Default | Description |
411
+ |---|---|---|
412
+ | `FLUENT_RETAILER_ID` | — | Default retailer for events and batch operations |
413
+ | `FLUENT_ACCOUNT_ID` | | Default account for events |
414
+
415
+ ### Resilience Tuning
416
+
417
+ | Variable | Default | Description |
418
+ |---|---|---|
419
+ | `FLUENT_REQUEST_TIMEOUT_MS` | `30000` | Request timeout |
420
+ | `FLUENT_RETRY_ATTEMPTS` | `3` | Retry attempts for read operations |
421
+ | `FLUENT_RETRY_INITIAL_DELAY_MS` | `300` | Initial backoff delay |
422
+ | `FLUENT_RETRY_MAX_DELAY_MS` | `5000` | Max backoff delay |
423
+ | `FLUENT_RETRY_FACTOR` | `2` | Backoff multiplier |
424
+
425
+ ### Response Shaping
426
+
427
+ Controls how large responses are handled before returning to the AI. When a response exceeds the budget, arrays are auto-summarized (not truncated) with record counts, field inventory, value distributions, and sample records giving the AI a complete analytical picture instead of cut-off data.
428
+
429
+ | Variable | Default | Description |
430
+ |---|---|---|
431
+ | `FLUENT_RESPONSE_BUDGET_CHARS` | `50000` | Max serialized response size (~12.5k tokens). `0` disables (unlimited). |
432
+ | `FLUENT_RESPONSE_MAX_ARRAY` | `50` | Arrays exceeding this size are auto-summarized. Only active when budget > 0. |
433
+ | `FLUENT_RESPONSE_SAMPLE_SIZE` | `3` | Number of sample records included in array summaries. |
434
+
435
+ ## Tools (39)
436
+
437
+ ### Diagnostics
438
+
439
+ | Tool | Description |
440
+ |---|---|
441
+ | `config.validate` | Validate auth and base URL configuration |
442
+ | `health.ping` | Quick connectivity check |
443
+ | `connection.test` | Full auth + GraphQL end-to-end test (returns user/account context) |
444
+
445
+ ### Events
446
+
447
+ | Tool | Description |
448
+ |---|---|
449
+ | `event.build` | Build event payload without sending (validation only) |
450
+ | `event.send` | Build and send event (supports `dryRun: true`) |
451
+ | `event.get` | Fetch a single event by ID |
452
+ | `event.list` | List/filter events with pagination |
453
+ | `event.flowInspect` | One-call root-entity flow forensics — works for ORDER/FULFILMENT/LOCATION/WAVE/PRODUCT and more |
454
+
455
+ `event.flowInspect` supports any entity type. Pass `rootEntityType` when you want strict filtering; omit it to inspect by root ref only. Use `rootEntityId` when refs are reused and you need exact disambiguation.
456
+
457
+ **Compact mode (default `compact: true`):** Returns a pre-analyzed summary (~2-3k tokens) with an `analysis` section containing anomaly findings, status flow, failed webhook endpoints, and slowest rulesets. Set `compact: false` for full raw data (~24k tokens).
458
+
459
+ **Default-on flags:** `compact`, `includeAudit`, `includeExceptions`, `includeNoMatchDetails`, `includeEventDetails`, `includeScheduled`
460
+
461
+ **Opt-in flags (default false):**
462
+ - `includeRuleDetails` per-rule execution trace with class name, props, and timing
463
+ - `includeCustomLogs` — custom plugin log messages (LogCollection)
464
+ - `includeSnapshots` — entity state snapshots at each processing point
465
+ - `includeCrossEntity` — child entity events (FULFILMENT_CHOICE, FULFILMENT)
466
+
467
+ **Example** — compact forensics (recommended first call):
468
+
469
+ ```json
470
+ {
471
+ "rootEntityRef": "ORD-001",
472
+ "rootEntityType": "ORDER"
473
+ }
474
+ ```
475
+
476
+ **Example** full data with all sections:
477
+
478
+ ```json
479
+ {
480
+ "rootEntityRef": "ORD-001",
481
+ "rootEntityType": "ORDER",
482
+ "compact": false,
483
+ "includeRuleDetails": true,
484
+ "includeCustomLogs": true,
485
+ "includeSnapshots": true,
486
+ "includeCrossEntity": true
487
+ }
488
+ ```
489
+
490
+ **Example** — lightweight (minimal output):
491
+
492
+ ```json
493
+ {
494
+ "rootEntityRef": "ORD-001",
495
+ "rootEntityType": "ORDER",
496
+ "includeAudit": false,
497
+ "includeEventDetails": false,
498
+ "includeExceptions": false,
499
+ "includeNoMatchDetails": false,
500
+ "maxDrilldowns": 0
501
+ }
502
+ ```
503
+
504
+ ### Local-First LLM Reduction (flowInspect)
505
+
506
+ If `event.flowInspect` returns large JSON, run local analysis first and only send compact artifacts to an LLM:
507
+
508
+ ```bash
509
+ npx tsx scripts/run-flow-inspect.ts <ROOT_ENTITY_REF> --profile <PROFILE>
510
+ ```
511
+
512
+ This writes:
513
+
514
+ - `EVENT_FLOW_INSPECT_<ref>.json` (raw)
515
+ - `EVENT_FLOW_INSPECT_<ref>.summary.json` (local anomaly + metrics summary)
516
+ - `EVENT_FLOW_INSPECT_<ref>.drilldown.json` (focused `event.get` extraction for top evidence IDs)
517
+ - `EVENT_FLOW_INSPECT_<ref>.llm-packet.md` (small LLM handoff packet)
518
+
519
+ Useful flags:
520
+
521
+ - `--light` uses compact fetch mode for faster runs
522
+ - `--root-type ...` and `--root-id ...` tighten entity matching
523
+ - `--drilldown` / `--no-drilldown` toggle focused `event.get` enrichment
524
+ - `--drilldown-limit` controls how many top evidence IDs get enriched
525
+ - `--drilldown-classes webhook,mutation,sendEvent,mismatch,exception,scheduled,slow,status` limits enrichment to selected evidence classes
526
+ - `--top-n`, `--evidence-limit`, `--truncate` control summary/packet compactness
527
+ - `--no-llm-pack` skips markdown packet output
528
+
529
+ ### Metrics
530
+
531
+ | Tool | Description |
532
+ |---|---|
533
+ | `metrics.query` | Query Prometheus metrics using instant or range mode |
534
+ | `metrics.healthCheck` | One-call anomaly check with Prometheus-first + Event API fallback |
535
+ | `metrics.sloReport` | Managed-services SLO snapshot (rates + p95 latency + findings) |
536
+ | `metrics.labelCatalog` | Discover supported metric labels from live series + known Fluent hints |
537
+ | `metrics.topEvents` | Aggregate and rank top events by name/entity/status in a time window |
538
+
539
+ ### Orchestration
540
+
541
+ | Tool | Description |
542
+ |---|---|
543
+ | `workflow.transitions` | Query available user actions/transitions for provided triggers (`POST /api/v4.1/transition`) |
544
+ | `plugin.list` | List all registered rules with metadata (`GET /orchestration/rest/v1/plugin`). Supports optional name filter. |
545
+
546
+ **`flexType` auto-derive:** When `type` and `subtype` are provided but `flexType` is omitted, it is auto-derived as `TYPE::SUBTYPE`. All three params (`module`, `flexType`, `flexVersion`) are required by the Transition API — omitting any one silently returns empty results.
547
+
548
+ **Example** get actions for a ServicePoint manifest trigger:
549
+
550
+ ```json
551
+ {
552
+ "triggers": [
553
+ {
554
+ "type": "MANIFEST",
555
+ "subtype": "DEFAULT",
556
+ "status": "PENDING",
557
+ "module": "servicepoint",
558
+ "flexType": "CARRIER::DEFAULT",
559
+ "retailerId": "2"
560
+ }
561
+ ]
562
+ }
563
+ ```
564
+
565
+ **Example** auto-derive flexType from type + subtype:
566
+
567
+ ```json
568
+ {
569
+ "triggers": [
570
+ {
571
+ "type": "CREDIT_MEMO",
572
+ "subtype": "APPEASEMENT",
573
+ "status": "CREATED",
574
+ "module": "adminconsole",
575
+ "flexVersion": "1.0",
576
+ "retailerId": "2"
577
+ }
578
+ ]
579
+ }
580
+ ```
581
+
582
+ **Example** — list all rules matching "SendEvent":
583
+
584
+ ```json
585
+ {
586
+ "name": "SendEvent"
587
+ }
588
+ ```
589
+
590
+ ### GraphQL
591
+
592
+ | Tool | Description |
593
+ |---|---|
594
+ | `graphql.query` | Execute any query or mutation |
595
+ | `graphql.queryAll` | Auto-paginated query — follows cursors across all pages |
596
+ | `graphql.batchMutate` | Execute up to 50 mutations in one request |
597
+ | `graphql.introspect` | Inspect schema types, mutations, and input fields |
598
+
599
+ **Example** — query orders:
600
+
601
+ ```json
602
+ {
603
+ "query": "{ orders(first: 5) { edges { cursor node { id ref status } } pageInfo { hasNextPage } } }"
604
+ }
605
+ ```
606
+
607
+ **Example** auto-paginate all active orders:
608
+
609
+ ```json
610
+ {
611
+ "query": "{ orders(first: 100, after: $cursor) { edges { cursor node { id ref status } } pageInfo { hasNextPage } } }",
612
+ "variables": { "cursor": null },
613
+ "maxRecords": 5000
614
+ }
615
+ ```
616
+
617
+ **Example** — batch update 3 orders:
618
+
619
+ ```json
620
+ {
621
+ "mutation": "updateOrder",
622
+ "inputs": [
623
+ { "id": "1", "status": "SHIPPED" },
624
+ { "id": "2", "status": "SHIPPED" },
625
+ { "id": "3", "status": "SHIPPED" }
626
+ ],
627
+ "returnFields": ["id", "ref", "status"]
628
+ }
629
+ ```
630
+
631
+ **Example** dry-run batch mutation (validates query without executing):
632
+
633
+ ```json
634
+ {
635
+ "mutation": "updateOrder",
636
+ "inputs": [{ "id": "1", "status": "SHIPPED" }],
637
+ "returnFields": ["id", "ref", "status"],
638
+ "dryRun": true
639
+ }
640
+ ```
641
+
642
+ With `dryRun: true`, returns the generated aliased mutation query and variables for review without making any API call. Use this to preview what will be sent before executing bulk operations.
643
+
644
+ ### Batch Ingestion
645
+
646
+ | Tool | Description |
647
+ |---|---|
648
+ | `batch.create` | Create an ingestion job |
649
+ | `batch.send` | Send records to a job |
650
+ | `batch.status` | Check job status |
651
+ | `batch.batchStatus` | Check a specific batch within a job |
652
+ | `batch.results` | Get per-record outcomes |
653
+
654
+ Typical flow: `batch.create` → `batch.send` → `batch.status` (poll) → `batch.results`
655
+
656
+ ### Webhook
657
+
658
+ | Tool | Description |
659
+ |---|---|
660
+ | `webhook.validate` | Validate payload fields and optionally verify cryptographic signature |
661
+
662
+ ### Entity Lifecycle
663
+
664
+ | Tool | Description |
665
+ |---|---|
666
+ | `entity.create` | Type-safe entity creation with field validation, compound key encoding, and retailer auto-injection. Supports 12 entity types. |
667
+ | `entity.update` | Status-aware entity updates with optional transition validation via `workflow.transitions` |
668
+ | `entity.get` | Unified entity lookup by ID or ref with optional edge inclusion |
669
+
670
+ **Supported types:** ORDER, FULFILMENT, LOCATION, NETWORK, CUSTOMER, PRODUCT, INVENTORY_POSITION, VIRTUAL_CATALOGUE, VIRTUAL_POSITION, CATEGORY, CARRIER, SETTING
671
+
672
+ **Example** create a location:
673
+
674
+ ```json
675
+ {
676
+ "entityType": "LOCATION",
677
+ "data": {
678
+ "ref": "LOC_WH_01",
679
+ "type": "WAREHOUSE",
680
+ "name": "Main Warehouse",
681
+ "openingSchedule": { "allHours": true }
682
+ },
683
+ "dryRun": true
684
+ }
685
+ ```
686
+
687
+ ### Workflow Management
688
+
689
+ | Tool | Description |
690
+ |---|---|
691
+ | `workflow.get` | Fetch a specific workflow by entity type and subtype via REST API. Works even when the list endpoint returns 401. |
692
+ | `workflow.list` | List all workflows for a retailer. Deduplicates to latest version per workflow name. |
693
+ | `workflow.upload` | Deploy workflow JSON via REST API with structure validation. For production, prefer `fluent module install` via CLI. |
694
+ | `workflow.diff` | Compare two workflow definitions — returns added/removed/modified rulesets with risk assessment. Supports `summary`, `detailed`, and `mermaid` formats. |
695
+ | `workflow.simulate` | Static analysis prediction of which rulesets would fire for a given status + event name. Does NOT execute Java rules or check runtime state — use `workflow.transitions` for authoritative live validation. |
696
+
697
+ **Example** — fetch a workflow and save to file:
698
+
699
+ ```json
700
+ {
701
+ "entityType": "ORDER",
702
+ "entitySubtype": "HD",
703
+ "retailerId": "2",
704
+ "outputFile": "accounts/MYPROFILE/workflows/MyRetailer/ORDER-HD.json"
705
+ }
706
+ ```
707
+
708
+ When `outputFile` is set, the full workflow JSON is saved to disk and only a summary is returned (status count, ruleset count, total rules). This reads from the **live server** via REST API — not the CLI workflowlog cache.
709
+
710
+ **Example** — list all workflows and download to directory:
711
+
712
+ ```json
713
+ {
714
+ "retailerId": "2",
715
+ "outputDir": "accounts/MYPROFILE/workflows/MyRetailer/"
716
+ }
717
+ ```
718
+
719
+ With `outputDir`, each workflow is saved as `{TYPE}-{SUBTYPE}.json` (e.g., `ORDER-HD.json`). The response lists saved files with paths and sizes. Without `outputDir`, returns metadata only (name, version, status count per workflow).
720
+
721
+ ### Settings Management
722
+
723
+ | Tool | Description |
724
+ |---|---|
725
+ | `setting.get` | Fetch settings by name (`%` wildcards supported), optionally save to local file to keep large JSON out of LLM context |
726
+ | `setting.upsert` | Create or update a setting with upsert semantics — queries existing by name + context + contextId first |
727
+ | `setting.bulkUpsert` | Batch create/update up to 50 settings with per-setting error handling |
728
+
729
+ **Contexts:** RETAILER, ACCOUNT, LOCATION, NETWORK, AGENT, CUSTOMER
730
+
731
+ **Example** fetch a manifest setting and save to file (keeps large JSON out of LLM context):
732
+
733
+ ```json
734
+ {
735
+ "name": "fc.mystique.manifest.oms",
736
+ "context": "ACCOUNT",
737
+ "contextId": 0,
738
+ "outputFile": "accounts/MYPROFILE/manifests/backups/fc.mystique.manifest.oms.json"
739
+ }
740
+ ```
741
+
742
+ When `outputFile` is set, the response returns metadata only (name, context, valueType, sizeBytes, savedTo path) — the full JSON goes to disk. For multiple matches (e.g., `name: "fc.mystique.manifest.%"`), each setting is saved as a separate file in the outputFile directory.
743
+
744
+ **Example** create/update a manifest setting with explicit `valueType`:
745
+
746
+ ```json
747
+ {
748
+ "name": "fc.mystique.manifest.oms.fragment.custom",
749
+ "context": "ACCOUNT",
750
+ "contextId": 0,
751
+ "valueType": "JSON",
752
+ "lobValue": { "manifestVersion": "2.0", "routes": [] }
753
+ }
754
+ ```
755
+
756
+ The `valueType` parameter accepts `"STRING"`, `"LOB"`, or `"JSON"`. For Mystique manifest settings, always use `valueType: "JSON"` — the default `LOB` breaks manifest parsing. A warning is emitted if a `fc.mystique.manifest.*` setting is created without `valueType: "JSON"`.
757
+
758
+ ### Environment
759
+
760
+ | Tool | Description |
761
+ |---|---|
762
+ | `environment.discover` | Full environment snapshot — retailer, locations, networks, catalogues, workflows, settings, modules, users. Each section is opt-in via `include` array. |
763
+ | `environment.validate` | Pre-flight validation checks: auth, retailer, locations, inventory, workflows, settings, modules |
764
+
765
+ ### Test Automation
766
+
767
+ | Tool | Description |
768
+ |---|---|
769
+ | `test.assert` | Assert entity state matches expectations. Supports status, type, attribute, and edge assertions. Optional polling mode retries until pass or timeout. |
770
+
771
+ **Example** — assert an order reached BOOKED with at least 1 fulfilment:
772
+
773
+ ```json
774
+ {
775
+ "entityType": "ORDER",
776
+ "ref": "HD-001",
777
+ "assertions": {
778
+ "status": "BOOKED",
779
+ "edges": { "fulfilments": { "minCount": 1 } }
780
+ },
781
+ "poll": true,
782
+ "timeoutMs": 60000
783
+ }
784
+ ```
785
+
786
+ ## Error Handling
787
+
788
+ All tools return a consistent envelope:
789
+
790
+ **Success:**
791
+
792
+ ```json
793
+ {
794
+ "ok": true,
795
+ "response": { }
796
+ }
797
+ ```
798
+
799
+ **Failure:**
800
+
801
+ ```json
802
+ {
803
+ "ok": false,
804
+ "error": {
805
+ "code": "AUTH_ERROR",
806
+ "message": "OAuth token request failed.",
807
+ "retryable": false,
808
+ "details": {}
809
+ }
810
+ }
811
+ ```
812
+
813
+ | Error Code | Meaning | Retryable |
814
+ |---|---|---|
815
+ | `CONFIG_ERROR` | Missing or invalid environment variables | No |
816
+ | `AUTH_ERROR` | Authentication failed | No |
817
+ | `VALIDATION_ERROR` | Invalid tool arguments | No |
818
+ | `TIMEOUT_ERROR` | Request timed out | Yes |
819
+ | `RATE_LIMIT` | API rate limit hit | Yes |
820
+ | `UPSTREAM_UNAVAILABLE` | Fluent API unreachable | Yes |
821
+ | `NETWORK_ERROR` | Network connectivity issue | Yes |
822
+ | `SDK_ERROR` | Unexpected SDK error | Varies |
823
+ | `UNKNOWN_ERROR` | Unclassified error | No |
824
+
825
+ ### Retry Behavior
826
+
827
+ Read operations (queries, list, get) use `execute()` which retries on transient failures (timeout, rate limit, network errors) with exponential backoff up to `FLUENT_RETRY_ATTEMPTS` times. Write operations (create, update, send, upload, upsert) use `executeOnce()` with **no automatic retry** to prevent duplicate side effects. Tune retry parameters via the [Resilience Tuning](#resilience-tuning) env vars above.
828
+
829
+ ## Support Scripts (Debugging and Validation)
830
+
831
+ These scripts are useful during tenant validation, support, and failure triage:
832
+
833
+ ```bash
834
+ # Positive smoke test
835
+ npm run e2e:smoke -- --profile YOUR_PROFILE --retailer YOUR_RETAILER_REF_OR_ID
836
+
837
+ # Interactive smoke setup
838
+ npm run e2e:smoke -- --wizard
839
+
840
+ # Negative-path validation (bad payloads, schema failures, error envelopes)
841
+ npx tsx scripts/e2e-negative.ts --profile YOUR_PROFILE --retailer YOUR_RETAILER_REF_OR_ID
842
+
843
+ # Check status of specific events and filtered event lists
844
+ npx tsx scripts/check-event-status.ts --profile YOUR_PROFILE --retailer YOUR_RETAILER_REF_OR_ID --event-id <EVENT_ID>
845
+ ```
846
+
847
+ Recommended operator flow:
848
+
849
+ 1. Run positive smoke (`e2e:smoke`).
850
+ 2. Run negative validation (`e2e-negative.ts`) to verify expected error handling.
851
+ 3. Use `check-event-status.ts` to trace real event outcomes when diagnosing failures.
852
+
853
+ ## Troubleshooting
854
+
855
+ | Symptom | Likely Cause | Fix |
856
+ |---|---|---|
857
+ | `config.validate` fails | Missing or invalid env vars | Check `FLUENT_BASE_URL` and at least one complete auth method |
858
+ | `FLUENT_PROFILE` auth fails | Profile/retailer ref mismatch or missing files | Verify `fluent profile list`, profile name, and `FLUENT_PROFILE_RETAILER` ref |
859
+ | `AUTH_ERROR` on any tool | Bad credentials or expired token | Verify OAuth values or regenerate token |
860
+ | `connection.test` fails | Network or URL mismatch | Verify API URL, check VPN/proxy, confirm tenant is reachable |
861
+ | `event.send` succeeds but workflow doesn't trigger | Event name not mapped in workflow | Check workflow event handlers and ruleset conditions |
862
+ | Server doesn't appear in MCP client | Config not reloaded | Restart IDE/client after editing `.mcp.json` |
863
+ | Events sent to wrong tenant | Wrong `FLUENT_BASE_URL` | Confirm the API URL and retailer ID |
864
+ | `RATE_LIMIT` errors | Too many requests | Reduce request frequency; retryable errors auto-retry up to `FLUENT_RETRY_ATTEMPTS` |
865
+
866
+ ## Development Workflow
867
+
868
+ For a step-by-step guide on using these MCP tools to add functionality and test end-to-end (scaffold rules, build modules, fire events, assert state transitions, debug failures), see the [Development Workflow Guide](../fluent-ai-skills/docs/DEV_WORKFLOW.md) in the companion `@fluentcommerce/ai-skills` package.
869
+
870
+ ## Workspace Integration
871
+
872
+ When used alongside `@fluentcommerce/ai-skills`, this extension server integrates with a workspace convention for managing source code, workflows, and analysis artifacts across multiple Fluent accounts:
873
+
874
+ ```
875
+ accounts/
876
+ <PROFILE>/
877
+ SOURCE/ # custom source code (account-level, shared across retailers)
878
+ backend/ # Java Maven plugin repos and JAR files
879
+ frontend/ # Mystique SDK component projects
880
+ workflows/ # downloaded workflow JSONs (scoped by retailer)
881
+ analysis/ # generated analysis artifacts
882
+ ```
883
+
884
+ Skills use this server's tools (`plugin.list`, `graphql.query`, `connection.test`, etc.) to:
885
+ - Build a deployed rule inventory by cross-referencing live registered rules with local source
886
+ - Validate connectivity during guided onboarding (`/fluent-connect`)
887
+ - Run entity count discovery queries during workspace setup
888
+ - Power end-to-end test flows with event dispatch and state assertions
889
+
890
+ See the [Workspace Setup](https://www.npmjs.com/package/@fluentcommerce/ai-skills#workspace-setup) section in `@fluentcommerce/ai-skills` for the full directory layout, how to place source code and JAR files, and how the guided onboarding wizard works.
891
+
892
+ ## Companion Packages
893
+
894
+ | Package | Purpose |
895
+ |---|---|
896
+ | [`@fluentcommerce/ai-skills`](https://www.npmjs.com/package/@fluentcommerce/ai-skills) | Install Fluent domain skills across AI coding assistants |
897
+ | Fluent CLI (`@fluentcommerce/cli`) | Official CLI and built-in MCP server |
898
+
899
+ ## NPM Publish Checklist (Maintainers)
900
+
901
+ Use this sequence before publishing:
902
+
903
+ 1. Confirm version and metadata in `package.json`.
904
+ 2. Build and test:
905
+ - `npm run build`
906
+ - `npm test`
907
+ 3. Run smoke checks:
908
+ - `npm run e2e:smoke -- --profile <PROFILE> --retailer <RETAILER>`
909
+ - `npx tsx scripts/e2e-negative.ts --profile <PROFILE> --retailer <RETAILER>`
910
+ 4. Validate package contents:
911
+ - `npm pack`
912
+ 5. Publish:
913
+ - `npm publish --access public`
914
+ 6. Post-publish sanity:
915
+ - start via MCP client and run `config.validate`, `health.ping`, `connection.test`
916
+
917
+ Notes:
918
+
919
+ - `prepublishOnly` already enforces `npm run build && npm test`.
920
+ - Keep credentials out of committed `.mcp.json` and docs examples.
921
+
922
+ ## License
923
+
924
+ [MIT](LICENSE)