@qingflow-tech/qingflow-app-builder-mcp 1.0.11 → 1.0.13

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.
Files changed (59) hide show
  1. package/README.md +6 -3
  2. package/docs/local-agent-install.md +54 -3
  3. package/entry_point.py +1 -1
  4. package/npm/bin/qingflow-skills.mjs +5 -0
  5. package/npm/lib/runtime.mjs +304 -13
  6. package/npm/scripts/postinstall.mjs +1 -5
  7. package/package.json +3 -2
  8. package/pyproject.toml +1 -1
  9. package/skills/qingflow-app-builder/SKILL.md +12 -12
  10. package/skills/qingflow-app-builder/references/create-app.md +3 -3
  11. package/skills/qingflow-app-builder/references/environments.md +1 -1
  12. package/skills/qingflow-app-builder/references/gotchas.md +1 -1
  13. package/skills/qingflow-app-builder/references/public-surface-sync.md +75 -0
  14. package/skills/qingflow-app-builder/references/tool-selection.md +6 -5
  15. package/skills/qingflow-app-builder/references/update-views.md +1 -1
  16. package/skills/qingflow-app-builder-code-integrations/SKILL.md +3 -3
  17. package/skills/qingflow-app-builder-code-integrations/references/code-block.md +1 -1
  18. package/skills/qingflow-app-builder-code-integrations/references/q-linker.md +1 -1
  19. package/src/qingflow_mcp/__main__.py +6 -2
  20. package/src/qingflow_mcp/builder_facade/models.py +11 -0
  21. package/src/qingflow_mcp/builder_facade/service.py +1488 -288
  22. package/src/qingflow_mcp/cli/commands/builder.py +2 -2
  23. package/src/qingflow_mcp/cli/commands/exports.py +2 -2
  24. package/src/qingflow_mcp/cli/commands/imports.py +1 -1
  25. package/src/qingflow_mcp/cli/commands/record.py +91 -19
  26. package/src/qingflow_mcp/cli/context.py +0 -3
  27. package/src/qingflow_mcp/cli/formatters.py +206 -7
  28. package/src/qingflow_mcp/cli/main.py +47 -3
  29. package/src/qingflow_mcp/errors.py +43 -2
  30. package/src/qingflow_mcp/public_surface.py +21 -15
  31. package/src/qingflow_mcp/response_trim.py +74 -13
  32. package/src/qingflow_mcp/server.py +11 -9
  33. package/src/qingflow_mcp/server_app_builder.py +3 -2
  34. package/src/qingflow_mcp/server_app_user.py +19 -13
  35. package/src/qingflow_mcp/session_store.py +11 -7
  36. package/src/qingflow_mcp/solution/executor.py +112 -15
  37. package/src/qingflow_mcp/tools/ai_builder_tools.py +36 -11
  38. package/src/qingflow_mcp/tools/app_tools.py +184 -43
  39. package/src/qingflow_mcp/tools/approval_tools.py +196 -34
  40. package/src/qingflow_mcp/tools/auth_tools.py +92 -16
  41. package/src/qingflow_mcp/tools/code_block_tools.py +298 -40
  42. package/src/qingflow_mcp/tools/custom_button_tools.py +64 -10
  43. package/src/qingflow_mcp/tools/directory_tools.py +236 -72
  44. package/src/qingflow_mcp/tools/export_tools.py +244 -34
  45. package/src/qingflow_mcp/tools/file_tools.py +7 -3
  46. package/src/qingflow_mcp/tools/import_tools.py +336 -49
  47. package/src/qingflow_mcp/tools/navigation_tools.py +91 -12
  48. package/src/qingflow_mcp/tools/package_tools.py +118 -6
  49. package/src/qingflow_mcp/tools/portal_tools.py +39 -3
  50. package/src/qingflow_mcp/tools/qingbi_report_tools.py +116 -7
  51. package/src/qingflow_mcp/tools/record_tools.py +1067 -349
  52. package/src/qingflow_mcp/tools/resource_read_tools.py +188 -39
  53. package/src/qingflow_mcp/tools/role_tools.py +80 -9
  54. package/src/qingflow_mcp/tools/solution_tools.py +57 -15
  55. package/src/qingflow_mcp/tools/task_context_tools.py +569 -119
  56. package/src/qingflow_mcp/tools/task_tools.py +113 -29
  57. package/src/qingflow_mcp/tools/view_tools.py +106 -3
  58. package/src/qingflow_mcp/tools/workflow_tools.py +17 -1
  59. package/src/qingflow_mcp/tools/workspace_tools.py +71 -3
