quickcall-integrations 0.5.0__py3-none-any.whl → 0.6.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.
@@ -1301,6 +1301,145 @@ class GitHubClient:
1301
1301
  "issue_number": issue_number,
1302
1302
  }
1303
1303
 
1304
+ def list_issue_comments(
1305
+ self,
1306
+ issue_number: int,
1307
+ owner: Optional[str] = None,
1308
+ repo: Optional[str] = None,
1309
+ limit: int = 10,
1310
+ order: str = "asc",
1311
+ ) -> List[Dict[str, Any]]:
1312
+ """
1313
+ List comments on a GitHub issue.
1314
+
1315
+ Args:
1316
+ issue_number: Issue number
1317
+ owner: Repository owner
1318
+ repo: Repository name
1319
+ limit: Maximum comments to return (default: 10)
1320
+ order: 'asc' for oldest first, 'desc' for newest first (default: 'asc')
1321
+
1322
+ Returns:
1323
+ List of comment dicts with id, body, author, timestamps, url
1324
+ """
1325
+ gh_repo = self._get_repo(owner, repo)
1326
+ issue = gh_repo.get_issue(issue_number)
1327
+
1328
+ comments = []
1329
+ all_comments = list(issue.get_comments())
1330
+
1331
+ # Apply order
1332
+ if order == "desc":
1333
+ all_comments = all_comments[::-1]
1334
+
1335
+ # Apply limit
1336
+ for comment in all_comments[:limit]:
1337
+ comments.append(
1338
+ {
1339
+ "id": comment.id,
1340
+ "body": comment.body,
1341
+ "author": comment.user.login if comment.user else "unknown",
1342
+ "created_at": comment.created_at.isoformat(),
1343
+ "updated_at": comment.updated_at.isoformat()
1344
+ if comment.updated_at
1345
+ else None,
1346
+ "html_url": comment.html_url,
1347
+ }
1348
+ )
1349
+
1350
+ return comments
1351
+
1352
+ def get_issue_comment(
1353
+ self,
1354
+ comment_id: int,
1355
+ owner: Optional[str] = None,
1356
+ repo: Optional[str] = None,
1357
+ ) -> Dict[str, Any]:
1358
+ """
1359
+ Get a specific comment by ID.
1360
+
1361
+ Args:
1362
+ comment_id: Comment ID
1363
+ owner: Repository owner
1364
+ repo: Repository name
1365
+
1366
+ Returns:
1367
+ Comment dict with id, body, author, timestamps, url
1368
+ """
1369
+ gh_repo = self._get_repo(owner, repo)
1370
+ comment = gh_repo.get_issue_comment(comment_id)
1371
+
1372
+ return {
1373
+ "id": comment.id,
1374
+ "body": comment.body,
1375
+ "author": comment.user.login if comment.user else "unknown",
1376
+ "created_at": comment.created_at.isoformat(),
1377
+ "updated_at": comment.updated_at.isoformat()
1378
+ if comment.updated_at
1379
+ else None,
1380
+ "html_url": comment.html_url,
1381
+ }
1382
+
1383
+ def update_issue_comment(
1384
+ self,
1385
+ comment_id: int,
1386
+ body: str,
1387
+ owner: Optional[str] = None,
1388
+ repo: Optional[str] = None,
1389
+ ) -> Dict[str, Any]:
1390
+ """
1391
+ Update an existing comment.
1392
+
1393
+ Args:
1394
+ comment_id: Comment ID
1395
+ body: New comment body
1396
+ owner: Repository owner
1397
+ repo: Repository name
1398
+
1399
+ Returns:
1400
+ Updated comment dict
1401
+ """
1402
+ gh_repo = self._get_repo(owner, repo)
1403
+ comment = gh_repo.get_issue_comment(comment_id)
1404
+ comment.edit(body)
1405
+
1406
+ return {
1407
+ "id": comment.id,
1408
+ "body": comment.body,
1409
+ "author": comment.user.login if comment.user else "unknown",
1410
+ "created_at": comment.created_at.isoformat(),
1411
+ "updated_at": comment.updated_at.isoformat()
1412
+ if comment.updated_at
1413
+ else None,
1414
+ "html_url": comment.html_url,
1415
+ }
1416
+
1417
+ def delete_issue_comment(
1418
+ self,
1419
+ comment_id: int,
1420
+ owner: Optional[str] = None,
1421
+ repo: Optional[str] = None,
1422
+ ) -> Dict[str, Any]:
1423
+ """
1424
+ Delete a comment.
1425
+
1426
+ Args:
1427
+ comment_id: Comment ID
1428
+ owner: Repository owner
1429
+ repo: Repository name
1430
+
1431
+ Returns:
1432
+ Dict with deleted comment_id
1433
+ """
1434
+ gh_repo = self._get_repo(owner, repo)
1435
+ comment = gh_repo.get_issue_comment(comment_id)
1436
+ comment.delete()
1437
+
1438
+ return {
1439
+ "deleted": True,
1440
+ "comment_id": comment_id,
1441
+ }
1442
+
1304
1443
  def get_issue(
1305
1444
  self,
1306
1445
  issue_number: int,
@@ -571,11 +571,12 @@ def create_github_tools(mcp: FastMCP) -> None:
571
571
  action: str = Field(
572
572
  ...,
573
573
  description="Action: 'list', 'view', 'create', 'update', 'close', 'reopen', 'comment', "
574
+ "'list_comments', 'update_comment', 'delete_comment', "
574
575
  "'add_sub_issue', 'remove_sub_issue', 'list_sub_issues'",
575
576
  ),
576
577
  issue_numbers: Optional[List[int]] = Field(
577
578
  default=None,
578
- description="Issue number(s). Required for view/update/close/reopen/comment/sub-issue/project ops.",
579
+ description="Issue number(s). Required for view/update/close/reopen/comment/sub-issue/comment ops.",
579
580
  ),
580
581
  title: Optional[str] = Field(
581
582
  default=None,
@@ -583,7 +584,7 @@ def create_github_tools(mcp: FastMCP) -> None:
583
584
  ),
584
585
  body: Optional[str] = Field(
585
586
  default=None,
586
- description="Issue body (for 'create'/'update') or comment text (for 'comment')",
587
+ description="Issue body (for 'create'/'update') or comment text (for 'comment'/'update_comment')",
587
588
  ),
588
589
  labels: Optional[List[str]] = Field(
589
590
  default=None,
@@ -602,6 +603,18 @@ def create_github_tools(mcp: FastMCP) -> None:
602
603
  description="Parent issue number. For 'create': attach new issue as sub-issue. "
603
604
  "For 'add_sub_issue'/'remove_sub_issue'/'list_sub_issues': the parent issue.",
604
605
  ),
606
+ comment_id: Optional[int] = Field(
607
+ default=None,
608
+ description="Comment ID for 'update_comment' or 'delete_comment' actions.",
609
+ ),
610
+ comments_limit: Optional[int] = Field(
611
+ default=10,
612
+ description="Max comments to return for 'list_comments' (default: 10).",
613
+ ),
614
+ comments_order: Optional[str] = Field(
615
+ default="asc",
616
+ description="Comment order for 'list_comments': 'asc' (oldest first) or 'desc' (newest first).",
617
+ ),
605
618
  owner: Optional[str] = Field(
606
619
  default=None,
607
620
  description="Repository owner",
@@ -644,6 +657,10 @@ def create_github_tools(mcp: FastMCP) -> None:
644
657
  - create as sub-issue: manage_issues(action="create", title="Task 1", parent_issue=42)
645
658
  - close multiple: manage_issues(action="close", issue_numbers=[1, 2, 3])
646
659
  - comment: manage_issues(action="comment", issue_numbers=[42], body="Fixed!")
660
+ - list comments: manage_issues(action="list_comments", issue_numbers=[42], comments_limit=5)
661
+ - list newest comments: manage_issues(action="list_comments", issue_numbers=[42], comments_order="desc")
662
+ - update comment: manage_issues(action="update_comment", issue_numbers=[42], comment_id=123, body="Updated")
663
+ - delete comment: manage_issues(action="delete_comment", issue_numbers=[42], comment_id=123)
647
664
  - add sub-issues: manage_issues(action="add_sub_issue", issue_numbers=[43,44], parent_issue=42)
648
665
  - remove sub-issue: manage_issues(action="remove_sub_issue", issue_numbers=[43], parent_issue=42)
649
666
  - list sub-issues: manage_issues(action="list_sub_issues", parent_issue=42)
@@ -830,6 +847,66 @@ def create_github_tools(mcp: FastMCP) -> None:
830
847
  }
831
848
  )
