@josephyan/qingflow-cli 0.2.0-beta.57 → 0.2.0-beta.59

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 (34) hide show
  1. package/README.md +3 -2
  2. package/docs/local-agent-install.md +9 -0
  3. package/npm/bin/qingflow.mjs +1 -1
  4. package/npm/lib/runtime.mjs +156 -21
  5. package/package.json +1 -1
  6. package/pyproject.toml +1 -1
  7. package/src/qingflow_mcp/builder_facade/service.py +137 -5
  8. package/src/qingflow_mcp/cli/commands/app.py +16 -16
  9. package/src/qingflow_mcp/cli/commands/auth.py +19 -16
  10. package/src/qingflow_mcp/cli/commands/builder.py +124 -162
  11. package/src/qingflow_mcp/cli/commands/common.py +21 -95
  12. package/src/qingflow_mcp/cli/commands/imports.py +42 -34
  13. package/src/qingflow_mcp/cli/commands/record.py +131 -133
  14. package/src/qingflow_mcp/cli/commands/task.py +43 -44
  15. package/src/qingflow_mcp/cli/commands/workspace.py +10 -10
  16. package/src/qingflow_mcp/cli/context.py +35 -32
  17. package/src/qingflow_mcp/cli/formatters.py +124 -121
  18. package/src/qingflow_mcp/cli/main.py +52 -17
  19. package/src/qingflow_mcp/server_app_builder.py +122 -190
  20. package/src/qingflow_mcp/server_app_user.py +63 -662
  21. package/src/qingflow_mcp/tools/solution_tools.py +95 -3
  22. package/src/qingflow_mcp/ops/__init__.py +0 -3
  23. package/src/qingflow_mcp/ops/apps.py +0 -64
  24. package/src/qingflow_mcp/ops/auth.py +0 -121
  25. package/src/qingflow_mcp/ops/base.py +0 -290
  26. package/src/qingflow_mcp/ops/builder.py +0 -323
  27. package/src/qingflow_mcp/ops/context.py +0 -120
  28. package/src/qingflow_mcp/ops/directory.py +0 -171
  29. package/src/qingflow_mcp/ops/feedback.py +0 -49
  30. package/src/qingflow_mcp/ops/files.py +0 -78
  31. package/src/qingflow_mcp/ops/imports.py +0 -140
  32. package/src/qingflow_mcp/ops/records.py +0 -415
  33. package/src/qingflow_mcp/ops/tasks.py +0 -171
  34. package/src/qingflow_mcp/ops/workspace.py +0 -76
@@ -4,9 +4,12 @@ from mcp.server.fastmcp import FastMCP
4
4
 
5
5
  from .backend_client import BackendClient
6
6
  from .config import DEFAULT_PROFILE
7
- from .ops.base import mcp_result_from_operation
8
- from .ops.context import build_operations_runtime
9
7
  from .session_store import SessionStore
8
+ from .tools.ai_builder_tools import AiBuilderTools
9
+ from .tools.auth_tools import AuthTools
10
+ from .tools.feedback_tools import FeedbackTools
11
+ from .tools.file_tools import FileTools
12
+ from .tools.workspace_tools import WorkspaceTools
10
13
 
11
14
 
12
15
  def build_builder_server() -> FastMCP:
@@ -30,7 +33,11 @@ def build_builder_server() -> FastMCP:
30
33
  )
31
34
  sessions = SessionStore()
32
35
  backend = BackendClient()
33
- runtime = build_operations_runtime(sessions=sessions, backend=backend, feedback_mcp_side="App Builder MCP")
36
+ auth = AuthTools(sessions, backend)
37
+ workspace = WorkspaceTools(sessions, backend)
38
+ files = FileTools(sessions, backend)
39
+ ai_builder = AiBuilderTools(sessions, backend)
40
+ feedback = FeedbackTools(backend, mcp_side="App Builder MCP")
34
41
 