@@ -0,0 +1,75 @@
1
+ # Qingflow Core Public Surface Sync
2
+
3
+ Use this file as the maintenance baseline for the core Qingflow skills.
4
+ It is not a user-facing product spec. It exists to prevent skill drift.
5
+
6
+ ## Current Public Defaults
7
+
8
+ ### User data
9
+
10
+ - Read range first with `app_get`, then `record_browse_schema_get(view_id=...)`
11
+ - Treat `record_browse_schema_get.fields` as the selected Qingflow table view header schema; `record_access.fields` and `record_list` field selectors must stay aligned with it.
12
+ - Standard flows:
13
+ - analyze: `app_get -> record_browse_schema_get -> record_access -> Python`
14
+ - browse detail: `app_get -> record_browse_schema_get -> record_list / record_get`
15
+ - explicit export/download/Excel: `app_get -> choose view_id -> view_get -> record_export_*` or `record_export_direct`; export tools require explicit `view_id`
16
+ - insert: `record_insert_schema_get -> record_insert(items)`
17
+ - update: `record_get -> record_update`; use `record_update_schema_get` only for failure diagnosis or ambiguous writable-field routing
18
+
19
+ ### Tasks
20
+
21
+ - Discovery stays on `task_list`
22
+ - `task_list --query` uses backend search first and only applies local fallback when backend returns zero rows
23
+ - Public actions are:
24
+ - `approve`
25
+ - `reject`
26
+ - `rollback`
27
+ - `transfer`
28
+ - `urge`
29
+ - `save_only`
30
+ - `reject` requires `payload.audit_feedback`
31
+ - `save_only` requires non-empty `fields`
32
+ - `TASK_RUNTIME_CONSUMED_AFTER_ACTION` is a normal post-success warning when the current node runtime is consumed and `46001` appears on re-read
33
+
34
+ ### Builder
35
+
36
+ - Official package entry: `package_get`, `package_apply`
37
+ - Official builder writes:
38
+ - `app_schema_apply`
39
+ - `app_layout_apply`
40
+ - `app_flow_apply`
41
+ - `app_views_apply`
42
+ - `app_custom_buttons_apply`
43
+ - `app_associated_resources_apply`
44
+ - `app_charts_apply`
45
+ - `portal_apply`
46
+ - `app_publish_verify`
47
+ - `portal_apply` edit mode may omit `sections` for base-info-only updates
48
+ - `app_charts_apply.visibility` is a public capability and should be treated as a base-only visibility update
49
+ - Existing object parameter replacement should use `patch_views`, `patch_buttons`, `patch_resources`, and `patch_charts`; `upsert_*` is for creation or full target config
50
+ - `app_get.editability` uses:
51
+ - `can_edit_app_base`
52
+ - `can_edit_form`
53
+ - `can_edit_flow`
54
+ - `can_edit_views`
55
+ - `can_edit_charts`
56
+
57
+ ## Known High-Drift Areas
58
+
59
+ - Task actions, especially `save_only`, reject payload requirements, and `46001` post-action interpretation
60
+ - Package public tools: do not regress to `package_create` / `package_attach_app` as the public default story
61
+ - App editability: do not let `can_edit_form` imply app base-info writes
62
+ - Portal and chart visibility: keep the public story on `portal_apply` / `app_charts_apply`, not low-level internal writes
63
+ - Analysis path: standard path stays `record_access -> Python`
64
+
65
+ ## Release Checklist For Skill Maintenance
66
+
67
+ After each beta that changes public behavior, re-check:
68
+
69
+ 1. `public_surface.py`
70
+ 2. `README.md`
71
+ 3. `server_app_builder.py` and `server.py` top-level guidance
72
+ 4. CLI help for `task`, `builder package`, `builder portal`, `builder charts`
73
+ 5. Whether new warnings or verification fields need to be explained in skills
74
+
75
+ If a tool behavior changed but the public surface did not, prefer updating the relevant skill section instead of expanding this file.
@@ -21,12 +21,12 @@ If the user asks for multiple forms/modules that relate to each other, this is a
21
21
 
