@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.
@@ -0,0 +1,312 @@
1
+ # Operations Runbook
2
+
3
+ This runbook explains how to configure, verify, and troubleshoot
4
+ `fluent-mcp-extn` in day-to-day usage.
5
+
6
+ ## 1) Prerequisites
7
+
8
+ - Node.js 20+
9
+ - npm available
10
+ - valid Fluent credentials (profile, OAuth, token command, or static token)
11
+
12
+ ## 2) Local setup
13
+
14
+ ```bash
15
+ npm install
16
+ npm run build
17
+ npm test
18
+ npm run e2e:smoke
19
+ ```
20
+
21
+ Profile-based shortcuts:
22
+
23
+ ```bash
24
+ npm run e2e:smoke -- --wizard
25
+ npm run e2e:smoke -- --profile CLIENT_PROFILE
26
+ npm run e2e:smoke -- --profile CLIENT_PROFILE --retailer RETAILER_REF_OR_ID
27
+ npm run e2e:smoke -- --profile CLIENT_PROFILE --all-retailers
28
+ ```
29
+
30
+ Notes:
31
+ - `--wizard` is interactive (TTY required).
32
+ - For CI/non-interactive runs, use explicit flags (`--profile <name> --retailer <id|ref>` or `--profile <name> --all-retailers`).
33
+ - `--profile` only mode may fall back to a retailer that has candidate orders for real-send validation; use `--retailer` for strict retailer scope.
34
+
35
+ ## 3) MCP registration
36
+
37
+ Add server in your workspace `.mcp.json`.
38
+
39
+ ### OAuth / Token Command mode
40
+
41
+ ```json
42
+ {
43
+ "mcpServers": {
44
+ "fluent-mcp-extn": {
45
+ "type": "stdio",
46
+ "command": "node",
47
+ "args": ["fluent-mcp-extn/dist/index.js"],
48
+ "env": {
49
+ "FLUENT_BASE_URL": "https://YOUR_ACCOUNT.sandbox.api.fluentretail.com",
50
+ "FLUENT_RETAILER_ID": "YOUR_RETAILER_ID",
51
+ "TOKEN_COMMAND": "vault read -field=token secret/fluent/client-dev"
52
+ }
53
+ }
54
+ }
55
+ }
56
+ ```
57
+
58
+ ### Profile mode (recommended)
59
+
60
+ ```json
61
+ {
62
+ "mcpServers": {
63
+ "fluent-mcp-extn": {
64
+ "type": "stdio",
65
+ "command": "node",
66
+ "args": ["fluent-mcp-extn/dist/index.js"],
67
+ "env": {
68
+ "FLUENT_PROFILE": "HMDEV",
69
+ "FLUENT_PROFILE_RETAILER": "HM_TEST"
70
+ }
71
+ }
72
+ }
73
+ }
74
+ ```
75
+
76
+ Profile mode reads credentials from `~/.fluentcommerce/<profile>/` and
77
+ auto-resolves the retailer ID from the retailer ref. No base URL, client ID,
78
+ or secrets are needed in `.mcp.json`.
79
+
80
+ Reload your IDE after editing `.mcp.json`.
81
+
82
+ ## 4) Startup verification checklist
83
+
84
+ Run tools in this order:
85
+
86
+ 1. `config.validate`
87
+ 2. `health.ping`
88
+ 3. `connection.test`
89
+ 4. `event.build`
90
+ 5. `event.send` with `dryRun: true`
91
+ 6. `event.send` with `dryRun: false`
92
+ 7. `event.get` using ID returned by send
93
+ 8. `graphql.query` simple read
94
+ 9. `entity.get` — verify entity lookup works (e.g., look up a known order by ref)
95
+ 10. `workflow.transitions` (optional) — verify User Action API access for a known trigger
96
+ 11. `graphql.queryAll` — verify auto-pagination and run-level timeout
97
+ 12. `graphql.introspect` with `listMutations: true` — verify schema access
98
+ 13. `environment.discover` with `include: ["retailer", "locations"]` — verify environment snapshot
99
+ 14. `environment.validate` with `checks: ["auth", "retailer", "locations"]` — verify pre-flight checks
100
+ 15. (optional) `graphql.query` synchronous fulfilment options call
101
+ (`createFulfilmentOption` with `executionMode: AWAIT_ORCHESTRATION`)
102
+ for live checkout readiness checks
103
+
104
+ If all steps pass, runtime wiring is healthy.
105
+
106
+ Write-safety note:
107
+ - non-idempotent write tools do not auto-retry
108
+ - callers should confirm failures before manual re-submission
109
+
110
+ ## 5) Response shaping configuration
111
+
112
+ Response shaping controls how large API responses are processed before being
113
+ returned to the LLM. When a response exceeds the budget, arrays are
114
+ auto-summarized (not truncated) with record counts, field inventories, value
115
+ distributions, and sample records.
116
+
117
+ | Env var | Default | Description |
118
+ |---------|---------|-------------|
119
+ | `FLUENT_RESPONSE_BUDGET_CHARS` | `50000` (~12.5k tokens) | Max serialized response size. Set to `0` to disable (unlimited). |
120
+ | `FLUENT_RESPONSE_MAX_ARRAY` | `50` | Arrays exceeding this size are auto-summarized. Only active when budget > 0. |
121
+ | `FLUENT_RESPONSE_SAMPLE_SIZE` | `3` | Number of sample records included in array summaries. |
122
+
123
+ Set these in the `env` block of your `.mcp.json`:
124
+
125
+ ```json
126
+ {
127
+ "mcpServers": {
128
+ "fluent-mcp-extn": {
129
+ "type": "stdio",
130
+ "command": "node",
131
+ "args": ["fluent-mcp-extn/dist/index.js"],
132
+ "env": {
133
+ "FLUENT_PROFILE": "HMDEV",
134
+ "FLUENT_RESPONSE_BUDGET_CHARS": "80000",
135
+ "FLUENT_RESPONSE_MAX_ARRAY": "100",
136
+ "FLUENT_RESPONSE_SAMPLE_SIZE": "5"
137
+ }
138
+ }
139
+ }
140
+ }
141
+ ```
142
+
143
+ When shaping is active, responses include a `_responseMeta` object with
144
+ `originalChars`, `shapedChars`, `reductionPercent`, and `summarizedArrays`.
145
+
146
+ ## 6) Troubleshooting by symptom
147
+
148
+ ### `sdk adapter: not configured`
149
+
150
+ Likely causes:
151
+
152
+ - `FLUENT_BASE_URL` missing
153
+ - auth vars missing or invalid
154
+ - `TOKEN_COMMAND` failing
155
+
156
+ Actions:
157
+
158
+ 1. call `config.validate`
159
+ 2. inspect `errors` and `warnings`
160
+ 3. verify env vars in `.mcp.json`
161
+ 4. reload your IDE's MCP process
162
+
163
+ ### `AUTH_ERROR`
164
+
165
+ Likely causes:
166
+
167
+ - invalid client credentials
168
+ - expired static token
169
+ - vault command returning stale/empty token
170
+
171
+ Actions:
172
+
173
+ 1. test auth source directly (OAuth or command output)
174
+ 2. ensure token command output is either raw token or JSON with
175
+ `access_token`/`token`
176
+ 3. confirm account permissions for target APIs
177
+ 4. for static token mode, rotate token at source (API still enforces true expiry)
178
+
179
+ ### `FLUENT_PROFILE` could not be loaded
180
+
181
+ Likely causes:
182
+
183
+ - profile name is wrong
184
+ - retailer ref in `FLUENT_PROFILE_RETAILER` does not match `retailer.<ref>.json`
185
+ - profile files are missing in `~/.fluentcommerce/<profile>/`
186
+
187
+ Actions:
188
+
189
+ 1. run `fluent profile list`
190
+ 2. verify `FLUENT_PROFILE` value and active profile files
191
+ 3. if using `FLUENT_PROFILE_RETAILER`, confirm it matches retailer **ref** (not ID)
192
+ 4. set `FLUENT_PROFILE_DIR` only if profiles are stored outside default path
193
+
194
+ ### `TIMEOUT_ERROR` / `NETWORK_ERROR`
195
+
196
+ Likely causes:
197
+
198
+ - temporary upstream instability
199
+ - strict timeout/retry values
200
+ - DNS/proxy/firewall constraints
201
+
202
+ Actions:
203
+
204
+ 1. increase `FLUENT_REQUEST_TIMEOUT_MS`
205
+ 2. increase `FLUENT_RETRY_ATTEMPTS`
206
+ 3. verify base URL and outbound connectivity
207
+ 4. for `graphql.queryAll`, increase tool-level `timeoutMs` (controls whole pagination run)
208
+
209
+ ### `VALIDATION_ERROR`
210
+
211
+ Likely causes:
212
+
213
+ - missing required tool fields
214
+ - wrong payload shape
215
+
216
+ Actions:
217
+
218
+ 1. follow examples in `docs/TOOL_REFERENCE.md`
219
+ 2. check `error.details.issues` path/message pairs
220
+
221
+ ### Webhook signature validation mismatches
222
+
223
+ Likely causes:
224
+
225
+ - validating a re-serialized JSON object rather than original webhook body bytes
226
+ - incorrect or incomplete public key
227
+
228
+ Actions:
229
+
230
+ 1. pass exact raw HTTP body via `rawBody` in `webhook.validate`
231
+ 2. verify signature header value is unchanged
232
+ 3. confirm algorithm (`SHA512withRSA` default)
233
+
234
+ ### `SDK_ERROR` with `Request failed: 400` on `event.send`
235
+
236
+ Likely causes:
237
+
238
+ - event payload `retailerId` does not match the target entity's retailer
239
+ - sending with only `entityRef` when workflow expects ID-aware routing
240
+
241
+ Actions:
242
+
243
+ 1. query the target entity via `graphql.query` and capture `id`, `ref`, and retailer
244
+ 2. send event with matching `retailerId`
245
+ 3. include `entityId` and `rootEntityId` when available
246
+
247
+ ### `SDK_ERROR` with `Workflow [FULFILMENT_OPTIONS::<type>] not found`
248
+
249
+ Likely causes:
250
+
251
+ - fulfilment options workflow not deployed for this retailer
252
+ - `type` / `orderType` does not map to a deployed workflow subtype
253
+ - mutation is sent to the wrong retailer ID/environment
254
+
255
+ Actions:
256
+
257
+ 1. list workflows for target context and confirm `FULFILMENT_OPTIONS::<type>`
258
+ exists
259
+ 2. deploy/merge the required fulfilment options workflow for checkout
260
+ 3. re-run mutation with matching `retailerId`, `type`, and `orderType`
261
+ 4. verify synchronous response includes `plans`/`fulfilments`
262
+
263
+ ### Response appears truncated or incomplete
264
+
265
+ Likely causes:
266
+
267
+ - `FLUENT_RESPONSE_BUDGET_CHARS` is set too low for the query
268
+ - large arrays are being auto-summarized (check for `_responseMeta` in response)
269
+
270
+ Actions:
271
+
272
+ 1. check the `_responseMeta` object — if `reductionPercent` is high, the budget
273
+ is actively shaping the response
274
+ 2. increase `FLUENT_RESPONSE_BUDGET_CHARS` (e.g., `80000` or `100000`)
275
+ 3. increase `FLUENT_RESPONSE_MAX_ARRAY` if specific arrays are being summarized
276
+ 4. set `FLUENT_RESPONSE_BUDGET_CHARS=0` to disable shaping entirely
277
+ 5. for `event.flowInspect`, use `compact: true` (default) to get a pre-analyzed
278
+ summary instead of raw arrays
279
+
280
+ ## 7) Reliability tuning guidance
281
+
282
+ Start with defaults and adjust only when needed.
283
+
284
+ - low latency APIs: keep defaults
285
+ - slower integrations: increase timeout to 45-60s
286
+ - intermittent networks: increase retries to 4-5
287
+ - write operations are timeout-only; retries apply to read paths only
288
+ - SDK internal retries are disabled; adapter policy is the single retry control
289
+
290
+ Example:
291
+
292
+ ```json
293
+ {
294
+ "FLUENT_REQUEST_TIMEOUT_MS": "45000",
295
+ "FLUENT_RETRY_ATTEMPTS": "4",
296
+ "FLUENT_RETRY_INITIAL_DELAY_MS": "400",
297
+ "FLUENT_RETRY_MAX_DELAY_MS": "6000",
298
+ "FLUENT_RETRY_FACTOR": "2"
299
+ }
300
+ ```
301
+
302
+ ## 8) Safe extension workflow
303
+
304
+ When adding or changing a tool:
305
+
306
+ 1. update schema in `src/tools.ts`
307
+ 2. keep response envelopes consistent
308
+ 3. route API calls via `FluentClientAdapter`
309
+ 4. add unit tests
310
+ 5. run:
311
+ - `npm run build`
312
+ - `npm test`