@fluentcommerce/fluent-mcp-extn 0.1.0 → 0.2.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 +0 -14
- package/docs/E2E_TESTING.md +8 -318
- package/docs/RUNBOOK.md +11 -90
- package/docs/TOOL_REFERENCE.md +35 -689
- package/package.json +1 -5
- package/docs/IMPLEMENTATION_GUIDE.md +0 -299
package/package.json
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fluentcommerce/fluent-mcp-extn",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "MCP (Model Context Protocol) extension server for Fluent Commerce. Exposes event dispatch, transition actions, GraphQL execution, Prometheus metrics, batch ingestion, and webhook validation as MCP tools.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
|
-
"types": "dist/index.d.ts",
|
|
8
7
|
"bin": {
|
|
9
8
|
"fluent-mcp-extn": "dist/index.js"
|
|
10
9
|
},
|
|
@@ -56,9 +55,6 @@
|
|
|
56
55
|
"@modelcontextprotocol/sdk": "^1.26.0",
|
|
57
56
|
"zod": "^4.3.6"
|
|
58
57
|
},
|
|
59
|
-
"publishConfig": {
|
|
60
|
-
"access": "public"
|
|
61
|
-
},
|
|
62
58
|
"devDependencies": {
|
|
63
59
|
"@types/node": "^25.2.3",
|
|
64
60
|
"tsx": "^4.21.0",
|
|
@@ -1,299 +0,0 @@
|
|
|
1
|
-
# Fluent MCP Extension - Implementation Guide
|
|
2
|
-
|
|
3
|
-
## 1) Why this project exists
|
|
4
|
-
|
|
5
|
-
This repository exists to provide a **client-agnostic extension layer** on top
|
|
6
|
-
of Fluent MCP capabilities without changing official Fluent tooling.
|
|
7
|
-
|
|
8
|
-
Key goals:
|
|
9
|
-
|
|
10
|
-
- keep `fluent-mcp` and Fluent CLI untouched (upgrade-safe)
|
|
11
|
-
- centralize custom tooling in one reusable service
|
|
12
|
-
- support multiple authentication strategies across environments
|
|
13
|
-
- improve reliability and observability for production usage
|
|
14
|
-
|
|
15
|
-
## 2) Why this should stay in its own repository
|
|
16
|
-
|
|
17
|
-
Keeping this extension separate from application/client repos is intentional.
|
|
18
|
-
|
|
19
|
-
- **Separation of concerns**: MCP tool runtime logic is independent from client
|
|
20
|
-
business workflows.
|
|
21
|
-
- **Independent release cadence**: auth/resilience/tooling updates can ship
|
|
22
|
-
without coupling to client app releases.
|
|
23
|
-
- **Multi-client reuse**: one codebase, environment-only customization.
|
|
24
|
-
- **Lower upgrade risk**: no forking or patching official SDK/CLI internals.
|
|
25
|
-
|
|
26
|
-
## 3) High-level architecture
|
|
27
|
-
|
|
28
|
-
The runtime is split into explicit layers across 15 source files:
|
|
29
|
-
|
|
30
|
-
### Core infrastructure
|
|
31
|
-
|
|
32
|
-
- `src/index.ts`
|
|
33
|
-
- entry point: loads config, initializes SDK client, starts MCP server
|
|
34
|
-
- `src/config.ts`
|
|
35
|
-
- reads env config
|
|
36
|
-
- applies defaults for timeout/retry values
|
|
37
|
-
- validates readiness (`config.validate`)
|
|
38
|
-
- `src/sdk-client.ts`
|
|
39
|
-
- creates SDK client
|
|
40
|
-
- resolves auth strategy (profile -> OAuth -> token command -> static token)
|
|
41
|
-
- includes temporary token bridge for command-based token refresh
|
|
42
|
-
- `src/fluent-client.ts`
|
|
43
|
-
- typed adapter over SDK client
|
|
44
|
-
- central execution path with idempotency-aware timeout/retry behavior
|
|
45
|
-
- `src/errors.ts`
|
|
46
|
-
- standard tool error codes and response format
|
|
47
|
-
- 9 typed error codes: `CONFIG_ERROR`, `AUTH_ERROR`, `VALIDATION_ERROR`,
|
|
48
|
-
`TIMEOUT_ERROR`, `RATE_LIMIT`, `UPSTREAM_UNAVAILABLE`, `NETWORK_ERROR`,
|
|
49
|
-
`SDK_ERROR`, `UNKNOWN_ERROR`
|
|
50
|
-
- `src/resilience.ts`
|
|
51
|
-
- `withTimeout` and `withRetry` primitives used by adapter
|
|
52
|
-
- `src/event-payload.ts`
|
|
53
|
-
- deterministic event payload builder
|
|
54
|
-
- `src/response-shaper.ts`
|
|
55
|
-
- auto-summarization engine for large API responses
|
|
56
|
-
- budget-based enforcement: prune nulls, cap arrays, summarize with record
|
|
57
|
-
counts, field inventories, value distributions, and sample records
|
|
58
|
-
|
|
59
|
-
### Tool definitions and handlers
|
|
60
|
-
|
|
61
|
-
- `src/tools.ts`
|
|
62
|
-
- MCP tool schemas and handlers (36 tools total: 25 core + 11 agentic)
|
|
63
|
-
- safe input parsing with `zod`
|
|
64
|
-
- normalized error responses
|
|
65
|
-
- all 36 tools registered in a single `TOOL_DEFINITIONS` array
|
|
66
|
-
|
|
67
|
-
### Entity layer (agentic)
|
|
68
|
-
|
|
69
|
-
- `src/entity-registry.ts`
|
|
70
|
-
- 12 entity types: ORDER, FULFILMENT, LOCATION, NETWORK, CUSTOMER, PRODUCT,
|
|
71
|
-
INVENTORY_POSITION, VIRTUAL_CATALOGUE, VIRTUAL_POSITION, CATEGORY, CARRIER,
|
|
72
|
-
SETTING
|
|
73
|
-
- required fields, compound keys, gotchas per entity type
|
|
74
|
-
- `src/entity-tools.ts`
|
|
75
|
-
- `entity.create`, `entity.update`, `entity.get` handlers
|
|
76
|
-
- status-aware updates with optional transition validation
|
|
77
|
-
|
|
78
|
-
### Workflow layer (agentic)
|
|
79
|
-
|
|
80
|
-
- `src/workflow-tools.ts`
|
|
81
|
-
- `workflow.upload` — deploy workflow JSON with structure validation
|
|
82
|
-
- `workflow.diff` — compare two workflow definitions (summary, detailed, mermaid)
|
|
83
|
-
- `workflow.simulate` — static prediction of event outcomes from workflow JSON
|
|
84
|
-
|
|
85
|
-
### Settings layer (agentic)
|
|
86
|
-
|
|
87
|
-
- `src/settings-tools.ts`
|
|
88
|
-
- `setting.upsert` — create-or-update with upsert semantics
|
|
89
|
-
- `setting.bulkUpsert` — batch upsert up to 50 settings
|
|
90
|
-
|
|
91
|
-
### Environment layer (agentic)
|
|
92
|
-
|
|
93
|
-
- `src/environment-tools.ts`
|
|
94
|
-
- `environment.discover` — full environment snapshot (retailer, locations,
|
|
95
|
-
networks, catalogues, workflows, settings, modules, users)
|
|
96
|
-
- `environment.validate` — pre-flight checks (auth, retailer, locations,
|
|
97
|
-
inventory, workflows, settings, modules)
|
|
98
|
-
|
|
99
|
-
### Test layer (agentic)
|
|
100
|
-
|
|
101
|
-
- `src/test-tools.ts`
|
|
102
|
-
- `test.assert` — entity state assertions with optional polling mode
|
|
103
|
-
|
|
104
|
-
## 4) End-to-end execution flow
|
|
105
|
-
|
|
106
|
-
### Startup flow
|
|
107
|
-
|
|
108
|
-
1. `src/index.ts` loads runtime config.
|
|
109
|
-
2. `initSDKClient()` creates SDK adapter using best auth strategy.
|
|
110
|
-
3. MCP server starts and registers all 36 tool handlers.
|
|
111
|
-
|
|
112
|
-
### Tool invocation flow
|
|
113
|
-
|
|
114
|
-
1. Tool input is validated by `zod` schema.
|
|
115
|
-
2. Business payload is built (for example, event payload assembly).
|
|
116
|
-
3. If API call is needed, tool goes through typed adapter.
|
|
117
|
-
4. Adapter applies policy by operation type:
|
|
118
|
-
- read paths: `withTimeout` + `withRetry`
|
|
119
|
-
- non-idempotent write paths: `withTimeout` only
|
|
120
|
-
5. Response is shaped through `response-shaper.ts` when budget is active.
|
|
121
|
-
6. Errors are normalized into a consistent payload format.
|
|
122
|
-
|
|
123
|
-
## 5) Authentication strategy and rationale
|
|
124
|
-
|
|
125
|
-
Auth strategy order is:
|
|
126
|
-
|
|
127
|
-
1. Fluent profile (`FLUENT_PROFILE`, optional `FLUENT_PROFILE_RETAILER`)
|
|
128
|
-
2. OAuth (`FLUENT_CLIENT_ID` + `FLUENT_CLIENT_SECRET`)
|
|
129
|
-
3. `TOKEN_COMMAND`
|
|
130
|
-
4. `FLUENT_ACCESS_TOKEN`
|
|
131
|
-
|
|
132
|
-
Why this order:
|
|
133
|
-
|
|
134
|
-
- Profile auth is preferred for local dev because it reuses Fluent CLI profile state.
|
|
135
|
-
- OAuth is preferred for CI/runtime because token lifecycle is managed by SDK.
|
|
136
|
-
- Command-based token retrieval supports vault and enterprise secret flows.
|
|
137
|
-
- Static token is a fallback for local/dev or temporary setups.
|
|
138
|
-
|
|
139
|
-
### Token command behavior
|
|
140
|
-
|
|
141
|
-
- accepts plain token output
|
|
142
|
-
- accepts JSON output with `access_token` or `token`
|
|
143
|
-
- enforces timeout via `TOKEN_COMMAND_TIMEOUT_MS`
|
|
144
|
-
- temporary bridge refreshes token when expiry window is reached
|
|
145
|
-
|
|
146
|
-
### Static token behavior
|
|
147
|
-
|
|
148
|
-
- static token mode (`FLUENT_ACCESS_TOKEN`) does not refresh automatically
|
|
149
|
-
- local expiry is intentionally long to avoid premature client-side invalidation
|
|
150
|
-
- true token validity remains enforced by Fluent API
|
|
151
|
-
|
|
152
|
-
## 6) Reliability model
|
|
153
|
-
|
|
154
|
-
Reliability settings are centralized in config:
|
|
155
|
-
|
|
156
|
-
- request timeout: `FLUENT_REQUEST_TIMEOUT_MS`
|
|
157
|
-
- retry attempts: `FLUENT_RETRY_ATTEMPTS`
|
|
158
|
-
- retry backoff:
|
|
159
|
-
- initial delay: `FLUENT_RETRY_INITIAL_DELAY_MS`
|
|
160
|
-
- max delay: `FLUENT_RETRY_MAX_DELAY_MS`
|
|
161
|
-
- factor: `FLUENT_RETRY_FACTOR`
|
|
162
|
-
|
|
163
|
-
This avoids per-tool custom retry logic and keeps behavior consistent.
|
|
164
|
-
|
|
165
|
-
Execution model:
|
|
166
|
-
|
|
167
|
-
- read operations retry transient failures using exponential backoff
|
|
168
|
-
- non-idempotent write operations are timeout-only (no automatic retry)
|
|
169
|
-
- `graphql.query` detects mutation operations and disables retries when needed
|
|
170
|
-
- `graphql.queryAll` uses pagination `timeoutMs` for whole-run timeout control
|
|
171
|
-
- SDK internal retries are disabled so adapter policy is authoritative
|
|
172
|
-
|
|
173
|
-
## 7) Response shaping model
|
|
174
|
-
|
|
175
|
-
Response shaping is controlled by three env vars:
|
|
176
|
-
|
|
177
|
-
- `FLUENT_RESPONSE_BUDGET_CHARS` (default 50000, ~12.5k tokens)
|
|
178
|
-
- `FLUENT_RESPONSE_MAX_ARRAY` (default 50)
|
|
179
|
-
- `FLUENT_RESPONSE_SAMPLE_SIZE` (default 3)
|
|
180
|
-
|
|
181
|
-
When a response exceeds the budget:
|
|
182
|
-
1. Null/empty values are stripped (protected keys like `ok`, `error`, `id`,
|
|
183
|
-
`ref`, `status` are preserved)
|
|
184
|
-
2. Arrays exceeding `maxArrayElements` are replaced with summaries containing
|
|
185
|
-
record count, field inventory, value distributions, and sample records
|
|
186
|
-
3. A `_responseMeta` object is attached with `originalChars`, `shapedChars`,
|
|
187
|
-
`reductionPercent`, and `summarizedArrays`
|
|
188
|
-
|
|
189
|
-
Design rationale: auto-summarize rather than truncate. Truncated arrays give
|
|
190
|
-
the LLM incomplete data it might trust. Summaries give a complete analytical
|
|
191
|
-
picture that is safe to reason from.
|
|
192
|
-
|
|
193
|
-
## 8) Error model
|
|
194
|
-
|
|
195
|
-
Tool responses standardize failures as:
|
|
196
|
-
|
|
197
|
-
```json
|
|
198
|
-
{
|
|
199
|
-
"ok": false,
|
|
200
|
-
"error": {
|
|
201
|
-
"code": "VALIDATION_ERROR",
|
|
202
|
-
"message": "Invalid tool arguments.",
|
|
203
|
-
"retryable": false,
|
|
204
|
-
"details": {}
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
```
|
|
208
|
-
|
|
209
|
-
Supported codes include:
|
|
210
|
-
|
|
211
|
-
- `CONFIG_ERROR`
|
|
212
|
-
- `AUTH_ERROR`
|
|
213
|
-
- `VALIDATION_ERROR`
|
|
214
|
-
- `TIMEOUT_ERROR`
|
|
215
|
-
- `RATE_LIMIT`
|
|
216
|
-
- `UPSTREAM_UNAVAILABLE`
|
|
217
|
-
- `NETWORK_ERROR`
|
|
218
|
-
- `SDK_ERROR`
|
|
219
|
-
- `UNKNOWN_ERROR`
|
|
220
|
-
|
|
221
|
-
Error classification uses HTTP status codes from error object properties first,
|
|
222
|
-
then Node.js error codes, then conservative keyword matching (never bare
|
|
223
|
-
substring matching on messages).
|
|
224
|
-
|
|
225
|
-
## 9) Tool inventory
|
|
226
|
-
|
|
227
|
-
36 tools across 12 categories:
|
|
228
|
-
|
|
229
|
-
| Category | Tools | Count |
|
|
230
|
-
|----------|-------|-------|
|
|
231
|
-
| Diagnostics | `config.validate`, `health.ping`, `connection.test` | 3 |
|
|
232
|
-
| Events | `event.build`, `event.send`, `event.get`, `event.list`, `event.flowInspect` | 5 |
|
|
233
|
-
| Metrics | `metrics.query`, `metrics.healthCheck`, `metrics.sloReport`, `metrics.labelCatalog`, `metrics.topEvents` | 5 |
|
|
234
|
-
| Orchestration | `workflow.transitions`, `plugin.list` | 2 |
|
|
235
|
-
| GraphQL | `graphql.query`, `graphql.queryAll`, `graphql.batchMutate`, `graphql.introspect` | 4 |
|
|
236
|
-
| Batch | `batch.create`, `batch.send`, `batch.status`, `batch.batchStatus`, `batch.results` | 5 |
|
|
237
|
-
| Webhook | `webhook.validate` | 1 |
|
|
238
|
-
| Entity | `entity.create`, `entity.update`, `entity.get` | 3 |
|
|
239
|
-
| Workflow | `workflow.upload`, `workflow.diff`, `workflow.simulate` | 3 |
|
|
240
|
-
| Settings | `setting.upsert`, `setting.bulkUpsert` | 2 |
|
|
241
|
-
| Environment | `environment.discover`, `environment.validate` | 2 |
|
|
242
|
-
| Test | `test.assert` | 1 |
|
|
243
|
-
|
|
244
|
-
## 10) Test coverage
|
|
245
|
-
|
|
246
|
-
256 tests across 14 test files (Vitest):
|
|
247
|
-
|
|
248
|
-
| Test file | Coverage area |
|
|
249
|
-
|-----------|--------------|
|
|
250
|
-
| `config.test.ts` | auth detection, validation, safe summary |
|
|
251
|
-
| `errors.test.ts` | error classification, HTTP status mapping, normalization |
|
|
252
|
-
| `event-payload.test.ts` | event payload builder defaults/overrides |
|
|
253
|
-
| `fluent-client.test.ts` | retry/no-retry idempotency, pagination, client validation |
|
|
254
|
-
| `metrics.test.ts` | metrics query, topEvents, sloReport, labelCatalog tools |
|
|
255
|
-
| `metrics-healthcheck.test.ts` | healthCheck anomaly detection and fallback logic |
|
|
256
|
-
| `resilience.test.ts` | withTimeout, withRetry, integration of both |
|
|
257
|
-
| `sdk-client.test.ts` | profile, OAuth, and null auth paths |
|
|
258
|
-
| `token-parser.test.ts` | command output token extraction |
|
|
259
|
-
| `tools-handlers.test.ts` | tool handler registration, input validation, error envelopes, flowInspect flag gating/cross-entity |
|
|
260
|
-
| `tools-helpers.test.ts` | event query params, transition request, mutation detection |
|
|
261
|
-
| `response-shaper.test.ts` | auto-summarization, null pruning, budget enforcement, connection summarizer |
|
|
262
|
-
| `simulation-tools.test.ts` | workflow.simulate direct handler tests, workflow.diff mermaid output |
|
|
263
|
-
| `agentic-tools.test.ts` | entity registry, entity CRUD, workflow upload/diff/simulate, settings upsert, environment discover/validate, test.assert |
|
|
264
|
-
|
|
265
|
-
Run with:
|
|
266
|
-
|
|
267
|
-
```bash
|
|
268
|
-
npm test
|
|
269
|
-
```
|
|
270
|
-
|
|
271
|
-
## 11) How to add a new tool safely
|
|
272
|
-
|
|
273
|
-
Recommended pattern:
|
|
274
|
-
|
|
275
|
-
1. add `zod` input schema in `src/tools.ts`
|
|
276
|
-
2. add tool metadata entry in `TOOL_DEFINITIONS`
|
|
277
|
-
3. implement handler in the appropriate module:
|
|
278
|
-
- entity operations: `src/entity-tools.ts`
|
|
279
|
-
- workflow operations: `src/workflow-tools.ts`
|
|
280
|
-
- settings operations: `src/settings-tools.ts`
|
|
281
|
-
- environment operations: `src/environment-tools.ts`
|
|
282
|
-
- test operations: `src/test-tools.ts`
|
|
283
|
-
- core operations: directly in `src/tools.ts` handler switch
|
|
284
|
-
4. for entity tools, add entity type to `src/entity-registry.ts` if new
|
|
285
|
-
5. return success payload via `json(...)`
|
|
286
|
-
6. rely on shared catch block for normalized errors
|
|
287
|
-
7. add focused unit tests for new logic
|
|
288
|
-
8. run `npm run build` and `npm test`
|
|
289
|
-
|
|
290
|
-
## 12) Known constraints and next improvements
|
|
291
|
-
|
|
292
|
-
Current bridge for `TOKEN_COMMAND` token injection is intentionally temporary
|
|
293
|
-
until the SDK exposes a first-class command/vault auth provider.
|
|
294
|
-
|
|
295
|
-
Next recommended enhancements:
|
|
296
|
-
|
|
297
|
-
- adopt SDK-native bearer/command auth provider once available
|
|
298
|
-
- add request correlation IDs in tool logs
|
|
299
|
-
- expand CI to enforce documentation integrity checks
|