22
22
  ## Resolve
23
23
 
24
- - `package_get`: read one known package by `package_id`
25
- - `package_apply`: create or update one package; use `create_if_missing=true` only after explicit user intent
24
+ - `package_get`: read one known package by `package_id`; it reads package `baseInfo` first and may warn `PACKAGE_DETAIL_READ_DEGRADED` when the richer detail endpoint needs package edit/add-app permission. Treat that warning as degraded detail, not as package-read failure.
25
+ - `package_apply`: create or update one package; use `create_if_missing=true` only after explicit user intent; layout/group/order changes require package edit permission because they call the backend package ordering route
26
26
  - `member_search`: resolve named people from the directory
27
27
  - `role_search`: resolve reusable roles from the directory
28
28
  - `role_create`: create a reusable role when the business owner wants role-based routing
29
- - `app_resolve`: locate an existing app by exactly one selector mode: `app_key`, or `app_name + package_id`
29
+ - `app_resolve`: locate an existing app by exactly one selector mode: `app_key`, or `app_name + package_id`; by-name resolution checks package detail/current visible apps before using broader admin-style app search, so a `/app/item` permission miss is not a frontend-visible-app failure
30
30
 
31
31
  ## Summary reads
32
32
 
@@ -36,6 +36,7 @@ If the user asks for multiple forms/modules that relate to each other, this is a
36
36
  - `app_get_views`: current view names, types, columns, group-by
37
37
  - `app_get_flow`: workflow enabled state, nodes, transitions
38
38
  - `app_get_charts`: current chart ids, names, types, order
39
+ - `chart_get`: one chart's base/config detail; base info is read through the Qingflow/qflow visible route first, and config may degrade from chart data when the CHART_SEE config endpoint is unavailable. Treat degraded config as a read-mode warning, not as proof the user cannot see the chart.
39
40
  - `portal_get`: current portal config detail and component inventory
40
41
 
41
42
  ## Apply tools
@@ -47,9 +48,9 @@ These execute normalized patches. Some app apply tools publish by default and st
47
48
  - `app_flow_apply`: replace workflow
48
49
  - `app_views_apply`: use `patch_views` for existing-view parameter replacement; use `upsert_views` for creation or full target config; remove views by key; new views default associated report/view display to visible with `limit_type="all"`
49
50
  - `app_custom_buttons_apply`: use `patch_buttons` for existing-button parameter replacement; use `upsert_buttons` for creation or full target config; configure add-data field mappings/default values; bind buttons to header/detail/list view positions; `placement=list` maps to the backend `INSIDE` row/list button position; merge-mode view configs require `buttons`; use `view_configs[].mode="replace"` or `buttons=[]` to clear a view's custom button bindings. For child-record creation linked to the current source record, map `source_field: "数据ID"` to the target relation field.
50
- - `app_associated_resources_apply`: attach existing BI reports/views to the Qingflow app associated-resource pool and per-view display area; it does not create or edit QingBI report bodies/configs. Use `patch_resources` for existing associated-resource parameter replacement; use `upsert_resources` for creation or full target config; `view_configs`, remove, and reorder may reference existing resources by internal `associated_item_id` or by `chart_id`/`chart_key`/`view_key`; use `match_mappings` for associated view/report filters; publishes after successful writes; omit raw `sourceType`, and use `report_source="dataset"` only to attach an existing BI dataset report. Before `upsert_resources`, read `app_get.associated_resources` and reuse an existing matching `target_app_key + view_key/chart_key`; repeated upsert can create duplicates because `client_key` is only valid inside one apply call.
51
+ - `app_associated_resources_apply`: attach existing BI reports/views to the Qingflow app associated-resource pool and per-view display area; it does not create or edit QingBI report bodies/configs. Permission is split like the backend: resource pool writes use EditAppAuth, while `view_configs` uses the view config/DataManageAuth path. Use `patch_resources` for existing associated-resource parameter replacement; use `upsert_resources` for creation or full target config; `view_configs`, remove, and reorder may reference existing resources by internal `associated_item_id` or by `chart_id`/`chart_key`/`view_key`; use `match_mappings` for associated view/report filters; publishes after successful writes; omit raw `sourceType`, and use `report_source="dataset"` only to attach an existing BI dataset report. Before `upsert_resources`, read `app_get.associated_resources` and reuse an existing matching `target_app_key + view_key/chart_key`; repeated upsert can create duplicates because `client_key` is only valid inside one apply call.
51
52
  - `app_charts_apply`: create/edit/remove/reorder app-source QingBI report bodies/configs with `dataSourceType=qingflow`; it does not create/edit dataset BI reports and does not attach reports to Qingflow app associated-resource display. Use `patch_charts` for existing-chart parameter replacement; use `upsert_charts` for creation or full target config; supports `target/table` aliases plus QingBI chart types such as `summary`, `columnar`, `area`, `funnel`, `radar`, `scatter`, `dualaxes`, and `map`; charts are immediate-live and do not publish; use `chart_id` when names are not unique