832
849
 
850
+ # === LIST COMMENTS ACTION ===
851
+ elif action == "list_comments":
852
+ comments = client.list_issue_comments(
853
+ issue_number=issue_number,
854
+ owner=owner,
855
+ repo=repo,
856
+ limit=comments_limit or 10,
857
+ order=comments_order or "asc",
858
+ )
859
+ results.append(
860
+ {
861
+ "number": issue_number,
862
+ "comments_count": len(comments),
863
+ "comments": comments,
864
+ }
865
+ )
866
+
867
+ # === UPDATE COMMENT ACTION ===
868
+ elif action == "update_comment":
869
+ if not comment_id:
870
+ raise ToolError(
871
+ "'comment_id' is required for 'update_comment' action"
872
+ )
873
+ if not body:
874
+ raise ToolError(
875
+ "'body' is required for 'update_comment' action"
876
+ )
877
+ updated = client.update_issue_comment(
878
+ comment_id=comment_id,
879
+ body=body,
880
+ owner=owner,
881
+ repo=repo,
882
+ )
883
+ results.append(
884
+ {
885
+ "number": issue_number,
886
+ "status": "comment_updated",
887
+ "comment": updated,
888
+ }
889
+ )
890
+
891
+ # === DELETE COMMENT ACTION ===
892
+ elif action == "delete_comment":
893
+ if not comment_id:
894
+ raise ToolError(
895
+ "'comment_id' is required for 'delete_comment' action"
896
+ )
897
+ client.delete_issue_comment(
898
+ comment_id=comment_id,
899
+ owner=owner,
900
+ repo=repo,
901
+ )
902
+ results.append(
903
+ {
904
+ "number": issue_number,
905
+ "status": "comment_deleted",
906
+ "comment_id": comment_id,
907
+ }
908
+ )
909
+
833
910
  else:
