@josephyan/qingflow-app-user-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.
@@ -35,39 +35,39 @@ class DirectoryTools(ToolBase):
35
35
  def directory_list_internal_users(
36
36
  profile: str = DEFAULT_PROFILE,
37
37
  keyword: str | None = None,
38
- dept_id: int | None = None,
38
+ department_id: int | None = None,
39
39
  role_id: int | None = None,
40
40
  page_num: int = 1,
41
41
  page_size: int = 20,
42
- contain_disable: bool = False,
42
+ include_disabled: bool = False,
43
43
  ) -> dict[str, Any]:
44
44
  return self.directory_list_internal_users(
45
45
  profile=profile,
46
46
  keyword=keyword,
47
- dept_id=dept_id,
47
+ dept_id=department_id,
48
48
  role_id=role_id,
49
49
  page_num=page_num,
50
50
  page_size=page_size,
51
- contain_disable=contain_disable,
51
+ contain_disable=include_disabled,
52
52
  )
53
53
 
54
54
  @mcp.tool()
55
55
  def directory_list_all_internal_users(
56
56
  profile: str = DEFAULT_PROFILE,
57
57
  keyword: str | None = None,
58
- dept_id: int | None = None,
58
+ department_id: int | None = None,
59
59
  role_id: int | None = None,
60
60
  page_size: int = 200,
61
- contain_disable: bool = False,
61
+ include_disabled: bool = False,
62
62
  max_pages: int = 100,
63
63
  ) -> dict[str, Any]:
64
64
  return self.directory_list_all_internal_users(
65
65
  profile=profile,
66
66
  keyword=keyword,
67
- dept_id=dept_id,
67
+ dept_id=department_id,
68
68
  role_id=role_id,
69
69
  page_size=page_size,
70
- contain_disable=contain_disable,
70
+ contain_disable=include_disabled,
71
71
  max_pages=max_pages,
72
72
  )
73
73
 
@@ -88,13 +88,13 @@ class DirectoryTools(ToolBase):
88
88
  @mcp.tool()
89
89
  def directory_list_all_departments(
90
90
  profile: str = DEFAULT_PROFILE,
91
- parent_dept_id: int | None = None,
91
+ parent_department_id: int | None = None,
92
92
  max_depth: int = 20,
93
93
  max_items: int = 2000,
94
94
  ) -> dict[str, Any]:
95
95
  return self.directory_list_all_departments(
96
96
  profile=profile,
97
- parent_dept_id=parent_dept_id,
97
+ parent_dept_id=parent_department_id,
98
98
  max_depth=max_depth,
99
99
  max_items=max_items,
100
100
  )
@@ -102,9 +102,9 @@ class DirectoryTools(ToolBase):
102
102
  @mcp.tool()
103
103
  def directory_list_sub_departments(
104
104
  profile: str = DEFAULT_PROFILE,
105
- parent_dept_id: int | None = None,
105
+ parent_department_id: int | None = None,
106
106
  ) -> dict[str, Any]:
107
- return self.directory_list_sub_departments(profile=profile, parent_dept_id=parent_dept_id)
107
+ return self.directory_list_sub_departments(profile=profile, parent_dept_id=parent_department_id)
108
108
 
109
109
  @mcp.tool()
110
110
  def directory_list_external_members(
@@ -150,9 +150,27 @@ class DirectoryTools(ToolBase):
150
150
  "pageSize": page_size,
151
151
  },
152
152
  )
153
- return {"profile": profile, "ws_id": session_profile.selected_ws_id, "result": result}
153
+ return {
154
+ "profile": profile,
155
+ "ws_id": session_profile.selected_ws_id,
156
+ "request_route": self._request_route_payload(context),
157
+ "result": result,
158
+ }
154
159
 
155
- return self._run(profile, runner)
160
+ raw = self._run(profile, runner)
161
+ items = [item for item in _directory_items(raw.get("result")) if isinstance(item, dict)]
162
+ return self._public_directory_response(
163
+ raw,
164
+ items=items,
165
+ pagination={
166
+ "page": page_num,
167
+ "page_size": page_size,
168
+ "returned_items": len(items),
169
+ "reported_total": _coerce_int(_payload_value(raw.get("result"), "total")),
170
+ "page_amount": _coerce_int(_payload_value(raw.get("result"), "pageAmount")),
171
+ },
172
+ selection={"query": query, "scopes": normalized_scopes},
173
+ )
156
174
 
