@josephyan/qingflow-app-user-mcp 0.2.0-beta.25 → 0.2.0-beta.27

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 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.25
6
+ npm install @josephyan/qingflow-app-user-mcp@0.2.0-beta.27
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.25 qingflow-app-user-mcp
12
+ npx -y -p @josephyan/qingflow-app-user-mcp@0.2.0-beta.27 qingflow-app-user-mcp
13
13
  ```
14
14
 
15
15
  Environment:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@josephyan/qingflow-app-user-mcp",
3
- "version": "0.2.0-beta.25",
3
+ "version": "0.2.0-beta.27",
4
4
  "description": "Operational end-user MCP for Qingflow records, tasks, comments, and directory workflows.",
5
5
  "license": "MIT",
6
6
  "type": "module",
package/pyproject.toml CHANGED
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "qingflow-mcp"
7
- version = "0.2.0b25"
7
+ version = "0.2.0b27"
8
8
  description = "User-authenticated MCP server for Qingflow"
9
9
  readme = "README.md"
10
10
  license = "MIT"
@@ -9,19 +9,8 @@ metadata:
9
9
 
10
10
  ## Overview
11
11
 
12
- This skill is a **router skill** for operational usage inside existing Qingflow apps.
13
-
14
- Use it when the request is operational, but you first need to decide which specialized skill should own it.
15
-
16
- This skill does **not** try to teach every detailed workflow itself.
17
- It routes to:
18
-
19
- - [$qingflow-record-crud](/Users/yanqidong/Documents/qingflow-next/.codex/skills/qingflow-record-crud/SKILL.md) for record browsing, detail lookup, create, update, and delete
20
- - [$qingflow-task-ops](/Users/yanqidong/Documents/qingflow-next/.codex/skills/qingflow-task-ops/SKILL.md) for task-center usage, comments, approvals, rollback, transfer, urge, and directory lookup
21
- - [$qingflow-record-analysis](/Users/yanqidong/Documents/qingflow-next/.codex/skills/qingflow-record-analysis/SKILL.md) for grouped analysis, ratios, rankings, trends, and final statistical conclusions
22
-
23
- Before operating on data, identify whether the task targets `test` or `prod` and read [references/environments.md](references/environments.md).
24
- If the user did not specify one, default to `prod`.
12
+ This skill is a lightweight router for operational Qingflow work.
13
+ Assumes MCP is connected, authenticated, and on the correct workspace.
25
14
 
26
15
  ## Default Paths
27
16
 
@@ -42,23 +31,19 @@ Route to exactly one of these specialized paths:
42
31
  ## Routing Rules
43
32
 
44
33
  - If the user does not know the target `app_key`, discover apps first with `app_list` or `app_search`, then route to the specialized skill
45
- - If the task is about browsing, reading, creating, updating, deleting, attachments, relations, or subtable writes, switch to `$qingflow-record-crud`
34
+ - If the task is about browsing, reading, creating, updating, deleting, attachments, relations, subtable writes, or member/department-field candidate lookup, switch to `$qingflow-record-crud`
46
35
  - If the task is about inbox, todo, cc, task-center workload, comments, approval, reject, rollback, transfer, urge, or directory lookup, switch to `$qingflow-task-ops`
47
36
  - If the task is about grouped distributions, ratios, rankings, trends, insights, or any final statistical conclusion, switch to `$qingflow-record-analysis`
48
37
  - If the MCP is not connected, authenticated, or bound to the right workspace, switch to `$qingflow-mcp-setup`
49
38
 
50
39
  ## Shared Preconditions
51
40
 
52
- - confirm environment first
53
- - ensure auth exists
54
- - ensure workspace is selected
55
41
  - prefer canonical app ids, record ids, task ids, and workflow node ids over guessed names
56
42
  - if a field or target is still ambiguous after schema/task lookup, ask the user to confirm from a short candidate list instead of guessing
57
43
  - if the task can stay read-only, do not write or act
58
44
 
59
45
  ## Resources
60
46
 
61
- - Environment switching: [references/environments.md](references/environments.md)
62
47
  - Record CRUD: [$qingflow-record-crud](/Users/yanqidong/Documents/qingflow-next/.codex/skills/qingflow-record-crud/SKILL.md)
63
48
  - Task center and workflow usage: [$qingflow-task-ops](/Users/yanqidong/Documents/qingflow-next/.codex/skills/qingflow-task-ops/SKILL.md)
64
49
  - Dedicated analysis workflow: [$qingflow-record-analysis](/Users/yanqidong/Documents/qingflow-next/.codex/skills/qingflow-record-analysis/SKILL.md)
@@ -7,15 +7,15 @@ metadata:
7
7
 
8
8
  # Qingflow Record Analysis
9
9
 
10
- Analysis tasks must start with `record_schema_get`.
11
- Use field_id-based DSLs only.
10
+ This skill is for final statistical conclusions only.
11
+ Assumes MCP is connected, authenticated, and on the correct workspace.
12
+ Analysis tasks must start with `record_schema_get`. Use field_id-based DSLs only.
12
13
 
13
14
  ## Step 1: `record_schema_get` → Step 2: build DSL → Step 3: `record_analyze`
14
15
 
15
16
  This is the ONLY execution order. Never skip step 1. Never call `record_analyze` without a schema.
16
17
 
17
- Tools: `record_schema_get`, `record_analyze`. Use `record_list`/`record_get` only for sample rows AFTER analysis, and treat those read paths as belonging to [$qingflow-record-crud](/Users/yanqidong/Documents/qingflow-next/.codex/skills/qingflow-record-crud/SKILL.md).
18
- Comments, approvals, rollback, transfer, urge, and directory lookup stay in [$qingflow-task-ops](/Users/yanqidong/Documents/qingflow-next/.codex/skills/qingflow-task-ops/SKILL.md), not in this analysis skill.
18
+ Core tools: `record_schema_get`, `record_analyze`. Use `record_list`/`record_get` only for post-analysis samples; task/comment work stays in [$qingflow-task-ops](/Users/yanqidong/Documents/qingflow-next/.codex/skills/qingflow-task-ops/SKILL.md).
19
19
 
20
20
  ---
21
21
 
@@ -74,56 +74,32 @@ Comments, approvals, rollback, transfer, urge, and directory lookup stay in [$qi
74
74
 
75
75
  ---
76
76
 
77
- ## COMPLETE DSL TEMPLATE copy, replace field_id, done
77
+ See [references/dsl-templates.md](references/dsl-templates.md) for complete copy-paste templates.
78
78
 
79
+ **Typical summary / distribution:**
79
80
  ```json
