@fluentcommerce/fluent-mcp-extn 0.1.0 → 0.2.1
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 +823 -818
- package/dist/fluent-client.js +12 -12
- package/dist/tools.js +17 -0
- package/docs/CONTRIBUTING.md +100 -100
- package/docs/E2E_TESTING.md +739 -739
- package/docs/HANDOVER_ENV.example +29 -29
- package/docs/HANDOVER_GITHUB_COPILOT.md +165 -165
- package/docs/RUNBOOK.md +312 -312
- package/docs/TOOL_REFERENCE.md +1810 -1810
- package/package.json +68 -68
- package/docs/IMPLEMENTATION_GUIDE.md +0 -299
package/dist/fluent-client.js
CHANGED
|
@@ -149,19 +149,19 @@ export class FluentClientAdapter {
|
|
|
149
149
|
async queryPrometheus(payload) {
|
|
150
150
|
const isRange = payload.type === "range";
|
|
151
151
|
const query = isRange
|
|
152
|
-
? `query MetricRange($query: String!, $start: DateTime!, $end: DateTime!, $step: String!) {
|
|
153
|
-
metricRange(query: $query, start: $start, end: $end, step: $step) {
|
|
154
|
-
status
|
|
155
|
-
data { resultType result { metric values } }
|
|
156
|
-
errorType error warnings
|
|
157
|
-
}
|
|
152
|
+
? `query MetricRange($query: String!, $start: DateTime!, $end: DateTime!, $step: String!) {
|
|
153
|
+
metricRange(query: $query, start: $start, end: $end, step: $step) {
|
|
154
|
+
status
|
|
155
|
+
data { resultType result { metric values } }
|
|
156
|
+
errorType error warnings
|
|
157
|
+
}
|
|
158
158
|
}`
|
|
159
|
-
: `query MetricInstant($query: String!${payload.time ? ", $time: DateTime" : ""}) {
|
|
160
|
-
metricInstant(query: $query${payload.time ? ", time: $time" : ""}) {
|
|
161
|
-
status
|
|
162
|
-
data { resultType result { metric value } }
|
|
163
|
-
errorType error warnings
|
|
164
|
-
}
|
|
159
|
+
: `query MetricInstant($query: String!${payload.time ? ", $time: DateTime" : ""}) {
|
|
160
|
+
metricInstant(query: $query${payload.time ? ", time: $time" : ""}) {
|
|
161
|
+
status
|
|
162
|
+
data { resultType result { metric value } }
|
|
163
|
+
errorType error warnings
|
|
164
|
+
}
|
|
165
165
|
}`;
|
|
166
166
|
const variables = { query: payload.query };
|
|
167
167
|
if (isRange) {
|
package/dist/tools.js
CHANGED
|
@@ -193,6 +193,7 @@ const GraphQLBatchMutateInputSchema = z.object({
|
|
|
193
193
|
inputs: z.array(z.record(z.string(), z.unknown())).min(1).max(50),
|
|
194
194
|
returnFields: z.array(z.string()).optional(),
|
|
195
195
|
operationName: z.string().optional(),
|
|
196
|
+
dryRun: z.boolean().default(false),
|
|
196
197
|
});
|
|
197
198
|
const GraphQLIntrospectInputSchema = z.object({
|
|
198
199
|
type: z.string().optional(),
|
|
@@ -888,6 +889,10 @@ const TOOL_DEFINITIONS = [
|
|
|
888
889
|
type: "string",
|
|
889
890
|
description: "Custom GraphQL operation name (default: Batch<MutationName>s).",
|
|
890
891
|
},
|
|
892
|
+
dryRun: {
|
|
893
|
+
type: "boolean",
|
|
894
|
+
description: "If true, builds and validates the mutation query without executing it. Returns the query, variables, and input count for review. Default: false.",
|
|
895
|
+
},
|
|
891
896
|
},
|
|
892
897
|
required: ["mutation", "inputs"],
|
|
893
898
|
additionalProperties: false,
|
|
@@ -2540,6 +2545,18 @@ export function registerToolHandlers(server, ctx) {
|
|
|
2540
2545
|
for (let i = 0; i < batchSize; i++) {
|
|
2541
2546
|
variables[`input${i + 1}`] = parsed.inputs[i];
|
|
2542
2547
|
}
|
|
2548
|
+
// Dry-run: return query + variables without executing
|
|
2549
|
+
if (parsed.dryRun) {
|
|
2550
|
+
return json({
|
|
2551
|
+
ok: true,
|
|
2552
|
+
dryRun: true,
|
|
2553
|
+
mutation: parsed.mutation,
|
|
2554
|
+
inputCount: batchSize,
|
|
2555
|
+
query,
|
|
2556
|
+
variables,
|
|
2557
|
+
note: "No API call made. Set dryRun=false to execute.",
|
|
2558
|
+
});
|
|
2559
|
+
}
|
|
2543
2560
|
const gqlPayload = {
|
|
2544
2561
|
query,
|
|
2545
2562
|
variables: toSdkVariables(variables),
|
package/docs/CONTRIBUTING.md
CHANGED
|
@@ -1,100 +1,100 @@
|
|
|
1
|
-
# Contributing Guide
|
|
2
|
-
|
|
3
|
-
This guide defines how to safely change `fluent-mcp-extn` while keeping
|
|
4
|
-
behavior predictable for all clients.
|
|
5
|
-
|
|
6
|
-
## 1) Core principles
|
|
7
|
-
|
|
8
|
-
- Keep the extension **client-agnostic** (no client-specific names in code/docs).
|
|
9
|
-
- Prefer **typed boundaries** and avoid unscoped `any`.
|
|
10
|
-
- Keep tool responses consistent:
|
|
11
|
-
- success: `{ "ok": true, ... }`
|
|
12
|
-
- failure: `{ "ok": false, "error": { ... } }`
|
|
13
|
-
- Route Fluent API calls through `FluentClientAdapter` only.
|
|
14
|
-
|
|
15
|
-
## 2) Local setup
|
|
16
|
-
|
|
17
|
-
```bash
|
|
18
|
-
npm install
|
|
19
|
-
npm run build
|
|
20
|
-
npm test
|
|
21
|
-
```
|
|
22
|
-
|
|
23
|
-
## 3) Change workflow
|
|
24
|
-
|
|
25
|
-
1. Make focused changes.
|
|
26
|
-
2. Add or update tests.
|
|
27
|
-
3. Run `npm run build`.
|
|
28
|
-
4. Run `npm test`.
|
|
29
|
-
5. Run `npm run e2e:smoke -- --skip-real-send` when touching tool runtime (requires `FLUENT_BASE_URL` + auth env, or `--profile`).
|
|
30
|
-
6. Update docs if tool behavior/config changed.
|
|
31
|
-
|
|
32
|
-
## 4) Adding a new tool (required checklist)
|
|
33
|
-
|
|
34
|
-
When adding a tool, update all of the following:
|
|
35
|
-
|
|
36
|
-
1. `src/tools.ts`
|
|
37
|
-
- add zod schema
|
|
38
|
-
- add `TOOL_DEFINITIONS` entry
|
|
39
|
-
- add handler branch
|
|
40
|
-
2. `src/index.ts`
|
|
41
|
-
- add tool name to startup log list
|
|
42
|
-
3. tests
|
|
43
|
-
- add/adjust unit tests in `test/`
|
|
44
|
-
4. docs
|
|
45
|
-
- update `docs/TOOL_REFERENCE.md`
|
|
46
|
-
- update `docs/E2E_TESTING.md` if smoke flow changes
|
|
47
|
-
|
|
48
|
-
## 5) Error handling standards
|
|
49
|
-
|
|
50
|
-
- Throw `ToolError` for domain/runtime failures.
|
|
51
|
-
- Do not return raw thrown errors directly.
|
|
52
|
-
- Let `toToolFailure()` convert unknown errors into normalized error payloads.
|
|
53
|
-
- Use specific error codes where possible (`AUTH_ERROR`, `VALIDATION_ERROR`, etc.).
|
|
54
|
-
|
|
55
|
-
## 6) Resilience standards
|
|
56
|
-
|
|
57
|
-
- Keep retry/timeout policy centralized via:
|
|
58
|
-
- `withTimeout()`
|
|
59
|
-
- `withRetry()`
|
|
60
|
-
- Avoid per-tool custom retry loops.
|
|
61
|
-
- Use config-driven values (`FLUENT_REQUEST_TIMEOUT_MS`, retry env vars).
|
|
62
|
-
- Preserve idempotency boundaries:
|
|
63
|
-
- read operations can use retry/backoff
|
|
64
|
-
- non-idempotent write operations must not auto-retry
|
|
65
|
-
- Keep SDK retry disabled and adapter retry as the single control plane.
|
|
66
|
-
|
|
67
|
-
## 7) Security and secrets
|
|
68
|
-
|
|
69
|
-
- Never log secrets or token values.
|
|
70
|
-
- Use redacted summaries via `toSafeConfigSummary()`.
|
|
71
|
-
- Prefer profile, `TOKEN_COMMAND`, or OAuth over static tokens in shared environments.
|
|
72
|
-
|
|
73
|
-
## 8) Documentation standards
|
|
74
|
-
|
|
75
|
-
- Keep docs concise and task-oriented.
|
|
76
|
-
- Include at least one valid request example when changing tool inputs.
|
|
77
|
-
- Update all cross-links in `README.md` when adding new docs.
|
|
78
|
-
- For behavior changes, update all affected docs end-to-end:
|
|
79
|
-
- `README.md`
|
|
80
|
-
- `docs/TOOL_REFERENCE.md`
|
|
81
|
-
- `docs/RUNBOOK.md`
|
|
82
|
-
- `docs/E2E_TESTING.md`
|
|
83
|
-
|
|
84
|
-
## 9) Pull request quality bar
|
|
85
|
-
|
|
86
|
-
A change is ready only if:
|
|
87
|
-
|
|
88
|
-
- build passes
|
|
89
|
-
- tests pass
|
|
90
|
-
- smoke runner passes (or is intentionally skipped with rationale)
|
|
91
|
-
- no lint errors introduced
|
|
92
|
-
- docs updated for behavior/interface changes
|
|
93
|
-
- no client-specific wording added
|
|
94
|
-
|
|
95
|
-
## 10) CI expectations
|
|
96
|
-
|
|
97
|
-
- CI workflow file: `.github/workflows/ci.yml`
|
|
98
|
-
- `build-and-test` must pass for every PR.
|
|
99
|
-
- `e2e-smoke` is manual (`workflow_dispatch`) and requires repository secrets.
|
|
100
|
-
|
|
1
|
+
# Contributing Guide
|
|
2
|
+
|
|
3
|
+
This guide defines how to safely change `fluent-mcp-extn` while keeping
|
|
4
|
+
behavior predictable for all clients.
|
|
5
|
+
|
|
6
|
+
## 1) Core principles
|
|
7
|
+
|
|
8
|
+
- Keep the extension **client-agnostic** (no client-specific names in code/docs).
|
|
9
|
+
- Prefer **typed boundaries** and avoid unscoped `any`.
|
|
10
|
+
- Keep tool responses consistent:
|
|
11
|
+
- success: `{ "ok": true, ... }`
|
|
12
|
+
- failure: `{ "ok": false, "error": { ... } }`
|
|
13
|
+
- Route Fluent API calls through `FluentClientAdapter` only.
|
|
14
|
+
|
|
15
|
+
## 2) Local setup
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npm install
|
|
19
|
+
npm run build
|
|
20
|
+
npm test
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## 3) Change workflow
|
|
24
|
+
|
|
25
|
+
1. Make focused changes.
|
|
26
|
+
2. Add or update tests.
|
|
27
|
+
3. Run `npm run build`.
|
|
28
|
+
4. Run `npm test`.
|
|
29
|
+
5. Run `npm run e2e:smoke -- --skip-real-send` when touching tool runtime (requires `FLUENT_BASE_URL` + auth env, or `--profile`).
|
|
30
|
+
6. Update docs if tool behavior/config changed.
|
|
31
|
+
|
|
32
|
+
## 4) Adding a new tool (required checklist)
|
|
33
|
+
|
|
34
|
+
When adding a tool, update all of the following:
|
|
35
|
+
|
|
36
|
+
1. `src/tools.ts`
|
|
37
|
+
- add zod schema
|
|
38
|
+
- add `TOOL_DEFINITIONS` entry
|
|
39
|
+
- add handler branch
|
|
40
|
+
2. `src/index.ts`
|
|
41
|
+
- add tool name to startup log list
|
|
42
|
+
3. tests
|
|
43
|
+
- add/adjust unit tests in `test/`
|
|
44
|
+
4. docs
|
|
45
|
+
- update `docs/TOOL_REFERENCE.md`
|
|
46
|
+
- update `docs/E2E_TESTING.md` if smoke flow changes
|
|
47
|
+
|
|
48
|
+
## 5) Error handling standards
|
|
49
|
+
|
|
50
|
+
- Throw `ToolError` for domain/runtime failures.
|
|
51
|
+
- Do not return raw thrown errors directly.
|
|
52
|
+
- Let `toToolFailure()` convert unknown errors into normalized error payloads.
|
|
53
|
+
- Use specific error codes where possible (`AUTH_ERROR`, `VALIDATION_ERROR`, etc.).
|
|
54
|
+
|
|
55
|
+
## 6) Resilience standards
|
|
56
|
+
|
|
57
|
+
- Keep retry/timeout policy centralized via:
|
|
58
|
+
- `withTimeout()`
|
|
59
|
+
- `withRetry()`
|
|
60
|
+
- Avoid per-tool custom retry loops.
|
|
61
|
+
- Use config-driven values (`FLUENT_REQUEST_TIMEOUT_MS`, retry env vars).
|
|
62
|
+
- Preserve idempotency boundaries:
|
|
63
|
+
- read operations can use retry/backoff
|
|
64
|
+
- non-idempotent write operations must not auto-retry
|
|
65
|
+
- Keep SDK retry disabled and adapter retry as the single control plane.
|
|
66
|
+
|
|
67
|
+
## 7) Security and secrets
|
|
68
|
+
|
|
69
|
+
- Never log secrets or token values.
|
|
70
|
+
- Use redacted summaries via `toSafeConfigSummary()`.
|
|
71
|
+
- Prefer profile, `TOKEN_COMMAND`, or OAuth over static tokens in shared environments.
|
|
72
|
+
|
|
73
|
+
## 8) Documentation standards
|
|
74
|
+
|
|
75
|
+
- Keep docs concise and task-oriented.
|
|
76
|
+
- Include at least one valid request example when changing tool inputs.
|
|
77
|
+
- Update all cross-links in `README.md` when adding new docs.
|
|
78
|
+
- For behavior changes, update all affected docs end-to-end:
|
|
79
|
+
- `README.md`
|
|
80
|
+
- `docs/TOOL_REFERENCE.md`
|
|
81
|
+
- `docs/RUNBOOK.md`
|
|
82
|
+
- `docs/E2E_TESTING.md`
|
|
83
|
+
|
|
84
|
+
## 9) Pull request quality bar
|
|
85
|
+
|
|
86
|
+
A change is ready only if:
|
|
87
|
+
|
|
88
|
+
- build passes
|
|
89
|
+
- tests pass
|
|
90
|
+
- smoke runner passes (or is intentionally skipped with rationale)
|
|
91
|
+
- no lint errors introduced
|
|
92
|
+
- docs updated for behavior/interface changes
|
|
93
|
+
- no client-specific wording added
|
|
94
|
+
|
|
95
|
+
## 10) CI expectations
|
|
96
|
+
|
|
97
|
+
- CI workflow file: `.github/workflows/ci.yml`
|
|
98
|
+
- `build-and-test` must pass for every PR.
|
|
99
|
+
- `e2e-smoke` is manual (`workflow_dispatch`) and requires repository secrets.
|
|
100
|
+
|