@josephyan/qingflow-app-builder-mcp 0.2.0-beta.29 → 0.2.0-beta.30

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.29
6
+ npm install @josephyan/qingflow-app-builder-mcp@0.2.0-beta.30
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.29 qingflow-app-builder-mcp
12
+ npx -y -p @josephyan/qingflow-app-builder-mcp@0.2.0-beta.30 qingflow-app-builder-mcp
13
13
  ```
14
14
 
15
15
  Environment:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@josephyan/qingflow-app-builder-mcp",
3
- "version": "0.2.0-beta.29",
3
+ "version": "0.2.0-beta.30",
4
4
  "description": "Builder MCP for Qingflow app/package/system design and staged solution 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.0b29"
7
+ version = "0.2.0b30"
8
8
  description = "User-authenticated MCP server for Qingflow"
9
9
  readme = "README.md"
10
10
  license = "MIT"
@@ -2,4 +2,4 @@ from __future__ import annotations
2
2
 
3
3
  __all__ = ["__version__"]
4
4
 
5
- __version__ = "0.2.0b29"
5
+ __version__ = "0.2.0b30"
@@ -11,14 +11,12 @@ from .tools.auth_tools import AuthTools
11
11
  from .tools.file_tools import FileTools
12
12
  from .tools.package_tools import PackageTools
13
13
  from .tools.navigation_tools import NavigationTools
14
- from .tools.approval_tools import ApprovalTools
15
14
  from .tools.directory_tools import DirectoryTools
16
15
  from .tools.portal_tools import PortalTools
17
16
  from .tools.qingbi_report_tools import QingbiReportTools
18
17
  from .tools.record_tools import RecordTools
19
18
  from .tools.role_tools import RoleTools
20
19
  from .tools.solution_tools import SolutionTools
21
- from .tools.task_tools import TaskTools
22
20
  from .tools.view_tools import ViewTools
23
21
  from .tools.workflow_tools import WorkflowTools
24
22
  from .tools.workspace_tools import WorkspaceTools
@@ -92,10 +90,6 @@ Analysis answers must include concrete numbers. When applicable, include percent
92
90
  - 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`.
93
91
  - For default-all member or department fields, prefer those field candidate tools instead of starting with `directory_*`.
94
92
 
95
- ## Task Center Path
96
-
97
- `task_summary -> task_list / task_facets -> task action`
98
-
99
93
  ## Time Handling
100
94
 
101
95
  Normalize relative dates before building DSL.
@@ -123,13 +117,11 @@ Avoid builder-side app or schema changes here.""",
123
117
  QingbiReportTools(sessions, backend).register(server)
124
118
  PackageTools(sessions, backend).register(server)
125
119
  NavigationTools(sessions, backend).register(server)
126
- ApprovalTools(sessions, backend).register(server)
127
120
  PortalTools(sessions, backend).register(server)
128
121
  DirectoryTools(sessions, backend).register(server)
129
122
  WorkflowTools(sessions, backend).register(server)
130
123
  ViewTools(sessions, backend).register(server)
131
124
  SolutionTools(sessions, backend).register(server)
132
- TaskTools(sessions, backend).register(server)
133
125
  return server
134
126
 
135
127
 
@@ -7,13 +7,11 @@ from mcp.server.fastmcp import FastMCP
7
7
  from .backend_client import BackendClient
8
8
  from .config import DEFAULT_PROFILE
9
9
  from .session_store import SessionStore
10
- from .tools.approval_tools import ApprovalTools
11
10
  from .tools.app_tools import AppTools
12
11
  from .tools.auth_tools import AuthTools
13
12
  from .tools.directory_tools import DirectoryTools
14
13
  from .tools.file_tools import FileTools
15
14
  from .tools.record_tools import RecordTools
16
- from .tools.task_tools import TaskTools
17
15
  from .tools.workspace_tools import WorkspaceTools
18
16
 
19
17
 
@@ -80,10 +78,6 @@ Analysis answers must include concrete numbers. When applicable, include percent
80
78
  - 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`.
81
79
  - For default-all member or department fields, prefer those field candidate tools instead of starting with `directory_*`.
82
80
 
83
- ## Task Center Path
84
-
85
- `task_summary -> task_list / task_facets -> task action`
86
-
87
81
  ## Time Handling
88
82
 
89
83
  Normalize relative dates before building DSL.
@@ -106,8 +100,6 @@ Avoid builder-side app or schema changes here.""",
106
100
  apps = AppTools(sessions, backend)
