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