@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
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
name: copilot-setup-steps
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_dispatch:
|
|
5
|
+
push:
|
|
6
|
+
# Change "main" if your default branch is different.
|
|
7
|
+
branches:
|
|
8
|
+
- main
|
|
9
|
+
|
|
10
|
+
permissions:
|
|
11
|
+
contents: read
|
|
12
|
+
|
|
13
|
+
jobs:
|
|
14
|
+
copilot-setup-steps:
|
|
15
|
+
runs-on: ubuntu-latest
|
|
16
|
+
permissions:
|
|
17
|
+
contents: read
|
|
18
|
+
steps:
|
|
19
|
+
- name: Checkout
|
|
20
|
+
uses: actions/checkout@v4
|
|
21
|
+
|
|
22
|
+
- name: Setup Node.js
|
|
23
|
+
uses: actions/setup-node@v4
|
|
24
|
+
with:
|
|
25
|
+
node-version: "20"
|
|
26
|
+
cache: "npm"
|
|
27
|
+
cache-dependency-path: "fluent-mcp-extn/package-lock.json"
|
|
28
|
+
|
|
29
|
+
- name: Install dependencies
|
|
30
|
+
working-directory: fluent-mcp-extn
|
|
31
|
+
run: npm ci
|
|
32
|
+
|
|
33
|
+
- name: Build MCP extension server
|
|
34
|
+
working-directory: fluent-mcp-extn
|
|
35
|
+
run: npm run build
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Choose one authentication strategy.
|
|
2
|
+
# Strategy 1 (recommended for local dev): Fluent CLI profile
|
|
3
|
+
# FLUENT_PROFILE=HMDEV
|
|
4
|
+
# FLUENT_PROFILE_RETAILER=HM_TEST
|
|
5
|
+
|
|
6
|
+
# Strategy 2 (recommended for CI/runtime): OAuth
|
|
7
|
+
FLUENT_BASE_URL=https://YOUR_ACCOUNT.sandbox.api.fluentretail.com
|
|
8
|
+
FLUENT_RETAILER_ID=YOUR_RETAILER_ID
|
|
9
|
+
FLUENT_CLIENT_ID=YOUR_CLIENT_ID
|
|
10
|
+
FLUENT_CLIENT_SECRET=YOUR_CLIENT_SECRET
|
|
11
|
+
FLUENT_USERNAME=YOUR_USERNAME
|
|
12
|
+
FLUENT_PASSWORD=YOUR_PASSWORD
|
|
13
|
+
|
|
14
|
+
# Strategy 3 (optional): Token command
|
|
15
|
+
# FLUENT_BASE_URL=https://YOUR_ACCOUNT.sandbox.api.fluentretail.com
|
|
16
|
+
# FLUENT_RETAILER_ID=YOUR_RETAILER_ID
|
|
17
|
+
# TOKEN_COMMAND=vault read -field=token secret/fluent/client-dev
|
|
18
|
+
|
|
19
|
+
# Strategy 4 (optional): Static token
|
|
20
|
+
# FLUENT_BASE_URL=https://YOUR_ACCOUNT.sandbox.api.fluentretail.com
|
|
21
|
+
# FLUENT_RETAILER_ID=YOUR_RETAILER_ID
|
|
22
|
+
# FLUENT_ACCESS_TOKEN=YOUR_BEARER_TOKEN
|
|
23
|
+
|
|
24
|
+
# Optional resilience tuning
|
|
25
|
+
# FLUENT_REQUEST_TIMEOUT_MS=30000
|
|
26
|
+
# FLUENT_RETRY_ATTEMPTS=3
|
|
27
|
+
# FLUENT_RETRY_INITIAL_DELAY_MS=300
|
|
28
|
+
# FLUENT_RETRY_MAX_DELAY_MS=5000
|
|
29
|
+
# FLUENT_RETRY_FACTOR=2
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
# fluent-mcp-extn Handover for GitHub Copilot
|
|
2
|
+
|
|
3
|
+
This handover pack explains how to run `fluent-mcp-extn` with:
|
|
4
|
+
|
|
5
|
+
1. GitHub Copilot in VS Code (local MCP server)
|
|
6
|
+
2. GitHub Copilot coding agent on GitHub.com (repository MCP configuration)
|
|
7
|
+
|
|
8
|
+
Use the checklists below exactly in order for first-time setup.
|
|
9
|
+
|
|
10
|
+
## Dependencies
|
|
11
|
+
|
|
12
|
+
`fluent-mcp-extn` talks directly to Fluent APIs through `@fluentcommerce/fc-connect-sdk`.
|
|
13
|
+
|
|
14
|
+
- Runtime dependency on Fluent CLI: **No**
|
|
15
|
+
- Runtime dependency on the official `fluent mcp server --stdio`: **No**
|
|
16
|
+
- Optional Fluent CLI usage: **Yes**, only if your team chooses CLI-based helpers (for example profile workflows or smoke test shortcuts) — not required for normal MCP runtime
|
|
17
|
+
|
|
18
|
+
## What colleagues need locally
|
|
19
|
+
|
|
20
|
+
- Node.js 20+
|
|
21
|
+
- npm
|
|
22
|
+
- Access to Fluent credentials (profile, OAuth, token command, or static token)
|
|
23
|
+
- This repository checked out locally
|
|
24
|
+
|
|
25
|
+
## A) VS Code Copilot (local MCP server)
|
|
26
|
+
|
|
27
|
+
### Step-by-step setup
|
|
28
|
+
|
|
29
|
+
1) Build the server (from repository root):
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
cd fluent-mcp-extn
|
|
33
|
+
npm install
|
|
34
|
+
npm run build
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
2) Create local env file:
|
|
38
|
+
|
|
39
|
+
Copy `fluent-mcp-extn/docs/HANDOVER_ENV.example` to `fluent-mcp-extn/.env.local` and fill real values.
|
|
40
|
+
Both paths are relative to the repository root.
|
|
41
|
+
|
|
42
|
+
3) Configure MCP in VS Code workspace:
|
|
43
|
+
|
|
44
|
+
Copy `fluent-mcp-extn/docs/HANDOVER_VSCODE_MCP_JSON.example.json` to `.vscode/mcp.json` (relative to the repository root).
|
|
45
|
+
|
|
46
|
+
4) Restart VS Code window (or reload) so MCP config is re-read.
|
|
47
|
+
|
|
48
|
+
5) Start the MCP server in VS Code:
|
|
49
|
+
|
|
50
|
+
1. Run `MCP: List Servers`
|
|
51
|
+
2. Start `fluentMcpExtn`
|
|
52
|
+
3. Accept trust prompt
|
|
53
|
+
4. Run `MCP: Reset Cached Tools` if tools are stale after upgrades
|
|
54
|
+
|
|
55
|
+
6) Verify in Copilot chat (agent mode), run:
|
|
56
|
+
|
|
57
|
+
1. `config.validate`
|
|
58
|
+
2. `health.ping`
|
|
59
|
+
3. `graphql.query` with `query { __typename }`
|
|
60
|
+
|
|
61
|
+
Expected minimum:
|
|
62
|
+
|
|
63
|
+
- `config.validate` returns `ok: true`
|
|
64
|
+
- `health.ping` returns `status: "ok"`
|
|
65
|
+
- GraphQL test returns data without auth/config errors
|
|
66
|
+
|
|
67
|
+
If these pass, local setup is complete.
|
|
68
|
+
|
|
69
|
+
Operational behavior to know:
|
|
70
|
+
|
|
71
|
+
- read operations use retry/backoff for transient failures
|
|
72
|
+
- non-idempotent write operations do not auto-retry
|
|
73
|
+
- `graphql.query` disables retries automatically when the request is a mutation
|
|
74
|
+
|
|
75
|
+
### Updating after code changes
|
|
76
|
+
|
|
77
|
+
When `fluent-mcp-extn` is updated (new tools, bug fixes), rebuild from the repository root:
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
cd fluent-mcp-extn
|
|
81
|
+
npm install
|
|
82
|
+
npm run build
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
Then restart the MCP server in VS Code (`MCP: List Servers` → stop → start).
|
|
86
|
+
|
|
87
|
+
## B) GitHub Copilot coding agent (GitHub.com)
|
|
88
|
+
|
|
89
|
+
### Step-by-step setup
|
|
90
|
+
|
|
91
|
+
1) Create/use repository environment (for example `copilot`).
|
|
92
|
+
|
|
93
|
+
2) Add environment secrets/variables in that environment with names beginning `COPILOT_MCP_`, such as:
|
|
94
|
+
|
|
95
|
+
- `COPILOT_MCP_FLUENT_BASE_URL`
|
|
96
|
+
- `COPILOT_MCP_FLUENT_RETAILER_ID`
|
|
97
|
+
- `COPILOT_MCP_FLUENT_CLIENT_ID`
|
|
98
|
+
- `COPILOT_MCP_FLUENT_CLIENT_SECRET`
|
|
99
|
+
- `COPILOT_MCP_FLUENT_USERNAME`
|
|
100
|
+
- `COPILOT_MCP_FLUENT_PASSWORD`
|
|
101
|
+
|
|
102
|
+
The MCP config maps these names as bare strings in the `env` block. The Copilot coding agent automatically resolves each string value from the repository environment secret/variable of the same name — no `${{ secrets.X }}` syntax is needed.
|
|
103
|
+
|
|
104
|
+
3) Ensure build runs in agent environment:
|
|
105
|
+
|
|
106
|
+
Use `.github/workflows/copilot-setup-steps.yml` based on
|
|
107
|
+
`docs/HANDOVER_COPILOT_SETUP_STEPS.example.yml`.
|
|
108
|
+
|
|
109
|
+
The example includes both `workflow_dispatch` and `push` on `main` so setup can
|
|
110
|
+
be run manually and also pre-built on default-branch pushes. If your default
|
|
111
|
+
branch is not `main`, change it in the workflow file.
|
|
112
|
+
|
|
113
|
+
4) Add MCP configuration in repository Copilot coding agent settings:
|
|
114
|
+
|
|
115
|
+
Use the JSON in `docs/HANDOVER_GITHUB_REPO_MCP_CONFIG.example.json`.
|
|
116
|
+
|
|
117
|
+
This configuration uses `type: "local"` and explicitly allowlists tools.
|
|
118
|
+
|
|
119
|
+
5) Validate in a Copilot coding agent session:
|
|
120
|
+
|
|
121
|
+
- trigger an agent task in the repository
|
|
122
|
+
- open session logs and confirm MCP server start step succeeds
|
|
123
|
+
- confirm tools are discovered (for example `config.validate`, `graphql.query`)
|
|
124
|
+
|
|
125
|
+
### Updating after code changes
|
|
126
|
+
|
|
127
|
+
The `copilot-setup-steps.yml` workflow runs `npm ci && npm run build` automatically, so the agent always uses the latest committed code. No manual rebuild is needed on GitHub — just push the updated `fluent-mcp-extn/` source.
|
|
128
|
+
|
|
129
|
+
## Synchronous fulfilment options support
|
|
130
|
+
|
|
131
|
+
`graphql.query` supports live checkout-style synchronous fulfilment options calls, for example:
|
|
132
|
+
|
|
133
|
+
- `createFulfilmentOption(..., executionMode: AWAIT_ORCHESTRATION)`
|
|
134
|
+
|
|
135
|
+
Important runtime requirement:
|
|
136
|
+
|
|
137
|
+
- The target environment must have matching workflow(s), e.g. `FULFILMENT_OPTIONS::<type>`.
|
|
138
|
+
- If missing, you will get:
|
|
139
|
+
- `Workflow [FULFILMENT_OPTIONS::<type>] not found`
|
|
140
|
+
|
|
141
|
+
## Common first-run issues
|
|
142
|
+
|
|
143
|
+
- `sdk adapter: not configured`
|
|
144
|
+
- check env values are present and mapped correctly
|
|
145
|
+
- `AUTH_ERROR`
|
|
146
|
+
- verify client credentials/user password/token source
|
|
147
|
+
- `FLUENT_CLIENT_ID` is the Fluent **Account ID** (the same value used as `client_id` in the OAuth token request). Do not confuse it with a separate application client identifier.
|
|
148
|
+
- `Workflow [FULFILMENT_OPTIONS::<type>] not found`
|
|
149
|
+
- deploy matching fulfilment options workflow for the selected retailer/type
|
|
150
|
+
- webhook signature mismatch
|
|
151
|
+
- provide exact `rawBody` to `webhook.validate` (signature checks are byte-sensitive)
|
|
152
|
+
|
|
153
|
+
## Security notes
|
|
154
|
+
|
|
155
|
+
- Never commit real secrets to `.mcp.json`, `mcp.json`, or docs.
|
|
156
|
+
- Prefer `envFile` locally (`.env.local`) and secret-backed values in GitHub environments.
|
|
157
|
+
- Rotate credentials immediately if accidentally exposed.
|
|
158
|
+
|
|
159
|
+
## Files in this handover pack
|
|
160
|
+
|
|
161
|
+
- `HANDOVER_GITHUB_COPILOT.md` (this guide)
|
|
162
|
+
- `HANDOVER_ENV.example`
|
|
163
|
+
- `HANDOVER_VSCODE_MCP_JSON.example.json`
|
|
164
|
+
- `HANDOVER_GITHUB_REPO_MCP_CONFIG.example.json`
|
|
165
|
+
- `HANDOVER_COPILOT_SETUP_STEPS.example.yml`
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"mcpServers": {
|
|
3
|
+
"fluent-mcp-extn": {
|
|
4
|
+
"type": "local",
|
|
5
|
+
"command": "node",
|
|
6
|
+
"args": ["fluent-mcp-extn/dist/index.js"],
|
|
7
|
+
"tools": [
|
|
8
|
+
"config.validate",
|
|
9
|
+
"health.ping",
|
|
10
|
+
"event.build",
|
|
11
|
+
"event.send",
|
|
12
|
+
"event.get",
|
|
13
|
+
"event.list",
|
|
14
|
+
"graphql.query",
|
|
15
|
+
"batch.create",
|
|
16
|
+
"batch.send",
|
|
17
|
+
"batch.status",
|
|
18
|
+
"batch.batchStatus",
|
|
19
|
+
"batch.results"
|
|
20
|
+
],
|
|
21
|
+
"env": {
|
|
22
|
+
"FLUENT_BASE_URL": "COPILOT_MCP_FLUENT_BASE_URL",
|
|
23
|
+
"FLUENT_RETAILER_ID": "COPILOT_MCP_FLUENT_RETAILER_ID",
|
|
24
|
+
"FLUENT_CLIENT_ID": "COPILOT_MCP_FLUENT_CLIENT_ID",
|
|
25
|
+
"FLUENT_CLIENT_SECRET": "COPILOT_MCP_FLUENT_CLIENT_SECRET",
|
|
26
|
+
"FLUENT_USERNAME": "COPILOT_MCP_FLUENT_USERNAME",
|
|
27
|
+
"FLUENT_PASSWORD": "COPILOT_MCP_FLUENT_PASSWORD"
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -0,0 +1,299 @@
|
|
|
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
|