35
42
  @server.tool()
36
43
  def auth_login(
@@ -41,15 +48,13 @@ def build_builder_server() -> FastMCP:
41
48
  password: str = "",
42
49
  persist: bool = True,
43
50
  ) -> dict:
44
- return mcp_result_from_operation(
45
- runtime.auth.login(
46
- profile=profile,
47
- base_url=base_url,
48
- qf_version=qf_version,
49
- email=email,
50
- password=password,
51
- persist=persist,
52
- )
51
+ return auth.auth_login(
52
+ profile=profile,
53
+ base_url=base_url,
54
+ qf_version=qf_version,
55
+ email=email,
56
+ password=password,
57
+ persist=persist,
53
58
  )
54
59
 
55
60
  @server.tool()
@@ -61,24 +66,22 @@ def build_builder_server() -> FastMCP:
61
66
  ws_id: int | None = None,
62
67
  persist: bool = False,
63
68
  ) -> dict:
64
- return mcp_result_from_operation(
65
- runtime.auth.use_token(
66
- profile=profile,
67
- base_url=base_url,
68
- qf_version=qf_version,
69
- token=token,
70
- ws_id=ws_id,
71
- persist=persist,
72
- )
69
+ return auth.auth_use_token(
70
+ profile=profile,
71
+ base_url=base_url,
72
+ qf_version=qf_version,
73
+ token=token,
74
+ ws_id=ws_id,
75
+ persist=persist,
73
76
  )
74
77
 
75
78
  @server.tool()
76
79
  def auth_whoami(profile: str = DEFAULT_PROFILE) -> dict:
77
- return mcp_result_from_operation(runtime.auth.me(profile=profile))
80
+ return auth.auth_whoami(profile=profile)
78
81
 
79
82
  @server.tool()
80
83
  def auth_logout(profile: str = DEFAULT_PROFILE, forget_persisted: bool = False) -> dict:
81
- return mcp_result_from_operation(runtime.auth.logout(profile=profile, forget_persisted=forget_persisted))
84
+ return auth.auth_logout(profile=profile, forget_persisted=forget_persisted)
82
85
 
83
86
  @server.tool()
84
87
  def workspace_list(
@@ -87,18 +90,16 @@ def build_builder_server() -> FastMCP:
87
90
  page_size: int = 20,
88
91
  include_external: bool = False,
89
92
  ) -> dict:
90
- return mcp_result_from_operation(
91
- runtime.workspace.list(
92
- profile=profile,
93
- page_num=page_num,
94
- page_size=page_size,
95
- include_external=include_external,
96
- )
93
+ return workspace.workspace_list(
94
+ profile=profile,
95
+ page_num=page_num,
96
+ page_size=page_size,
97
+ include_external=include_external,
97
98
  )
98
99
 
99
100
  @server.tool()
100
101
  def workspace_select(profile: str = DEFAULT_PROFILE, ws_id: int = 0) -> dict:
101
- return mcp_result_from_operation(runtime.workspace.use(profile=profile, ws_id=ws_id))
102
+ return workspace.workspace_select(profile=profile, ws_id=ws_id)
102
103
 
103
104
  @server.tool()
104
105
  def file_upload_local(
@@ -111,64 +112,34 @@ def build_builder_server() -> FastMCP:
111
112
  path_id: int | None = None,
112
113
  file_related_url: str | None = None,
113
114
  ) -> dict:
114
- return mcp_result_from_operation(
115
- runtime.files.upload_local(
116
- profile=profile,
117
- upload_kind=upload_kind,
118
- file_path=file_path,
119
- upload_mark=upload_mark,
120
- content_type=content_type,
121
- bucket_type=bucket_type,
122
- path_id=path_id,
123
- file_related_url=file_related_url,
124
- )
115
+ return files.file_upload_local(
116
+ profile=profile,
117
+ upload_kind=upload_kind,
118
+ file_path=file_path,
119
+ upload_mark=upload_mark,
120
+ content_type=content_type,
121
+ bucket_type=bucket_type,
122
+ path_id=path_id,
123
+ file_related_url=file_related_url,
125
124
  )
126
125
 
127
- @server.tool()
128
- def feedback_submit(
129
- category: str = "",
130
- title: str = "",
131
- description: str = "",
132
- expected_behavior: str | None = None,
133
- actual_behavior: str | None = None,
134
- impact_scope: str | None = None,
135
- tool_name: str | None = None,
136
- app_key: str | None = None,
137
- record_id: str | int | None = None,
138
- workflow_node_id: str | int | None = None,
139
- note: str | None = None,
140
- ) -> dict:
141
- return mcp_result_from_operation(
142
- runtime.feedback.submit(
143
- category=category,
144
- title=title,
145
- description=description,
146
- expected_behavior=expected_behavior,
147
- actual_behavior=actual_behavior,
148
- impact_scope=impact_scope,
149
- tool_name=tool_name,
150
- app_key=app_key,
151
- record_id=record_id,
152
- workflow_node_id=workflow_node_id,
153
- note=note,
154
- )
155
- )
126
+ feedback.register(server)
156
127
 
157
128
  @server.tool()
158
129
  def package_list(profile: str = DEFAULT_PROFILE, trial_status: str = "all") -> dict:
159
- return mcp_result_from_operation(runtime.builder.package_list(profile=profile, trial_status=trial_status))
130
+ return ai_builder.package_list(profile=profile, trial_status=trial_status)
160
131
 
161
132
  @server.tool()
162
133
  def package_resolve(profile: str = DEFAULT_PROFILE, package_name: str = "") -> dict:
163
- return mcp_result_from_operation(runtime.builder.package_resolve(profile=profile, package_name=package_name))
134
+ return ai_builder.package_resolve(profile=profile, package_name=package_name)
164
135
 
165
136
  @server.tool()
166
137
  def builder_tool_contract(tool_name: str = "") -> dict:
167
- return mcp_result_from_operation(runtime.builder.builder_tool_contract(tool_name=tool_name))
138
+ return ai_builder.builder_tool_contract(tool_name=tool_name)
168
139
 
169
140
  @server.tool()
170
141
  def package_create(profile: str = DEFAULT_PROFILE, package_name: str = "") -> dict:
171
- return mcp_result_from_operation(runtime.builder.package_create(profile=profile, package_name=package_name))
142
+ return ai_builder.package_create(profile=profile, package_name=package_name)
172
143
 
173
144
  @server.tool()
174
145
  def member_search(
@@ -178,14 +149,12 @@ def build_builder_server() -> FastMCP:
178
149
  page_size: int = 20,
179
150
  contain_disable: bool = False,
180
151
  ) -> dict:
181
- return mcp_result_from_operation(
182
- runtime.builder.member_search(
183
- profile=profile,
184
- query=query,
185
- page_num=page_num,
186
- page_size=page_size,
187
- contain_disable=contain_disable,
188
- )
152
+ return ai_builder.member_search(
153
+ profile=profile,
154
+ query=query,
155
+ page_num=page_num,
156
+ page_size=page_size,
157
+ contain_disable=contain_disable,
189
158
  )
190
159
 
191
160
  @server.tool()
@@ -195,9 +164,7 @@ def build_builder_server() -> FastMCP:
195
164
  page_num: int = 1,
196
165
  page_size: int = 20,
197
166
  ) -> dict:
198
- return mcp_result_from_operation(
199
- runtime.builder.role_search(profile=profile, keyword=keyword, page_num=page_num, page_size=page_size)
200
- )
167
+ return ai_builder.role_search(profile=profile, keyword=keyword, page_num=page_num, page_size=page_size)
201
168
 
202
169
  @server.tool()
203
170
  def role_create(
@@ -208,15 +175,13 @@ def build_builder_server() -> FastMCP:
208
175
  member_names: list[str] | None = None,
209
176
  role_icon: str = "ex-user-outlined",
210
177
  ) -> dict:
211
- return mcp_result_from_operation(
212
- runtime.builder.role_create(
213
- profile=profile,
214
- role_name=role_name,
215
- member_uids=member_uids or [],
216
- member_emails=member_emails or [],
217
- member_names=member_names or [],
218
- role_icon=role_icon,
219
- )
178
+ return ai_builder.role_create(
179
+ profile=profile,
180
+ role_name=role_name,
181
+ member_uids=member_uids or [],
182
+ member_emails=member_emails or [],
183
+ member_names=member_names or [],
184
+ role_icon=role_icon,
220
185
  )
221
186
 
222
187
  @server.tool()
@@ -226,9 +191,7 @@ def build_builder_server() -> FastMCP:
226
191
  app_key: str = "",
227
192
  app_title: str = "",
228
193
  ) -> dict:
229
- return mcp_result_from_operation(
230
- runtime.builder.package_attach_app(profile=profile, tag_id=tag_id, app_key=app_key, app_title=app_title)
231
- )
194
+ return ai_builder.package_attach_app(profile=profile, tag_id=tag_id, app_key=app_key, app_title=app_title)
232
195
 
233
196
  @server.tool()
234
197
  def app_release_edit_lock_if_mine(
@@ -237,13 +200,11 @@ def build_builder_server() -> FastMCP:
237
200
  lock_owner_email: str = "",
238
201
  lock_owner_name: str = "",
239
202
  ) -> dict:
240
- return mcp_result_from_operation(
241
- runtime.builder.release_edit_lock_if_mine(
242
- profile=profile,
243
- app_key=app_key,
244
- lock_owner_email=lock_owner_email,
245
- lock_owner_name=lock_owner_name,
246
- )
203
+ return ai_builder.app_release_edit_lock_if_mine(
204
+ profile=profile,
205
+ app_key=app_key,
206
+ lock_owner_email=lock_owner_email,
207
+ lock_owner_name=lock_owner_name,
247
208
  )
248
209
 
249
210
  @server.tool()
@@ -253,38 +214,31 @@ def build_builder_server() -> FastMCP:
253
214
  app_name: str = "",
254
215
  package_tag_id: int | None = None,
255
216
  ) -> dict:
256
- return mcp_result_from_operation(
257
- runtime.builder.app_resolve(
258
- profile=profile,
259
- app_key=app_key,
260
- app_name=app_name,
261
- package_tag_id=package_tag_id,
262
- )
263
- )
217
+ return ai_builder.app_resolve(profile=profile, app_key=app_key, app_name=app_name, package_tag_id=package_tag_id)
264
218
 
265
219
  @server.tool()
266
220
  def app_read_summary(profile: str = DEFAULT_PROFILE, app_key: str = "") -> dict:
267
- return mcp_result_from_operation(runtime.builder.app_show(profile=profile, app_key=app_key))
221
+ return ai_builder.app_read_summary(profile=profile, app_key=app_key)
268
222
 
269
223
  @server.tool()
270
224
  def app_read_fields(profile: str = DEFAULT_PROFILE, app_key: str = "") -> dict:
271
- return mcp_result_from_operation(runtime.builder.fields_show(profile=profile, app_key=app_key))
225
+ return ai_builder.app_read_fields(profile=profile, app_key=app_key)
272
226
 
273
227
  @server.tool()
274
228
  def app_read_layout_summary(profile: str = DEFAULT_PROFILE, app_key: str = "") -> dict:
275
- return mcp_result_from_operation(runtime.builder.layout_show(profile=profile, app_key=app_key))
229
+ return ai_builder.app_read_layout_summary(profile=profile, app_key=app_key)
276
230
 
277
231
  @server.tool()
278
232
  def app_read_views_summary(profile: str = DEFAULT_PROFILE, app_key: str = "") -> dict:
279
- return mcp_result_from_operation(runtime.builder.views_show(profile=profile, app_key=app_key))
233
+ return ai_builder.app_read_views_summary(profile=profile, app_key=app_key)
280
234
 
281
235
  @server.tool()
282
236
  def app_read_flow_summary(profile: str = DEFAULT_PROFILE, app_key: str = "") -> dict:
283
- return mcp_result_from_operation(runtime.builder.flow_show(profile=profile, app_key=app_key))
237
+ return ai_builder.app_read_flow_summary(profile=profile, app_key=app_key)
284
238
 
285
239
  @server.tool()
286
240
  def app_read_charts_summary(profile: str = DEFAULT_PROFILE, app_key: str = "") -> dict:
287
- return mcp_result_from_operation(runtime.builder.charts_show(profile=profile, app_key=app_key))
241
+ return ai_builder.app_read_charts_summary(profile=profile, app_key=app_key)
288
242
 
289
243
  @server.tool()
290
244
  def portal_read_summary(
@@ -292,9 +246,7 @@ def build_builder_server() -> FastMCP:
292
246
  dash_key: str = "",
293
247
  being_draft: bool = True,
294
248
  ) -> dict:
295
- return mcp_result_from_operation(
296
- runtime.builder.portal_show(profile=profile, dash_key=dash_key, being_draft=being_draft)
297
- )
249
+ return ai_builder.portal_read_summary(profile=profile, dash_key=dash_key, being_draft=being_draft)
298
250
 
299
251
  @server.tool()
300
252
  def app_schema_apply(
@@ -309,19 +261,17 @@ def build_builder_server() -> FastMCP:
309
261
  update_fields: list[dict] | None = None,
310
262
  remove_fields: list[dict] | None = None,
311
263
  ) -> dict:
312
- return mcp_result_from_operation(
313
- runtime.builder.fields_apply(
314
- profile=profile,
315
- app_key=app_key,
316
- package_tag_id=package_tag_id,
317
- app_name=app_name,
318
- app_title=app_title,
319
- create_if_missing=create_if_missing,
320
- publish=publish,
321
- add_fields=add_fields or [],
322
- update_fields=update_fields or [],
323
- remove_fields=remove_fields or [],
324
- )
264
+ return ai_builder.app_schema_apply(
265
+ profile=profile,
266
+ app_key=app_key,
267
+ package_tag_id=package_tag_id,
268
+ app_name=app_name,
269
+ app_title=app_title,
270
+ create_if_missing=create_if_missing,
271
+ publish=publish,
272
+ add_fields=add_fields or [],
273
+ update_fields=update_fields or [],
274
+ remove_fields=remove_fields or [],
325
275
  )
326
276
 
327
277
  @server.tool()
@@ -332,15 +282,7 @@ def build_builder_server() -> FastMCP:
332
282
  publish: bool = True,
333
283
  sections: list[dict] | None = None,
334
284
  ) -> dict:
335
- return mcp_result_from_operation(
336
- runtime.builder.layout_apply(
337
- profile=profile,
338
- app_key=app_key,
339
- mode=mode,
340
- publish=publish,
341
- sections=sections or [],
342
- )
343
- )
285
+ return ai_builder.app_layout_apply(profile=profile, app_key=app_key, mode=mode, publish=publish, sections=sections or [])
344
286
 
345
287
  @server.tool()
346
288
  def app_flow_apply(
@@ -351,15 +293,13 @@ def build_builder_server() -> FastMCP:
351
293
  nodes: list[dict] | None = None,
352
294
  transitions: list[dict] | None = None,
353
295
  ) -> dict:
354
- return mcp_result_from_operation(
355
- runtime.builder.flow_apply(
356
- profile=profile,
357
- app_key=app_key,
358
- mode=mode,
359
- publish=publish,
360
- nodes=nodes or [],
361
- transitions=transitions or [],
362
- )
296
+ return ai_builder.app_flow_apply(
297
+ profile=profile,
298
+ app_key=app_key,
299
+ mode=mode,
300
+ publish=publish,
301
+ nodes=nodes or [],
302
+ transitions=transitions or [],
363
303
  )
364
304
 
365
305
  @server.tool()
@@ -370,14 +310,12 @@ def build_builder_server() -> FastMCP:
370
310
  upsert_views: list[dict] | None = None,
371
311
  remove_views: list[str] | None = None,
372
312
  ) -> dict:
373
- return mcp_result_from_operation(
374
- runtime.builder.views_apply(
375
- profile=profile,
376
- app_key=app_key,
377
- publish=publish,
378
- upsert_views=upsert_views or [],
379
- remove_views=remove_views or [],
380
- )
313
+ return ai_builder.app_views_apply(
314
+ profile=profile,
315
+ app_key=app_key,
316
+ publish=publish,
317
+ upsert_views=upsert_views or [],
318
+ remove_views=remove_views or [],
381
319
  )
382
320
 
383
321
  @server.tool()
@@ -388,14 +326,12 @@ def build_builder_server() -> FastMCP:
388
326
  remove_chart_ids: list[str] | None = None,
389
327
  reorder_chart_ids: list[str] | None = None,
390
328
  ) -> dict:
391
- return mcp_result_from_operation(
392
- runtime.builder.charts_apply(
393
- profile=profile,
394
- app_key=app_key,
395
- upsert_charts=upsert_charts or [],
396
- remove_chart_ids=remove_chart_ids or [],
397
- reorder_chart_ids=reorder_chart_ids or [],
398
- )
329
+ return ai_builder.app_charts_apply(
330
+ profile=profile,
331
+ app_key=app_key,
332
+ upsert_charts=upsert_charts or [],
333
+ remove_chart_ids=remove_chart_ids or [],
334
+ reorder_chart_ids=reorder_chart_ids or [],
399
335
  )
400
336
 
401
337
  @server.tool()
@@ -413,21 +349,19 @@ def build_builder_server() -> FastMCP:
413
349
  dash_global_config: dict | None = None,
414
350
  config: dict | None = None,
415
351
  ) -> dict:
416
- return mcp_result_from_operation(
417
- runtime.builder.portal_apply(
418
- profile=profile,
419
- dash_key=dash_key,
420
- dash_name=dash_name,
421
- package_tag_id=package_tag_id,
422
- publish=publish,
423
- sections=sections or [],
424
- auth=auth,
425
- icon=icon,
426
- color=color,
427
- hide_copyright=hide_copyright,
428
- dash_global_config=dash_global_config,
429
- config=config or {},
430
- )
352
+ return ai_builder.portal_apply(
353
+ profile=profile,
354
+ dash_key=dash_key,
355
+ dash_name=dash_name,
356
+ package_tag_id=package_tag_id,
357
+ publish=publish,
358
+ sections=sections or [],
359
+ auth=auth,
360
+ icon=icon,
361
+ color=color,
362
+ hide_copyright=hide_copyright,
363
+ dash_global_config=dash_global_config,
364
+ config=config or {},
431
365
  )
432
366
 
433
367
  @server.tool()
@@ -436,12 +370,10 @@ def build_builder_server() -> FastMCP:
436
370
  app_key: str = "",
437
371
  expected_package_tag_id: int | None = None,
438
372
  ) -> dict:
439
- return mcp_result_from_operation(
440
- runtime.builder.publish_verify(
441
- profile=profile,
442
- app_key=app_key,
443
- expected_package_tag_id=expected_package_tag_id,
444
- )
373
+ return ai_builder.app_publish_verify(
374
+ profile=profile,
375
+ app_key=app_key,
376
+ expected_package_tag_id=expected_package_tag_id,
445
377
  )
446
378
 
447
379
  return server