107
101
  workspace = WorkspaceTools(sessions, backend)
108
102
  files = FileTools(sessions, backend)
109
- approvals = ApprovalTools(sessions, backend)
110
- tasks = TaskTools(sessions, backend)
111
103
 
112
104
  @server.tool()
113
105
  def auth_login(
@@ -227,8 +219,6 @@ Avoid builder-side app or schema changes here.""",
227
219
 
228
220
  RecordTools(sessions, backend).register(server)
229
221
  DirectoryTools(sessions, backend).register(server)
230
- approvals.register(server)
231
- tasks.register(server)
232
222
 
233
223
  return server
234
224
 
@@ -178,6 +178,7 @@ class FileTools(ToolBase):
178
178
  "download_url": download_url,
179
179
  "attachment_value": {
180
180
  "value": download_url,
181
+ "otherInfo": file_name,
181
182
  "name": file_name,
182
183
  },
183
184
  "comment_file_info": {
@@ -4971,6 +4971,12 @@ def _extract_field_value(answer_list: list[JSONValue], field: FormField | None)
4971
4971
  values = answer.get("values")
4972
4972
  if not isinstance(values, list) or not values:
4973
4973
  return None
4974
+ if field.que_type in ATTACHMENT_QUE_TYPES:
4975
+ extracted_attachments = [_extract_attachment_item(item) for item in values]
4976
+ extracted_attachments = [item for item in extracted_attachments if item is not None]
4977
+ if not extracted_attachments:
4978
+ return None
4979
+ return extracted_attachments[0] if len(extracted_attachments) == 1 else extracted_attachments
4974
4980
  extracted = [_extract_value_item(item) for item in values]
4975
4981
  return extracted[0] if len(extracted) == 1 else extracted
4976
4982
  return None
@@ -5997,12 +6003,29 @@ def _attachment_value(value: JSONValue) -> JSONObject:
5997
6003
  details={"received_value": value},
5998
6004
  )
5999
6005
  payload: JSONObject = {"value": value.get("value", value.get("url"))}
6000
- if value.get("name") is not None:
6001
- payload["name"] = value["name"]
6006
+ file_name = value.get("otherInfo", value.get("name", value.get("fileName")))
6007
+ if file_name is not None:
6008
+ payload["otherInfo"] = file_name
6002
6009
  return payload
6003
6010
  return {"value": _stringify_json(value)}
6004
6011
 
6005
6012
 
6013
+ def _extract_attachment_item(value: JSONValue) -> JSONObject | None:
6014
+ if not isinstance(value, dict):
6015
+ text = _normalize_optional_text(value)
6016
+ return {"value": text, "name": None} if text else None
6017
+ file_url = value.get("value", value.get("url"))
6018
+ normalized_url = _normalize_optional_text(file_url) or (_stringify_json(file_url) if file_url is not None else None)
6019
+ if not normalized_url:
6020
+ return None
6021
+ file_name = value.get("otherInfo", value.get("name", value.get("fileName")))
6022
+ normalized_name = _normalize_optional_text(file_name) or (_stringify_json(file_name) if file_name is not None else None)
6023
+ payload: JSONObject = {"value": normalized_url}
6024
+ if normalized_name:
6025
+ payload["name"] = normalized_name
6026
+ return payload
6027
+
6028
+
6006
6029
  def _relation_value(value: JSONValue) -> JSONObject:
6007
6030
  return _relation_value_payload(None, value)[0]
6008
6031