@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/LICENSE +21 -0
- package/README.md +818 -0
- package/dist/config.js +195 -0
- package/dist/entity-registry.js +418 -0
- package/dist/entity-tools.js +414 -0
- package/dist/environment-tools.js +573 -0
- package/dist/errors.js +150 -0
- package/dist/event-payload.js +22 -0
- package/dist/fluent-client.js +229 -0
- package/dist/index.js +47 -0
- package/dist/resilience.js +52 -0
- package/dist/response-shaper.js +361 -0
- package/dist/sdk-client.js +237 -0
- package/dist/settings-tools.js +348 -0
- package/dist/test-tools.js +388 -0
- package/dist/tools.js +3254 -0
- package/dist/workflow-tools.js +752 -0
- package/docs/CONTRIBUTING.md +100 -0
- package/docs/E2E_TESTING.md +739 -0
- package/docs/HANDOVER_COPILOT_SETUP_STEPS.example.yml +35 -0
- package/docs/HANDOVER_ENV.example +29 -0
- package/docs/HANDOVER_GITHUB_COPILOT.md +165 -0
- package/docs/HANDOVER_GITHUB_REPO_MCP_CONFIG.example.json +31 -0
- package/docs/HANDOVER_VSCODE_MCP_JSON.example.json +10 -0
- package/docs/IMPLEMENTATION_GUIDE.md +299 -0
- package/docs/RUNBOOK.md +312 -0
- package/docs/TOOL_REFERENCE.md +1810 -0
- package/package.json +68 -0
package/docs/RUNBOOK.md
ADDED
|
@@ -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`
|