@josephyan/qingflow-app-user-mcp 0.2.0-beta.18 → 0.2.0-beta.19
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 +2 -2
- package/package.json +1 -1
- package/pyproject.toml +1 -1
- package/skills/qingflow-record-analysis/SKILL.md +34 -0
- package/skills/qingflow-record-analysis/references/analysis-gotchas.md +66 -0
- package/skills/qingflow-record-analysis/references/analysis-patterns.md +41 -4
- package/skills/qingflow-record-analysis/references/confidence-reporting.md +30 -0
- package/src/qingflow_mcp/__init__.py +1 -1
- package/src/qingflow_mcp/tools/record_tools.py +294 -1062
package/README.md
CHANGED
|
@@ -3,13 +3,13 @@
|
|
|
3
3
|
Install:
|
|
4
4
|
|
|
5
5
|
```bash
|
|
6
|
-
npm install @josephyan/qingflow-app-user-mcp@0.2.0-beta.
|
|
6
|
+
npm install @josephyan/qingflow-app-user-mcp@0.2.0-beta.19
|
|
7
7
|
```
|
|
8
8
|
|
|
9
9
|
Run:
|
|
10
10
|
|
|
11
11
|
```bash
|
|
12
|
-
npx -y -p @josephyan/qingflow-app-user-mcp@0.2.0-beta.
|
|
12
|
+
npx -y -p @josephyan/qingflow-app-user-mcp@0.2.0-beta.19 qingflow-app-user-mcp
|
|
13
13
|
```
|
|
14
14
|
|
|
15
15
|
Environment:
|
package/package.json
CHANGED
package/pyproject.toml
CHANGED
|
@@ -29,6 +29,9 @@ Use `record_query(query_mode="list")` or `record_get` only when you need sample
|
|
|
29
29
|
- Analysis tasks must start with `record_schema_get`
|
|
30
30
|
- Build one or more small DSLs, then run `record_analyze` separately for each question
|
|
31
31
|
- DSL field references must use `field_id` only
|
|
32
|
+
- Normalize relative time phrases into explicit legal date ranges before building the DSL
|
|
33
|
+
- If the user asks for `最近一个完整自然月 / 上个月 / 最近30天 / 本季度 / 去年同期`, first convert that phrase into concrete dates, then verify the dates are legal before calling MCP
|
|
34
|
+
- Never send impossible dates such as `2026-02-29`; if the intended month is February 2026, the legal upper bound is `2026-02-28`
|
|
32
35
|
- If the schema still leaves multiple plausible fields, stop and ask the user to confirm from a short candidate list instead of guessing
|
|
33
36
|
- Do not keep retrying different guessed field names in a loop
|
|
34
37
|
- `record_query(list)` is never the basis for a final statistical conclusion
|
|
@@ -36,6 +39,14 @@ Use `record_query(query_mode="list")` or `record_get` only when you need sample
|
|
|
36
39
|
- Do not mix full totals from `record_analyze` with sample-only list observations as one combined `全量结论`
|
|
37
40
|
- Do not manually tune paging or scan-budget parameters for analysis; `record_analyze` hides them
|
|
38
41
|
- For final conclusions, prefer `strict_full=true`
|
|
42
|
+
- Before choosing a DSL shape, first decide whether the question needs `count`, `sum`, `avg`, `distinct_count`, `ratio`, or `ranking`
|
|
43
|
+
- Do not guess a metric just because the user said `数量`, `单量`, `人数`, or `金额`
|
|
44
|
+
- If one business question depends on multiple metrics, split it into smaller structured questions and build multiple focused DSLs
|
|
45
|
+
- `渗透率 / 转化率 / 占比类结论必须先定义分子和分母`
|
|
46
|
+
- Do not claim a metric you did not query.
|
|
47
|
+
- Derived ratios must be computed outside the DSL after trusted numerator and denominator queries complete; do not invent `div`, `formula`, or expression metrics inside `record_analyze`
|
|
48
|
+
- If the requested business question requires unsupported derived math, split it into multiple DSLs and compute the final ratio only in the reasoning layer after the source metrics are confirmed
|
|
49
|
+
- If the user asks for multiple conclusions and only part of them is completed reliably, explicitly disclose which parts are complete and which parts remain unresolved
|
|
39
50
|
|
|
40
51
|
## Standard Operating Order
|
|
41
52
|
|
|
@@ -52,6 +63,26 @@ For analysis:
|
|
|
52
63
|
- `样本观察`
|
|
53
64
|
- `待验证假设`
|
|
54
65
|
|
|
66
|
+
## Semantic Guardrails
|
|
67
|
+
|
|
68
|
+
- If the user asks for penetration, conversion, share-of-total, win rate, non-standard ratio, or any `%` metric, first write down:
|
|
69
|
+
- numerator definition
|
|
70
|
+
- denominator definition
|
|
71
|
+
- whether each side needs its own DSL
|
|
72
|
+
- If you cannot name the denominator from real schema fields and filters, do not use words like `渗透率`, `转化率`, `占比`, `比例`, or `%`
|
|
73
|
+
- If a field is still ambiguous after `record_schema_get`, do not guess; either select one unique `field_id` from the schema or ask the user to confirm from a short candidate list
|
|
74
|
+
- If a statement depends on `count`, query `count`
|
|
75
|
+
- If a statement depends on total amount, query `sum`
|
|
76
|
+
- If a statement depends on average level, query `avg` or derive it from trusted `sum + count`
|
|
77
|
+
- If a statement depends on trend, query a time dimension with `bucket`
|
|
78
|
+
- If a statement depends on a ratio that the DSL cannot express directly, run the numerator and denominator separately, then compute the ratio outside MCP only after both sides are complete and compatible
|
|
79
|
+
- Rankings must come from structured sorted results, not from loose natural-language restatement
|
|
80
|
+
- When grouped rows are truncated, describe them as `已返回分组中` or `主要分组`
|
|
81
|
+
- If `presentation.rows_truncated=true` or `presentation.statement_scope=returned_groups_only`, do not use words like `各部门`、`所有分组`、`完整名单`、`全部渠道`
|
|
82
|
+
- If grouped rows are truncated, explicitly downgrade the wording to `前 N 个分组` or `主要分组`, never `全部`
|
|
83
|
+
- Complex answers should default to `先结构、后解读`: present the table / metrics / ordering first, then add concise interpretation
|
|
84
|
+
- Final wording should stay as close as possible to schema titles, dimension aliases, and metric aliases; do not rename the business object or field title unless the user asked for a rewrite
|
|
85
|
+
|
|
55
86
|
## DSL Contract
|
|
56
87
|
|
|
57
88
|
Use `record_schema_get` as the source of truth for every DSL field reference:
|
|
@@ -125,6 +156,7 @@ Practical rules:
|
|
|
125
156
|
- For trend analysis, use one time dimension with `bucket`, then sort by that time alias ascending.
|
|
126
157
|
- For cross analysis, use multiple `dimensions` and a small set of metrics.
|
|
127
158
|
- Do not attempt formulas, joins, having clauses, cohort analysis, or manual paging controls in this DSL.
|
|
159
|
+
- Do not pass unsupported keys such as `formula`, `expr`, `numerator`, `denominator`, `left`, `right`, or `operator` inside metric items.
|
|
128
160
|
|
|
129
161
|
## Minimal DSL Templates
|
|
130
162
|
|
|
@@ -206,6 +238,8 @@ Two-dimensional cross analysis:
|
|
|
206
238
|
|
|
207
239
|
- Only write `全量可信结论` when the supporting `record_analyze` calls report `completeness.status=complete` and `safe_for_final_conclusion=true`
|
|
208
240
|
- If any key analysis call is incomplete, downgrade the answer to `初步观察` or `部分结果`
|
|
241
|
+
- Treat `safe_for_final_conclusion=true` as necessary but not sufficient when the metric definition is incomplete or grouped rows are truncated
|
|
242
|
+
- If `presentation.statement_scope=returned_groups_only`, you may still give full-population conclusions about totals or ratios, but not a full grouped enumeration claim
|
|
209
243
|
- If aggregate-style output is full but list evidence is sample-only, split the answer into:
|
|
210
244
|
- `全量可信结论`
|
|
211
245
|
- `样本观察(不作为最终结论)`
|
|
@@ -11,6 +11,16 @@ Correct recovery:
|
|
|
11
11
|
3. build one or more small DSLs
|
|
12
12
|
4. run `record_analyze`
|
|
13
13
|
|
|
14
|
+
## Normalize relative time phrases before building the DSL.
|
|
15
|
+
|
|
16
|
+
Examples:
|
|
17
|
+
|
|
18
|
+
- `最近一个完整自然月` -> convert to an explicit full-month date range
|
|
19
|
+
- `上个月` -> convert to a concrete month range
|
|
20
|
+
- `最近30天` -> convert to exact start/end dates
|
|
21
|
+
|
|
22
|
+
Do not pass vague time phrases or impossible dates into MCP.
|
|
23
|
+
|
|
14
24
|
## Do not treat 200-row list output as full data
|
|
15
25
|
|
|
16
26
|
`record_query(query_mode="list")` can hit:
|
|
@@ -39,6 +49,19 @@ Split them into:
|
|
|
39
49
|
- `全量可信结论`
|
|
40
50
|
- `样本观察`
|
|
41
51
|
|
|
52
|
+
## Do not present truncated grouped rows as a full grouped list
|
|
53
|
+
|
|
54
|
+
If `presentation.rows_truncated=true` or `presentation.statement_scope=returned_groups_only`:
|
|
55
|
+
|
|
56
|
+
- do not say `各部门`
|
|
57
|
+
- do not say `所有分组`
|
|
58
|
+
- do not say `完整名单`
|
|
59
|
+
|
|
60
|
+
Correct recovery:
|
|
61
|
+
|
|
62
|
+
- do not describe the answer as complete grouped coverage
|
|
63
|
+
- keep the wording inside the returned group scope
|
|
64
|
+
|
|
42
65
|
## Do not guess fields under ambiguity
|
|
43
66
|
|
|
44
67
|
If the field is uncertain:
|
|
@@ -73,3 +96,46 @@ When the result is incomplete:
|
|
|
73
96
|
1. narrow the scope with views or filters
|
|
74
97
|
2. reduce the analysis problem into smaller DSLs
|
|
75
98
|
3. keep the answer at `初步观察` or `部分结果` if completeness is still not enough
|
|
99
|
+
|
|
100
|
+
## Do not guess metric semantics from loose business wording
|
|
101
|
+
|
|
102
|
+
Before building the DSL, first decide whether the question needs:
|
|
103
|
+
|
|
104
|
+
- `count`
|
|
105
|
+
- `sum`
|
|
106
|
+
- `avg`
|
|
107
|
+
- `distinct_count`
|
|
108
|
+
- a ratio with numerator + denominator
|
|
109
|
+
- a sorted ranking result
|
|
110
|
+
|
|
111
|
+
Do not jump straight from words like `数量`, `人数`, `单量`, or `金额` to one assumed metric.
|
|
112
|
+
|
|
113
|
+
## Do not hide partial completion
|
|
114
|
+
|
|
115
|
+
If the user asked for several outputs and only part of them is stable:
|
|
116
|
+
|
|
117
|
+
- say which parts are complete
|
|
118
|
+
- say which parts are still unresolved
|
|
119
|
+
- do not present the answer as fully finished
|
|
120
|
+
|
|
121
|
+
## Do not send unsupported formula or div-style metrics into `record_analyze`.
|
|
122
|
+
|
|
123
|
+
Examples to avoid:
|
|
124
|
+
|
|
125
|
+
- `{"op":"div", ...}`
|
|
126
|
+
- metric items with `formula`, `expr`, `numerator`, or `denominator`
|
|
127
|
+
|
|
128
|
+
Correct recovery:
|
|
129
|
+
|
|
130
|
+
1. query the source metrics with separate DSLs
|
|
131
|
+
2. confirm both sides are complete and compatible
|
|
132
|
+
3. compute the derived ratio outside MCP in the reasoning layer
|
|
133
|
+
|
|
134
|
+
## Do not call something a ratio without the denominator
|
|
135
|
+
|
|
136
|
+
If the user asks for penetration / conversion / 占比:
|
|
137
|
+
|
|
138
|
+
1. define numerator
|
|
139
|
+
2. define denominator
|
|
140
|
+
3. query both sides explicitly
|
|
141
|
+
4. only then compute and report the ratio
|
|
@@ -16,9 +16,10 @@ Use this skill when the user asks for:
|
|
|
16
16
|
## Canonical analysis sequence
|
|
17
17
|
|
|
18
18
|
1. `record_schema_get`
|
|
19
|
-
2.
|
|
20
|
-
3.
|
|
21
|
-
4. `
|
|
19
|
+
2. decide whether the question needs `count`, `sum`, `avg`, `distinct_count`, `ratio`, or `ranking`
|
|
20
|
+
3. build one or more field_id-based DSLs
|
|
21
|
+
4. `record_analyze`
|
|
22
|
+
5. `record_query(query_mode="list")` only for sample inspection
|
|
22
23
|
|
|
23
24
|
## Distribution / ratio pattern
|
|
24
25
|
|
|
@@ -34,6 +35,21 @@ Use this skill when the user asks for:
|
|
|
34
35
|
- `backend_total_count`
|
|
35
36
|
- `scanned_count`
|
|
36
37
|
- `safe_for_final_conclusion`
|
|
38
|
+
- `presentation.statement_scope`
|
|
39
|
+
7. If grouped rows are truncated, describe the answer as `主要分组` or `已返回分组中`, not `各部门` or `全部`
|
|
40
|
+
|
|
41
|
+
## penetration / conversion / share-of-total pattern
|
|
42
|
+
|
|
43
|
+
1. Run `record_schema_get`
|
|
44
|
+
2. Write down the business definition in plain language:
|
|
45
|
+
- numerator
|
|
46
|
+
- denominator
|
|
47
|
+
- grouping dimension, if any
|
|
48
|
+
3. Build separate DSLs when numerator and denominator are not the same filtered population
|
|
49
|
+
4. Query the numerator first
|
|
50
|
+
5. Query the denominator second
|
|
51
|
+
6. Only compute the ratio outside MCP after both source results are complete and use compatible scopes
|
|
52
|
+
7. If the denominator is missing, do not call the output `渗透率`, `转化率`, `占比`, or `%`
|
|
37
53
|
|
|
38
54
|
## Average / ranking pattern
|
|
39
55
|
|
|
@@ -43,7 +59,8 @@ Use this skill when the user asks for:
|
|
|
43
59
|
- `dimensions=[...]`
|
|
44
60
|
- `metrics=[count,sum]` or `metrics=[count,avg,min,max]`
|
|
45
61
|
4. Run `record_analyze`
|
|
46
|
-
5.
|
|
62
|
+
5. If the answer uses ranking language, make the ranking come from structured sorted results
|
|
63
|
+
6. Use list mode only to inspect examples after the aggregate result is understood
|
|
47
64
|
|
|
48
65
|
## Trend pattern
|
|
49
66
|
|
|
@@ -52,6 +69,7 @@ Use this skill when the user asks for:
|
|
|
52
69
|
3. Build a DSL with `bucket=day|week|month|quarter|year`
|
|
53
70
|
4. Run `record_analyze`
|
|
54
71
|
5. Treat the result as final only if `safe_for_final_conclusion=true`
|
|
72
|
+
6. If the user asked for a relative time phrase such as `最近一个完整自然月`, translate it into an explicit legal date range before building the DSL
|
|
55
73
|
|
|
56
74
|
## Sample inspection pattern
|
|
57
75
|
|
|
@@ -64,6 +82,17 @@ Only use `record_query(query_mode="list")` after schema/analyze when you need:
|
|
|
64
82
|
|
|
65
83
|
Never use list mode alone to justify final averages, shares, rankings, or regional distribution claims.
|
|
66
84
|
|
|
85
|
+
## Statement-to-query discipline
|
|
86
|
+
|
|
87
|
+
- If you want to say `单量低` or `volume low`, query `count`
|
|
88
|
+
- If you want to say `金额高`, query `sum`
|
|
89
|
+
- If you want to say `客单价高`, query `avg` or trusted `sum + count`
|
|
90
|
+
- If you want to say `增长` or `下降`, query a time bucket
|
|
91
|
+
- If you want to say `渗透率` or `占比`, query both numerator and denominator
|
|
92
|
+
- If you want to say `各部门` / `全部渠道` / `完整名单`, make sure `presentation.statement_scope=full_population` and `presentation.rows_truncated=false`
|
|
93
|
+
- If you want to say `Top N` or `排名`, make sure the result is explicitly sorted and the conclusion follows that returned order
|
|
94
|
+
- If the task is complex, default to `先结构、后解读`
|
|
95
|
+
|
|
67
96
|
## Ambiguous field recovery
|
|
68
97
|
|
|
69
98
|
If the user asks for something like “来源分布” or “类型占比” and the exact field is unclear:
|
|
@@ -74,3 +103,11 @@ If the user asks for something like “来源分布” or “类型占比” and
|
|
|
74
103
|
4. if multiple candidates are still plausible, ask the user to confirm which field they want
|
|
75
104
|
|
|
76
105
|
Do not keep retrying different guessed field names in a loop.
|
|
106
|
+
|
|
107
|
+
## Partial completion discipline
|
|
108
|
+
|
|
109
|
+
If the user asked for several conclusions and only some of them are fully supported:
|
|
110
|
+
|
|
111
|
+
1. state which parts are complete
|
|
112
|
+
2. state which parts are still unresolved
|
|
113
|
+
3. do not present the answer as fully complete
|
|
@@ -15,6 +15,8 @@ Only write `全量可信结论` when:
|
|
|
15
15
|
- `record_schema_get` was used
|
|
16
16
|
- the analysis path used one or more `record_analyze` calls
|
|
17
17
|
- every key analysis result has `safe_for_final_conclusion=true`
|
|
18
|
+
- `safe_for_final_conclusion=true is necessary but not sufficient`
|
|
19
|
+
- no key result depends on an invalid time phrase, an undefined denominator, or an unsupported derived metric
|
|
18
20
|
- the result is not just a capped list sample
|
|
19
21
|
|
|
20
22
|
## Sample observation gate
|
|
@@ -44,6 +46,34 @@ Instead:
|
|
|
44
46
|
- full totals and distributions go into `全量可信结论`
|
|
45
47
|
- illustrative rows go into `样本观察`
|
|
46
48
|
|
|
49
|
+
## Semantic gate
|
|
50
|
+
|
|
51
|
+
Even when `safe_for_final_conclusion=true`, do not overstate the answer if:
|
|
52
|
+
|
|
53
|
+
- the metric definition is incomplete
|
|
54
|
+
- the denominator was not queried
|
|
55
|
+
- the conclusion mentions trend but no time bucket was queried
|
|
56
|
+
- the conclusion mentions单量/volume but no `count` metric was queried
|
|
57
|
+
- the conclusion depends on a derived metric the DSL cannot natively express
|
|
58
|
+
- `presentation.statement_scope=returned_groups_only`
|
|
59
|
+
- `presentation.rows_truncated=true`
|
|
60
|
+
|
|
61
|
+
## Grouped enumeration gate
|
|
62
|
+
|
|
63
|
+
If grouped rows were truncated:
|
|
64
|
+
|
|
65
|
+
- do not call the grouped output `各部门`, `全部渠道`, `完整名单`, or `所有分组`
|
|
66
|
+
- use `已返回分组中`, `主要分组`, or `前 N 个分组`
|
|
67
|
+
- keep full-population statements only for metrics that still cover the full analyzed population
|
|
68
|
+
|
|
69
|
+
## Partial completion disclosure
|
|
70
|
+
|
|
71
|
+
If the user asked for multiple conclusions but only some are complete:
|
|
72
|
+
|
|
73
|
+
- explicitly disclose which parts are complete
|
|
74
|
+
- explicitly disclose which parts are not yet complete
|
|
75
|
+
- do not collapse the answer into one all-clear conclusion
|
|
76
|
+
|
|
47
77
|
## Example skeleton
|
|
48
78
|
|
|
49
79
|
### 全量可信结论
|