quickcall-integrations 0.3.6__tar.gz → 0.3.7__tar.gz
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.
- {quickcall_integrations-0.3.6 → quickcall_integrations-0.3.7}/PKG-INFO +1 -1
- {quickcall_integrations-0.3.6 → quickcall_integrations-0.3.7}/mcp_server/api_clients/github_client.py +226 -0
- {quickcall_integrations-0.3.6 → quickcall_integrations-0.3.7}/mcp_server/tools/github_tools.py +128 -10
- {quickcall_integrations-0.3.6 → quickcall_integrations-0.3.7}/plugins/quickcall/.claude-plugin/plugin.json +1 -1
- {quickcall_integrations-0.3.6 → quickcall_integrations-0.3.7}/pyproject.toml +1 -1
- {quickcall_integrations-0.3.6 → quickcall_integrations-0.3.7}/uv.lock +1 -1
- {quickcall_integrations-0.3.6 → quickcall_integrations-0.3.7}/.claude-plugin/marketplace.json +0 -0
- {quickcall_integrations-0.3.6 → quickcall_integrations-0.3.7}/.github/workflows/publish-pypi.yml +0 -0
- {quickcall_integrations-0.3.6 → quickcall_integrations-0.3.7}/.gitignore +0 -0
- {quickcall_integrations-0.3.6 → quickcall_integrations-0.3.7}/.pre-commit-config.yaml +0 -0
- {quickcall_integrations-0.3.6 → quickcall_integrations-0.3.7}/.quickcall-issue-template.yaml +0 -0
- {quickcall_integrations-0.3.6 → quickcall_integrations-0.3.7}/Dockerfile +0 -0
- {quickcall_integrations-0.3.6 → quickcall_integrations-0.3.7}/README.md +0 -0
- {quickcall_integrations-0.3.6 → quickcall_integrations-0.3.7}/assets/logo.png +0 -0
- {quickcall_integrations-0.3.6 → quickcall_integrations-0.3.7}/mcp_server/__init__.py +0 -0
- {quickcall_integrations-0.3.6 → quickcall_integrations-0.3.7}/mcp_server/api_clients/__init__.py +0 -0
- {quickcall_integrations-0.3.6 → quickcall_integrations-0.3.7}/mcp_server/api_clients/slack_client.py +0 -0
- {quickcall_integrations-0.3.6 → quickcall_integrations-0.3.7}/mcp_server/auth/__init__.py +0 -0
- {quickcall_integrations-0.3.6 → quickcall_integrations-0.3.7}/mcp_server/auth/credentials.py +0 -0
- {quickcall_integrations-0.3.6 → quickcall_integrations-0.3.7}/mcp_server/auth/device_flow.py +0 -0
- {quickcall_integrations-0.3.6 → quickcall_integrations-0.3.7}/mcp_server/resources/__init__.py +0 -0
- {quickcall_integrations-0.3.6 → quickcall_integrations-0.3.7}/mcp_server/resources/github_resources.py +0 -0
- {quickcall_integrations-0.3.6 → quickcall_integrations-0.3.7}/mcp_server/resources/slack_resources.py +0 -0
- {quickcall_integrations-0.3.6 → quickcall_integrations-0.3.7}/mcp_server/server.py +0 -0
- {quickcall_integrations-0.3.6 → quickcall_integrations-0.3.7}/mcp_server/tools/__init__.py +0 -0
- {quickcall_integrations-0.3.6 → quickcall_integrations-0.3.7}/mcp_server/tools/auth_tools.py +0 -0
- {quickcall_integrations-0.3.6 → quickcall_integrations-0.3.7}/mcp_server/tools/git_tools.py +0 -0
- {quickcall_integrations-0.3.6 → quickcall_integrations-0.3.7}/mcp_server/tools/slack_tools.py +0 -0
- {quickcall_integrations-0.3.6 → quickcall_integrations-0.3.7}/mcp_server/tools/utility_tools.py +0 -0
- {quickcall_integrations-0.3.6 → quickcall_integrations-0.3.7}/plugins/quickcall/commands/appraisal.md +0 -0
- {quickcall_integrations-0.3.6 → quickcall_integrations-0.3.7}/plugins/quickcall/commands/connect-github-pat.md +0 -0
- {quickcall_integrations-0.3.6 → quickcall_integrations-0.3.7}/plugins/quickcall/commands/connect.md +0 -0
- {quickcall_integrations-0.3.6 → quickcall_integrations-0.3.7}/plugins/quickcall/commands/slack-summary.md +0 -0
- {quickcall_integrations-0.3.6 → quickcall_integrations-0.3.7}/plugins/quickcall/commands/status.md +0 -0
- {quickcall_integrations-0.3.6 → quickcall_integrations-0.3.7}/plugins/quickcall/commands/updates.md +0 -0
- {quickcall_integrations-0.3.6 → quickcall_integrations-0.3.7}/requirements.txt +0 -0
- {quickcall_integrations-0.3.6 → quickcall_integrations-0.3.7}/tests/README.md +0 -0
- {quickcall_integrations-0.3.6 → quickcall_integrations-0.3.7}/tests/appraisal/__init__.py +0 -0
- {quickcall_integrations-0.3.6 → quickcall_integrations-0.3.7}/tests/appraisal/setup_test_data.py +0 -0
- {quickcall_integrations-0.3.6 → quickcall_integrations-0.3.7}/tests/test_appraisal_integration.py +0 -0
- {quickcall_integrations-0.3.6 → quickcall_integrations-0.3.7}/tests/test_appraisal_tools.py +0 -0
- {quickcall_integrations-0.3.6 → quickcall_integrations-0.3.7}/tests/test_integrations.py +0 -0
- {quickcall_integrations-0.3.6 → quickcall_integrations-0.3.7}/tests/test_tools.py +0 -0
|
@@ -686,6 +686,232 @@ class GitHubClient:
|
|
|
686
686
|
"issue_number": issue_number,
|
|
687
687
|
}
|
|
688
688
|
|
|
689
|
+
def get_issue(
|
|
690
|
+
self,
|
|
691
|
+
issue_number: int,
|
|
692
|
+
owner: Optional[str] = None,
|
|
693
|
+
repo: Optional[str] = None,
|
|
694
|
+
include_sub_issues: bool = True,
|
|
695
|
+
) -> Dict[str, Any]:
|
|
696
|
+
"""
|
|
697
|
+
Get detailed information about a GitHub issue.
|
|
698
|
+
|
|
699
|
+
Args:
|
|
700
|
+
issue_number: Issue number
|
|
701
|
+
owner: Repository owner
|
|
702
|
+
repo: Repository name
|
|
703
|
+
include_sub_issues: Whether to fetch sub-issues list
|
|
704
|
+
|
|
705
|
+
Returns:
|
|
706
|
+
Issue details including sub-issues if requested
|
|
707
|
+
"""
|
|
708
|
+
gh_repo = self._get_repo(owner, repo)
|
|
709
|
+
issue = gh_repo.get_issue(issue_number)
|
|
710
|
+
|
|
711
|
+
result = {
|
|
712
|
+
"number": issue.number,
|
|
713
|
+
"id": issue.id, # Internal ID needed for sub-issues API
|
|
714
|
+
"title": issue.title,
|
|
715
|
+
"body": issue.body,
|
|
716
|
+
"state": issue.state,
|
|
717
|
+
"html_url": issue.html_url,
|
|
718
|
+
"labels": [label.name for label in issue.labels],
|
|
719
|
+
"assignees": [a.login for a in issue.assignees],
|
|
720
|
+
"created_at": issue.created_at.isoformat(),
|
|
721
|
+
"updated_at": issue.updated_at.isoformat() if issue.updated_at else None,
|
|
722
|
+
"closed_at": issue.closed_at.isoformat() if issue.closed_at else None,
|
|
723
|
+
"comments_count": issue.comments,
|
|
724
|
+
"author": issue.user.login if issue.user else "unknown",
|
|
725
|
+
}
|
|
726
|
+
|
|
727
|
+
# Fetch sub-issues if requested
|
|
728
|
+
if include_sub_issues:
|
|
729
|
+
owner = owner or self.default_owner
|
|
730
|
+
repo_name = repo or self.default_repo
|
|
731
|
+
sub_issues = self.list_sub_issues(issue_number, owner=owner, repo=repo_name)
|
|
732
|
+
result["sub_issues"] = sub_issues
|
|
733
|
+
result["sub_issues_count"] = len(sub_issues)
|
|
734
|
+
|
|
735
|
+
return result
|
|
736
|
+
|
|
737
|
+
# ========================================================================
|
|
738
|
+
# Sub-Issue Operations (GitHub's native sub-issues feature)
|
|
739
|
+
# ========================================================================
|
|
740
|
+
|
|
741
|
+
def list_sub_issues(
|
|
742
|
+
self,
|
|
743
|
+
parent_issue_number: int,
|
|
744
|
+
owner: Optional[str] = None,
|
|
745
|
+
repo: Optional[str] = None,
|
|
746
|
+
) -> List[Dict[str, Any]]:
|
|
747
|
+
"""
|
|
748
|
+
List sub-issues of a parent issue.
|
|
749
|
+
|
|
750
|
+
Args:
|
|
751
|
+
parent_issue_number: Parent issue number
|
|
752
|
+
owner: Repository owner
|
|
753
|
+
repo: Repository name
|
|
754
|
+
|
|
755
|
+
Returns:
|
|
756
|
+
List of sub-issue summaries
|
|
757
|
+
"""
|
|
758
|
+
owner = owner or self.default_owner
|
|
759
|
+
repo = repo or self.default_repo
|
|
760
|
+
|
|
761
|
+
if not owner or not repo:
|
|
762
|
+
raise ValueError("Repository owner and name must be specified")
|
|
763
|
+
|
|
764
|
+
try:
|
|
765
|
+
with httpx.Client() as client:
|
|
766
|
+
response = client.get(
|
|
767
|
+
f"https://api.github.com/repos/{owner}/{repo}/issues/{parent_issue_number}/sub_issues",
|
|
768
|
+
headers={
|
|
769
|
+
"Authorization": f"Bearer {self.token}",
|
|
770
|
+
"Accept": "application/vnd.github+json",
|
|
771
|
+
"X-GitHub-Api-Version": "2022-11-28",
|
|
772
|
+
},
|
|
773
|
+
timeout=30.0,
|
|
774
|
+
)
|
|
775
|
+
response.raise_for_status()
|
|
776
|
+
data = response.json()
|
|
777
|
+
|
|
778
|
+
return [
|
|
779
|
+
{
|
|
780
|
+
"number": item["number"],
|
|
781
|
+
"id": item["id"],
|
|
782
|
+
"title": item["title"],
|
|
783
|
+
"state": item["state"],
|
|
784
|
+
"html_url": item["html_url"],
|
|
785
|
+
}
|
|
786
|
+
for item in data
|
|
787
|
+
]
|
|
788
|
+
except httpx.HTTPStatusError as e:
|
|
789
|
+
if e.response.status_code == 404:
|
|
790
|
+
# No sub-issues or feature not enabled
|
|
791
|
+
return []
|
|
792
|
+
logger.error(f"Failed to list sub-issues: HTTP {e.response.status_code}")
|
|
793
|
+
raise GithubException(e.response.status_code, e.response.json())
|
|
794
|
+
except Exception as e:
|
|
795
|
+
logger.error(f"Failed to list sub-issues: {e}")
|
|
796
|
+
return []
|
|
797
|
+
|
|
798
|
+
def add_sub_issue(
|
|
799
|
+
self,
|
|
800
|
+
parent_issue_number: int,
|
|
801
|
+
child_issue_number: int,
|
|
802
|
+
owner: Optional[str] = None,
|
|
803
|
+
repo: Optional[str] = None,
|
|
804
|
+
) -> Dict[str, Any]:
|
|
805
|
+
"""
|
|
806
|
+
Add an existing issue as a sub-issue to a parent.
|
|
807
|
+
|
|
808
|
+
Args:
|
|
809
|
+
parent_issue_number: Parent issue number
|
|
810
|
+
child_issue_number: Child issue number to add as sub-issue
|
|
811
|
+
owner: Repository owner
|
|
812
|
+
repo: Repository name
|
|
813
|
+
|
|
814
|
+
Returns:
|
|
815
|
+
Result with parent and child info
|
|
816
|
+
"""
|
|
817
|
+
owner = owner or self.default_owner
|
|
818
|
+
repo = repo or self.default_repo
|
|
819
|
+
|
|
820
|
+
if not owner or not repo:
|
|
821
|
+
raise ValueError("Repository owner and name must be specified")
|
|
822
|
+
|
|
823
|
+
# First, get the child issue's internal ID (required by API)
|
|
824
|
+
gh_repo = self._get_repo(owner, repo)
|
|
825
|
+
child_issue = gh_repo.get_issue(child_issue_number)
|
|
826
|
+
child_id = child_issue.id
|
|
827
|
+
|
|
828
|
+
try:
|
|
829
|
+
with httpx.Client() as client:
|
|
830
|
+
response = client.post(
|
|
831
|
+
f"https://api.github.com/repos/{owner}/{repo}/issues/{parent_issue_number}/sub_issues",
|
|
832
|
+
headers={
|
|
833
|
+
"Authorization": f"Bearer {self.token}",
|
|
834
|
+
"Accept": "application/vnd.github+json",
|
|
835
|
+
"X-GitHub-Api-Version": "2022-11-28",
|
|
836
|
+
},
|
|
837
|
+
json={"sub_issue_id": child_id},
|
|
838
|
+
timeout=30.0,
|
|
839
|
+
)
|
|
840
|
+
response.raise_for_status()
|
|
841
|
+
|
|
842
|
+
return {
|
|
843
|
+
"success": True,
|
|
844
|
+
"parent_issue": parent_issue_number,
|
|
845
|
+
"child_issue": child_issue_number,
|
|
846
|
+
"child_id": child_id,
|
|
847
|
+
}
|
|
848
|
+
except httpx.HTTPStatusError as e:
|
|
849
|
+
logger.error(f"Failed to add sub-issue: HTTP {e.response.status_code}")
|
|
850
|
+
error_data = e.response.json() if e.response.content else {}
|
|
851
|
+
raise GithubException(
|
|
852
|
+
e.response.status_code,
|
|
853
|
+
error_data,
|
|
854
|
+
message=f"Failed to add #{child_issue_number} as sub-issue of #{parent_issue_number}",
|
|
855
|
+
)
|
|
856
|
+
|
|
857
|
+
def remove_sub_issue(
|
|
858
|
+
self,
|
|
859
|
+
parent_issue_number: int,
|
|
860
|
+
child_issue_number: int,
|
|
861
|
+
owner: Optional[str] = None,
|
|
862
|
+
repo: Optional[str] = None,
|
|
863
|
+
) -> Dict[str, Any]:
|
|
864
|
+
"""
|
|
865
|
+
Remove a sub-issue from a parent.
|
|
866
|
+
|
|
867
|
+
Args:
|
|
868
|
+
parent_issue_number: Parent issue number
|
|
869
|
+
child_issue_number: Child issue number to remove
|
|
870
|
+
owner: Repository owner
|
|
871
|
+
repo: Repository name
|
|
872
|
+
|
|
873
|
+
Returns:
|
|
874
|
+
Result with parent and child info
|
|
875
|
+
"""
|
|
876
|
+
owner = owner or self.default_owner
|
|
877
|
+
repo = repo or self.default_repo
|
|
878
|
+
|
|
879
|
+
if not owner or not repo:
|
|
880
|
+
raise ValueError("Repository owner and name must be specified")
|
|
881
|
+
|
|
882
|
+
# Get the child issue's internal ID
|
|
883
|
+
gh_repo = self._get_repo(owner, repo)
|
|
884
|
+
child_issue = gh_repo.get_issue(child_issue_number)
|
|
885
|
+
child_id = child_issue.id
|
|
886
|
+
|
|
887
|
+
try:
|
|
888
|
+
with httpx.Client() as client:
|
|
889
|
+
response = client.delete(
|
|
890
|
+
f"https://api.github.com/repos/{owner}/{repo}/issues/{parent_issue_number}/sub_issues/{child_id}",
|
|
891
|
+
headers={
|
|
892
|
+
"Authorization": f"Bearer {self.token}",
|
|
893
|
+
"Accept": "application/vnd.github+json",
|
|
894
|
+
"X-GitHub-Api-Version": "2022-11-28",
|
|
895
|
+
},
|
|
896
|
+
timeout=30.0,
|
|
897
|
+
)
|
|
898
|
+
response.raise_for_status()
|
|
899
|
+
|
|
900
|
+
return {
|
|
901
|
+
"success": True,
|
|
902
|
+
"parent_issue": parent_issue_number,
|
|
903
|
+
"child_issue": child_issue_number,
|
|
904
|
+
"removed": True,
|
|
905
|
+
}
|
|
906
|
+
except httpx.HTTPStatusError as e:
|
|
907
|
+
logger.error(f"Failed to remove sub-issue: HTTP {e.response.status_code}")
|
|
908
|
+
error_data = e.response.json() if e.response.content else {}
|
|
909
|
+
raise GithubException(
|
|
910
|
+
e.response.status_code,
|
|
911
|
+
error_data,
|
|
912
|
+
message=f"Failed to remove #{child_issue_number} from #{parent_issue_number}",
|
|
913
|
+
)
|
|
914
|
+
|
|
689
915
|
# ========================================================================
|
|
690
916
|
# Search Operations (for Appraisals)
|
|
691
917
|
# ========================================================================
|
{quickcall_integrations-0.3.6 → quickcall_integrations-0.3.7}/mcp_server/tools/github_tools.py
RENAMED
|
@@ -570,11 +570,12 @@ def create_github_tools(mcp: FastMCP) -> None:
|
|
|
570
570
|
def manage_issues(
|
|
571
571
|
action: str = Field(
|
|
572
572
|
...,
|
|
573
|
-
description="Action: 'create', 'update', 'close', 'reopen',
|
|
573
|
+
description="Action: 'view', 'create', 'update', 'close', 'reopen', 'comment', "
|
|
574
|
+
"'add_sub_issue', 'remove_sub_issue', 'list_sub_issues'",
|
|
574
575
|
),
|
|
575
576
|
issue_numbers: Optional[List[int]] = Field(
|
|
576
577
|
default=None,
|
|
577
|
-
description="Issue number(s). Required for update/close/reopen/comment
|
|
578
|
+
description="Issue number(s). Required for view/update/close/reopen/comment/sub-issue ops.",
|
|
578
579
|
),
|
|
579
580
|
title: Optional[str] = Field(
|
|
580
581
|
default=None,
|
|
@@ -594,7 +595,12 @@ def create_github_tools(mcp: FastMCP) -> None:
|
|
|
594
595
|
),
|
|
595
596
|
template: Optional[str] = Field(
|
|
596
597
|
default=None,
|
|
597
|
-
description="Template name for 'create' (e.g., '
|
|
598
|
+
description="Template name for 'create' (e.g., 'bug_report', 'feature_request')",
|
|
599
|
+
),
|
|
600
|
+
parent_issue: Optional[int] = Field(
|
|
601
|
+
default=None,
|
|
602
|
+
description="Parent issue number. For 'create': attach new issue as sub-issue. "
|
|
603
|
+
"For 'add_sub_issue'/'remove_sub_issue'/'list_sub_issues': the parent issue.",
|
|
598
604
|
),
|
|
599
605
|
owner: Optional[str] = Field(
|
|
600
606
|
default=None,
|
|
@@ -606,18 +612,24 @@ def create_github_tools(mcp: FastMCP) -> None:
|
|
|
606
612
|
),
|
|
607
613
|
) -> dict:
|
|
608
614
|
"""
|
|
609
|
-
Manage GitHub issues: create, update, close, reopen,
|
|
615
|
+
Manage GitHub issues: view, create, update, close, reopen, comment, and sub-issues.
|
|
610
616
|
|
|
611
|
-
Supports bulk operations for close/reopen/comment via issue_numbers list.
|
|
617
|
+
Supports bulk operations for view/close/reopen/comment via issue_numbers list.
|
|
612
618
|
|
|
613
619
|
Examples:
|
|
614
|
-
-
|
|
620
|
+
- view: manage_issues(action="view", issue_numbers=[42])
|
|
621
|
+
- create: manage_issues(action="create", title="Bug", template="bug_report")
|
|
622
|
+
- create as sub-issue: manage_issues(action="create", title="Task 1", parent_issue=42)
|
|
615
623
|
- close multiple: manage_issues(action="close", issue_numbers=[1, 2, 3])
|
|
616
624
|
- comment: manage_issues(action="comment", issue_numbers=[42], body="Fixed!")
|
|
625
|
+
- add sub-issues: manage_issues(action="add_sub_issue", issue_numbers=[43,44], parent_issue=42)
|
|
626
|
+
- remove sub-issue: manage_issues(action="remove_sub_issue", issue_numbers=[43], parent_issue=42)
|
|
627
|
+
- list sub-issues: manage_issues(action="list_sub_issues", parent_issue=42)
|
|
617
628
|
"""
|
|
618
629
|
try:
|
|
619
630
|
client = _get_client()
|
|
620
631
|
|
|
632
|
+
# === CREATE ACTION ===
|
|
621
633
|
if action == "create":
|
|
622
634
|
if not title:
|
|
623
635
|
raise ToolError("'title' is required for 'create' action")
|
|
@@ -625,24 +637,79 @@ def create_github_tools(mcp: FastMCP) -> None:
|
|
|
625
637
|
tpl = _load_issue_template(template)
|
|
626
638
|
final_body = body if body is not None else tpl.get("body", "")
|
|
627
639
|
final_labels = labels if labels is not None else tpl.get("labels", [])
|
|
640
|
+
final_assignees = (
|
|
641
|
+
assignees if assignees is not None else tpl.get("assignees", [])
|
|
642
|
+
)
|
|
643
|
+
|
|
644
|
+
# Apply title prefix from template if present
|
|
645
|
+
title_prefix = tpl.get("title_prefix", "")
|
|
646
|
+
if title_prefix and not title.startswith(title_prefix):
|
|
647
|
+
title = f"{title_prefix}{title}"
|
|
628
648
|
|
|
629
649
|
issue = client.create_issue(
|
|
630
650
|
title=title,
|
|
631
651
|
body=final_body,
|
|
632
652
|
labels=final_labels,
|
|
633
|
-
assignees=
|
|
653
|
+
assignees=final_assignees,
|
|
654
|
+
owner=owner,
|
|
655
|
+
repo=repo,
|
|
656
|
+
)
|
|
657
|
+
|
|
658
|
+
result = {"action": "created", "issue": issue}
|
|
659
|
+
|
|
660
|
+
# If parent_issue specified, add as sub-issue
|
|
661
|
+
if parent_issue:
|
|
662
|
+
try:
|
|
663
|
+
sub_result = client.add_sub_issue(
|
|
664
|
+
parent_issue_number=parent_issue,
|
|
665
|
+
child_issue_number=issue["number"],
|
|
666
|
+
owner=owner,
|
|
667
|
+
repo=repo,
|
|
668
|
+
)
|
|
669
|
+
result["sub_issue_of"] = parent_issue
|
|
670
|
+
result["sub_issue_linked"] = sub_result.get("success", False)
|
|
671
|
+
except Exception as e:
|
|
672
|
+
result["sub_issue_error"] = str(e)
|
|
673
|
+
|
|
674
|
+
return result
|
|
675
|
+
|
|
676
|
+
# === LIST SUB-ISSUES ACTION ===
|
|
677
|
+
if action == "list_sub_issues":
|
|
678
|
+
if not parent_issue:
|
|
679
|
+
raise ToolError(
|
|
680
|
+
"'parent_issue' is required for 'list_sub_issues' action"
|
|
681
|
+
)
|
|
682
|
+
|
|
683
|
+
sub_issues = client.list_sub_issues(
|
|
684
|
+
parent_issue_number=parent_issue,
|
|
634
685
|
owner=owner,
|
|
635
686
|
repo=repo,
|
|
636
687
|
)
|
|
637
|
-
return {
|
|
688
|
+
return {
|
|
689
|
+
"action": "list_sub_issues",
|
|
690
|
+
"parent_issue": parent_issue,
|
|
691
|
+
"count": len(sub_issues),
|
|
692
|
+
"sub_issues": sub_issues,
|
|
693
|
+
}
|
|
638
694
|
|
|
639
|
-
#
|
|
695
|
+
# === ALL OTHER ACTIONS REQUIRE issue_numbers ===
|
|
640
696
|
if not issue_numbers:
|
|
641
697
|
raise ToolError(f"'issue_numbers' required for '{action}' action")
|
|
642
698
|
|
|
643
699
|
results = []
|
|
644
700
|
for issue_number in issue_numbers:
|
|
645
|
-
|
|
701
|
+
# === VIEW ACTION ===
|
|
702
|
+
if action == "view":
|
|
703
|
+
issue_data = client.get_issue(
|
|
704
|
+
issue_number=issue_number,
|
|
705
|
+
owner=owner,
|
|
706
|
+
repo=repo,
|
|
707
|
+
include_sub_issues=True,
|
|
708
|
+
)
|
|
709
|
+
results.append(issue_data)
|
|
710
|
+
|
|
711
|
+
# === UPDATE ACTION ===
|
|
712
|
+
elif action == "update":
|
|
646
713
|
client.update_issue(
|
|
647
714
|
issue_number=issue_number,
|
|
648
715
|
title=title,
|
|
@@ -654,14 +721,17 @@ def create_github_tools(mcp: FastMCP) -> None:
|
|
|
654
721
|
)
|
|
655
722
|
results.append({"number": issue_number, "status": "updated"})
|
|
656
723
|
|
|
724
|
+
# === CLOSE ACTION ===
|
|
657
725
|
elif action == "close":
|
|
658
726
|
client.close_issue(issue_number, owner=owner, repo=repo)
|
|
659
727
|
results.append({"number": issue_number, "status": "closed"})
|
|
660
728
|
|
|
729
|
+
# === REOPEN ACTION ===
|
|
661
730
|
elif action == "reopen":
|
|
662
731
|
client.reopen_issue(issue_number, owner=owner, repo=repo)
|
|
663
732
|
results.append({"number": issue_number, "status": "reopened"})
|
|
664
733
|
|
|
734
|
+
# === COMMENT ACTION ===
|
|
665
735
|
elif action == "comment":
|
|
666
736
|
if not body:
|
|
667
737
|
raise ToolError("'body' is required for 'comment' action")
|
|
@@ -676,9 +746,57 @@ def create_github_tools(mcp: FastMCP) -> None:
|
|
|
676
746
|
}
|
|
677
747
|
)
|
|
678
748
|
|
|
749
|
+
# === ADD SUB-ISSUE ACTION ===
|
|
750
|
+
elif action == "add_sub_issue":
|
|
751
|
+
if not parent_issue:
|
|
752
|
+
raise ToolError(
|
|
753
|
+
"'parent_issue' is required for 'add_sub_issue' action"
|
|
754
|
+
)
|
|
755
|
+
sub_result = client.add_sub_issue(
|
|
756
|
+
parent_issue_number=parent_issue,
|
|
757
|
+
child_issue_number=issue_number,
|
|
758
|
+
owner=owner,
|
|
759
|
+
repo=repo,
|
|
760
|
+
)
|
|
761
|
+
results.append(
|
|
762
|
+
{
|
|
763
|
+
"number": issue_number,
|
|
764
|
+
"status": "added_as_sub_issue",
|
|
765
|
+
"parent_issue": parent_issue,
|
|
766
|
+
}
|
|
767
|
+
)
|
|
768
|
+
|
|
769
|
+
# === REMOVE SUB-ISSUE ACTION ===
|
|
770
|
+
elif action == "remove_sub_issue":
|
|
771
|
+
if not parent_issue:
|
|
772
|
+
raise ToolError(
|
|
773
|
+
"'parent_issue' is required for 'remove_sub_issue' action"
|
|
774
|
+
)
|
|
775
|
+
client.remove_sub_issue(
|
|
776
|
+
parent_issue_number=parent_issue,
|
|
777
|
+
child_issue_number=issue_number,
|
|
778
|
+
owner=owner,
|
|
779
|
+
repo=repo,
|
|
780
|
+
)
|
|
781
|
+
results.append(
|
|
782
|
+
{
|
|
783
|
+
"number": issue_number,
|
|
784
|
+
"status": "removed_from_parent",
|
|
785
|
+
"parent_issue": parent_issue,
|
|
786
|
+
}
|
|
787
|
+
)
|
|
788
|
+
|
|
679
789
|
else:
|
|
680
790
|
raise ToolError(f"Invalid action: {action}")
|
|
681
791
|
|
|
792
|
+
# Return format depends on action
|
|
793
|
+
if action == "view":
|
|
794
|
+
return {
|
|
795
|
+
"action": "view",
|
|
796
|
+
"count": len(results),
|
|
797
|
+
"issues": results,
|
|
798
|
+
}
|
|
799
|
+
|
|
682
800
|
return {"action": action, "count": len(results), "results": results}
|
|
683
801
|
|
|
684
802
|
except ToolError:
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "quickcall",
|
|
3
3
|
"description": "Integrate quickcall into dev workflows - eliminate interruptions for developers. Ask about your work, get instant answers. No more context switching.",
|
|
4
|
-
"version": "0.6.
|
|
4
|
+
"version": "0.6.6",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Sagar Sarkale"
|
|
7
7
|
}
|
{quickcall_integrations-0.3.6 → quickcall_integrations-0.3.7}/.claude-plugin/marketplace.json
RENAMED
|
File without changes
|
{quickcall_integrations-0.3.6 → quickcall_integrations-0.3.7}/.github/workflows/publish-pypi.yml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{quickcall_integrations-0.3.6 → quickcall_integrations-0.3.7}/.quickcall-issue-template.yaml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{quickcall_integrations-0.3.6 → quickcall_integrations-0.3.7}/mcp_server/api_clients/__init__.py
RENAMED
|
File without changes
|
{quickcall_integrations-0.3.6 → quickcall_integrations-0.3.7}/mcp_server/api_clients/slack_client.py
RENAMED
|
File without changes
|
|
File without changes
|
{quickcall_integrations-0.3.6 → quickcall_integrations-0.3.7}/mcp_server/auth/credentials.py
RENAMED
|
File without changes
|
{quickcall_integrations-0.3.6 → quickcall_integrations-0.3.7}/mcp_server/auth/device_flow.py
RENAMED
|
File without changes
|
{quickcall_integrations-0.3.6 → quickcall_integrations-0.3.7}/mcp_server/resources/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{quickcall_integrations-0.3.6 → quickcall_integrations-0.3.7}/mcp_server/tools/auth_tools.py
RENAMED
|
File without changes
|
|
File without changes
|
{quickcall_integrations-0.3.6 → quickcall_integrations-0.3.7}/mcp_server/tools/slack_tools.py
RENAMED
|
File without changes
|
{quickcall_integrations-0.3.6 → quickcall_integrations-0.3.7}/mcp_server/tools/utility_tools.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{quickcall_integrations-0.3.6 → quickcall_integrations-0.3.7}/plugins/quickcall/commands/connect.md
RENAMED
|
File without changes
|
|
File without changes
|
{quickcall_integrations-0.3.6 → quickcall_integrations-0.3.7}/plugins/quickcall/commands/status.md
RENAMED
|
File without changes
|
{quickcall_integrations-0.3.6 → quickcall_integrations-0.3.7}/plugins/quickcall/commands/updates.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{quickcall_integrations-0.3.6 → quickcall_integrations-0.3.7}/tests/appraisal/setup_test_data.py
RENAMED
|
File without changes
|
{quickcall_integrations-0.3.6 → quickcall_integrations-0.3.7}/tests/test_appraisal_integration.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|