834
911
  raise ToolError(f"Invalid action: {action}")
835
912
 
@@ -841,6 +918,13 @@ def create_github_tools(mcp: FastMCP) -> None:
841
918
  "issues": results,
842
919
  }
843
920
 
921
+ if action == "list_comments":
922
+ return {
923
+ "action": "list_comments",
924
+ "count": len(results),
925
+ "issues": results,
926
+ }
927
+
844
928
  return {"action": action, "count": len(results), "results": results}
845
929
 
846
930
  except ToolError:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: quickcall-integrations
3
- Version: 0.5.0
3
+ Version: 0.6.0
4
4
  Summary: MCP server with developer integrations for Claude Code and Cursor
5
5
  Requires-Python: >=3.10
6
6
  Requires-Dist: fastmcp>=2.13.0
@@ -252,10 +252,28 @@ The `manage_issues` tool provides full issue lifecycle management:
252
252
  | `close` | Close issue(s) |
253
253
  | `reopen` | Reopen issue(s) |
254
254
  | `comment` | Add comment to issue(s) |
255
+ | `list_comments` | List comments with limit and order |
256
+ | `update_comment` | Edit existing comment by ID |
257
+ | `delete_comment` | Delete comment by ID |
255
258
  | `add_sub_issue` | Add child issue to parent |
256
259
  | `remove_sub_issue` | Remove child from parent |
257
260
  | `list_sub_issues` | List sub-issues of a parent |
258
261
 
262
+ ### Comment Management
263
+
264
+ | Parameter | Description |
265
+ |-----------|-------------|
266
+ | `comment_id` | Comment ID for update/delete operations |
267
+ | `comments_limit` | Max comments to return (default: 10) |
268
+ | `comments_order` | `'asc'` (oldest first) or `'desc'` (newest first) |
269
+
270
+ **Examples:**
271
+ ```
272
+ List last 5 comments on issue #42 (newest first)
273
+ Update comment 123456 on issue #42 with new text
274
+ Delete comment 123456 from issue #42
275
+ ```
276
+
259
277
  ### List Filters