52
- - `portal_apply`: create or replace-update portal pages; use `dash_key` for update mode or `package_id + dash_name` for create mode; edit mode may omit `sections` for base-info-only updates; when sections are supplied they still use replace semantics
53
+ - `portal_apply`: create or replace-update portal pages; use `dash_key` for update mode or `package_id + dash_name` for create mode; create mode only prechecks package add_app, matching backend portal creation; edit mode may omit `sections` for base-info-only updates; when sections are supplied they still use replace semantics
53
54
 
54
55
  For object-level updates, the safe partial syntax is `patch_*` with the object's real selector field plus `set` and optional `unset`. `selector` is only a concept, not a literal key. Examples: `patch_views: [{"view_key": "VIEW_KEY", "set": {...}}]`, `patch_buttons: [{"button_id": 1001, "set": {...}}]`, `patch_resources: [{"associated_item_id": 123, "set": {...}}]`, `patch_charts: [{"chart_id": 456, "set": {...}}]`. The tool reads the current backend config, merges the patch, then submits the full backend payload internally. Do not send a partial `upsert_*` and expect missing required fields to be preserved.
55
56
 
@@ -31,7 +31,7 @@ Canonical rules before any example:
31
31
  - Use `filters` with canonical keys `field_name`, `operator`, `value`/`values`
32
32
  - Use `query_conditions` for the frontend query panel. Do not put query-panel fields into `filters`.
33
33
  - New views created by `app_views_apply` default the frontend associated report/view area to visible with `limit_type="all"`. Existing views preserve their current associated-resource display unless `associated_resources` is explicitly patched.
34
- - Use `app_associated_resources_apply` for the associated report/view resource pool, selected resources, and match rules. `associated_item_id` is the internal associated-resource id from `app_get.associated_resources`; `view_configs`, remove, and reorder may also pass an existing resource's `chart_id`/`chart_key`/`view_key`, which the tool resolves to the internal id. Do not write backend raw `sourceType`; reports default to BI app reports, and dataset reports use `report_source="dataset"`. Use `match_mappings` for associated view/report filters; read `match-rules.md` if field type compatibility is unclear.
34
+ - Use `app_associated_resources_apply` for the associated report/view resource pool, selected resources, and match rules. Permission is split like the backend: resource pool writes use EditAppAuth, while `view_configs` uses the view config/DataManageAuth path. `associated_item_id` is the internal associated-resource id from `app_get.associated_resources`; `view_configs`, remove, and reorder may also pass an existing resource's `chart_id`/`chart_key`/`view_key`, which the tool resolves to the internal id. Do not write backend raw `sourceType`; reports default to BI app reports, and dataset reports use `report_source="dataset"`. Use `match_mappings` for associated view/report filters; read `match-rules.md` if field type compatibility is unclear.
35
35
  - For gantt, use `start_field`, `end_field`, and optionally `title_field`
36
36
  - If `app_get.views` or `app_get_views` shows duplicate view names, include `view_key` in `upsert_views[]` and update that exact target
37
37
  - Builder view writes always use the raw `view_key` from `app_get.views[].view_key`, such as `emsrao25rs02`. Do not pass `custom:emsrao25rs02`; that prefixed form is only for record-data `view_id`.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: qingflow-app-builder-code-integrations
