@josephyan/qingflow-app-builder-mcp 0.2.0-beta.20 → 0.2.0-beta.21
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/package.json +1 -1
- package/pyproject.toml +1 -1
- package/src/qingflow_mcp/__init__.py +1 -1
- package/src/qingflow_mcp/server.py +6 -6
- package/src/qingflow_mcp/server_app_user.py +8 -183
- package/src/qingflow_mcp/tools/approval_tools.py +357 -75
- package/src/qingflow_mcp/tools/directory_tools.py +158 -28
- package/src/qingflow_mcp/tools/record_tools.py +619 -120
- package/src/qingflow_mcp/tools/task_tools.py +376 -225
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.21
|
|
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.21 qingflow-app-builder-mcp
|
|
13
13
|
```
|
|
14
14
|
|
|
15
15
|
Environment:
|
package/package.json
CHANGED
package/pyproject.toml
CHANGED
|
@@ -29,15 +29,15 @@ def build_server() -> FastMCP:
|
|
|
29
29
|
"Use auth_login first, then workspace_list and workspace_select. "
|
|
30
30
|
"All resource tools operate with the logged-in user's Qingflow permissions.\n\n"
|
|
31
31
|
"For analytics, use record_schema_get first, let the model build field_id-based DSL, "
|
|
32
|
-
"then call record_analyze.
|
|
32
|
+
"then call record_analyze. For operational record reads, use record_schema_get first, then record_list or record_get. "
|
|
33
|
+
"For writes, use record_schema_get and then record_write with mode=plan or apply.\n\n"
|
|
33
34
|
"Task Center (待办/已办) handling:\n"
|
|
34
|
-
"- Use
|
|
35
|
-
"- Use task_list
|
|
36
|
-
"- Use
|
|
35
|
+
"- Use task_summary to get headline counts.\n"
|
|
36
|
+
"- Use task_list for flat task browsing with task_box and flow_status.\n"
|
|
37
|
+
"- Use task_facets when worksheet or workflow-node buckets matter.\n"
|
|
37
38
|
"- Use task_mark_read to mark a specific task as read.\n"
|
|
38
39
|
"- Use task_urge to send an urgent reminder for a pending task.\n"
|
|
39
|
-
"-
|
|
40
|
-
"- After identifying the exact task node and record, use record_approve, record_reject, record_rollback, record_transfer, record_reassign, or record_countersign as needed."
|
|
40
|
+
"- After identifying the exact task node and record, use task_approve, task_reject, task_rollback, or task_transfer as needed."
|
|
41
41
|
),
|
|
42
42
|
)
|
|
43
43
|
sessions = SessionStore()
|
|
@@ -18,9 +18,11 @@ def build_user_server() -> FastMCP:
|
|
|
18
18
|
server = FastMCP(
|
|
19
19
|
"Qingflow App User MCP",
|
|
20
20
|
instructions=(
|
|
21
|
-
"Use this server for Qingflow
|
|
22
|
-
"
|
|
23
|
-
"
|
|
21
|
+
"Use this server for Qingflow operational workflows with a schema-first path. "
|
|
22
|
+
"For records, start with record_schema_get, then choose record_list, record_get, or record_write. "
|
|
23
|
+
"For analytics, switch to record_schema_get and record_analyze. "
|
|
24
|
+
"For task center, use task_summary, task_list, and task_facets before any explicit task action. "
|
|
25
|
+
"Avoid builder-side app or schema changes here."
|
|
24
26
|
),
|
|
25
27
|
)
|
|
26
28
|
sessions = SessionStore()
|
|
@@ -137,189 +139,12 @@ def build_user_server() -> FastMCP:
|
|
|
137
139
|
bucket_type=bucket_type,
|
|
138
140
|
path_id=path_id,
|
|
139
141
|
file_related_url=file_related_url,
|
|
140
|
-
|
|
142
|
+
)
|
|
141
143
|
|
|
142
144
|
RecordTools(sessions, backend).register(server)
|
|
143
145
|
DirectoryTools(sessions, backend).register(server)
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
def record_comment_add(
|
|
147
|
-
profile: str = DEFAULT_PROFILE,
|
|
148
|
-
app_key: str = "",
|
|
149
|
-
apply_id: int = 0,
|
|
150
|
-
payload: dict | None = None,
|
|
151
|
-
) -> dict:
|
|
152
|
-
return approvals.record_comment_add(profile=profile, app_key=app_key, apply_id=apply_id, payload=payload or {})
|
|
153
|
-
|
|
154
|
-
@server.tool()
|
|
155
|
-
def record_comment_list(
|
|
156
|
-
profile: str = DEFAULT_PROFILE,
|
|
157
|
-
app_key: str = "",
|
|
158
|
-
apply_id: int = 0,
|
|
159
|
-
page_size: int = 20,
|
|
160
|
-
list_type: int | None = None,
|
|
161
|
-
page_num: int | None = 1,
|
|
162
|
-
) -> dict:
|
|
163
|
-
return approvals.record_comment_list(
|
|
164
|
-
profile=profile,
|
|
165
|
-
app_key=app_key,
|
|
166
|
-
apply_id=apply_id,
|
|
167
|
-
page_size=page_size,
|
|
168
|
-
list_type=list_type,
|
|
169
|
-
page_num=page_num,
|
|
170
|
-
)
|
|
171
|
-
|
|
172
|
-
@server.tool()
|
|
173
|
-
def record_comment_mention_candidates(
|
|
174
|
-
profile: str = DEFAULT_PROFILE,
|
|
175
|
-
app_key: str = "",
|
|
176
|
-
apply_id: int = 0,
|
|
177
|
-
page_size: int = 20,
|
|
178
|
-
page_num: int = 1,
|
|
179
|
-
list_type: int | None = None,
|
|
180
|
-
keyword: str | None = None,
|
|
181
|
-
) -> dict:
|
|
182
|
-
return approvals.record_comment_mention_candidates(
|
|
183
|
-
profile=profile,
|
|
184
|
-
app_key=app_key,
|
|
185
|
-
apply_id=apply_id,
|
|
186
|
-
page_size=page_size,
|
|
187
|
-
page_num=page_num,
|
|
188
|
-
list_type=list_type,
|
|
189
|
-
keyword=keyword,
|
|
190
|
-
)
|
|
191
|
-
|
|
192
|
-
@server.tool()
|
|
193
|
-
def record_comment_mark_read(profile: str = DEFAULT_PROFILE, app_key: str = "", apply_id: int = 0) -> dict:
|
|
194
|
-
return approvals.record_comment_mark_read(profile=profile, app_key=app_key, apply_id=apply_id)
|
|
195
|
-
|
|
196
|
-
@server.tool()
|
|
197
|
-
def record_comment_stats(profile: str = DEFAULT_PROFILE, app_key: str = "", apply_id: int = 0) -> dict:
|
|
198
|
-
return approvals.record_comment_stats(profile=profile, app_key=app_key, apply_id=apply_id)
|
|
199
|
-
|
|
200
|
-
@server.tool()
|
|
201
|
-
def task_list(
|
|
202
|
-
profile: str = DEFAULT_PROFILE,
|
|
203
|
-
type: int = 1,
|
|
204
|
-
process_status: int = 1,
|
|
205
|
-
app_key: str | None = None,
|
|
206
|
-
node_id: int | None = None,
|
|
207
|
-
search_key: str | None = None,
|
|
208
|
-
page_num: int = 1,
|
|
209
|
-
page_size: int = 20,
|
|
210
|
-
create_time_asc: bool | None = None,
|
|
211
|
-
) -> dict:
|
|
212
|
-
return tasks.task_list(
|
|
213
|
-
profile=profile,
|
|
214
|
-
type=type,
|
|
215
|
-
process_status=process_status,
|
|
216
|
-
app_key=app_key,
|
|
217
|
-
node_id=node_id,
|
|
218
|
-
search_key=search_key,
|
|
219
|
-
page_num=page_num,
|
|
220
|
-
page_size=page_size,
|
|
221
|
-
create_time_asc=create_time_asc,
|
|
222
|
-
)
|
|
223
|
-
|
|
224
|
-
@server.tool()
|
|
225
|
-
def task_list_grouped(
|
|
226
|
-
profile: str = DEFAULT_PROFILE,
|
|
227
|
-
type: int = 1,
|
|
228
|
-
process_status: int = 1,
|
|
229
|
-
app_key: str | None = None,
|
|
230
|
-
node_id: int | None = None,
|
|
231
|
-
search_key: str | None = None,
|
|
232
|
-
page_num: int = 1,
|
|
233
|
-
page_size: int = 20,
|
|
234
|
-
) -> dict:
|
|
235
|
-
return tasks.task_list_grouped(
|
|
236
|
-
profile=profile,
|
|
237
|
-
type=type,
|
|
238
|
-
process_status=process_status,
|
|
239
|
-
app_key=app_key,
|
|
240
|
-
node_id=node_id,
|
|
241
|
-
search_key=search_key,
|
|
242
|
-
page_num=page_num,
|
|
243
|
-
page_size=page_size,
|
|
244
|
-
)
|
|
245
|
-
|
|
246
|
-
@server.tool()
|
|
247
|
-
def task_statistics(profile: str = DEFAULT_PROFILE, app_key: str | None = None) -> dict:
|
|
248
|
-
return tasks.task_statistics(profile=profile, app_key=app_key)
|
|
249
|
-
|
|
250
|
-
@server.tool()
|
|
251
|
-
def task_urge(profile: str = DEFAULT_PROFILE, app_key: str = "", row_record_id: int = 0) -> dict:
|
|
252
|
-
return tasks.task_urge(profile=profile, app_key=app_key, row_record_id=row_record_id)
|
|
253
|
-
|
|
254
|
-
@server.tool(description=approvals._high_risk_tool_description(operation="approve", target="workflow task"))
|
|
255
|
-
def task_approve(
|
|
256
|
-
profile: str = DEFAULT_PROFILE,
|
|
257
|
-
app_key: str = "",
|
|
258
|
-
apply_id: int = 0,
|
|
259
|
-
payload: dict | None = None,
|
|
260
|
-
) -> dict:
|
|
261
|
-
return approvals.record_approve(profile=profile, app_key=app_key, apply_id=apply_id, payload=payload or {})
|
|
262
|
-
|
|
263
|
-
@server.tool(description=approvals._high_risk_tool_description(operation="reject", target="workflow task"))
|
|
264
|
-
def task_reject(
|
|
265
|
-
profile: str = DEFAULT_PROFILE,
|
|
266
|
-
app_key: str = "",
|
|
267
|
-
apply_id: int = 0,
|
|
268
|
-
payload: dict | None = None,
|
|
269
|
-
) -> dict:
|
|
270
|
-
return approvals.record_reject(profile=profile, app_key=app_key, apply_id=apply_id, payload=payload or {})
|
|
271
|
-
|
|
272
|
-
@server.tool()
|
|
273
|
-
def task_rollback_candidates(
|
|
274
|
-
profile: str = DEFAULT_PROFILE,
|
|
275
|
-
app_key: str = "",
|
|
276
|
-
apply_id: int = 0,
|
|
277
|
-
audit_node_id: int = 0,
|
|
278
|
-
) -> dict:
|
|
279
|
-
return approvals.record_rollback_candidates(
|
|
280
|
-
profile=profile,
|
|
281
|
-
app_key=app_key,
|
|
282
|
-
apply_id=apply_id,
|
|
283
|
-
audit_node_id=audit_node_id,
|
|
284
|
-
)
|
|
285
|
-
|
|
286
|
-
@server.tool()
|
|
287
|
-
def task_rollback(
|
|
288
|
-
profile: str = DEFAULT_PROFILE,
|
|
289
|
-
app_key: str = "",
|
|
290
|
-
apply_id: int = 0,
|
|
291
|
-
payload: dict | None = None,
|
|
292
|
-
) -> dict:
|
|
293
|
-
return approvals.record_rollback(profile=profile, app_key=app_key, apply_id=apply_id, payload=payload or {})
|
|
294
|
-
|
|
295
|
-
@server.tool()
|
|
296
|
-
def task_transfer_candidates(
|
|
297
|
-
profile: str = DEFAULT_PROFILE,
|
|
298
|
-
app_key: str = "",
|
|
299
|
-
apply_id: int = 0,
|
|
300
|
-
page_size: int = 20,
|
|
301
|
-
page_num: int = 1,
|
|
302
|
-
audit_node_id: int = 0,
|
|
303
|
-
keyword: str | None = None,
|
|
304
|
-
) -> dict:
|
|
305
|
-
return approvals.record_transfer_candidates(
|
|
306
|
-
profile=profile,
|
|
307
|
-
app_key=app_key,
|
|
308
|
-
apply_id=apply_id,
|
|
309
|
-
page_size=page_size,
|
|
310
|
-
page_num=page_num,
|
|
311
|
-
audit_node_id=audit_node_id,
|
|
312
|
-
keyword=keyword,
|
|
313
|
-
)
|
|
314
|
-
|
|
315
|
-
@server.tool()
|
|
316
|
-
def task_transfer(
|
|
317
|
-
profile: str = DEFAULT_PROFILE,
|
|
318
|
-
app_key: str = "",
|
|
319
|
-
apply_id: int = 0,
|
|
320
|
-
payload: dict | None = None,
|
|
321
|
-
) -> dict:
|
|
322
|
-
return approvals.record_transfer(profile=profile, app_key=app_key, apply_id=apply_id, payload=payload or {})
|
|
146
|
+
approvals.register(server)
|
|
147
|
+
tasks.register(server)
|
|
323
148
|
|
|
324
149
|
return server
|
|
325
150
|
|