@josephyan/qingflow-app-builder-mcp 0.2.0-beta.27 → 0.2.0-beta.28
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-builder-mcp@0.2.0-beta.
|
|
6
|
+
npm install @josephyan/qingflow-app-builder-mcp@0.2.0-beta.28
|
|
7
7
|
```
|
|
8
8
|
|
|
9
9
|
Run:
|
|
10
10
|
|
|
11
11
|
```bash
|
|
12
|
-
npx -y -p @josephyan/qingflow-app-builder-mcp@0.2.0-beta.
|
|
12
|
+
npx -y -p @josephyan/qingflow-app-builder-mcp@0.2.0-beta.28 qingflow-app-builder-mcp
|
|
13
13
|
```
|
|
14
14
|
|
|
15
15
|
Environment:
|
package/package.json
CHANGED
package/pyproject.toml
CHANGED
|
@@ -53,6 +53,7 @@ Always call `record_schema_get` before `record_list`, `record_get`, `record_writ
|
|
|
53
53
|
|
|
54
54
|
- Hidden fields are omitted.
|
|
55
55
|
- Missing fields mean the field is not visible in the current permission scope.
|
|
56
|
+
- Read `fields` and `suggested_*` from the top level of the schema response.
|
|
56
57
|
|
|
57
58
|
## Analytics Path
|
|
58
59
|
|
|
@@ -79,6 +80,8 @@ Analysis answers must include concrete numbers. When applicable, include percent
|
|
|
79
80
|
|
|
80
81
|
`record_schema_get -> record_list / record_get / record_write`
|
|
81
82
|
|
|
83
|
+
- For `columns`, prefer `[{{field_id}}]`; bare integer field ids remain supported for compatibility.
|
|
84
|
+
|
|
82
85
|
`record_write` uses SQL-like JSON clauses:
|
|
83
86
|
|
|
84
87
|
- `insert` -> `values`
|
|
@@ -41,6 +41,7 @@ Always call `record_schema_get` before `record_list`, `record_get`, `record_writ
|
|
|
41
41
|
|
|
42
42
|
- Hidden fields are omitted.
|
|
43
43
|
- Missing fields mean the field is not visible in the current permission scope.
|
|
44
|
+
- Read `fields` and `suggested_*` from the top level of the schema response.
|
|
44
45
|
|
|
45
46
|
## Analytics Path
|
|
46
47
|
|
|
@@ -67,6 +68,8 @@ Analysis answers must include concrete numbers. When applicable, include percent
|
|
|
67
68
|
|
|
68
69
|
`record_schema_get -> record_list / record_get / record_write`
|
|
69
70
|
|
|
71
|
+
- For `columns`, prefer `[{{field_id}}]`; bare integer field ids remain supported for compatibility.
|
|
72
|
+
|
|
70
73
|
`record_write` uses SQL-like JSON clauses:
|
|
71
74
|
|
|
72
75
|
- `insert` -> `values`
|
|
@@ -269,7 +269,7 @@ class RecordTools(ToolBase):
|
|
|
269
269
|
def record_list(
|
|
270
270
|
profile: str = DEFAULT_PROFILE,
|
|
271
271
|
app_key: str = "",
|
|
272
|
-
columns: list[int] | None = None,
|
|
272
|
+
columns: list[JSONObject | int] | None = None,
|
|
273
273
|
where: list[JSONObject] | None = None,
|
|
274
274
|
order_by: list[JSONObject] | None = None,
|
|
275
275
|
limit: int = 50,
|
|
@@ -296,7 +296,7 @@ class RecordTools(ToolBase):
|
|
|
296
296
|
profile: str = DEFAULT_PROFILE,
|
|
297
297
|
app_key: str = "",
|
|
298
298
|
record_id: int = 0,
|
|
299
|
-
columns: list[int] | None = None,
|
|
299
|
+
columns: list[JSONObject | int] | None = None,
|
|
300
300
|
workflow_node_id: int | None = None,
|
|
301
301
|
output_profile: str = "normal",
|
|
302
302
|
) -> JSONObject:
|
|
@@ -389,23 +389,21 @@ class RecordTools(ToolBase):
|
|
|
389
389
|
"ok": True,
|
|
390
390
|
"status": "success",
|
|
391
391
|
"request_route": self._request_route_payload(context),
|
|
392
|
-
"
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
"
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
"type": applicant_node.type,
|
|
399
|
-
},
|
|
400
|
-
"view_resolution": _view_selection_payload(view_selection),
|
|
401
|
-
"fields": fields,
|
|
402
|
-
"suggested_dimensions": suggested_dimensions,
|
|
403
|
-
"suggested_metrics": suggested_metrics,
|
|
404
|
-
"suggested_time_fields": suggested_time_fields,
|
|
392
|
+
"app_key": app_key,
|
|
393
|
+
"schema_scope": "applicant_node",
|
|
394
|
+
"workflow_node": {
|
|
395
|
+
"workflow_node_id": applicant_node.workflow_node_id,
|
|
396
|
+
"name": applicant_node.name,
|
|
397
|
+
"type": applicant_node.type,
|
|
405
398
|
},
|
|
399
|
+
"view_resolution": _view_selection_payload(view_selection),
|
|
400
|
+
"fields": fields,
|
|
401
|
+
"suggested_dimensions": suggested_dimensions,
|
|
402
|
+
"suggested_metrics": suggested_metrics,
|
|
403
|
+
"suggested_time_fields": suggested_time_fields,
|
|
406
404
|
}
|
|
407
405
|
if output_profile == "verbose":
|
|
408
|
-
response["
|
|
406
|
+
response["field_count"] = len(fields)
|
|
409
407
|
return response
|
|
410
408
|
|
|
411
409
|
return self._run_record_tool(profile, runner)
|
|
@@ -605,7 +603,7 @@ class RecordTools(ToolBase):
|
|
|
605
603
|
*,
|
|
606
604
|
profile: str,
|
|
607
605
|
app_key: str,
|
|
608
|
-
columns: list[int],
|
|
606
|
+
columns: list[JSONObject | int],
|
|
609
607
|
where: list[JSONObject],
|
|
610
608
|
order_by: list[JSONObject],
|
|
611
609
|
limit: int,
|
|
@@ -617,10 +615,9 @@ class RecordTools(ToolBase):
|
|
|
617
615
|
normalized_output_profile = self._normalize_public_output_profile(output_profile)
|
|
618
616
|
if not app_key:
|
|
619
617
|
raise_tool_error(QingflowApiError.config_error("app_key is required"))
|
|
620
|
-
|
|
618
|
+
normalized_columns = _normalize_public_column_selectors(columns)
|
|
619
|
+
if not normalized_columns:
|
|
621
620
|
raise_tool_error(QingflowApiError.config_error("columns is required"))
|
|
622
|
-
if any(not isinstance(item, int) or item < 0 for item in columns):
|
|
623
|
-
raise_tool_error(QingflowApiError.config_error("columns must be a list of field_id integers"))
|
|
624
621
|
if limit <= 0:
|
|
625
622
|
raise_tool_error(QingflowApiError.config_error("limit must be positive"))
|
|
626
623
|
if page <= 0:
|
|
@@ -640,8 +637,8 @@ class RecordTools(ToolBase):
|
|
|
640
637
|
filters=self._normalize_record_list_where(where),
|
|
641
638
|
sorts=self._normalize_record_list_order_by(order_by),
|
|
642
639
|
max_rows=limit,
|
|
643
|
-
max_columns=len(
|
|
644
|
-
select_columns=
|
|
640
|
+
max_columns=len(normalized_columns),
|
|
641
|
+
select_columns=normalized_columns,
|
|
645
642
|
amount_column=None,
|
|
646
643
|
time_range={},
|
|
647
644
|
stat_policy={},
|
|
@@ -674,7 +671,7 @@ class RecordTools(ToolBase):
|
|
|
674
671
|
"result_amount": pagination.get("result_amount"),
|
|
675
672
|
},
|
|
676
673
|
"selection": {
|
|
677
|
-
"columns":
|
|
674
|
+
"columns": [_column_selector_payload(field_id) for field_id in normalized_columns],
|
|
678
675
|
"view": cast(JSONObject, raw["data"]).get("view"),
|
|
679
676
|
},
|
|
680
677
|
},
|
|
@@ -695,17 +692,16 @@ class RecordTools(ToolBase):
|
|
|
695
692
|
profile: str,
|
|
696
693
|
app_key: str,
|
|
697
694
|
record_id: int,
|
|
698
|
-
columns: list[int],
|
|
695
|
+
columns: list[JSONObject | int],
|
|
699
696
|
workflow_node_id: int | None,
|
|
700
697
|
output_profile: str,
|
|
701
698
|
) -> JSONObject:
|
|
702
699
|
normalized_output_profile = self._normalize_public_output_profile(output_profile)
|
|
703
700
|
if record_id <= 0:
|
|
704
701
|
raise_tool_error(QingflowApiError.config_error("record_id must be positive"))
|
|
705
|
-
|
|
706
|
-
raise_tool_error(QingflowApiError.config_error("columns must be a list of field_id integers"))
|
|
702
|
+
normalized_columns = _normalize_public_column_selectors(columns)
|
|
707
703
|
|
|
708
|
-
if
|
|
704
|
+
if normalized_columns:
|
|
709
705
|
raw = self.record_query(
|
|
710
706
|
profile=profile,
|
|
711
707
|
query_mode="record",
|
|
@@ -720,8 +716,8 @@ class RecordTools(ToolBase):
|
|
|
720
716
|
filters=[],
|
|
721
717
|
sorts=[],
|
|
722
718
|
max_rows=1,
|
|
723
|
-
max_columns=len(
|
|
724
|
-
select_columns=
|
|
719
|
+
max_columns=len(normalized_columns),
|
|
720
|
+
select_columns=normalized_columns,
|
|
725
721
|
amount_column=None,
|
|
726
722
|
time_range={},
|
|
727
723
|
stat_policy={},
|
|
@@ -742,7 +738,7 @@ class RecordTools(ToolBase):
|
|
|
742
738
|
"record_id": record_id,
|
|
743
739
|
"record": record_data.get("row"),
|
|
744
740
|
"selection": {
|
|
745
|
-
"columns":
|
|
741
|
+
"columns": [_column_selector_payload(field_id) for field_id in normalized_columns],
|
|
746
742
|
"workflow_node_id": workflow_node_id,
|
|
747
743
|
},
|
|
748
744
|
},
|
|
@@ -5262,6 +5258,28 @@ def _extract_sort_selector(item: JSONObject) -> JSONValue:
|
|
|
5262
5258
|
return None
|
|
5263
5259
|
|
|
5264
5260
|
|
|
5261
|
+
def _normalize_public_column_selectors(columns: list[JSONObject | int]) -> list[int]:
|
|
5262
|
+
normalized: list[int] = []
|
|
5263
|
+
for item in columns:
|
|
5264
|
+
field_id: int | None = None
|
|
5265
|
+
if isinstance(item, int):
|
|
5266
|
+
field_id = item
|
|
5267
|
+
elif isinstance(item, dict):
|
|
5268
|
+
field_id = _coerce_count(item.get("field_id", item.get("fieldId")))
|
|
5269
|
+
if field_id is None or field_id < 0:
|
|
5270
|
+
raise_tool_error(
|
|
5271
|
+
QingflowApiError.config_error(
|
|
5272
|
+
"columns must be a list of field_id integers or {field_id} objects"
|
|
5273
|
+
)
|
|
5274
|
+
)
|
|
5275
|
+
normalized.append(field_id)
|
|
5276
|
+
return normalized
|
|
5277
|
+
|
|
5278
|
+
|
|
5279
|
+
def _column_selector_payload(field_id: int) -> JSONObject:
|
|
5280
|
+
return {"field_id": field_id}
|
|
5281
|
+
|
|
5282
|
+
|
|
5265
5283
|
def _resolve_sort_ascend(item: JSONObject) -> bool:
|
|
5266
5284
|
if "isAscend" in item:
|
|
5267
5285
|
return bool(item["isAscend"])
|