@josephyan/qingflow-cli 0.2.0-beta.984 → 0.2.0-beta.986
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/docs/local-agent-install.md +70 -11
- package/package.json +1 -1
- package/pyproject.toml +1 -1
- package/src/qingflow_mcp/__init__.py +1 -1
- package/src/qingflow_mcp/builder_facade/service.py +47 -21
- package/src/qingflow_mcp/cli/commands/auth.py +14 -43
- package/src/qingflow_mcp/cli/commands/task.py +4 -1
- package/src/qingflow_mcp/cli/commands/workspace.py +0 -8
- package/src/qingflow_mcp/cli/formatters.py +0 -21
- package/src/qingflow_mcp/config.py +39 -0
- package/src/qingflow_mcp/errors.py +2 -2
- package/src/qingflow_mcp/public_surface.py +2 -6
- package/src/qingflow_mcp/response_trim.py +1 -8
- package/src/qingflow_mcp/server.py +1 -1
- package/src/qingflow_mcp/server_app_builder.py +4 -28
- package/src/qingflow_mcp/server_app_user.py +4 -28
- package/src/qingflow_mcp/session_store.py +31 -5
- package/src/qingflow_mcp/tools/ai_builder_tools.py +117 -1
- package/src/qingflow_mcp/tools/app_tools.py +51 -1
- package/src/qingflow_mcp/tools/approval_tools.py +82 -1
- package/src/qingflow_mcp/tools/auth_tools.py +258 -288
- package/src/qingflow_mcp/tools/base.py +204 -4
- package/src/qingflow_mcp/tools/code_block_tools.py +21 -0
- package/src/qingflow_mcp/tools/custom_button_tools.py +24 -1
- package/src/qingflow_mcp/tools/directory_tools.py +28 -1
- package/src/qingflow_mcp/tools/feedback_tools.py +8 -0
- package/src/qingflow_mcp/tools/file_tools.py +25 -1
- package/src/qingflow_mcp/tools/import_tools.py +40 -1
- package/src/qingflow_mcp/tools/navigation_tools.py +34 -1
- package/src/qingflow_mcp/tools/package_tools.py +37 -1
- package/src/qingflow_mcp/tools/portal_tools.py +28 -1
- package/src/qingflow_mcp/tools/qingbi_report_tools.py +38 -1
- package/src/qingflow_mcp/tools/record_tools.py +255 -2
- package/src/qingflow_mcp/tools/repository_dev_tools.py +21 -2
- package/src/qingflow_mcp/tools/resource_read_tools.py +23 -1
- package/src/qingflow_mcp/tools/role_tools.py +19 -1
- package/src/qingflow_mcp/tools/solution_tools.py +56 -1
- package/src/qingflow_mcp/tools/task_context_tools.py +205 -6
- package/src/qingflow_mcp/tools/task_tools.py +49 -3
- package/src/qingflow_mcp/tools/view_tools.py +56 -1
- package/src/qingflow_mcp/tools/workflow_tools.py +65 -1
- package/src/qingflow_mcp/tools/workspace_tools.py +14 -225
|
@@ -7,7 +7,7 @@ from mcp.server.fastmcp import FastMCP
|
|
|
7
7
|
from ..config import DEFAULT_PROFILE
|
|
8
8
|
from ..errors import QingflowApiError, raise_tool_error
|
|
9
9
|
from ..list_type_labels import get_record_list_type_label, get_task_type_label
|
|
10
|
-
from .base import ToolBase
|
|
10
|
+
from .base import ToolBase, tool_cn_name
|
|
11
11
|
|
|
12
12
|
TASK_BOX_TO_TYPE = {
|
|
13
13
|
"todo": 1,
|
|
@@ -31,7 +31,9 @@ FLOW_STATUS_TO_PROCESS_STATUS = {
|
|
|
31
31
|
|
|
32
32
|
|
|
33
33
|
class TaskTools(ToolBase):
|
|
34
|
-
"""
|
|
34
|
+
"""任务中心工具(中文名:任务列表与操作)
|
|
35
|
+
|
|
36
|
+
类型:流程任务运营工具。
|
|
35
37
|
|
|
36
38
|
提供对工作流任务的管理功能,包括:
|
|
37
39
|
- 查询待办/已办列表
|
|
@@ -59,6 +61,7 @@ class TaskTools(ToolBase):
|
|
|
59
61
|
"""
|
|
60
62
|
|
|
61
63
|
def register(self, mcp: FastMCP) -> None:
|
|
64
|
+
"""注册当前工具到 MCP 服务。"""
|
|
62
65
|
@mcp.tool()
|
|
63
66
|
def task_summary(
|
|
64
67
|
profile: str = DEFAULT_PROFILE,
|
|
@@ -139,12 +142,14 @@ class TaskTools(ToolBase):
|
|
|
139
142
|
) -> dict[str, Any]:
|
|
140
143
|
return self.task_urge_public(profile=profile, app_key=app_key, record_id=record_id)
|
|
141
144
|
|
|
145
|
+
@tool_cn_name("任务摘要")
|
|
142
146
|
def task_summary(
|
|
143
147
|
self,
|
|
144
148
|
*,
|
|
145
149
|
profile: str,
|
|
146
150
|
app_key: str | None,
|
|
147
151
|
) -> dict[str, Any]:
|
|
152
|
+
"""执行任务相关逻辑。"""
|
|
148
153
|
raw = self.task_statistics(profile=profile, app_key=app_key)
|
|
149
154
|
statistics = raw.get("statistics", {})
|
|
150
155
|
summary = self._normalize_task_summary_payload(statistics)
|
|
@@ -160,6 +165,7 @@ class TaskTools(ToolBase):
|
|
|
160
165
|
},
|
|
161
166
|
}
|
|
162
167
|
|
|
168
|
+
@tool_cn_name("任务列表")
|
|
163
169
|
def task_list_public(
|
|
164
170
|
self,
|
|
165
171
|
*,
|
|
@@ -174,6 +180,7 @@ class TaskTools(ToolBase):
|
|
|
174
180
|
sort_by: str | None,
|
|
175
181
|
sort_direction: str,
|
|
176
182
|
) -> dict[str, Any]:
|
|
183
|
+
"""执行任务相关逻辑。"""
|
|
177
184
|
normalized_type = self._task_box_to_type(task_box)
|
|
178
185
|
normalized_status = self._flow_status_to_process_status(flow_status)
|
|
179
186
|
create_time_asc = self._task_sort_to_create_time_asc(sort_by, sort_direction)
|
|
@@ -216,6 +223,7 @@ class TaskTools(ToolBase):
|
|
|
216
223
|
},
|
|
217
224
|
}
|
|
218
225
|
|
|
226
|
+
@tool_cn_name("任务分面统计")
|
|
219
227
|
def task_facets(
|
|
220
228
|
self,
|
|
221
229
|
*,
|
|
@@ -227,6 +235,7 @@ class TaskTools(ToolBase):
|
|
|
227
235
|
query: str | None,
|
|
228
236
|
limit: int,
|
|
229
237
|
) -> dict[str, Any]:
|
|
238
|
+
"""执行任务相关逻辑。"""
|
|
230
239
|
normalized_type = self._task_box_to_type(task_box)
|
|
231
240
|
normalized_status = self._flow_status_to_process_status(flow_status)
|
|
232
241
|
if dimension not in {"worksheet", "workflow_node"}:
|
|
@@ -288,6 +297,7 @@ class TaskTools(ToolBase):
|
|
|
288
297
|
},
|
|
289
298
|
}
|
|
290
299
|
|
|
300
|
+
@tool_cn_name("任务标记已读")
|
|
291
301
|
def task_mark_read_public(
|
|
292
302
|
self,
|
|
293
303
|
*,
|
|
@@ -296,6 +306,7 @@ class TaskTools(ToolBase):
|
|
|
296
306
|
task_id: int,
|
|
297
307
|
task_box: str,
|
|
298
308
|
) -> dict[str, Any]:
|
|
309
|
+
"""执行任务相关逻辑。"""
|
|
299
310
|
raw = self.task_mark_read(profile=profile, app_key=app_key, id=task_id, type=self._task_box_to_type(task_box))
|
|
300
311
|
return self._public_task_action_response(
|
|
301
312
|
raw,
|
|
@@ -304,12 +315,14 @@ class TaskTools(ToolBase):
|
|
|
304
315
|
selection={"task_box": task_box},
|
|
305
316
|
)
|
|
306
317
|
|
|
318
|
+
@tool_cn_name("抄送全部已读")
|
|
307
319
|
def task_mark_all_cc_read_public(
|
|
308
320
|
self,
|
|
309
321
|
*,
|
|
310
322
|
profile: str,
|
|
311
323
|
flow_status: str,
|
|
312
324
|
) -> dict[str, Any]:
|
|
325
|
+
"""执行任务相关逻辑。"""
|
|
313
326
|
raw = self.task_mark_all_cc_read(profile=profile, type=TASK_BOX_TO_TYPE["cc"], process_status=self._flow_status_to_process_status(flow_status))
|
|
314
327
|
return self._public_task_action_response(
|
|
315
328
|
raw,
|
|
@@ -318,6 +331,7 @@ class TaskTools(ToolBase):
|
|
|
318
331
|
selection={"task_box": "cc", "flow_status": flow_status},
|
|
319
332
|
)
|
|
320
333
|
|
|
334
|
+
@tool_cn_name("任务催办")
|
|
321
335
|
def task_urge_public(
|
|
322
336
|
self,
|
|
323
337
|
*,
|
|
@@ -325,6 +339,7 @@ class TaskTools(ToolBase):
|
|
|
325
339
|
app_key: str,
|
|
326
340
|
record_id: int,
|
|
327
341
|
) -> dict[str, Any]:
|
|
342
|
+
"""执行任务相关逻辑。"""
|
|
328
343
|
raw = self.task_urge(profile=profile, app_key=app_key, row_record_id=record_id)
|
|
329
344
|
return self._public_task_action_response(
|
|
330
345
|
raw,
|
|
@@ -333,6 +348,7 @@ class TaskTools(ToolBase):
|
|
|
333
348
|
selection={},
|
|
334
349
|
)
|
|
335
350
|
|
|
351
|
+
@tool_cn_name("任务列表(兼容)")
|
|
336
352
|
def task_list(
|
|
337
353
|
self,
|
|
338
354
|
*,
|
|
@@ -346,9 +362,9 @@ class TaskTools(ToolBase):
|
|
|
346
362
|
page_size: int,
|
|
347
363
|
create_time_asc: bool | None,
|
|
348
364
|
) -> dict[str, Any]:
|
|
365
|
+
"""执行任务相关逻辑。"""
|
|
349
366
|
self._validate_type(type)
|
|
350
367
|
self._validate_process_status(process_status)
|
|
351
|
-
|
|
352
368
|
def runner(session_profile, context):
|
|
353
369
|
payload: dict[str, Any] = {
|
|
354
370
|
"type": type,
|
|
@@ -379,6 +395,7 @@ class TaskTools(ToolBase):
|
|
|
379
395
|
|
|
380
396
|
return self._run(profile, runner)
|
|
381
397
|
|
|
398
|
+
@tool_cn_name("任务分组列表")
|
|
382
399
|
def task_list_grouped(
|
|
383
400
|
self,
|
|
384
401
|
*,
|
|
@@ -391,6 +408,7 @@ class TaskTools(ToolBase):
|
|
|
391
408
|
page_num: int,
|
|
392
409
|
page_size: int,
|
|
393
410
|
) -> dict[str, Any]:
|
|
411
|
+
"""执行任务相关逻辑。"""
|
|
394
412
|
self._validate_type(type)
|
|
395
413
|
self._validate_process_status(process_status)
|
|
396
414
|
|
|
@@ -422,12 +440,14 @@ class TaskTools(ToolBase):
|
|
|
422
440
|
|
|
423
441
|
return self._run(profile, runner)
|
|
424
442
|
|
|
443
|
+
@tool_cn_name("任务统计")
|
|
425
444
|
def task_statistics(
|
|
426
445
|
self,
|
|
427
446
|
*,
|
|
428
447
|
profile: str,
|
|
429
448
|
app_key: str | None,
|
|
430
449
|
) -> dict[str, Any]:
|
|
450
|
+
"""执行任务相关逻辑。"""
|
|
431
451
|
def runner(session_profile, context):
|
|
432
452
|
params: dict[str, Any] = {}
|
|
433
453
|
if app_key:
|
|
@@ -443,6 +463,7 @@ class TaskTools(ToolBase):
|
|
|
443
463
|
|
|
444
464
|
return self._run(profile, runner)
|
|
445
465
|
|
|
466
|
+
@tool_cn_name("任务流程节点")
|
|
446
467
|
def task_workflow_nodes(
|
|
447
468
|
self,
|
|
448
469
|
*,
|
|
@@ -454,6 +475,7 @@ class TaskTools(ToolBase):
|
|
|
454
475
|
page_num: int,
|
|
455
476
|
page_size: int,
|
|
456
477
|
) -> dict[str, Any]:
|
|
478
|
+
"""执行任务相关逻辑。"""
|
|
457
479
|
self._validate_type(type)
|
|
458
480
|
|
|
459
481
|
def runner(session_profile, context):
|
|
@@ -482,6 +504,7 @@ class TaskTools(ToolBase):
|
|
|
482
504
|
|
|
483
505
|
return self._run(profile, runner)
|
|
484
506
|
|
|
507
|
+
@tool_cn_name("任务节点统计")
|
|
485
508
|
def task_node_statistics(
|
|
486
509
|
self,
|
|
487
510
|
*,
|
|
@@ -490,6 +513,7 @@ class TaskTools(ToolBase):
|
|
|
490
513
|
type: int,
|
|
491
514
|
search_key: str | None,
|
|
492
515
|
) -> dict[str, Any]:
|
|
516
|
+
"""执行任务相关逻辑。"""
|
|
493
517
|
self._validate_type(type)
|
|
494
518
|
if not app_key:
|
|
495
519
|
raise_tool_error(QingflowApiError.config_error("app_key is required"))
|
|
@@ -516,6 +540,7 @@ class TaskTools(ToolBase):
|
|
|
516
540
|
|
|
517
541
|
return self._run(profile, runner)
|
|
518
542
|
|
|
543
|
+
@tool_cn_name("任务应用统计")
|
|
519
544
|
def task_worksheet_statistics(
|
|
520
545
|
self,
|
|
521
546
|
*,
|
|
@@ -525,6 +550,7 @@ class TaskTools(ToolBase):
|
|
|
525
550
|
page_num: int,
|
|
526
551
|
page_size: int,
|
|
527
552
|
) -> dict[str, Any]:
|
|
553
|
+
"""执行任务相关逻辑。"""
|
|
528
554
|
self._validate_type(type)
|
|
529
555
|
|
|
530
556
|
def runner(session_profile, context):
|
|
@@ -549,6 +575,7 @@ class TaskTools(ToolBase):
|
|
|
549
575
|
|
|
550
576
|
return self._run(profile, runner)
|
|
551
577
|
|
|
578
|
+
@tool_cn_name("任务已读(兼容)")
|
|
552
579
|
def task_mark_read(
|
|
553
580
|
self,
|
|
554
581
|
*,
|
|
@@ -557,6 +584,7 @@ class TaskTools(ToolBase):
|
|
|
557
584
|
id: int,
|
|
558
585
|
type: int,
|
|
559
586
|
) -> dict[str, Any]:
|
|
587
|
+
"""执行任务相关逻辑。"""
|
|
560
588
|
if not app_key:
|
|
561
589
|
raise_tool_error(QingflowApiError.config_error("app_key is required"))
|
|
562
590
|
if id <= 0:
|
|
@@ -583,6 +611,7 @@ class TaskTools(ToolBase):
|
|
|
583
611
|
|
|
584
612
|
return self._run(profile, runner)
|
|
585
613
|
|
|
614
|
+
@tool_cn_name("抄送已读(兼容)")
|
|
586
615
|
def task_mark_all_cc_read(
|
|
587
616
|
self,
|
|
588
617
|
*,
|
|
@@ -590,6 +619,7 @@ class TaskTools(ToolBase):
|
|
|
590
619
|
type: int,
|
|
591
620
|
process_status: int,
|
|
592
621
|
) -> dict[str, Any]:
|
|
622
|
+
"""执行任务相关逻辑。"""
|
|
593
623
|
self._validate_type(type)
|
|
594
624
|
self._validate_process_status(process_status)
|
|
595
625
|
|
|
@@ -612,6 +642,7 @@ class TaskTools(ToolBase):
|
|
|
612
642
|
|
|
613
643
|
return self._run(profile, runner)
|
|
614
644
|
|
|
645
|
+
@tool_cn_name("任务催办(兼容)")
|
|
615
646
|
def task_urge(
|
|
616
647
|
self,
|
|
617
648
|
*,
|
|
@@ -619,6 +650,7 @@ class TaskTools(ToolBase):
|
|
|
619
650
|
app_key: str,
|
|
620
651
|
row_record_id: int,
|
|
621
652
|
) -> dict[str, Any]:
|
|
653
|
+
"""执行任务相关逻辑。"""
|
|
622
654
|
if not app_key:
|
|
623
655
|
raise_tool_error(QingflowApiError.config_error("app_key is required"))
|
|
624
656
|
if row_record_id <= 0:
|
|
@@ -641,6 +673,7 @@ class TaskTools(ToolBase):
|
|
|
641
673
|
|
|
642
674
|
return self._run(profile, runner)
|
|
643
675
|
|
|
676
|
+
@tool_cn_name("任务分组详情")
|
|
644
677
|
def task_group_detail(
|
|
645
678
|
self,
|
|
646
679
|
*,
|
|
@@ -648,6 +681,7 @@ class TaskTools(ToolBase):
|
|
|
648
681
|
app_key: str,
|
|
649
682
|
group_id: int,
|
|
650
683
|
) -> dict[str, Any]:
|
|
684
|
+
"""执行任务相关逻辑。"""
|
|
651
685
|
if not app_key:
|
|
652
686
|
raise_tool_error(QingflowApiError.config_error("app_key is required"))
|
|
653
687
|
if group_id <= 0:
|
|
@@ -670,6 +704,7 @@ class TaskTools(ToolBase):
|
|
|
670
704
|
|
|
671
705
|
return self._run(profile, runner)
|
|
672
706
|
|
|
707
|
+
@tool_cn_name("批处理任务数量")
|
|
673
708
|
def task_batch_processing_amount(
|
|
674
709
|
self,
|
|
675
710
|
*,
|
|
@@ -678,6 +713,7 @@ class TaskTools(ToolBase):
|
|
|
678
713
|
list_type: int,
|
|
679
714
|
task_center_filter: dict[str, Any] | None,
|
|
680
715
|
) -> dict[str, Any]:
|
|
716
|
+
"""执行任务相关逻辑。"""
|
|
681
717
|
if not app_key:
|
|
682
718
|
raise_tool_error(QingflowApiError.config_error("app_key is required"))
|
|
683
719
|
|
|
@@ -707,6 +743,7 @@ class TaskTools(ToolBase):
|
|
|
707
743
|
return self._run(profile, runner)
|
|
708
744
|
|
|
709
745
|
def _validate_type(self, type: int) -> None:
|
|
746
|
+
"""执行内部辅助逻辑。"""
|
|
710
747
|
valid_types = [1, 2, 3, 5] # TODO, INITIATED, CC, DONE
|
|
711
748
|
if type not in valid_types:
|
|
712
749
|
raise_tool_error(
|
|
@@ -716,6 +753,7 @@ class TaskTools(ToolBase):
|
|
|
716
753
|
)
|
|
717
754
|
|
|
718
755
|
def _validate_process_status(self, process_status: int) -> None:
|
|
756
|
+
"""执行内部辅助逻辑。"""
|
|
719
757
|
valid_statuses = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
|
|
720
758
|
if process_status not in valid_statuses:
|
|
721
759
|
raise_tool_error(
|
|
@@ -725,12 +763,14 @@ class TaskTools(ToolBase):
|
|
|
725
763
|
)
|
|
726
764
|
|
|
727
765
|
def _task_box_to_type(self, task_box: str) -> int:
|
|
766
|
+
"""执行内部辅助逻辑。"""
|
|
728
767
|
normalized = (task_box or "").strip().lower()
|
|
729
768
|
if normalized not in TASK_BOX_TO_TYPE:
|
|
730
769
|
raise_tool_error(QingflowApiError.config_error("task_box must be todo, initiated, cc, or done"))
|
|
731
770
|
return TASK_BOX_TO_TYPE[normalized]
|
|
732
771
|
|
|
733
772
|
def _flow_status_to_process_status(self, flow_status: str) -> int:
|
|
773
|
+
"""执行内部辅助逻辑。"""
|
|
734
774
|
normalized = (flow_status or "").strip().lower()
|
|
735
775
|
if normalized not in FLOW_STATUS_TO_PROCESS_STATUS:
|
|
736
776
|
raise_tool_error(
|
|
@@ -741,6 +781,7 @@ class TaskTools(ToolBase):
|
|
|
741
781
|
return FLOW_STATUS_TO_PROCESS_STATUS[normalized]
|
|
742
782
|
|
|
743
783
|
def _task_sort_to_create_time_asc(self, sort_by: str | None, sort_direction: str) -> bool | None:
|
|
784
|
+
"""执行内部辅助逻辑。"""
|
|
744
785
|
normalized_sort_by = (sort_by or "").strip().lower() if sort_by is not None else ""
|
|
745
786
|
normalized_direction = (sort_direction or "desc").strip().lower()
|
|
746
787
|
if normalized_direction not in {"asc", "desc"}:
|
|
@@ -752,11 +793,13 @@ class TaskTools(ToolBase):
|
|
|
752
793
|
return normalized_direction == "asc"
|
|
753
794
|
|
|
754
795
|
def _task_applied_sort(self, sort_by: str | None, sort_direction: str) -> list[dict[str, Any]]:
|
|
796
|
+
"""执行内部辅助逻辑。"""
|
|
755
797
|
if not sort_by:
|
|
756
798
|
return []
|
|
757
799
|
return [{"by": "created_at", "order": (sort_direction or "desc").strip().lower()}]
|
|
758
800
|
|
|
759
801
|
def _normalize_task_summary_payload(self, payload: Any) -> dict[str, Any]:
|
|
802
|
+
"""执行内部辅助逻辑。"""
|
|
760
803
|
if not isinstance(payload, dict):
|
|
761
804
|
return {}
|
|
762
805
|
return {
|
|
@@ -769,6 +812,7 @@ class TaskTools(ToolBase):
|
|
|
769
812
|
}
|
|
770
813
|
|
|
771
814
|
def _normalize_task_facets(self, payload: Any) -> list[dict[str, Any]]:
|
|
815
|
+
"""执行内部辅助逻辑。"""
|
|
772
816
|
items = _task_page_items(payload)
|
|
773
817
|
groups: list[dict[str, Any]] = []
|
|
774
818
|
for item in items:
|
|
@@ -788,6 +832,7 @@ class TaskTools(ToolBase):
|
|
|
788
832
|
resource: dict[str, Any],
|
|
789
833
|
selection: dict[str, Any],
|
|
790
834
|
) -> dict[str, Any]:
|
|
835
|
+
"""执行内部辅助逻辑。"""
|
|
791
836
|
response = dict(raw)
|
|
792
837
|
response["ok"] = bool(raw.get("ok", True))
|
|
793
838
|
response["warnings"] = []
|
|
@@ -801,6 +846,7 @@ class TaskTools(ToolBase):
|
|
|
801
846
|
return response
|
|
802
847
|
|
|
803
848
|
def _request_route_payload(self, context) -> dict[str, Any]: # type: ignore[no-untyped-def]
|
|
849
|
+
"""执行内部辅助逻辑。"""
|
|
804
850
|
describe_route = getattr(self.backend, "describe_route", None)
|
|
805
851
|
if callable(describe_route):
|
|
806
852
|
payload = describe_route(context)
|
|
@@ -5,11 +5,21 @@ from mcp.server.fastmcp import FastMCP
|
|
|
5
5
|
from ..config import DEFAULT_PROFILE
|
|
6
6
|
from ..errors import QingflowApiError, raise_tool_error
|
|
7
7
|
from ..json_types import JSONObject, JSONValue
|
|
8
|
-
from .base import ToolBase
|
|
8
|
+
from .base import ToolBase, tool_cn_name
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
class ViewTools(ToolBase):
|
|
12
|
+
"""视图工具(中文名:视图查询与配置读取)。
|
|
13
|
+
|
|
14
|
+
类型:视图配置工具。
|
|
15
|
+
主要职责:
|
|
16
|
+
1. 查询应用视图列表;
|
|
17
|
+
2. 获取视图配置与结构信息;
|
|
18
|
+
3. 为记录查询和分析提供视图侧元数据。
|
|
19
|
+
"""
|
|
20
|
+
|
|
12
21
|
def register(self, mcp: FastMCP) -> None:
|
|
22
|
+
"""注册当前工具到 MCP 服务。"""
|
|
13
23
|
@mcp.tool()
|
|
14
24
|
def view_list(profile: str = DEFAULT_PROFILE, app_key: str = "") -> JSONObject:
|
|
15
25
|
return self.view_list(profile=profile, app_key=app_key)
|
|
@@ -46,15 +56,21 @@ class ViewTools(ToolBase):
|
|
|
46
56
|
def view_get_workflow_status(profile: str = DEFAULT_PROFILE, viewgraph_key: str = "", row_record_id: int = 0) -> JSONObject:
|
|
47
57
|
return self.view_get_workflow_status(profile=profile, viewgraph_key=viewgraph_key, row_record_id=row_record_id)
|
|
48
58
|
|
|
59
|
+
@tool_cn_name("视图列表")
|
|
49
60
|
def view_list(self, *, profile: str, app_key: str) -> JSONObject:
|
|
61
|
+
"""执行视图相关逻辑。"""
|
|
50
62
|
self._require_app_key(app_key)
|
|
51
63
|
return self._request(profile, "GET", f"/app/{app_key}/view/viewList", app_key=app_key)
|
|
52
64
|
|
|
65
|
+
@tool_cn_name("视图列表(扁平)")
|
|
53
66
|
def view_list_flat(self, *, profile: str, app_key: str) -> JSONObject:
|
|
67
|
+
"""执行视图相关逻辑。"""
|
|
54
68
|
self._require_app_key(app_key)
|
|
55
69
|
return self._request(profile, "GET", f"/app/{app_key}/view/views", app_key=app_key)
|
|
56
70
|
|
|
71
|
+
@tool_cn_name("视图排序")
|
|
57
72
|
def view_reorder(self, *, profile: str, app_key: str, payload: list[JSONObject]) -> JSONObject:
|
|
73
|
+
"""执行视图相关逻辑。"""
|
|
58
74
|
self._require_app_key(app_key)
|
|
59
75
|
if not isinstance(payload, list) or not payload:
|
|
60
76
|
raise_tool_error(QingflowApiError.config_error("payload must be a non-empty array"))
|
|
@@ -66,26 +82,36 @@ class ViewTools(ToolBase):
|
|
|
66
82
|
json_body=self._normalize_reorder_payload(payload),
|
|
67
83
|
)
|
|
68
84
|
|
|
85
|
+
@tool_cn_name("设置视图列宽")
|
|
69
86
|
def view_set_column_width(self, *, profile: str, app_key: str, payload: JSONObject) -> JSONObject:
|
|
87
|
+
"""执行视图相关逻辑。"""
|
|
70
88
|
self._require_app_key(app_key)
|
|
71
89
|
body = self._require_dict(payload)
|
|
72
90
|
return self._request(profile, "POST", f"/app/{app_key}/view/que/width", app_key=app_key, json_body=body)
|
|
73
91
|
|
|
92
|
+
@tool_cn_name("创建视图")
|
|
74
93
|
def view_create(self, *, profile: str, payload: JSONObject) -> JSONObject:
|
|
94
|
+
"""执行视图相关逻辑。"""
|
|
75
95
|
body = self._require_dict(payload)
|
|
76
96
|
app_key = str(body.get("appKey") or "")
|
|
77
97
|
return self._request(profile, "POST", "/view/viewConfig", app_key=app_key, json_body=body)
|
|
78
98
|
|
|
99
|
+
@tool_cn_name("视图配置")
|
|
79
100
|
def view_get_config(self, *, profile: str, viewgraph_key: str) -> JSONObject:
|
|
101
|
+
"""执行视图相关逻辑。"""
|
|
80
102
|
self._require_viewgraph_key(viewgraph_key)
|
|
81
103
|
return self._request(profile, "GET", f"/view/{viewgraph_key}/viewConfig", viewgraph_key=viewgraph_key)
|
|
82
104
|
|
|
105
|
+
@tool_cn_name("视图基础信息")
|
|
83
106
|
def view_get_base_info(self, *, profile: str, viewgraph_key: str, passcode: str | None) -> JSONObject:
|
|
107
|
+
"""执行视图相关逻辑。"""
|
|
84
108
|
self._require_viewgraph_key(viewgraph_key)
|
|
85
109
|
params = {"pass": passcode} if passcode else None
|
|
86
110
|
return self._request(profile, "GET", f"/view/{viewgraph_key}/viewConfig/baseInfo", viewgraph_key=viewgraph_key, params=params)
|
|
87
111
|
|
|
112
|
+
@tool_cn_name("更新视图配置")
|
|
88
113
|
def view_update(self, *, profile: str, viewgraph_key: str, payload: JSONObject) -> JSONObject:
|
|
114
|
+
"""执行视图相关逻辑。"""
|
|
89
115
|
self._require_viewgraph_key(viewgraph_key)
|
|
90
116
|
body = self._require_dict(payload)
|
|
91
117
|
return self._request(
|
|
@@ -98,7 +124,9 @@ class ViewTools(ToolBase):
|
|
|
98
124
|
risk_target="view configuration",
|
|
99
125
|
)
|
|
100
126
|
|
|
127
|
+
@tool_cn_name("删除视图")
|
|
101
128
|
def view_delete(self, *, profile: str, viewgraph_key: str) -> JSONObject:
|
|
129
|
+
"""执行视图相关逻辑。"""
|
|
102
130
|
self._require_viewgraph_key(viewgraph_key)
|
|
103
131
|
return self._request(
|
|
104
132
|
profile,
|
|
@@ -109,19 +137,27 @@ class ViewTools(ToolBase):
|
|
|
109
137
|
risk_target="view configuration",
|
|
110
138
|
)
|
|
111
139
|
|
|
140
|
+
@tool_cn_name("复制视图")
|
|
112
141
|
def view_copy(self, *, profile: str, viewgraph_key: str) -> JSONObject:
|
|
142
|
+
"""执行视图相关逻辑。"""
|
|
113
143
|
self._require_viewgraph_key(viewgraph_key)
|
|
114
144
|
return self._request(profile, "POST", f"/view/{viewgraph_key}/copy", viewgraph_key=viewgraph_key)
|
|
115
145
|
|
|
146
|
+
@tool_cn_name("视图字段列表")
|
|
116
147
|
def view_list_questions(self, *, profile: str, viewgraph_key: str) -> JSONObject:
|
|
148
|
+
"""执行视图相关逻辑。"""
|
|
117
149
|
self._require_viewgraph_key(viewgraph_key)
|
|
118
150
|
return self._request(profile, "GET", f"/view/{viewgraph_key}/question", viewgraph_key=viewgraph_key)
|
|
119
151
|
|
|
152
|
+
@tool_cn_name("视图关联列表")
|
|
120
153
|
def view_list_associations(self, *, profile: str, viewgraph_key: str) -> JSONObject:
|
|
154
|
+
"""执行视图相关逻辑。"""
|
|
121
155
|
self._require_viewgraph_key(viewgraph_key)
|
|
122
156
|
return self._request(profile, "GET", f"/view/{viewgraph_key}/association", viewgraph_key=viewgraph_key)
|
|
123
157
|
|
|
158
|
+
@tool_cn_name("更新视图成员配置")
|
|
124
159
|
def view_update_member_config(self, *, profile: str, viewgraph_key: str, payload: JSONObject) -> JSONObject:
|
|
160
|
+
"""执行视图相关逻辑。"""
|
|
125
161
|
self._require_viewgraph_key(viewgraph_key)
|
|
126
162
|
body = self._require_dict(payload)
|
|
127
163
|
return self._request(
|
|
@@ -134,7 +170,9 @@ class ViewTools(ToolBase):
|
|
|
134
170
|
risk_target="view member visibility",
|
|
135
171
|
)
|
|
136
172
|
|
|
173
|
+
@tool_cn_name("更新视图数据配置")
|
|
137
174
|
def view_update_apply_config(self, *, profile: str, viewgraph_key: str, payload: JSONObject) -> JSONObject:
|
|
175
|
+
"""执行视图相关逻辑。"""
|
|
138
176
|
self._require_viewgraph_key(viewgraph_key)
|
|
139
177
|
body = self._require_dict(payload)
|
|
140
178
|
return self._request(
|
|
@@ -147,7 +185,9 @@ class ViewTools(ToolBase):
|
|
|
147
185
|
risk_target="view apply visibility",
|
|
148
186
|
)
|
|
149
187
|
|
|
188
|
+
@tool_cn_name("看板泳道配置")
|
|
150
189
|
def view_board_set_lane_config(self, *, profile: str, viewgraph_key: str, payload: JSONObject) -> JSONObject:
|
|
190
|
+
"""执行视图相关逻辑。"""
|
|
151
191
|
self._require_viewgraph_key(viewgraph_key)
|
|
152
192
|
body = self._require_dict(payload)
|
|
153
193
|
return self._request(
|
|
@@ -160,7 +200,9 @@ class ViewTools(ToolBase):
|
|
|
160
200
|
risk_target="board lane configuration",
|
|
161
201
|
)
|
|
162
202
|
|
|
203
|
+
@tool_cn_name("看板泳道基础信息")
|
|
163
204
|
def view_board_get_lane_base_info(self, *, profile: str, viewgraph_key: str, page_num: int, page_size: int) -> JSONObject:
|
|
205
|
+
"""执行视图相关逻辑。"""
|
|
164
206
|
self._require_viewgraph_key(viewgraph_key)
|
|
165
207
|
return self._request(
|
|
166
208
|
profile,
|
|
@@ -170,7 +212,9 @@ class ViewTools(ToolBase):
|
|
|
170
212
|
params={"pageNum": page_num, "pageSize": page_size},
|
|
171
213
|
)
|
|
172
214
|
|
|
215
|
+
@tool_cn_name("甘特图自动校准")
|
|
173
216
|
def view_gantt_switch_auto_calibration(self, *, profile: str, viewgraph_key: str, payload: JSONObject) -> JSONObject:
|
|
217
|
+
"""执行视图相关逻辑。"""
|
|
174
218
|
self._require_viewgraph_key(viewgraph_key)
|
|
175
219
|
body = self._require_dict(payload)
|
|
176
220
|
return self._request(
|
|
@@ -183,7 +227,9 @@ class ViewTools(ToolBase):
|
|
|
183
227
|
risk_target="gantt auto calibration settings",
|
|
184
228
|
)
|
|
185
229
|
|
|
230
|
+
@tool_cn_name("甘特图批量更新时间")
|
|
186
231
|
def view_gantt_batch_update_time(self, *, profile: str, viewgraph_key: str, payload: JSONObject) -> JSONObject:
|
|
232
|
+
"""执行视图相关逻辑。"""
|
|
187
233
|
self._require_viewgraph_key(viewgraph_key)
|
|
188
234
|
body = self._require_dict(payload)
|
|
189
235
|
return self._request(
|
|
@@ -196,7 +242,9 @@ class ViewTools(ToolBase):
|
|
|
196
242
|
risk_target="gantt task timing",
|
|
197
243
|
)
|
|
198
244
|
|
|
245
|
+
@tool_cn_name("视图后续节点")
|
|
199
246
|
def view_get_future_nodes(self, *, profile: str, viewgraph_key: str, apply_id: int, app_key: str) -> JSONObject:
|
|
247
|
+
"""执行视图相关逻辑。"""
|
|
200
248
|
self._require_viewgraph_key(viewgraph_key)
|
|
201
249
|
self._require_app_key(app_key)
|
|
202
250
|
self._require_positive("apply_id", apply_id)
|
|
@@ -210,7 +258,9 @@ class ViewTools(ToolBase):
|
|
|
210
258
|
params={"appKey": app_key},
|
|
211
259
|
)
|
|
212
260
|
|
|
261
|
+
@tool_cn_name("视图流程状态")
|
|
213
262
|
def view_get_workflow_status(self, *, profile: str, viewgraph_key: str, row_record_id: int) -> JSONObject:
|
|
263
|
+
"""执行视图相关逻辑。"""
|
|
214
264
|
self._require_viewgraph_key(viewgraph_key)
|
|
215
265
|
self._require_positive("row_record_id", row_record_id)
|
|
216
266
|
return self._request(profile, "GET", f"/view/{viewgraph_key}/workflow/status/{row_record_id}", viewgraph_key=viewgraph_key, row_record_id=row_record_id)
|
|
@@ -227,6 +277,7 @@ class ViewTools(ToolBase):
|
|
|
227
277
|
risk_target: str | None = None,
|
|
228
278
|
**extra: JSONValue,
|
|
229
279
|
) -> JSONObject:
|
|
280
|
+
"""执行内部辅助逻辑。"""
|
|
230
281
|
def runner(session_profile, context):
|
|
231
282
|
result = self.backend.request(method, context, path, json_body=json_body, params=params)
|
|
232
283
|
response: JSONObject = {"profile": profile, "ws_id": session_profile.selected_ws_id, "result": result}
|
|
@@ -238,18 +289,22 @@ class ViewTools(ToolBase):
|
|
|
238
289
|
return self._run(profile, runner)
|
|
239
290
|
|
|
240
291
|
def _require_app_key(self, app_key: str) -> None:
|
|
292
|
+
"""执行内部辅助逻辑。"""
|
|
241
293
|
if not app_key:
|
|
242
294
|
raise_tool_error(QingflowApiError.config_error("app_key is required"))
|
|
243
295
|
|
|
244
296
|
def _require_viewgraph_key(self, viewgraph_key: str) -> None:
|
|
297
|
+
"""执行内部辅助逻辑。"""
|
|
245
298
|
if not viewgraph_key:
|
|
246
299
|
raise_tool_error(QingflowApiError.config_error("viewgraph_key is required"))
|
|
247
300
|
|
|
248
301
|
def _require_positive(self, field_name: str, value: int) -> None:
|
|
302
|
+
"""执行内部辅助逻辑。"""
|
|
249
303
|
if value <= 0:
|
|
250
304
|
raise_tool_error(QingflowApiError.config_error(f"{field_name} must be positive"))
|
|
251
305
|
|
|
252
306
|
def _normalize_reorder_payload(self, payload: list[JSONObject]) -> list[JSONObject]:
|
|
307
|
+
"""执行内部辅助逻辑。"""
|
|
253
308
|
first_item = payload[0]
|
|
254
309
|
if "ordinalType" in first_item and "viewKeyList" in first_item:
|
|
255
310
|
return payload
|