emdash-core 0.1.7__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.
- emdash_core/__init__.py +3 -0
- emdash_core/agent/__init__.py +37 -0
- emdash_core/agent/agents.py +225 -0
- emdash_core/agent/code_reviewer.py +476 -0
- emdash_core/agent/compaction.py +143 -0
- emdash_core/agent/context_manager.py +140 -0
- emdash_core/agent/events.py +338 -0
- emdash_core/agent/handlers.py +224 -0
- emdash_core/agent/inprocess_subagent.py +377 -0
- emdash_core/agent/mcp/__init__.py +50 -0
- emdash_core/agent/mcp/client.py +346 -0
- emdash_core/agent/mcp/config.py +302 -0
- emdash_core/agent/mcp/manager.py +496 -0
- emdash_core/agent/mcp/tool_factory.py +213 -0
- emdash_core/agent/prompts/__init__.py +38 -0
- emdash_core/agent/prompts/main_agent.py +104 -0
- emdash_core/agent/prompts/subagents.py +131 -0
- emdash_core/agent/prompts/workflow.py +136 -0
- emdash_core/agent/providers/__init__.py +34 -0
- emdash_core/agent/providers/base.py +143 -0
- emdash_core/agent/providers/factory.py +80 -0
- emdash_core/agent/providers/models.py +220 -0
- emdash_core/agent/providers/openai_provider.py +463 -0
- emdash_core/agent/providers/transformers_provider.py +217 -0
- emdash_core/agent/research/__init__.py +81 -0
- emdash_core/agent/research/agent.py +143 -0
- emdash_core/agent/research/controller.py +254 -0
- emdash_core/agent/research/critic.py +428 -0
- emdash_core/agent/research/macros.py +469 -0
- emdash_core/agent/research/planner.py +449 -0
- emdash_core/agent/research/researcher.py +436 -0
- emdash_core/agent/research/state.py +523 -0
- emdash_core/agent/research/synthesizer.py +594 -0
- emdash_core/agent/reviewer_profile.py +475 -0
- emdash_core/agent/rules.py +123 -0
- emdash_core/agent/runner.py +601 -0
- emdash_core/agent/session.py +262 -0
- emdash_core/agent/spec_schema.py +66 -0
- emdash_core/agent/specification.py +479 -0
- emdash_core/agent/subagent.py +397 -0
- emdash_core/agent/subagent_prompts.py +13 -0
- emdash_core/agent/toolkit.py +482 -0
- emdash_core/agent/toolkits/__init__.py +64 -0
- emdash_core/agent/toolkits/base.py +96 -0
- emdash_core/agent/toolkits/explore.py +47 -0
- emdash_core/agent/toolkits/plan.py +55 -0
- emdash_core/agent/tools/__init__.py +141 -0
- emdash_core/agent/tools/analytics.py +436 -0
- emdash_core/agent/tools/base.py +131 -0
- emdash_core/agent/tools/coding.py +484 -0
- emdash_core/agent/tools/github_mcp.py +592 -0
- emdash_core/agent/tools/history.py +13 -0
- emdash_core/agent/tools/modes.py +153 -0
- emdash_core/agent/tools/plan.py +206 -0
- emdash_core/agent/tools/plan_write.py +135 -0
- emdash_core/agent/tools/search.py +412 -0
- emdash_core/agent/tools/spec.py +341 -0
- emdash_core/agent/tools/task.py +262 -0
- emdash_core/agent/tools/task_output.py +204 -0
- emdash_core/agent/tools/tasks.py +454 -0
- emdash_core/agent/tools/traversal.py +588 -0
- emdash_core/agent/tools/web.py +179 -0
- emdash_core/analytics/__init__.py +5 -0
- emdash_core/analytics/engine.py +1286 -0
- emdash_core/api/__init__.py +5 -0
- emdash_core/api/agent.py +308 -0
- emdash_core/api/agents.py +154 -0
- emdash_core/api/analyze.py +264 -0
- emdash_core/api/auth.py +173 -0
- emdash_core/api/context.py +77 -0
- emdash_core/api/db.py +121 -0
- emdash_core/api/embed.py +131 -0
- emdash_core/api/feature.py +143 -0
- emdash_core/api/health.py +93 -0
- emdash_core/api/index.py +162 -0
- emdash_core/api/plan.py +110 -0
- emdash_core/api/projectmd.py +210 -0
- emdash_core/api/query.py +320 -0
- emdash_core/api/research.py +122 -0
- emdash_core/api/review.py +161 -0
- emdash_core/api/router.py +76 -0
- emdash_core/api/rules.py +116 -0
- emdash_core/api/search.py +119 -0
- emdash_core/api/spec.py +99 -0
- emdash_core/api/swarm.py +223 -0
- emdash_core/api/tasks.py +109 -0
- emdash_core/api/team.py +120 -0
- emdash_core/auth/__init__.py +17 -0
- emdash_core/auth/github.py +389 -0
- emdash_core/config.py +74 -0
- emdash_core/context/__init__.py +52 -0
- emdash_core/context/models.py +50 -0
- emdash_core/context/providers/__init__.py +11 -0
- emdash_core/context/providers/base.py +74 -0
- emdash_core/context/providers/explored_areas.py +183 -0
- emdash_core/context/providers/touched_areas.py +360 -0
- emdash_core/context/registry.py +73 -0
- emdash_core/context/reranker.py +199 -0
- emdash_core/context/service.py +260 -0
- emdash_core/context/session.py +352 -0
- emdash_core/core/__init__.py +104 -0
- emdash_core/core/config.py +454 -0
- emdash_core/core/exceptions.py +55 -0
- emdash_core/core/models.py +265 -0
- emdash_core/core/review_config.py +57 -0
- emdash_core/db/__init__.py +67 -0
- emdash_core/db/auth.py +134 -0
- emdash_core/db/models.py +91 -0
- emdash_core/db/provider.py +222 -0
- emdash_core/db/providers/__init__.py +5 -0
- emdash_core/db/providers/supabase.py +452 -0
- emdash_core/embeddings/__init__.py +24 -0
- emdash_core/embeddings/indexer.py +534 -0
- emdash_core/embeddings/models.py +192 -0
- emdash_core/embeddings/providers/__init__.py +7 -0
- emdash_core/embeddings/providers/base.py +112 -0
- emdash_core/embeddings/providers/fireworks.py +141 -0
- emdash_core/embeddings/providers/openai.py +104 -0
- emdash_core/embeddings/registry.py +146 -0
- emdash_core/embeddings/service.py +215 -0
- emdash_core/graph/__init__.py +26 -0
- emdash_core/graph/builder.py +134 -0
- emdash_core/graph/connection.py +692 -0
- emdash_core/graph/schema.py +416 -0
- emdash_core/graph/writer.py +667 -0
- emdash_core/ingestion/__init__.py +7 -0
- emdash_core/ingestion/change_detector.py +150 -0
- emdash_core/ingestion/git/__init__.py +5 -0
- emdash_core/ingestion/git/commit_analyzer.py +196 -0
- emdash_core/ingestion/github/__init__.py +6 -0
- emdash_core/ingestion/github/pr_fetcher.py +296 -0
- emdash_core/ingestion/github/task_extractor.py +100 -0
- emdash_core/ingestion/orchestrator.py +540 -0
- emdash_core/ingestion/parsers/__init__.py +10 -0
- emdash_core/ingestion/parsers/base_parser.py +66 -0
- emdash_core/ingestion/parsers/call_graph_builder.py +121 -0
- emdash_core/ingestion/parsers/class_extractor.py +154 -0
- emdash_core/ingestion/parsers/function_extractor.py +202 -0
- emdash_core/ingestion/parsers/import_analyzer.py +119 -0
- emdash_core/ingestion/parsers/python_parser.py +123 -0
- emdash_core/ingestion/parsers/registry.py +72 -0
- emdash_core/ingestion/parsers/ts_ast_parser.js +313 -0
- emdash_core/ingestion/parsers/typescript_parser.py +278 -0
- emdash_core/ingestion/repository.py +346 -0
- emdash_core/models/__init__.py +38 -0
- emdash_core/models/agent.py +68 -0
- emdash_core/models/index.py +77 -0
- emdash_core/models/query.py +113 -0
- emdash_core/planning/__init__.py +7 -0
- emdash_core/planning/agent_api.py +413 -0
- emdash_core/planning/context_builder.py +265 -0
- emdash_core/planning/feature_context.py +232 -0
- emdash_core/planning/feature_expander.py +646 -0
- emdash_core/planning/llm_explainer.py +198 -0
- emdash_core/planning/similarity.py +509 -0
- emdash_core/planning/team_focus.py +821 -0
- emdash_core/server.py +153 -0
- emdash_core/sse/__init__.py +5 -0
- emdash_core/sse/stream.py +196 -0
- emdash_core/swarm/__init__.py +17 -0
- emdash_core/swarm/merge_agent.py +383 -0
- emdash_core/swarm/session_manager.py +274 -0
- emdash_core/swarm/swarm_runner.py +226 -0
- emdash_core/swarm/task_definition.py +137 -0
- emdash_core/swarm/worker_spawner.py +319 -0
- emdash_core/swarm/worktree_manager.py +278 -0
- emdash_core/templates/__init__.py +10 -0
- emdash_core/templates/defaults/agent-builder.md.template +82 -0
- emdash_core/templates/defaults/focus.md.template +115 -0
- emdash_core/templates/defaults/pr-review-enhanced.md.template +309 -0
- emdash_core/templates/defaults/pr-review.md.template +80 -0
- emdash_core/templates/defaults/project.md.template +85 -0
- emdash_core/templates/defaults/research_critic.md.template +112 -0
- emdash_core/templates/defaults/research_planner.md.template +85 -0
- emdash_core/templates/defaults/research_synthesizer.md.template +128 -0
- emdash_core/templates/defaults/reviewer.md.template +81 -0
- emdash_core/templates/defaults/spec.md.template +41 -0
- emdash_core/templates/defaults/tasks.md.template +78 -0
- emdash_core/templates/loader.py +296 -0
- emdash_core/utils/__init__.py +45 -0
- emdash_core/utils/git.py +84 -0
- emdash_core/utils/image.py +502 -0
- emdash_core/utils/logger.py +51 -0
- emdash_core-0.1.7.dist-info/METADATA +35 -0
- emdash_core-0.1.7.dist-info/RECORD +187 -0
- emdash_core-0.1.7.dist-info/WHEEL +4 -0
- emdash_core-0.1.7.dist-info/entry_points.txt +3 -0
|
@@ -0,0 +1,592 @@
|
|
|
1
|
+
"""GitHub MCP tools for live GitHub integration.
|
|
2
|
+
|
|
3
|
+
These tools use the GitHub MCP server to provide real-time
|
|
4
|
+
GitHub functionality including code search, PR analysis, and more.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import json
|
|
8
|
+
from typing import Any, Optional
|
|
9
|
+
|
|
10
|
+
from .base import BaseTool, ToolResult, ToolCategory
|
|
11
|
+
from ...utils.logger import log
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class MCPBaseTool(BaseTool):
|
|
15
|
+
"""Base class for MCP-backed tools."""
|
|
16
|
+
|
|
17
|
+
category = ToolCategory.HISTORY
|
|
18
|
+
|
|
19
|
+
def _get_mcp_client(self):
|
|
20
|
+
"""Get the MCP client, starting if needed.
|
|
21
|
+
|
|
22
|
+
Returns:
|
|
23
|
+
GitHubMCPClient instance or None
|
|
24
|
+
"""
|
|
25
|
+
try:
|
|
26
|
+
from ..mcp.client import GitHubMCPClient
|
|
27
|
+
|
|
28
|
+
client = GitHubMCPClient()
|
|
29
|
+
if not client.is_running:
|
|
30
|
+
client.start()
|
|
31
|
+
return client
|
|
32
|
+
except Exception as e:
|
|
33
|
+
log.warning(f"Failed to get MCP client: {e}")
|
|
34
|
+
return None
|
|
35
|
+
|
|
36
|
+
def _call_mcp_tool(
|
|
37
|
+
self,
|
|
38
|
+
tool_name: str,
|
|
39
|
+
arguments: dict,
|
|
40
|
+
) -> ToolResult:
|
|
41
|
+
"""Call an MCP tool and return result.
|
|
42
|
+
|
|
43
|
+
Args:
|
|
44
|
+
tool_name: MCP tool name
|
|
45
|
+
arguments: Tool arguments
|
|
46
|
+
|
|
47
|
+
Returns:
|
|
48
|
+
ToolResult
|
|
49
|
+
"""
|
|
50
|
+
client = self._get_mcp_client()
|
|
51
|
+
if not client:
|
|
52
|
+
return ToolResult.error_result(
|
|
53
|
+
"GitHub MCP not available",
|
|
54
|
+
suggestions=["Check GITHUB_TOKEN is set", "Install github-mcp-server"],
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
try:
|
|
58
|
+
response = client.call_tool(tool_name, arguments)
|
|
59
|
+
|
|
60
|
+
if response.is_error:
|
|
61
|
+
return ToolResult.error_result(response.get_text())
|
|
62
|
+
|
|
63
|
+
# Parse response content
|
|
64
|
+
result_data = {"raw": response.get_text()}
|
|
65
|
+
|
|
66
|
+
# Try to parse as JSON
|
|
67
|
+
for item in response.content:
|
|
68
|
+
if item.get("type") == "text":
|
|
69
|
+
try:
|
|
70
|
+
parsed = json.loads(item.get("text", ""))
|
|
71
|
+
if isinstance(parsed, dict):
|
|
72
|
+
result_data.update(parsed)
|
|
73
|
+
elif isinstance(parsed, list):
|
|
74
|
+
result_data["results"] = parsed
|
|
75
|
+
except json.JSONDecodeError:
|
|
76
|
+
pass
|
|
77
|
+
|
|
78
|
+
return ToolResult.success_result(data=result_data)
|
|
79
|
+
|
|
80
|
+
except Exception as e:
|
|
81
|
+
log.exception(f"MCP tool call failed: {tool_name}")
|
|
82
|
+
return ToolResult.error_result(f"MCP call failed: {str(e)}")
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
class GitHubSearchCodeTool(MCPBaseTool):
|
|
86
|
+
"""Search code on GitHub."""
|
|
87
|
+
|
|
88
|
+
name = "github_search_code"
|
|
89
|
+
description = """Search for code across GitHub repositories.
|
|
90
|
+
Finds code matching a query, useful for finding implementations,
|
|
91
|
+
patterns, or usage examples."""
|
|
92
|
+
|
|
93
|
+
def execute(
|
|
94
|
+
self,
|
|
95
|
+
query: str,
|
|
96
|
+
repo: Optional[str] = None,
|
|
97
|
+
language: Optional[str] = None,
|
|
98
|
+
per_page: int = 10,
|
|
99
|
+
) -> ToolResult:
|
|
100
|
+
"""Search GitHub code.
|
|
101
|
+
|
|
102
|
+
Args:
|
|
103
|
+
query: Search query
|
|
104
|
+
repo: Optional repo filter (owner/repo)
|
|
105
|
+
language: Optional language filter
|
|
106
|
+
per_page: Results per page
|
|
107
|
+
|
|
108
|
+
Returns:
|
|
109
|
+
ToolResult with code matches
|
|
110
|
+
"""
|
|
111
|
+
full_query = query
|
|
112
|
+
if repo:
|
|
113
|
+
full_query += f" repo:{repo}"
|
|
114
|
+
if language:
|
|
115
|
+
full_query += f" language:{language}"
|
|
116
|
+
|
|
117
|
+
return self._call_mcp_tool("search_code", {
|
|
118
|
+
"query": full_query,
|
|
119
|
+
"per_page": per_page,
|
|
120
|
+
})
|
|
121
|
+
|
|
122
|
+
def get_schema(self) -> dict:
|
|
123
|
+
"""Get OpenAI function schema."""
|
|
124
|
+
return self._make_schema(
|
|
125
|
+
properties={
|
|
126
|
+
"query": {
|
|
127
|
+
"type": "string",
|
|
128
|
+
"description": "Search query for code",
|
|
129
|
+
},
|
|
130
|
+
"repo": {
|
|
131
|
+
"type": "string",
|
|
132
|
+
"description": "Repository filter (owner/repo)",
|
|
133
|
+
},
|
|
134
|
+
"language": {
|
|
135
|
+
"type": "string",
|
|
136
|
+
"description": "Language filter",
|
|
137
|
+
},
|
|
138
|
+
"per_page": {
|
|
139
|
+
"type": "integer",
|
|
140
|
+
"description": "Results per page",
|
|
141
|
+
"default": 10,
|
|
142
|
+
},
|
|
143
|
+
},
|
|
144
|
+
required=["query"],
|
|
145
|
+
)
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
class GitHubGetFileContentTool(MCPBaseTool):
|
|
149
|
+
"""Get file content from GitHub."""
|
|
150
|
+
|
|
151
|
+
name = "github_get_file_content"
|
|
152
|
+
description = """Get the content of a file from a GitHub repository.
|
|
153
|
+
Retrieves the actual file content for analysis."""
|
|
154
|
+
|
|
155
|
+
def execute(
|
|
156
|
+
self,
|
|
157
|
+
owner: str,
|
|
158
|
+
repo: str,
|
|
159
|
+
path: str,
|
|
160
|
+
ref: Optional[str] = None,
|
|
161
|
+
) -> ToolResult:
|
|
162
|
+
"""Get file content.
|
|
163
|
+
|
|
164
|
+
Args:
|
|
165
|
+
owner: Repository owner
|
|
166
|
+
repo: Repository name
|
|
167
|
+
path: File path
|
|
168
|
+
ref: Optional git ref (branch, tag, commit)
|
|
169
|
+
|
|
170
|
+
Returns:
|
|
171
|
+
ToolResult with file content
|
|
172
|
+
"""
|
|
173
|
+
args = {"owner": owner, "repo": repo, "path": path}
|
|
174
|
+
if ref:
|
|
175
|
+
args["ref"] = ref
|
|
176
|
+
|
|
177
|
+
return self._call_mcp_tool("get_file_contents", args)
|
|
178
|
+
|
|
179
|
+
def get_schema(self) -> dict:
|
|
180
|
+
"""Get OpenAI function schema."""
|
|
181
|
+
return self._make_schema(
|
|
182
|
+
properties={
|
|
183
|
+
"owner": {
|
|
184
|
+
"type": "string",
|
|
185
|
+
"description": "Repository owner",
|
|
186
|
+
},
|
|
187
|
+
"repo": {
|
|
188
|
+
"type": "string",
|
|
189
|
+
"description": "Repository name",
|
|
190
|
+
},
|
|
191
|
+
"path": {
|
|
192
|
+
"type": "string",
|
|
193
|
+
"description": "Path to the file",
|
|
194
|
+
},
|
|
195
|
+
"ref": {
|
|
196
|
+
"type": "string",
|
|
197
|
+
"description": "Git reference (branch, tag, commit)",
|
|
198
|
+
},
|
|
199
|
+
},
|
|
200
|
+
required=["owner", "repo", "path"],
|
|
201
|
+
)
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
class GitHubPRDetailsTool(MCPBaseTool):
|
|
205
|
+
"""Get detailed PR information."""
|
|
206
|
+
|
|
207
|
+
name = "github_pr_details"
|
|
208
|
+
description = """Get detailed information about a pull request.
|
|
209
|
+
Includes diff, comments, reviews, and status."""
|
|
210
|
+
|
|
211
|
+
def execute(
|
|
212
|
+
self,
|
|
213
|
+
owner: str,
|
|
214
|
+
repo: str,
|
|
215
|
+
pull_number: int,
|
|
216
|
+
) -> ToolResult:
|
|
217
|
+
"""Get PR details.
|
|
218
|
+
|
|
219
|
+
Args:
|
|
220
|
+
owner: Repository owner
|
|
221
|
+
repo: Repository name
|
|
222
|
+
pull_number: PR number
|
|
223
|
+
|
|
224
|
+
Returns:
|
|
225
|
+
ToolResult with PR details
|
|
226
|
+
"""
|
|
227
|
+
return self._call_mcp_tool("get_pull_request", {
|
|
228
|
+
"owner": owner,
|
|
229
|
+
"repo": repo,
|
|
230
|
+
"pull_number": pull_number,
|
|
231
|
+
})
|
|
232
|
+
|
|
233
|
+
def get_schema(self) -> dict:
|
|
234
|
+
"""Get OpenAI function schema."""
|
|
235
|
+
return self._make_schema(
|
|
236
|
+
properties={
|
|
237
|
+
"owner": {
|
|
238
|
+
"type": "string",
|
|
239
|
+
"description": "Repository owner",
|
|
240
|
+
},
|
|
241
|
+
"repo": {
|
|
242
|
+
"type": "string",
|
|
243
|
+
"description": "Repository name",
|
|
244
|
+
},
|
|
245
|
+
"pull_number": {
|
|
246
|
+
"type": "integer",
|
|
247
|
+
"description": "Pull request number",
|
|
248
|
+
},
|
|
249
|
+
},
|
|
250
|
+
required=["owner", "repo", "pull_number"],
|
|
251
|
+
)
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
class GitHubListPRsTool(MCPBaseTool):
|
|
255
|
+
"""List pull requests."""
|
|
256
|
+
|
|
257
|
+
name = "github_list_prs"
|
|
258
|
+
description = """List pull requests for a repository.
|
|
259
|
+
Can filter by state (open, closed, all)."""
|
|
260
|
+
|
|
261
|
+
def execute(
|
|
262
|
+
self,
|
|
263
|
+
owner: str,
|
|
264
|
+
repo: str,
|
|
265
|
+
state: str = "open",
|
|
266
|
+
per_page: int = 10,
|
|
267
|
+
) -> ToolResult:
|
|
268
|
+
"""List PRs.
|
|
269
|
+
|
|
270
|
+
Args:
|
|
271
|
+
owner: Repository owner
|
|
272
|
+
repo: Repository name
|
|
273
|
+
state: PR state filter (open, closed, all)
|
|
274
|
+
per_page: Results per page
|
|
275
|
+
|
|
276
|
+
Returns:
|
|
277
|
+
ToolResult with PR list
|
|
278
|
+
"""
|
|
279
|
+
return self._call_mcp_tool("list_pull_requests", {
|
|
280
|
+
"owner": owner,
|
|
281
|
+
"repo": repo,
|
|
282
|
+
"state": state,
|
|
283
|
+
"per_page": per_page,
|
|
284
|
+
})
|
|
285
|
+
|
|
286
|
+
def get_schema(self) -> dict:
|
|
287
|
+
"""Get OpenAI function schema."""
|
|
288
|
+
return self._make_schema(
|
|
289
|
+
properties={
|
|
290
|
+
"owner": {
|
|
291
|
+
"type": "string",
|
|
292
|
+
"description": "Repository owner",
|
|
293
|
+
},
|
|
294
|
+
"repo": {
|
|
295
|
+
"type": "string",
|
|
296
|
+
"description": "Repository name",
|
|
297
|
+
},
|
|
298
|
+
"state": {
|
|
299
|
+
"type": "string",
|
|
300
|
+
"enum": ["open", "closed", "all"],
|
|
301
|
+
"description": "PR state filter",
|
|
302
|
+
"default": "open",
|
|
303
|
+
},
|
|
304
|
+
"per_page": {
|
|
305
|
+
"type": "integer",
|
|
306
|
+
"description": "Results per page",
|
|
307
|
+
"default": 10,
|
|
308
|
+
},
|
|
309
|
+
},
|
|
310
|
+
required=["owner", "repo"],
|
|
311
|
+
)
|
|
312
|
+
|
|
313
|
+
|
|
314
|
+
class GitHubSearchReposTool(MCPBaseTool):
|
|
315
|
+
"""Search GitHub repositories."""
|
|
316
|
+
|
|
317
|
+
name = "github_search_repos"
|
|
318
|
+
description = """Search for repositories on GitHub.
|
|
319
|
+
Find repos by topic, name, or description."""
|
|
320
|
+
|
|
321
|
+
def execute(
|
|
322
|
+
self,
|
|
323
|
+
query: str,
|
|
324
|
+
per_page: int = 10,
|
|
325
|
+
) -> ToolResult:
|
|
326
|
+
"""Search repositories.
|
|
327
|
+
|
|
328
|
+
Args:
|
|
329
|
+
query: Search query
|
|
330
|
+
per_page: Results per page
|
|
331
|
+
|
|
332
|
+
Returns:
|
|
333
|
+
ToolResult with repo matches
|
|
334
|
+
"""
|
|
335
|
+
return self._call_mcp_tool("search_repositories", {
|
|
336
|
+
"query": query,
|
|
337
|
+
"per_page": per_page,
|
|
338
|
+
})
|
|
339
|
+
|
|
340
|
+
def get_schema(self) -> dict:
|
|
341
|
+
"""Get OpenAI function schema."""
|
|
342
|
+
return self._make_schema(
|
|
343
|
+
properties={
|
|
344
|
+
"query": {
|
|
345
|
+
"type": "string",
|
|
346
|
+
"description": "Search query",
|
|
347
|
+
},
|
|
348
|
+
"per_page": {
|
|
349
|
+
"type": "integer",
|
|
350
|
+
"description": "Results per page",
|
|
351
|
+
"default": 10,
|
|
352
|
+
},
|
|
353
|
+
},
|
|
354
|
+
required=["query"],
|
|
355
|
+
)
|
|
356
|
+
|
|
357
|
+
|
|
358
|
+
class GitHubSearchPRsTool(MCPBaseTool):
|
|
359
|
+
"""Search pull requests on GitHub."""
|
|
360
|
+
|
|
361
|
+
name = "github_search_prs"
|
|
362
|
+
description = """Search for pull requests across GitHub.
|
|
363
|
+
Find PRs by title, body, or comments."""
|
|
364
|
+
|
|
365
|
+
def execute(
|
|
366
|
+
self,
|
|
367
|
+
query: str,
|
|
368
|
+
repo: Optional[str] = None,
|
|
369
|
+
state: Optional[str] = None,
|
|
370
|
+
per_page: int = 10,
|
|
371
|
+
) -> ToolResult:
|
|
372
|
+
"""Search PRs.
|
|
373
|
+
|
|
374
|
+
Args:
|
|
375
|
+
query: Search query
|
|
376
|
+
repo: Optional repo filter
|
|
377
|
+
state: Optional state filter
|
|
378
|
+
per_page: Results per page
|
|
379
|
+
|
|
380
|
+
Returns:
|
|
381
|
+
ToolResult with PR matches
|
|
382
|
+
"""
|
|
383
|
+
full_query = query + " is:pr"
|
|
384
|
+
if repo:
|
|
385
|
+
full_query += f" repo:{repo}"
|
|
386
|
+
if state:
|
|
387
|
+
full_query += f" is:{state}"
|
|
388
|
+
|
|
389
|
+
return self._call_mcp_tool("search_issues", {
|
|
390
|
+
"query": full_query,
|
|
391
|
+
"per_page": per_page,
|
|
392
|
+
})
|
|
393
|
+
|
|
394
|
+
def get_schema(self) -> dict:
|
|
395
|
+
"""Get OpenAI function schema."""
|
|
396
|
+
return self._make_schema(
|
|
397
|
+
properties={
|
|
398
|
+
"query": {
|
|
399
|
+
"type": "string",
|
|
400
|
+
"description": "Search query",
|
|
401
|
+
},
|
|
402
|
+
"repo": {
|
|
403
|
+
"type": "string",
|
|
404
|
+
"description": "Repository filter (owner/repo)",
|
|
405
|
+
},
|
|
406
|
+
"state": {
|
|
407
|
+
"type": "string",
|
|
408
|
+
"enum": ["open", "closed"],
|
|
409
|
+
"description": "PR state filter",
|
|
410
|
+
},
|
|
411
|
+
"per_page": {
|
|
412
|
+
"type": "integer",
|
|
413
|
+
"description": "Results per page",
|
|
414
|
+
"default": 10,
|
|
415
|
+
},
|
|
416
|
+
},
|
|
417
|
+
required=["query"],
|
|
418
|
+
)
|
|
419
|
+
|
|
420
|
+
|
|
421
|
+
class GitHubGetIssueTool(MCPBaseTool):
|
|
422
|
+
"""Get issue details from GitHub."""
|
|
423
|
+
|
|
424
|
+
name = "github_get_issue"
|
|
425
|
+
description = """Get detailed information about an issue.
|
|
426
|
+
Includes body, comments, labels, and assignees."""
|
|
427
|
+
|
|
428
|
+
def execute(
|
|
429
|
+
self,
|
|
430
|
+
owner: str,
|
|
431
|
+
repo: str,
|
|
432
|
+
issue_number: int,
|
|
433
|
+
) -> ToolResult:
|
|
434
|
+
"""Get issue details.
|
|
435
|
+
|
|
436
|
+
Args:
|
|
437
|
+
owner: Repository owner
|
|
438
|
+
repo: Repository name
|
|
439
|
+
issue_number: Issue number
|
|
440
|
+
|
|
441
|
+
Returns:
|
|
442
|
+
ToolResult with issue details
|
|
443
|
+
"""
|
|
444
|
+
return self._call_mcp_tool("get_issue", {
|
|
445
|
+
"owner": owner,
|
|
446
|
+
"repo": repo,
|
|
447
|
+
"issue_number": issue_number,
|
|
448
|
+
})
|
|
449
|
+
|
|
450
|
+
def get_schema(self) -> dict:
|
|
451
|
+
"""Get OpenAI function schema."""
|
|
452
|
+
return self._make_schema(
|
|
453
|
+
properties={
|
|
454
|
+
"owner": {
|
|
455
|
+
"type": "string",
|
|
456
|
+
"description": "Repository owner",
|
|
457
|
+
},
|
|
458
|
+
"repo": {
|
|
459
|
+
"type": "string",
|
|
460
|
+
"description": "Repository name",
|
|
461
|
+
},
|
|
462
|
+
"issue_number": {
|
|
463
|
+
"type": "integer",
|
|
464
|
+
"description": "Issue number",
|
|
465
|
+
},
|
|
466
|
+
},
|
|
467
|
+
required=["owner", "repo", "issue_number"],
|
|
468
|
+
)
|
|
469
|
+
|
|
470
|
+
|
|
471
|
+
class GitHubViewRepoStructureTool(MCPBaseTool):
|
|
472
|
+
"""View repository structure."""
|
|
473
|
+
|
|
474
|
+
name = "github_view_repo_structure"
|
|
475
|
+
description = """View the directory structure of a GitHub repository.
|
|
476
|
+
Shows files and folders in a tree format."""
|
|
477
|
+
|
|
478
|
+
def execute(
|
|
479
|
+
self,
|
|
480
|
+
owner: str,
|
|
481
|
+
repo: str,
|
|
482
|
+
path: str = "",
|
|
483
|
+
ref: Optional[str] = None,
|
|
484
|
+
) -> ToolResult:
|
|
485
|
+
"""View repo structure.
|
|
486
|
+
|
|
487
|
+
Args:
|
|
488
|
+
owner: Repository owner
|
|
489
|
+
repo: Repository name
|
|
490
|
+
path: Path within repo
|
|
491
|
+
ref: Git reference
|
|
492
|
+
|
|
493
|
+
Returns:
|
|
494
|
+
ToolResult with directory structure
|
|
495
|
+
"""
|
|
496
|
+
args = {"owner": owner, "repo": repo}
|
|
497
|
+
if path:
|
|
498
|
+
args["path"] = path
|
|
499
|
+
if ref:
|
|
500
|
+
args["ref"] = ref
|
|
501
|
+
|
|
502
|
+
return self._call_mcp_tool("get_directory_contents", args)
|
|
503
|
+
|
|
504
|
+
def get_schema(self) -> dict:
|
|
505
|
+
"""Get OpenAI function schema."""
|
|
506
|
+
return self._make_schema(
|
|
507
|
+
properties={
|
|
508
|
+
"owner": {
|
|
509
|
+
"type": "string",
|
|
510
|
+
"description": "Repository owner",
|
|
511
|
+
},
|
|
512
|
+
"repo": {
|
|
513
|
+
"type": "string",
|
|
514
|
+
"description": "Repository name",
|
|
515
|
+
},
|
|
516
|
+
"path": {
|
|
517
|
+
"type": "string",
|
|
518
|
+
"description": "Path within the repository",
|
|
519
|
+
"default": "",
|
|
520
|
+
},
|
|
521
|
+
"ref": {
|
|
522
|
+
"type": "string",
|
|
523
|
+
"description": "Git reference (branch, tag, commit)",
|
|
524
|
+
},
|
|
525
|
+
},
|
|
526
|
+
required=["owner", "repo"],
|
|
527
|
+
)
|
|
528
|
+
|
|
529
|
+
|
|
530
|
+
class GitHubCreateReviewTool(MCPBaseTool):
|
|
531
|
+
"""Create a PR review."""
|
|
532
|
+
|
|
533
|
+
name = "github_create_review"
|
|
534
|
+
description = """Create a review on a pull request.
|
|
535
|
+
Can approve, request changes, or comment."""
|
|
536
|
+
|
|
537
|
+
def execute(
|
|
538
|
+
self,
|
|
539
|
+
owner: str,
|
|
540
|
+
repo: str,
|
|
541
|
+
pull_number: int,
|
|
542
|
+
event: str,
|
|
543
|
+
body: str,
|
|
544
|
+
) -> ToolResult:
|
|
545
|
+
"""Create a review.
|
|
546
|
+
|
|
547
|
+
Args:
|
|
548
|
+
owner: Repository owner
|
|
549
|
+
repo: Repository name
|
|
550
|
+
pull_number: PR number
|
|
551
|
+
event: Review event (APPROVE, REQUEST_CHANGES, COMMENT)
|
|
552
|
+
body: Review body
|
|
553
|
+
|
|
554
|
+
Returns:
|
|
555
|
+
ToolResult with review details
|
|
556
|
+
"""
|
|
557
|
+
return self._call_mcp_tool("create_pull_request_review", {
|
|
558
|
+
"owner": owner,
|
|
559
|
+
"repo": repo,
|
|
560
|
+
"pull_number": pull_number,
|
|
561
|
+
"event": event,
|
|
562
|
+
"body": body,
|
|
563
|
+
})
|
|
564
|
+
|
|
565
|
+
def get_schema(self) -> dict:
|
|
566
|
+
"""Get OpenAI function schema."""
|
|
567
|
+
return self._make_schema(
|
|
568
|
+
properties={
|
|
569
|
+
"owner": {
|
|
570
|
+
"type": "string",
|
|
571
|
+
"description": "Repository owner",
|
|
572
|
+
},
|
|
573
|
+
"repo": {
|
|
574
|
+
"type": "string",
|
|
575
|
+
"description": "Repository name",
|
|
576
|
+
},
|
|
577
|
+
"pull_number": {
|
|
578
|
+
"type": "integer",
|
|
579
|
+
"description": "Pull request number",
|
|
580
|
+
},
|
|
581
|
+
"event": {
|
|
582
|
+
"type": "string",
|
|
583
|
+
"enum": ["APPROVE", "REQUEST_CHANGES", "COMMENT"],
|
|
584
|
+
"description": "Review event type",
|
|
585
|
+
},
|
|
586
|
+
"body": {
|
|
587
|
+
"type": "string",
|
|
588
|
+
"description": "Review body/comment",
|
|
589
|
+
},
|
|
590
|
+
},
|
|
591
|
+
required=["owner", "repo", "pull_number", "event", "body"],
|
|
592
|
+
)
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"""History tools placeholder.
|
|
2
|
+
|
|
3
|
+
History tools have been moved to GitHub MCP for live GitHub integration.
|
|
4
|
+
Use the following GitHub MCP tools instead:
|
|
5
|
+
|
|
6
|
+
- github_list_prs: List pull requests
|
|
7
|
+
- github_pr_details: Get PR details with diff
|
|
8
|
+
- github_search_prs: Search PRs by keywords
|
|
9
|
+
- github_get_issue: Get issue details
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
# This file is intentionally minimal.
|
|
13
|
+
# All history functionality is now provided by GitHub MCP tools.
|