157
175
  def directory_list_internal_users(
158
176
  self,
@@ -178,9 +196,27 @@ class DirectoryTools(ToolBase):
178
196
  if role_id is not None:
179
197
  params["roleId"] = role_id
180
198
  result = self.backend.request("GET", context, "/contact", params=params)
181
- return {"profile": profile, "ws_id": session_profile.selected_ws_id, "result": result}
199
+ return {
200
+ "profile": profile,
201
+ "ws_id": session_profile.selected_ws_id,
202
+ "request_route": self._request_route_payload(context),
203
+ "result": result,
204
+ }
182
205
 
183
- return self._run(profile, runner)
206
+ raw = self._run(profile, runner)
207
+ items = [item for item in _directory_items(raw.get("result")) if isinstance(item, dict)]
208
+ return self._public_directory_response(
209
+ raw,
210
+ items=items,
211
+ pagination={
212
+ "page": page_num,
213
+ "page_size": page_size,
214
+ "returned_items": len(items),
215
+ "reported_total": _coerce_int(_payload_value(raw.get("result"), "total")),
216
+ "page_amount": _coerce_int(_payload_value(raw.get("result"), "pageAmount")),
217
+ },
218
+ selection={"keyword": keyword, "department_id": dept_id, "role_id": role_id, "include_disabled": contain_disable},
219
+ )
184
220
 
185
221
  def directory_list_all_internal_users(
186
222
  self,
@@ -237,6 +273,7 @@ class DirectoryTools(ToolBase):
237
273
  return {
238
274
  "profile": profile,
239
275
  "ws_id": session_profile.selected_ws_id,
276
+ "request_route": self._request_route_payload(context),
240
277
  "items": items,
241
278
  "pagination": {
242
279
  "page_size": page_size,
@@ -250,7 +287,13 @@ class DirectoryTools(ToolBase):
250
287
  },
251
288
  }
252
289
 
253
- return self._run(profile, runner)
290
+ raw = self._run(profile, runner)
291
+ return self._public_directory_response(
292
+ raw,
293
+ items=[item for item in raw.get("items", []) if isinstance(item, dict)],
294
+ pagination=raw.get("pagination", {}),
295
+ selection={"keyword": keyword, "department_id": dept_id, "role_id": role_id, "include_disabled": contain_disable},
296
+ )
254
297
 
255
298
  def directory_list_internal_departments(
256
299
  self,
@@ -270,9 +313,27 @@ class DirectoryTools(ToolBase):
270
313
  "/contact/deptByPage",
271
314
  params={"keyword": keyword, "pageNum": page_num, "pageSize": page_size},
272
315
  )
273
- return {"profile": profile, "ws_id": session_profile.selected_ws_id, "page": result}
316
+ return {
317
+ "profile": profile,
318
+ "ws_id": session_profile.selected_ws_id,
319
+ "request_route": self._request_route_payload(context),
320
+ "page": result,
321
+ }
274
322
 
275
- return self._run(profile, runner)
323
+ raw = self._run(profile, runner)
324
+ items = [item for item in _directory_items(raw.get("page")) if isinstance(item, dict)]
325
+ return self._public_directory_response(
326
+ raw,
327
+ items=items,
328
+ pagination={
329
+ "page": page_num,
330
+ "page_size": page_size,
331
+ "returned_items": len(items),
332
+ "reported_total": _coerce_int(_payload_value(raw.get("page"), "total")),
333
+ "page_amount": _coerce_int(_payload_value(raw.get("page"), "pageAmount")),
334
+ },
335
+ selection={"keyword": keyword},
336
+ )
276
337
 
277
338
  def directory_list_all_departments(
278
339
  self,
@@ -304,18 +365,25 @@ class DirectoryTools(ToolBase):
304
365
  return {
305
366
  "profile": profile,
306
367
  "ws_id": session_profile.selected_ws_id,
368
+ "request_route": self._request_route_payload(context),
307
369
  "items": items,
308
- "traversal": {
309
- "root_parent_dept_id": parent_dept_id,
370
+ "pagination": {
371
+ "root_parent_department_id": parent_dept_id,
310
372
  "returned_items": len(items),
311
- "max_depth": deepest_depth,
312
- "truncated": truncated,
373
+ "fetched_pages": deepest_depth + 1 if items else 0,
313
374
  "is_complete": not truncated,
375
+ "has_more": truncated,
314
376
  "max_items": max_items,
315
377
  },
316
378
  }
317
379
 
318
- return self._run(profile, runner)
380
+ raw = self._run(profile, runner)
381
+ return self._public_directory_response(
382
+ raw,
383
+ items=[item for item in raw.get("items", []) if isinstance(item, dict)],
384
+ pagination=raw.get("pagination", {}),
385
+ selection={"parent_department_id": parent_dept_id, "max_depth": max_depth, "max_items": max_items},
386
+ )
319
387
 
320
388
  def directory_list_sub_departments(self, *, profile: str, parent_dept_id: int | None) -> dict[str, Any]:
321
389
  def runner(session_profile, context):
@@ -323,9 +391,21 @@ class DirectoryTools(ToolBase):
323
391
  if parent_dept_id is not None:
324
392
  params["parentDeptId"] = parent_dept_id
325
393
  result = self.backend.request("GET", context, "/contact/subDeptList", params=params)
326
- return {"profile": profile, "ws_id": session_profile.selected_ws_id, "items": result}
394
+ return {
395
+ "profile": profile,
396
+ "ws_id": session_profile.selected_ws_id,
397
+ "request_route": self._request_route_payload(context),
398
+ "items": result,
399
+ }
327
400
 
328
- return self._run(profile, runner)
401
+ raw = self._run(profile, runner)
402
+ items = [item for item in raw.get("items", []) if isinstance(item, dict)]
403
+ return self._public_directory_response(
404
+ raw,
405
+ items=items,
406
+ pagination={"returned_items": len(items)},
407
+ selection={"parent_department_id": parent_dept_id},
408
+ )
329
409
 
330
410
  def directory_list_external_members(
331
411
  self,
@@ -349,9 +429,59 @@ class DirectoryTools(ToolBase):
349
429
  if keyword:
350
430
  params["keyword"] = keyword
351
431
  result = self.backend.request("GET", context, "/external/member/pageList", params=params)
352
- return {"profile": profile, "ws_id": session_profile.selected_ws_id, "page": result, "simple": simple}
432
+ return {
433
+ "profile": profile,
434
+ "ws_id": session_profile.selected_ws_id,
435
+ "request_route": self._request_route_payload(context),
436
+ "page": result,
437
+ "simple": simple,
438
+ }
353
439
 
354
- return self._run(profile, runner)
440
+ raw = self._run(profile, runner)
441
+ items = [item for item in _directory_items(raw.get("page")) if isinstance(item, dict)]
442
+ return self._public_directory_response(
443
+ raw,
444
+ items=items,
445
+ pagination={
446
+ "page": page_num,
447
+ "page_size": page_size,
448
+ "returned_items": len(items),
449
+ "reported_total": _coerce_int(_payload_value(raw.get("page"), "total")),
450
+ "page_amount": _coerce_int(_payload_value(raw.get("page"), "pageAmount")),
451
+ },
452
+ selection={"keyword": keyword, "simple": simple},
453
+ )
454
+
455
+ def _request_route_payload(self, context) -> dict[str, Any]: # type: ignore[no-untyped-def]
456
+ describe_route = getattr(self.backend, "describe_route", None)
457
+ if callable(describe_route):
458
+ payload = describe_route(context)
459
+ if isinstance(payload, dict):
460
+ return payload
461
+ return {
462
+ "base_url": getattr(context, "base_url", None),
463
+ "qf_version": getattr(context, "qf_version", None),
464
+ "qf_version_source": getattr(context, "qf_version_source", None) or ("context" if getattr(context, "qf_version", None) else "unknown"),
465
+ }
466
+
467
+ def _public_directory_response(
468
+ self,
469
+ raw: dict[str, Any],
470
+ *,
471
+ items: list[dict[str, Any]],
472
+ pagination: dict[str, Any],
473
+ selection: dict[str, Any],
474
+ ) -> dict[str, Any]:
475
+ response = dict(raw)
476
+ response["ok"] = bool(raw.get("ok", True))
477
+ response["warnings"] = []
478
+ response["output_profile"] = "normal"
479
+ response["data"] = {
480
+ "items": items,
481
+ "pagination": pagination,
482
+ "selection": selection,
483
+ }
484
+ return response
355
485
 
356
486
  def _walk_department_tree(
357
487
  self,