@bangdao-ai/zentao-mcp 2.0.0 → 2.0.1

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bangdao-ai/zentao-mcp",
3
- "version": "2.0.0",
3
+ "version": "2.0.1",
4
4
  "description": "禅道项目管理AI中枢 v2.0 — 35+MCP工具覆盖需求·任务·Bug·用例·发布·我的地盘全生命周期,原生API模式,Bug智能分类引擎+CSV批量用例导入+截图上传,一句话驱动禅道",
5
5
  "main": "index.js",
6
6
  "bin": {
@@ -36,7 +36,7 @@ def _safe_path(path: str, must_exist: bool = False) -> str:
36
36
  """
37
37
  _init_allowed_dirs()
38
38
  real = os.path.realpath(os.path.expanduser(path))
39
- if not any(real.startswith(d) for d in _ALLOWED_WORK_DIRS):
39
+ if not any(real == d or real.startswith(d + os.sep) for d in _ALLOWED_WORK_DIRS):
40
40
  _security_logger.warning("路径安全拒绝: %s (resolved: %s)", path, real)
41
41
  raise ValueError(f"路径不在允许的工作目录内: {path}")
42
42
  if must_exist and not os.path.exists(real):
@@ -1071,14 +1071,21 @@ class ZenTaoNexus:
1071
1071
  if not gateway_payload.get("mold"):
1072
1072
  gateway_payload["mold"] = "20"
1073
1073
  result = self.client.task_create_by_gateway(gateway_payload)
1074
- if result.get("status") == 1 and result.get("taskID"):
1074
+ if result.get("status") == 1:
1075
+ tid = result.get("taskID")
1076
+ if not tid and task_name:
1077
+ tid = self._find_recent_task_id_by_name(task_name)
1078
+ if tid:
1079
+ result["taskID"] = tid
1075
1080
  result["projectID"] = str(project_id)
1076
1081
  result["create_channel"] = "gateway"
1082
+ if not tid:
1083
+ result["warning"] = "任务已通过网关创建成功,但无法获取 taskID"
1077
1084
  return result
1078
1085
 
1079
1086
  gateway_error = result
1080
1087
 
1081
- # 2) 网关失败时回退到原生 task.create(仍要求必须拿到 taskID)
1088
+ # 2) 网关失败时回退到原生 task.create
1082
1089
  native_result = self.client.task_create(project_id, task_data)
1083
1090
  if native_result.get("status") == 1:
1084
1091
  data = native_result.get("data", {})
@@ -1087,25 +1094,18 @@ class ZenTaoNexus:
1087
1094
  tid = self._find_recent_task_id_by_name(task_name)
1088
1095
  if tid:
1089
1096
  native_result["taskID"] = tid
1090
- native_result["projectID"] = str(project_id)
1091
- native_result["create_channel"] = "native"
1092
- return native_result
1093
- result = {
1094
- "status": 0,
1095
- "message": "fail",
1096
- "info": "任务创建返回 success 但无 taskID,判定为未实际创建",
1097
- "data": data,
1098
- "projectID": str(project_id),
1099
- "gateway_error": gateway_error,
1100
- }
1101
- else:
1102
- result = dict(native_result) if isinstance(native_result, dict) else {
1103
- "status": 0, "message": "fail", "info": str(native_result), "data": {}
1104
- }
1105
- result["gateway_error"] = gateway_error
1097
+ native_result["projectID"] = str(project_id)
1098
+ native_result["create_channel"] = "native"
1099
+ if not tid:
1100
+ native_result["warning"] = "任务已通过原生接口创建成功,但无法获取 taskID"
1101
+ return native_result
1102
+
1103
+ result = dict(native_result) if isinstance(native_result, dict) else {
1104
+ "status": 0, "message": "fail", "info": str(native_result), "data": {}
1105
+ }
1106
+ result["gateway_error"] = gateway_error
1106
1107
 
1107
1108
  if str(project_id) == "0":
1108
- # 便于排查:当无法自动选出项目时返回候选项
1109
1109
  candidates = self.get_product_projects(product_id)
1110
1110
  if candidates.get("status") == 1:
1111
1111
  result["project_candidates"] = candidates.get("data", {}).get("projects", [])
@@ -1333,20 +1333,29 @@ class ZenTaoNexus:
1333
1333
  case_id = self._find_recent_case_id_by_name(case_title)
1334
1334
  if case_id:
1335
1335
  result["caseID"] = case_id
1336
- return result
1336
+ result["create_channel"] = "native"
1337
+ if not case_id:
1338
+ result["warning"] = "用例已通过原生接口创建成功,但无法获取 caseID"
1339
+ return result
1337
1340
 
1338
- # 原生成功但无法拿到 caseID 时,回退网关创建,确保后续流程可追踪 caseID。
1341
+ # 原生创建失败时,回退到网关创建
1339
1342
  gateway_payload = dict(case_data)
1340
1343
  gateway_result = self.client.testcase_create_by_gateway(gateway_payload)
1341
- if gateway_result.get("status") == 1 and gateway_result.get("caseID"):
1344
+ if gateway_result.get("status") == 1:
1342
1345
  gateway_result["create_channel"] = "gateway"
1346
+ if not gateway_result.get("caseID") and case_title:
1347
+ cid = self._find_recent_case_id_by_name(case_title)
1348
+ if cid:
1349
+ gateway_result["caseID"] = cid
1350
+ if not gateway_result.get("caseID"):
1351
+ gateway_result["warning"] = "用例已通过网关创建成功,但无法获取 caseID"
1343
1352
  return gateway_result
1344
1353
 
1345
- return result if result.get("status") != 1 else {
1354
+ return {
1346
1355
  "status": 0,
1347
1356
  "message": "fail",
1348
- "info": "用例创建返回 success 但无 caseID,且网关回退失败",
1349
- "data": result.get("data", {}),
1357
+ "info": "原生和网关均创建失败",
1358
+ "native_error": result,
1350
1359
  "gateway_error": gateway_result,
1351
1360
  }
1352
1361