3
- description: Configure Qingflow code block and Q-Linker fields through the builder surface when the task involves input field insertion, alias parsing, target field binding, or troubleshooting broken code/q-linker form configurations. Use after MCP is connected and authenticated, especially for CRM-style scoring, lookup, and enrichment forms.
3
+ description: Configure Qingflow code block and Q-Linker fields through the builder surface when the task involves input field insertion, alias parsing, target field binding, or troubleshooting broken code/q-linker form configurations. In Wingent Momo runtime, use the injected MCP session and recover auth/workspace only after a tool error.
4
4
  metadata:
5
5
  short-description: Configure Qingflow code blocks and Q-Linkers safely
6
6
  ---
@@ -58,7 +58,7 @@ For code block or Q-Linker work, use this order:
58
58
 
59
59
  1. Resolve the app and read fields:
60
60
  - `app_resolve`
61
- - `app_read_fields`
61
+ - `app_get_fields`
62
62
  2. Confirm the target field set already exists.
63
63
  3. Apply schema updates with `app_schema_apply`.
64
64
  4. Read fields again and verify:
@@ -115,7 +115,7 @@ Hard rules:
115
115
 
116
116
  After each code block or Q-Linker change, verify all of these:
117
117
 
118
- - `app_read_fields` shows the intended field type
118
+ - `app_get_fields` shows the intended field type
119
119
  - the high-level config is readable and stable
120
120
  - target fields still have valid types
121
121
  - insert schema can be opened
@@ -59,7 +59,7 @@ Do not bind code block outputs to:
59
59
 
60
60
  ## Safe Verification
61
61
 
62
- - `app_read_fields`
62
+ - `app_get_fields`
63
63
  - `record_insert_schema_get`
64
64
  - optional `record_code_block_run`
65
65
 
@@ -70,7 +70,7 @@ Avoid:
70
70
 
71
71
  ## Safe Verification
72
72
 
73
- - `app_read_fields`
73
+ - `app_get_fields`
74
74
  - `record_insert_schema_get`
75
75
  - `record_insert`
76
76
 
@@ -1,5 +1,9 @@
1
- """Entry point for running qingflow_mcp as a module."""
2
- from qingflow_mcp.server import main
1
+ """Entry point for running qingflow_mcp as a module.
2
+
3
+ Default to the curated user-facing MCP surface. Split package and console
4
+ entrypoints can still start the builder server explicitly.
5
+ """
6
+ from qingflow_mcp.server_app_user import main
3
7
 
4
8
  if __name__ == "__main__":
5
9
  main()
@@ -1610,6 +1610,7 @@ class AssociatedResourcesApplyRequest(StrictModel):
1610
1610
  if not isinstance(value, dict):
1611
1611
  return value
1612
1612
  payload = dict(value)
1613
+ default_target_app_key = str(payload.get("app_key", payload.get("appKey", "")) or "").strip()
1613
1614
  if "upsertResources" in payload and "upsert_resources" not in payload:
1614
1615
  payload["upsert_resources"] = payload.pop("upsertResources")
1615
1616
  if "patchResources" in payload and "patch_resources" not in payload:
@@ -1622,6 +1623,16 @@ class AssociatedResourcesApplyRequest(StrictModel):
1622
1623
  payload["reorder_associated_item_ids"] = payload.pop("reorderAssociatedItemIds")
1623
1624
  if "viewConfigs" in payload and "view_configs" not in payload:
1624
1625
  payload["view_configs"] = payload.pop("viewConfigs")
1626
+ if default_target_app_key and isinstance(payload.get("upsert_resources"), list):
1627
+ normalized_resources = []
1628
+ for item in payload["upsert_resources"]:
1629
+ if isinstance(item, dict) and not any(
1630
+ str(item.get(key) or "").strip()
1631
+ for key in ("target_app_key", "targetAppKey", "app_key", "appKey")
1632
+ ):
1633
+ item = {**item, "target_app_key": default_target_app_key}
1634
+ normalized_resources.append(item)
1635
+ payload["upsert_resources"] = normalized_resources
1625
1636
  return payload
1626
1637
 
1627
1638
  @model_validator(mode="after")