80
81
  {
81
- "app_key": "YOUR_APP_KEY",
82
- "dimensions": [
83
- { "field_id": FIELD_ID_FROM_SCHEMA, "alias": "维度名" }
84
- ],
85
- "metrics": [
86
- { "op": "count", "alias": "记录数" }
87
- ],
88
- "filters": [
89
- { "field_id": TIME_FIELD_ID, "op": "between", "value": ["2024-03-01", "2024-03-31"] }
90
- ],
91
- "sort": [
92
- { "by": "记录数", "order": "desc" }
93
- ],
82
+ "dimensions": [{ "field_id": FIELD_ID_FROM_SCHEMA, "alias": "维度名" }],
83
+ "metrics": [{ "op": "count", "alias": "记录数" }],
84
+ "sort": [{ "by": "记录数", "order": "desc" }],
94
85
  "limit": 50,
95
86
  "strict_full": true
96
87
  }
97
88
  ```
98
89
 
99
- More templates:
100
-
101
- **Whole-table count (no grouping):**
102
- ```json
103
- { "dimensions": [], "metrics": [{"op":"count","alias":"记录数"}], "strict_full": true }
104
- ```
105
-
106
- **Monthly trend:**
107
- ```json
108
- {
109
- "dimensions": [{"field_id": 3, "alias": "月份", "bucket":"month"}],
110
- "metrics": [{"op":"count","alias":"记录数"}],
111
- "sort": [{"by":"月份","order":"asc"}],
112
- "limit": 24, "strict_full": true
113
- }
114
- ```
115
-
116
- **Cross analysis with sum:**
90
+ **Typical time-filter / trend:**
117
91
  ```json
