fenix-mcp 1.8.0__py3-none-any.whl → 1.10.0__py3-none-any.whl

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.
fenix_mcp/__init__.py CHANGED
@@ -8,4 +8,4 @@ Fênix Cloud MCP Server (Python edition).
8
8
  __all__ = ["__version__"]
9
9
 
10
10
 
11
- __version__ = "1.8.0"
11
+ __version__ = "1.10.0"
@@ -78,6 +78,10 @@ class KnowledgeAction(str, Enum):
78
78
  "work_assign_to_me",
79
79
  "Assigns a work item to the current user.",
80
80
  )
81
+ WORK_MINE = (
82
+ "work_mine",
83
+ "Lists work items assigned to the current user. Automatically excludes items with status 'done' or 'cancelled'. Supports pagination via limit and offset parameters.",
84
+ )
81
85
  WORK_BULK_CREATE = (
82
86
  "work_bulk_create",
83
87
  "Creates multiple work items atomically with hierarchy. Use temp_id as temporary identifier and parent_temp_id to reference parent in the same batch, or parent_key to reference an existing work item (e.g., TEMA-0056). Cannot use both parent_temp_id and parent_key on the same item. Example: [{temp_id:'epic-1', title:'My Epic', item_type:'epic', work_category:'backend'}, {temp_id:'task-1', parent_temp_id:'epic-1', title:'My Task', item_type:'task', work_category:'backend'}] or [{temp_id:'task-1', parent_key:'TEMA-0056', title:'My Task', item_type:'task', work_category:'backend'}]",
@@ -493,6 +497,16 @@ class KnowledgeTool(Tool):
493
497
  work = await self._service.work_assign_to_me(work_id)
494
498
  return text(_format_work(work, header="✅ Work item assigned to you"))
495
499
 
500
+ if action is KnowledgeAction.WORK_MINE:
501
+ items = await self._service.work_mine(
502
+ limit=payload.limit,
503
+ offset=payload.offset,
504
+ )
505
+ if not items:
506
+ return text("🎯 No work items assigned to you.")
507
+ body = "\n\n".join(_format_work(item) for item in items)
508
+ return text(f"🎯 **Your work items ({len(items)}):**\n\n{body}")
509
+
496
510
  if action is KnowledgeAction.WORK_BACKLOG:
497
511
  items = await self._service.work_backlog()
498
512
  if not items:
@@ -622,18 +636,66 @@ class KnowledgeTool(Tool):
622
636
 
623
637
  items = await self._service.work_bulk_create({"items": payload.work_items})
624
638
 
625
- # Format response with summary
626
- type_counts: Dict[str, int] = {}
627
- for item in items:
628
- item_type = item.get("item_type", "unknown")
629
- type_counts[item_type] = type_counts.get(item_type, 0) + 1
630
-
639
+ # Format response as hierarchical tree
631
640
  lines = [f"✅ **{len(items)} work items created**", ""]
641
+
642
+ # Build tree structure
643
+ items_by_id: Dict[str, Dict[str, Any]] = {}
644
+ children_map: Dict[str, List[str]] = {}
645
+ root_ids: List[str] = []
646
+
632
647
  for item in items:
648
+ item_id = item.get("id", "")
649
+ items_by_id[item_id] = item
650
+ parent_id = item.get("parent_id")
651
+ if parent_id and parent_id in items_by_id:
652
+ if parent_id not in children_map:
653
+ children_map[parent_id] = []
654
+ children_map[parent_id].append(item_id)
655
+ else:
656
+ root_ids.append(item_id)
657
+
658
+ def format_tree_node(
659
+ item_id: str, prefix: str = "", is_last: bool = True
660
+ ) -> List[str]:
661
+ """Format a node and its children as tree lines."""
662
+ node_lines: List[str] = []
663
+ item = items_by_id.get(item_id, {})
633
664
  key = item.get("key", "")
634
665
  title = item.get("title", "Untitled")
635
666
  item_type = item.get("item_type", "unknown")
636
- lines.append(f"- [{key}] {title} ({item_type})")
667
+
668
+ # Determine connector
669
+ if prefix == "":
670
+ connector = ""
671
+ child_prefix = ""
672
+ else:
673
+ connector = "└── " if is_last else "├── "
674
+ child_prefix = prefix + (" " if is_last else "│ ")
675
+
676
+ node_lines.append(f"{prefix}{connector}{item_type}: {key} - {title}")
677
+
678
+ # Process children
679
+ child_ids = children_map.get(item_id, [])
680
+ for i, child_id in enumerate(child_ids):
681
+ is_last_child = i == len(child_ids) - 1
682
+ node_lines.extend(
683
+ format_tree_node(child_id, child_prefix, is_last_child)
684
+ )
685
+
686
+ return node_lines
687
+
688
+ # Format root items and their children
689
+ for i, root_id in enumerate(root_ids):
690
+ lines.extend(format_tree_node(root_id))
691
+ if i < len(root_ids) - 1:
692
+ lines.append("") # Add blank line between root trees
693
+
694
+ # Summary by type
695
+ type_counts: Dict[str, int] = {}
696
+ for item in items:
697
+ item_type = item.get("item_type", "unknown")
698
+ type_counts[item_type] = type_counts.get(item_type, 0) + 1
637
699
 
638
700
  lines.append("")
639
701
  lines.append("**Summary by type:**")
@@ -78,6 +78,13 @@ class KnowledgeService:
78
78
  async def work_assign_to_me(self, work_id: str) -> Dict[str, Any]:
79
79
  return await self._call_dict(self.api.assign_work_item_to_me, work_id)
80
80
 
81
+ async def work_mine(
82
+ self, *, limit: int = 50, offset: int = 0
83
+ ) -> List[Dict[str, Any]]:
84
+ return await self._call_list(
85
+ self.api.get_work_items_mine, limit=limit, offset=offset
86
+ )
87
+
81
88
  async def work_update(
82
89
  self, work_id: str, payload: Dict[str, Any]
83
90
  ) -> Dict[str, Any]:
@@ -498,6 +498,10 @@ class FenixApiClient:
498
498
  def assign_work_item_to_me(self, item_id: str) -> Any:
499
499
  return self._request("POST", f"/api/work-items/{item_id}/assign-to-me")
500
500
 
501
+ def get_work_items_mine(self, *, limit: int = 50, offset: int = 0) -> Any:
502
+ params = self._build_params(optional={"limit": limit, "offset": offset})
503
+ return self._request("GET", "/api/work-items/mine", params=params)
504
+
501
505
  def update_work_item(self, item_id: str, payload: Mapping[str, Any]) -> Any:
502
506
  return self._request("PATCH", f"/api/work-items/{item_id}", json=payload)
503
507
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fenix-mcp
3
- Version: 1.8.0
3
+ Version: 1.10.0
4
4
  Summary: Fênix Cloud MCP server implemented in Python
5
5
  Author: Fenix Inc
6
6
  Requires-Python: >=3.10
@@ -1,4 +1,4 @@
1
- fenix_mcp/__init__.py,sha256=1rPPMWBN4_kt19tylpYO9VURpib6wyxuNU5d3n6gYfk,180
1
+ fenix_mcp/__init__.py,sha256=3PxTTWdV2eIo9b1Kbb5YH180Z0_H6btnEjdqz98JwlQ,181
2
2
  fenix_mcp/main.py,sha256=iJV-9btNMDJMObvcn7wBQdbLLKjkYCQ1ANGEwHGHlMU,2857
3
3
  fenix_mcp/application/presenters.py,sha256=fGME54PdCDhTBhXO-JUB9yLdBHiE1aeXLTC2fCuxnxM,689
4
4
  fenix_mcp/application/tool_base.py,sha256=YJk7aSVGjXEvAkXrOHOuUjCFhYni9NPKFyPKiZqkrCc,4235
@@ -7,23 +7,23 @@ fenix_mcp/application/tools/__init__.py,sha256=Gi1YvYh-KdL9HD8gLVrknHrxiKKEOhHBE
7
7
  fenix_mcp/application/tools/health.py,sha256=m5DxhoRbdwl6INzd6PISxv1NAv-ljCrezsr773VB0wE,834
8
8
  fenix_mcp/application/tools/initialize.py,sha256=YfsE3fVYiqGEwvaI_jg5-0K7pGURXxpB3WNwETmGBPc,5499
9
9
  fenix_mcp/application/tools/intelligence.py,sha256=fXfjBwAQmZCn3Zc8BqFnQFAJkpd9JsfOPa_uXJj-bMU,15778
10
- fenix_mcp/application/tools/knowledge.py,sha256=TOXyiXzEzeq_IiLTJ9kR_o8Kgc2oDmnQOQVvDPimAAA,58408
10
+ fenix_mcp/application/tools/knowledge.py,sha256=XWi5qac0cXkmnll2Adi3pbiY60I4s-RA3UI5Nowu4ak,61009
11
11
  fenix_mcp/application/tools/productivity.py,sha256=wyJ7-2VqgI2cdrliBD_ejwNvQhN1DecpXSQVrCxcUpQ,11231
12
12
  fenix_mcp/application/tools/user_config.py,sha256=O5AVg7IUKL9uIoUoBSFovBDHl9jofhKWzhFK7CnKi4s,6470
13
13
  fenix_mcp/domain/initialization.py,sha256=AZhdSNITQ7O3clELBuqGvjJc-c8pFKc7zQz-XR2xXPc,6933
14
14
  fenix_mcp/domain/intelligence.py,sha256=j1kkxT-pjuzLQeAGDd2H8gd3O1aeUIRgHFnMGvNwQYg,8636
15
- fenix_mcp/domain/knowledge.py,sha256=4zCEpfzQxXiMDIphWfKiKnqvsVQ-B8yoUk1Zog3lJnE,20928
15
+ fenix_mcp/domain/knowledge.py,sha256=xZt2Mjikf4HxcXERDC6ov1fxoHnm4LPU6FI2FZxqq0w,21152
16
16
  fenix_mcp/domain/productivity.py,sha256=PzY664eRPuBCfZGUY_Uv1GNeyMWsw6xqC54C-nobQns,6799
17
17
  fenix_mcp/domain/user_config.py,sha256=8rzhJCNqIArfaCoKxxQXFoemCU7qww3hq0RDanIf_2Y,2028
18
18
  fenix_mcp/infrastructure/config.py,sha256=zhJ3hhsP-bRfICcdq8rIDh5NGDe_u7AGpcgjcc2U1nY,1908
19
19
  fenix_mcp/infrastructure/context.py,sha256=kiDiamiPbHZpTGyZMylcQwtLhfaDXrxAkWSst_DWQNw,470
20
20
  fenix_mcp/infrastructure/http_client.py,sha256=QLIPhGYR_cBQGsbIO4RTR6ksyvkQt-OKHQU1JhPyap8,2470
21
21
  fenix_mcp/infrastructure/logging.py,sha256=bHrWlSi_0HshRe3--BK_5nzUszW-gh37q6jsd0ShS2Y,1371
22
- fenix_mcp/infrastructure/fenix_api/client.py,sha256=GZrrWiUGxMaFM7kT7M8YYeWN1X5EetaJg6Co1-RBI0o,28457
22
+ fenix_mcp/infrastructure/fenix_api/client.py,sha256=YIoDIUQdNd7zzt2X3OsgajjxH5Jqb_85A6BvQDN6H6o,28693
23
23
  fenix_mcp/interface/mcp_server.py,sha256=5UM2NJuNbwHkmCEprIFataJ5nFZiO8efTtP_oW3_iX0,2331
24
24
  fenix_mcp/interface/transports.py,sha256=PxdhfjH8UMl03f7nuCLc-M6tMx6-Y-btVz_mSqXKrSI,8138
25
- fenix_mcp-1.8.0.dist-info/METADATA,sha256=I9_mtSYu17C0GPL2tEyygd3L3giTE8wo-rq88IQP0Os,7260
26
- fenix_mcp-1.8.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
27
- fenix_mcp-1.8.0.dist-info/entry_points.txt,sha256=o52x_YHBupEd-1Z1GSfUjv3gJrx5_I-EkHhCgt1WBaE,49
28
- fenix_mcp-1.8.0.dist-info/top_level.txt,sha256=2G1UtKpwjaIGQyE7sRoHecxaGLeuexfjrOUjv9DDKh4,10
29
- fenix_mcp-1.8.0.dist-info/RECORD,,
25
+ fenix_mcp-1.10.0.dist-info/METADATA,sha256=1GZaLx3YrJbSaeeVJ9SzvF4Zdh1fkc67AnpA2SqiLhk,7261
26
+ fenix_mcp-1.10.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
27
+ fenix_mcp-1.10.0.dist-info/entry_points.txt,sha256=o52x_YHBupEd-1Z1GSfUjv3gJrx5_I-EkHhCgt1WBaE,49
28
+ fenix_mcp-1.10.0.dist-info/top_level.txt,sha256=2G1UtKpwjaIGQyE7sRoHecxaGLeuexfjrOUjv9DDKh4,10
29
+ fenix_mcp-1.10.0.dist-info/RECORD,,