260
278
 
261
279
  | Filter | Description |
@@ -1,7 +1,7 @@
1
1
  mcp_server/__init__.py,sha256=6KGzjSPyVB6vQh150DwBjINM_CsZNDhOzwSQFWpXz0U,301
2
2
  mcp_server/server.py,sha256=kv5hh0J-M7yENUBBNI1bkq1y7MB0zn5R_-R1tib6_sk,3108
3
3
  mcp_server/api_clients/__init__.py,sha256=kOG5_sxIVpAx_tvf1nq_P0QCkqojAVidRE-wenLS-Wc,207
4
- mcp_server/api_clients/github_client.py,sha256=kwqwZN1UeClQqdE7n3Nv9Mc4RS1dtNvSgCO9yCaGCaw,86256
4
+ mcp_server/api_clients/github_client.py,sha256=oKB7NyjuCvs9-BI2061XRxfxIM6lMrrBJJfbCgUxizE,90249
5
5
  mcp_server/api_clients/slack_client.py,sha256=w3rcGghttfYw8Ird2beNo2LEYLc3rCTbUKMH4X7QQuQ,16447
6
6
  mcp_server/auth/__init__.py,sha256=D-JS0Qe7FkeJjYx92u_AqPx8ZRoB3dKMowzzJXlX6cc,780
7
7
  mcp_server/auth/credentials.py,sha256=sDS0W5c16i_UGvhG8Sh1RO93FxRn-hHVAdI9hlWuhx0,20011
@@ -12,10 +12,10 @@ mcp_server/resources/slack_resources.py,sha256=b_CPxAicwkF3PsBXIat4QoLbDUHM2g_iP
12
12
  mcp_server/tools/__init__.py,sha256=vIR2ujAaTXm2DgpTsVNz3brI4G34p-Jeg44Qe0uvWc0,405
13
13
  mcp_server/tools/auth_tools.py,sha256=BPuj9M0pZOvvWHxH0HPdiVm-Y6DJyD-PEvtrIh68vbc,25409
14
14
  mcp_server/tools/git_tools.py,sha256=jyCTQR2eSzUFXMt0Y8x66758-VY8YCY14DDUJt7GY2U,13957
15
- mcp_server/tools/github_tools.py,sha256=heVaftmWbeAAhJRS0YlE0BjtnjbFQbcExS9O4F7hI9o,66804
15
+ mcp_server/tools/github_tools.py,sha256=scfgo48_-uvuj5ehWaoB-VtKx5RqSME8fetpMphVh-w,70461
16
16
  mcp_server/tools/slack_tools.py,sha256=-HVE_x3Z1KMeYGi1xhyppEwz5ZF-I-ZD0-Up8yBeoYE,11796
17
17
  mcp_server/tools/utility_tools.py,sha256=oxAXpdqtPeB5Ug5dvk54V504r-8v1AO4_px-sO6LFOw,3910
18
- quickcall_integrations-0.5.0.dist-info/METADATA,sha256=5_sYSB2zIJrzh4heXS2EUooYCHKbOYmEoZN6_xuI4R4,10936
19
- quickcall_integrations-0.5.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
20
- quickcall_integrations-0.5.0.dist-info/entry_points.txt,sha256=kkcunmJUzncYvQ1rOR35V2LPm2HcFTKzdI2l3n7NwiM,66
21
- quickcall_integrations-0.5.0.dist-info/RECORD,,
18
+ quickcall_integrations-0.6.0.dist-info/METADATA,sha256=IG765WJlLD7A98ikmPH2Ru8fRQhcMFbanKS8eeQn-v4,11519
19
+ quickcall_integrations-0.6.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
20
+ quickcall_integrations-0.6.0.dist-info/entry_points.txt,sha256=kkcunmJUzncYvQ1rOR35V2LPm2HcFTKzdI2l3n7NwiM,66
21
+ quickcall_integrations-0.6.0.dist-info/RECORD,,