118
92
  {
119
- "dimensions": [{"field_id": 2, "alias": "状态"}, {"field_id": 5, "alias": "负责人"}],
120
- "metrics": [{"op":"count","alias":"记录数"}, {"op":"sum","field_id": 7, "alias":"总金额"}],
121
- "sort": [{"by":"记录数","order":"desc"}],
122
- "limit": 100, "strict_full": true
93
+ "dimensions": [{ "field_id": TIME_FIELD_ID, "alias": "月份", "bucket": "month" }],
94
+ "metrics": [{ "op": "count", "alias": "记录数" }],
95
+ "filters": [{ "field_id": TIME_FIELD_ID, "op": "between", "value": ["2024-03-01", "2024-03-31"] }],
96
+ "sort": [{ "by": "月份", "order": "asc" }],
97
+ "limit": 24,
98
+ "strict_full": true
123
99
  }
124
100
  ```
125
101
 
126
- ### Top-level arguments
102
+ Top-level arguments:
127
103
 
128
104
  - `app_key`: required.
129
105
  - `dimensions`: `[]` = whole-table summary; `[{...}]` = grouped.
@@ -136,12 +112,10 @@ More templates:
136
112
 
137
113
  ## RULES
138
114
 
139
- - Normalize relative time phrases into explicit legal date ranges.
140
115
  - 渗透率 / 转化率 / 占比类结论必须先定义分子和分母。
141
116
  - Do not claim a metric you did not query.
142
117
  - Derived ratios must be computed outside the DSL.
143
118
  - Before choosing a DSL shape, first decide whether the question needs `count`, `sum`, `avg`, `distinct_count`, `ratio`, or `ranking`.
144
- - If a field is still ambiguous after `record_schema_get`, do not guess; ask the user to confirm from a short candidate list.
145
119
  - Rankings must come from structured sorted results.
146
120
  - For partial answers, explicitly disclose which parts are complete and which parts remain unresolved.
147
121
  - Complex answers should default to `先结构、后解读`.
@@ -150,33 +124,25 @@ More templates:
150
124
  - Final wording should stay as close as possible to schema titles.
151
125
  - Do not pass field titles, aliases, or guessed ids.
152
126
  - If `completeness.statement_scope=returned_groups_only` or `completeness.rows_truncated=true`, downgrade wording to returned groups only.
153
- - All `field_id` MUST come from `record_schema_get`. Never guess or use field titles.
154
127
  - One DSL per question. Multiple small DSLs > one overloaded request.
155
- - Normalize relative dates to concrete ranges BEFORE building DSL. Never send impossible dates (e.g. `2026-02-29`).
156
- - If schema has ambiguous fields, ask user to pick from a short list. Do not guess.
157
128
  - `record_list` is NEVER the basis for final statistics.
158
- - Derived ratios: run numerator and denominator as separate DSLs, compute ratio in your reasoning.
159
129
  - Set `alias` for any metric you will sort by, compare, or quote.
160
130
 
161
131
  ---
162
132
 
163
- ## OUTPUT (CRITICAL — final answer must show concrete numbers)
164
-
165
- ### 必须逐行列出数据(硬性要求)
166
-
167
- final_answer MUST include a table with every row from `result.rows`:
168
-
169
- | {维度别名} | {指标别名} | 占比 |
170
- |------------|-----------|------|
171
- | {row.dimensions.X} | {row.metrics.Y} | {Y / total * 100}% |
172
-
173
- - 占比 = 行指标值 / `result.totals.metric_totals` 总值, 保留一位小数
174
- - 如 `metric_totals` 不存在, 用各行之和作分母
175
- - 超过 20 行展示 Top 20 并注明
176
- - 不得只写"共 N 种类型"而省略明细
177
-
178
- ### 结论分级
133
+ ## OUTPUT
179
134
 
135
+ - Final answer must show concrete numbers.
136
+ - If `result.rows` exists, list each returned row; if there are more than 20 rows, show Top 20 and say so.
137
+ - 占比 = 行指标值 / `result.totals.metric_totals` 总值;如 `metric_totals` 缺失,用各行之和作分母。
138
+ - Prefer the structured `ranking` block when it exists.
180
139
  - `safe_for_final_conclusion=true` → `全量可信结论`
181
- - 不完整 → `初步观察`
140
+ - Otherwise → `初步观察`
182
141
  - `rows_truncated=true` → 用 `前 N 个分组`, 不用 `全部`/`所有`
142
+
143
+ ## Resources
144
+
145
+ - DSL templates: [references/dsl-templates.md](references/dsl-templates.md)
146
+ - Analysis patterns: [references/analysis-patterns.md](references/analysis-patterns.md)
147
+ - Confidence reporting: [references/confidence-reporting.md](references/confidence-reporting.md)
148
+ - Analysis gotchas: [references/analysis-gotchas.md](references/analysis-gotchas.md)
@@ -0,0 +1,93 @@
1
+ # DSL Templates
2
+
3
+ Use these copy-paste templates after `record_schema_get`.
4
+
5
+ ## Whole-table summary
6
+
7
+ ```json
8
+ {
9
+ "dimensions": [],
10
+ "metrics": [
11
+ { "op": "count", "alias": "记录数" }
12
+ ],
13
+ "strict_full": true
14
+ }
15
+ ```
16
+
17
+ ## Distribution / ranking
18
+
19
+ ```json
20
+ {
21
+ "dimensions": [
22
+ { "field_id": 9500572, "alias": "报价类型" }
23
+ ],
24
+ "metrics": [
25
+ { "op": "count", "alias": "记录数" }
26
+ ],
27
+ "sort": [
28
+ { "by": "记录数", "order": "desc" }
29
+ ],
30
+ "limit": 50,
31
+ "strict_full": true
32
+ }
33
+ ```
34
+
35
+ ## Time-filtered distribution
36
+
37
+ ```json
38
+ {
39
+ "app_key": "YOUR_APP_KEY",
40
+ "dimensions": [
41
+ { "field_id": 9500572, "alias": "维度名" }
42
+ ],
43
+ "metrics": [
44
+ { "op": "count", "alias": "记录数" }
45
+ ],
46
+ "filters": [
47
+ { "field_id": 3, "op": "between", "value": ["2024-03-01", "2024-03-31"] }
48
+ ],
49
+ "sort": [
50
+ { "by": "记录数", "order": "desc" }
51
+ ],
52
+ "limit": 50,
53
+ "strict_full": true
54
+ }
55
+ ```
56
+
57
+ ## Monthly trend
58
+
59
+ ```json
60
+ {
61
+ "dimensions": [
62
+ { "field_id": 3, "alias": "月份", "bucket": "month" }
63
+ ],
64
+ "metrics": [
65
+ { "op": "count", "alias": "记录数" }
66
+ ],
67
+ "sort": [
68
+ { "by": "月份", "order": "asc" }
69
+ ],
70
+ "limit": 24,
71
+ "strict_full": true
72
+ }
73
+ ```
74
+
75
+ ## Cross analysis with sum
76
+
77
+ ```json
78
+ {
79
+ "dimensions": [
80
+ { "field_id": 2, "alias": "状态" },
81
+ { "field_id": 5, "alias": "负责人" }
82
+ ],
83
+ "metrics": [
84
+ { "op": "count", "alias": "记录数" },
85
+ { "op": "sum", "field_id": 7, "alias": "总金额" }
86
+ ],
87
+ "sort": [
88
+ { "by": "记录数", "order": "desc" }
89
+ ],
90
+ "limit": 100,
91
+ "strict_full": true
92
+ }
93
+ ```
@@ -9,44 +9,16 @@ metadata:
9
9
 
10
10
  ## Overview
11
11
 
12
- This skill is for **record CRUD only** inside existing Qingflow apps.
13
-
14
- Use it for:
15
-
16
- - record browsing
17
- - record detail lookup
18
- - record create / update / delete
19
- - attachment preflight before a write
20
- - relation/member/department lookup that directly supports a write
21
-
22
- Do **not** use this skill for:
23
-
24
- - grouped analysis, ratios, rankings, trends, or final statistical conclusions
25
- Switch to [$qingflow-record-analysis](/Users/yanqidong/Documents/qingflow-next/.codex/skills/qingflow-record-analysis/SKILL.md)
26
- - task-center workflow actions, comments, or directory-driven operational workflows
27
- Switch to [$qingflow-task-ops](/Users/yanqidong/Documents/qingflow-next/.codex/skills/qingflow-task-ops/SKILL.md)
28
-
29
- This skill assumes the MCP is already connected, authenticated, and bound to the correct workspace.
30
- If not, switch to [$qingflow-mcp-setup](/Users/yanqidong/.codex/skills/qingflow-mcp-setup/SKILL.md) first.
31
-
32
- Before operating on data, identify whether the task targets `test` or `prod` and read [references/environments.md](references/environments.md).
33
- If the user did not specify one, default to `prod`.
12
+ This skill is for record CRUD only inside existing Qingflow apps.
13
+ Assumes MCP is connected, authenticated, and on the correct workspace.
34
14
 
35
15
  ## Default Paths
36
16
 
37
17
  Use exactly one of these default paths:
38
18
 
39
- 1. Browse records
40
- `record_schema_get -> record_list`
41
-
42
- 2. Read one record
43
- `record_schema_get -> record_get`
44
-
45
- 3. Write records
46
- `record_schema_get -> record_write`
47
-
48
- 4. Analysis
49
- Switch to [$qingflow-record-analysis](/Users/yanqidong/Documents/qingflow-next/.codex/skills/qingflow-record-analysis/SKILL.md)
19
+ 1. Browse records: `record_schema_get -> record_list`
20
+ 2. Read one record: `record_schema_get -> record_get`
21
+ 3. Write records: `record_schema_get -> record_write`
50
22
 
51
23
  ## Core Tools
52
24
 
@@ -55,16 +27,14 @@ Use exactly one of these default paths:
55
27
  - `record_get`
56
28
  - `record_write`
57
29
 
58
- `record_schema_get` now returns the **current user's applicant-node schema only**:
59
-
60
- - only fields visible to the current user at the applicant node are returned
61
- - hidden fields are omitted entirely
62
- - missing fields should be treated as `当前用户在申请人节点下不可见/不可用`, not as a reason to guess a different field
30
+ `record_schema_get` only exposes the current user's applicant-node visible fields; if a field is missing, treat it as unavailable in the current permission scope.
63
31
 
64
32
  ## Supporting Tools
65
33
 
66
34
  - `app_list`
67
35
  - `app_search`
36
+ - `record_member_candidates`
37
+ - `record_department_candidates`
68
38
  - `directory_search`
69
39
  - `directory_list_internal_users`
70
40
  - `directory_list_internal_departments`
@@ -90,15 +60,7 @@ Use exactly one of these default paths:
90
60
  - Use `record_list` for browse/export/sample inspection only
91
61
  - Use `record_get` when `record_id` is known
92
62
  - `record_get` without explicit `columns` still returns only applicant-node visible fields; do not assume it exposes the full builder-side record
93
- - `record_list` accepts:
94
- - `columns`
95
- - `where`
96
- - `order_by`
97
- - `limit`
98
- - `page`
99
63
  - `record_list` and `record_get` may reject hidden-field `field_id`s because record tools now validate against the applicant-node visible schema only
100
- - `record_list` is **not** an analysis tool
101
- - If a request turns into grouped distributions, ratios, rankings, trends, or final statistical conclusions, switch to [$qingflow-record-analysis](/Users/yanqidong/Documents/qingflow-next/.codex/skills/qingflow-record-analysis/SKILL.md)
102
64
 
103
65
  ## Record Write Rules
104
66
 
@@ -108,51 +70,24 @@ Use `record_write` as the only default write tool.
108
70
 
109
71
  1. Run `record_schema_get`
110
72
  2. Decide whether the task is `insert`, `update`, or `delete`
111
- 3. Build SQL-like JSON clauses
112
- 4. Run `record_write`
113
- 5. If `ok=false`, explain `field_errors` first, then summarize blockers; do not report a write as executed
114
- 6. If `ok=true`, report the affected `record_id` or created resource
115
- 7. For important writes, keep `verify_write=true`
73
+ 3. For relation fields, read `target_app_key / target_app_name` from schema first
74
+ 4. For member fields with unknown ids, run `record_member_candidates`
75
+ 5. For department fields with unknown ids, run `record_department_candidates`
76
+ 6. Build SQL-like JSON clauses
77
+ 7. Run `record_write`
78
+ 8. If `ok=false`, explain `field_errors` first, then summarize blockers; do not report a write as executed
79
+ 9. If `ok=true`, report the affected `record_id` or created resource
80
+ 10. For important writes, keep `verify_write=true`
116
81
 
117
82
  ### SQL-like JSON DSL
118
83
 
119
84
  The DSL is clause-shaped like SQL, but it is **not raw SQL text**.
120
85
 
121
- #### Insert
122
-
123
- ```json
124
- {
125
- "operation": "insert",
126
- "values": [
127
- { "field_id": 12, "value": "测试客户" },
128
- { "field_id": 18, "value": 1000 }
129
- ],
130
- "submit_type": "submit",
131
- "verify_write": true
132
- }
133
- ```
134
-
135
- #### Update
136
-
137
- ```json
138
- {
139
- "operation": "update",
140
- "record_id": 123,
141
- "set": [
142
- { "field_id": 18, "value": 2000 }
143
- ],
144
- "verify_write": true
145
- }
146
- ```
147
-
148
- #### Delete
149
-
150
- ```json
151
- {
152
- "operation": "delete",
153
- "record_ids": [123, 124]
154
- }
155
- ```
86
+ | operation | required shape | compact example |
87
+ |-----------|----------------|-----------------|
88
+ | `insert` | `values` | `{"operation":"insert","values":[{"field_id":12,"value":"测试客户"}]}` |
89
+ | `update` | `record_id + set` | `{"operation":"update","record_id":123,"set":[{"field_id":18,"value":2000}]}` |
90
+ | `delete` | `record_id` or `record_ids` | `{"operation":"delete","record_ids":[123,124]}` |
156
91
 
157
92
  ### Write discipline
158
93
 
@@ -164,7 +99,9 @@ The DSL is clause-shaped like SQL, but it is **not raw SQL text**.
164
99
  - Do not use free-form `WHERE` updates or deletes
165
100
  - Do not auto-fill missing fields
166
101
  - Do not auto-resolve relation targets without first querying them
167
- - Do not assume `record_schema_get` is a builder/full-field schema. It is the current user's applicant-node visible schema only.
102
+ - Do not assume member display names resolve automatically; `record_member_candidates` returns ids, but direct name-to-id write is not automatic
103
+ - Do not assume department names resolve automatically; `record_department_candidates` returns ids, but direct name-to-id write is not automatic
104
+ - Do not assume `record_schema_get` is a builder/full-field schema.
168
105
 
169
106
  ## Response Interpretation
170
107
 
@@ -173,12 +110,10 @@ The DSL is clause-shaped like SQL, but it is **not raw SQL text**.
173
110
  - If `record_write` returns `ok=false`, the write was blocked and not executed
174
111
  - Prefer explaining `field_errors` before summarizing top-level blockers
175
112
  - If `record_write` returns `ok=true`, still check `verification` and `warnings` before claiming success
176
- - Treat `request_route` as the source of truth for live route debugging
177
113
  - Prefer canonical schema titles and aliases in your final wording
178
114
  - If only part of the requested work is completed, explicitly disclose which parts are done and which are not
179
115
 
180
116
  ## Resources
181
117
 
182
- - Environment switching: [references/environments.md](references/environments.md)
183
118
  - Record operation patterns: [references/record-patterns.md](references/record-patterns.md)
184
119
  - Data gotchas: [references/data-gotchas.md](references/data-gotchas.md)
@@ -9,29 +9,8 @@ metadata:
9
9
 
10
10
  ## Overview
11
11
 
12
- This skill is for **task-center and workflow usage operations** inside existing Qingflow apps.
13
-
14
- Use it for:
15
-
16
- - task-center browsing
17
- - headline task counts
18
- - grouped worksheet or workflow-node workload views
19
- - approve / reject / rollback / transfer / urge
20
- - record comments
21
- - directory lookup that supports task or comment actions
22
-
23
- Do **not** use this skill for:
24
-
25
- - record create / update / delete
26
- Switch to [$qingflow-record-crud](/Users/yanqidong/Documents/qingflow-next/.codex/skills/qingflow-record-crud/SKILL.md)
27
- - grouped analysis, ratios, rankings, trends, or final statistical conclusions
28
- Switch to [$qingflow-record-analysis](/Users/yanqidong/Documents/qingflow-next/.codex/skills/qingflow-record-analysis/SKILL.md)
29
-
30
- This skill assumes the MCP is already connected, authenticated, and bound to the correct workspace.
31
- If not, switch to [$qingflow-mcp-setup](/Users/yanqidong/.codex/skills/qingflow-mcp-setup/SKILL.md) first.
32
-
33
- Before operating on live work, identify whether the task targets `test` or `prod` and read [references/environments.md](references/environments.md).
34
- If the user did not specify one, default to `prod`.
12
+ This skill is for task-center and workflow usage operations only.
13
+ Assumes MCP is connected, authenticated, and on the correct workspace.
35
14
 
36
15
  ## Default Paths
37
16
 
@@ -143,6 +122,4 @@ Use exactly one of these default paths:
143
122
 
144
123
  ## Resources
145
124
 
146
- - Environment switching: [references/environments.md](references/environments.md)
147
125
  - Workflow and task usage actions: [references/workflow-usage.md](references/workflow-usage.md)
148
-
@@ -2,4 +2,4 @@ from __future__ import annotations
2
2
 
3
3
  __all__ = ["__version__"]
4
4
 
5
- __version__ = "0.2.0b25"
5
+ __version__ = "0.2.0b27"
@@ -1,5 +1,7 @@
1
1
  from __future__ import annotations
2
2
 
3
+ from datetime import date
4
+
3
5
  from mcp.server.fastmcp import FastMCP
4
6
 
5
7
  from .backend_client import BackendClient
@@ -23,25 +25,88 @@ from .tools.workspace_tools import WorkspaceTools
23
25
 
24
26
 
25
27
  def build_server() -> FastMCP:
28
+ today = date.today()
29
+ current_year = today.year
26
30
  server = FastMCP(
27
31
  "Qingflow MCP",
28
- instructions=(
29
- "Use auth_login first, then workspace_list and workspace_select. "
30
- "All resource tools operate with the logged-in user's Qingflow permissions.\n\n"
31
- "If app_key is unknown, use app_list or app_search first to discover current-user visible apps in the selected workspace. "
32
- "For analytics, use record_schema_get first, let the model build field_id-based DSL, "
33
- "then call record_analyze. record_analyze returns compact business-first output as query/result/ranking/ratios/completeness/presentation; use verbose only for route/debug details. "
34
- "record_schema_get returns the current user's applicant-node visible schema only; hidden fields are omitted and missing fields should be treated as not visible in the current permission scope. "
35
- "For operational record reads, use record_schema_get first, then record_list or record_get. "
36
- "For writes, use record_schema_get and then call record_write once; it performs internal preflight before any apply and refuses fields outside the applicant-node writable schema.\n\n"
37
- "Task Center (待办/已办) handling:\n"
38
- "- Use task_summary to get headline counts.\n"
39
- "- Use task_list for flat task browsing with task_box and flow_status.\n"
40
- "- Use task_facets when worksheet or workflow-node buckets matter.\n"
41
- "- Use task_mark_read to mark a specific task as read.\n"
42
- "- Use task_urge to send an urgent reminder for a pending task.\n"
43
- "- After identifying the exact task node and record, use task_approve, task_reject, task_rollback, or task_transfer as needed."
44
- ),
32
+ instructions=f"""Use this server for Qingflow operational workflows. Current date: `{today.isoformat()}`.
33
+
34
+ ## Authentication
35
+
36
+ Use `auth_login` first, then `workspace_list` and `workspace_select`.
37
+ All resource tools operate with the logged-in user's Qingflow permissions.
38
+
39
+ ## App Discovery
40
+
41
+ If `app_key` is unknown, use `app_list` or `app_search` first.
42
+
43
+ ## Schema-First Rule
44
+
45
+ Always call `record_schema_get` before `record_list`, `record_get`, `record_write`, or `record_analyze`.
46
+
47
+ - All `field_id` values must come from the schema response.
48
+ - Never guess field names or ids.
49
+
50
+ ## Schema Scope
51
+
52
+ `record_schema_get` returns the current user's applicant-node visible fields only.
53
+
54
+ - Hidden fields are omitted.
55
+ - Missing fields mean the field is not visible in the current permission scope.
56
+
57
+ ## Analytics Path
58
+
59
+ `record_schema_get -> record_analyze`
60
+
61
+ Use this DSL shape:
62
+
63
+ - `dimensions`: `{{field_id, alias, bucket}}`
64
+ - `metrics`: `{{op, field_id, alias}}`
65
+ - `filters`: `{{field_id, op, value}}`
66
+ - `sort`: `{{by, order}}`
67
+
68
+ Important key rules:
69
+
70
+ - Use `op`
71
+ - Do **not** use `type`
72
+ - Do **not** use `agg`
73
+ - Do **not** use `aggregation`
74
+ - Do **not** use `operator`
75
+
76
+ Analysis answers must include concrete numbers. When applicable, include percentages based on the returned totals.
77
+
78
+ ## Record CRUD Path
79
+
80
+ `record_schema_get -> record_list / record_get / record_write`
81
+
82
+ `record_write` uses SQL-like JSON clauses:
83
+
84
+ - `insert` -> `values`
85
+ - `update` -> `record_id + set`
86
+ - `delete` -> `record_id` or `record_ids`
87
+
88
+ - Read relation targets from `record_schema_get.target_app_key` / `target_app_name` before preparing relation writes.
89
+ - If a member or department field id is known but candidate ids are not, use `record_member_candidates` or `record_department_candidates` before `record_write`.
90
+
91
+ ## Task Center Path
92
+
93
+ `task_summary -> task_list / task_facets -> task action`
94
+
95
+ ## Time Handling
96
+
97
+ Normalize relative dates before building DSL.
98
+
99
+ - If the user says `3月` without a year, use the current year: `{current_year}`
100
+ - Convert month-only phrases into explicit legal date ranges
101
+ - Never send impossible dates such as `2026-02-29`
102
+
103
+ ## Environment
104
+
105
+ Default to `prod` unless the user explicitly specifies `test`.
106
+
107
+ ## Constraints
108
+
109
+ Avoid builder-side app or schema changes here.""",
45
110
  )
46
111
  sessions = SessionStore()
47
112
  backend = BackendClient()