@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,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,10 @@
1
+ {
2
+ "servers": {
3
+ "fluentMcpExtn": {
4
+ "type": "stdio",
5
+ "command": "node",
6
+ "args": ["${workspaceFolder}/fluent-mcp-extn/dist/index.js"],
7
+ "envFile": "${workspaceFolder}/fluent-mcp-extn/.env.local"
8
+ }
9
+ }
10
+ }
@@ -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