octocode-mcp 2.3.10 → 2.3.11
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/README.md +71 -173
- package/build/index.js +211 -166
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
**The Perfect AI Code Assistant - Advanced Search & Discovery Across GitHub & NPM**
|
|
4
4
|
|
|
5
5
|
<div>
|
|
6
|
-
<img src="./assets/logo.png">
|
|
6
|
+
<img src="./assets/logo.png" width="400px">
|
|
7
7
|
|
|
8
8
|
[](./package.json)
|
|
9
9
|
[](./package.json)
|
|
@@ -13,44 +13,25 @@
|
|
|
13
13
|
|
|
14
14
|
## What is Octocode? 🐙
|
|
15
15
|
|
|
16
|
-
**The perfect code assistant that can help understand anything.** Octocode
|
|
17
|
-
|
|
18
|
-
Instead of manually browsing repositories, you can ask questions like:
|
|
16
|
+
**The perfect code assistant that can help understand anything.** Octocode provides AI-powered advanced search with heuristic discovery and smart fallbacks to understand connections between repositories and NPM packages across any privilege level you have.
|
|
19
17
|
|
|
18
|
+
Instead of manually browsing repositories, ask questions like:
|
|
20
19
|
- *"How did React implement concurrent rendering?"*
|
|
21
20
|
- *"Show me authentication patterns in Next.js applications"*
|
|
22
21
|
- *"Find examples of how to use this specific API"*
|
|
23
22
|
- *"What's the architecture of this library?"*
|
|
24
23
|
- *"How do I use this MCP tool effectively?"*
|
|
25
24
|
|
|
26
|
-
## Recommended Use Cases
|
|
27
|
-
|
|
28
|
-
**Use Octocode when you need to:**
|
|
29
|
-
|
|
30
|
-
- **🔍 Understand implementations** - See how features work across different repositories
|
|
31
|
-
- **📚 Find real code examples** - Discover patterns and best practices from production code
|
|
32
|
-
- **🏗️ Analyze architecture** - Explore how systems are designed and structured
|
|
33
|
-
- **🔬 Research approaches** - Compare different implementation strategies
|
|
34
|
-
- **💡 Learn from code** - Deep-dive into technical details and understand "how does this work?"
|
|
35
|
-
|
|
36
25
|
## Unique Value Proposition
|
|
37
26
|
|
|
38
27
|
**The most advanced AI-powered code assistant for understanding connections across the entire GitHub & NPM ecosystem.** While other GitHub MCPs focus on project management or basic operations, Octocode provides unparalleled depth for code discovery and technical research.
|
|
39
28
|
|
|
40
|
-
**🚀 Out-of-the-Box Advanced Search (Powered by AI):**
|
|
41
|
-
- **🧠 Heuristic Search** - Intelligent pattern recognition that finds relevant code even with vague queries
|
|
42
|
-
- **🔄 Smart Fallbacks** - Automatic retry with alternative search strategies when initial searches fail
|
|
43
|
-
- **🎯 Smart Discovery** - AI-guided exploration that uncovers hidden connections and patterns
|
|
44
|
-
- **🔗 Connection Intelligence** - Understands relationships between repositories, packages, and dependencies
|
|
45
|
-
- **📊 Multi-dimensional Analysis** - Combines code, commits, issues, discussions, and package data
|
|
46
|
-
|
|
47
29
|
**Key Differentiators:**
|
|
48
|
-
- **🧠
|
|
49
|
-
- **🔐
|
|
50
|
-
- **🔗
|
|
51
|
-
- **🌐
|
|
52
|
-
|
|
53
|
-
It's the tool you reach for when you need to understand *"how does this work?"* rather than *"how do I manage this project?"*
|
|
30
|
+
- **🧠 AI-Powered Search** - Heuristic algorithms with smart fallbacks that understand code context and find relevant code even with vague queries
|
|
31
|
+
- **🔐 Zero-Config Security** - Uses GitHub CLI authentication - no personal access tokens needed
|
|
32
|
+
- **🔗 Connection Intelligence** - Maps NPM packages to repositories, traces dependencies, finds related implementations
|
|
33
|
+
- **🌐 Universal Access** - Works seamlessly with public, private, and organization repositories
|
|
34
|
+
- **⚡ LLM Optimized** - Advanced content minification and partial fetching reduces token usage by 80-90%
|
|
54
35
|
|
|
55
36
|
## Quick Start 🚀
|
|
56
37
|
|
|
@@ -74,13 +55,11 @@ gh auth login
|
|
|
74
55
|
npm login
|
|
75
56
|
```
|
|
76
57
|
|
|
77
|
-
**🔐
|
|
78
|
-
- ✅ **No personal access tokens
|
|
79
|
-
- ✅ **Secure OAuth flow** - Browser-based authentication, no tokens to store
|
|
58
|
+
**🔐 Authentication Benefits:**
|
|
59
|
+
- ✅ **No personal access tokens** - Uses GitHub CLI OAuth flow
|
|
80
60
|
- ✅ **Enterprise ready** - Works with SSO, 2FA, and organization access
|
|
81
|
-
- ✅ **
|
|
82
|
-
- ✅ **Zero configuration** - Uses
|
|
83
|
-
|
|
61
|
+
- ✅ **Automatic organization detection** - Instantly accesses your private repositories
|
|
62
|
+
- ✅ **Zero configuration** - Uses existing `gh` CLI permissions
|
|
84
63
|
|
|
85
64
|
### 3. Add to MCP Configuration
|
|
86
65
|
```json
|
|
@@ -92,157 +71,95 @@ npm login
|
|
|
92
71
|
}
|
|
93
72
|
```
|
|
94
73
|
|
|
95
|
-
**That's it!**
|
|
74
|
+
**That's it!** Octocode automatically works with your organization's private repositories.
|
|
96
75
|
|
|
97
|
-
## How
|
|
76
|
+
## How It Works 🔄
|
|
98
77
|
|
|
99
78
|
**Smart Discovery Flow:**
|
|
100
|
-
1. **🔍 Query Analysis** → AI determines the best search strategy
|
|
101
|
-
2. **⚡ Multi-Tool Orchestration** → Intelligently combines 10 specialized tools
|
|
102
|
-
3. **🔄 Smart Fallbacks** → Automatically retries with different approaches
|
|
103
|
-
4. **🔗 Cross-Reference Discovery** → Links packages to repositories
|
|
104
|
-
5. **🎯 Context Synthesis** → Provides comprehensive understanding
|
|
79
|
+
1. **🔍 Query Analysis** → AI determines the best search strategy
|
|
80
|
+
2. **⚡ Multi-Tool Orchestration** → Intelligently combines 10 specialized tools
|
|
81
|
+
3. **🔄 Smart Fallbacks** → Automatically retries with different approaches
|
|
82
|
+
4. **🔗 Cross-Reference Discovery** → Links packages to repositories with commit SHA integration
|
|
83
|
+
5. **🎯 Context Synthesis** → Provides comprehensive understanding
|
|
105
84
|
|
|
106
85
|
## Example Flows
|
|
107
86
|
|
|
108
87
|
### Example 1: LangGraph Node.js Implementation Tutorial
|
|
109
88
|
**Query:** "Show implementations of langgraph in node js. Make a tutorial for how to implement a simple agent using OpenAI API."
|
|
110
89
|
|
|
111
|
-
|
|
90
|
+
<a href="https://youtu.be/E5HUlRckpvg?si=XXLle59C92esDscS"><img src="assets/langchainTutorial.gif" alt="LangGraph Node.js Tutorial" width="50%"></a>
|
|
112
91
|
|
|
113
92
|
### Example 2: Zustand React State Management
|
|
114
93
|
**Query:** "Show me how to add zustand to react application. Show examples and best practices"
|
|
115
94
|
|
|
116
|
-
|
|
95
|
+
<a href="https://youtu.be/EgYbsuWmqsI?si=CN_KwCPgwprImynU"><img src="assets/reactZustand.gif" alt="Zustand React State Management" width="50%"></a>
|
|
117
96
|
|
|
118
97
|
### Example 3: React vs Vue.js Rendering Comparison
|
|
119
98
|
**Query:** "How did React implement their concurrent rendering flows? How is it different from Vue.js rendering mechanism? Which is better?"
|
|
120
99
|
|
|
121
|
-
|
|
100
|
+
<a href="https://youtu.be/-_pbCbLXKDc?si=KiPeGCzmwWtb6G3r"><img src="assets/reactVSVueJS.gif" alt="React vs Vue.js Rendering Comparison" width="50%"></a>
|
|
122
101
|
|
|
123
102
|
## Core Features 🛠️
|
|
124
103
|
|
|
125
|
-
### 🧠 AI-Powered
|
|
126
|
-
- **
|
|
127
|
-
- **
|
|
128
|
-
- **
|
|
129
|
-
- **
|
|
130
|
-
- **
|
|
131
|
-
- **Graceful Error Recovery** - Comprehensive error handling with intelligent retry mechanisms
|
|
132
|
-
|
|
133
|
-
### 🔗 Connection Intelligence
|
|
134
|
-
- **Repository-Package Mapping** - Automatically links NPM packages to their GitHub repositories
|
|
135
|
-
- **Dependency Tracing** - Follows dependency chains across the entire ecosystem
|
|
136
|
-
- **Cross-Reference Analysis** - Finds how different projects implement similar patterns
|
|
137
|
-
- **Ecosystem Understanding** - Maps relationships between libraries, frameworks, and tools
|
|
138
|
-
|
|
139
|
-
### 🌐 Universal Access & Discovery
|
|
140
|
-
- **Cross-Privilege Search** - Works with any access level you have (public, private, organization)
|
|
141
|
-
- **Organization-Aware** - Automatically detects and uses your GitHub organization memberships
|
|
142
|
-
- **Smart Repository Discovery** - Finds relevant repositories even when you don't know they exist
|
|
143
|
-
- **Progressive Refinement** - AI-guided search that gets more precise with each iteration
|
|
144
|
-
|
|
145
|
-
### 📊 Multi-Dimensional Analysis
|
|
146
|
-
- **Code + Context** - Combines source code with commits, issues, discussions, and documentation
|
|
147
|
-
- **Historical Understanding** - Tracks how implementations evolved over time
|
|
148
|
-
- **Community Insights** - Discovers patterns from real-world usage and discussions
|
|
149
|
-
- **Quality Signals** - Uses NPM publication and GitHub activity as quality indicators
|
|
104
|
+
### 🧠 AI-Powered Intelligence
|
|
105
|
+
- **Advanced Search** - Heuristic pattern recognition with automatic fallback strategies
|
|
106
|
+
- **Connection Mapping** - Automatically links NPM packages to GitHub repositories
|
|
107
|
+
- **Cross-Reference Analysis** - Discovers how different projects implement similar patterns
|
|
108
|
+
- **Progressive Refinement** - AI-guided search that improves with each iteration
|
|
109
|
+
- **Context-Aware Discovery** - Understands relationships between code, commits, issues, and discussions
|
|
150
110
|
|
|
151
111
|
### 🔗 Commit SHA Integration
|
|
152
|
-
- **Time Travel Code Viewing** - View files from specific commits and pull requests
|
|
153
|
-
- **PR Code Analysis** - Automatically fetch commit SHAs
|
|
154
|
-
- **Historical Implementation** - Compare
|
|
155
|
-
- **Cross-Reference Discovery** - Link commits, pull requests, and current implementations seamlessly
|
|
156
|
-
|
|
157
|
-
### ⚡ LLM Content Optimization
|
|
158
|
-
- **Intelligent Content Selection** - Automatically identifies and extracts only relevant code sections for research
|
|
159
|
-
- **Smart Minification** - Advanced content compression that preserves meaning while reducing tokens by 80-90%
|
|
160
|
-
- **Partial File Access** - Fetches targeted line ranges from search results, avoiding full file downloads
|
|
161
|
-
- **Context-Aware Processing** - Indentation-aware minification for 15+ programming languages
|
|
162
|
-
- **Binary Detection & Filtering** - Automatically skips non-text files and suggests alternatives
|
|
163
|
-
- **Token Efficiency** - Optimizes content for maximum LLM comprehension with minimal token usage
|
|
164
|
-
- **Line Number Preservation** - Maintains precise line references for code navigation and debugging
|
|
165
|
-
|
|
166
|
-
**Optimization Workflow:**
|
|
167
|
-
1. **🎯 Smart Targeting** → Extract specific line ranges from search results
|
|
168
|
-
2. **🧹 Content Filtering** → Remove comments, whitespace, and non-essential elements
|
|
169
|
-
3. **🗜️ Intelligent Compression** → Language-aware minification preserving code structure
|
|
170
|
-
4. **📍 Context Preservation** → Keep essential context and line number references
|
|
171
|
-
5. **⚡ Token Optimization** → Deliver maximum code insight with minimal LLM token consumption
|
|
112
|
+
- **Time Travel Code Viewing** - View files from specific commits and pull requests
|
|
113
|
+
- **PR Code Analysis** - Automatically fetch commit SHAs for precise code comparison
|
|
114
|
+
- **Historical Implementation** - Compare code evolution across versions
|
|
172
115
|
|
|
173
|
-
|
|
116
|
+
### ⚡ Performance Optimization
|
|
117
|
+
- **Smart Content Selection** - Extracts only relevant code sections
|
|
118
|
+
- **Advanced Minification** - Language-aware compression preserving meaning
|
|
119
|
+
- **Partial File Access** - Fetches targeted line ranges
|
|
120
|
+
- **Token Efficiency** - 80-90% reduction in LLM token usage
|
|
174
121
|
|
|
175
|
-
|
|
122
|
+
## Available Tools
|
|
176
123
|
|
|
177
|
-
|
|
178
|
-
- **Repository Search** - Find repositories by topic, language, stars, and organization
|
|
179
|
-
- **Package Search** - Discover NPM packages by functionality and keywords
|
|
124
|
+
**10 specialized tools** working together intelligently:
|
|
180
125
|
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
126
|
+
**Discovery:** Repository Search, Package Search
|
|
127
|
+
**Analysis:** Code Search, Package Analysis, Repository Structure
|
|
128
|
+
**Activity:** Commit Search, Pull Request Search, Issue Search
|
|
129
|
+
**Content:** File Content Fetching, API Status Check
|
|
185
130
|
|
|
186
|
-
|
|
187
|
-
- **Commit Search** - Find commits by message, author, and date with SHA integration
|
|
188
|
-
- **Pull Request Search** - Discover PRs with automatic commit SHA extraction
|
|
189
|
-
- **Issue Search** - Find bug reports, feature requests, and discussions
|
|
131
|
+
All tools feature automatic cross-referencing and intelligent fallbacks.
|
|
190
132
|
|
|
191
|
-
|
|
192
|
-
- **File Content Fetching** - Read files from any commit, branch, or PR using commit SHAs
|
|
193
|
-
- **API Status Check** - Verify authentication and discover organization access
|
|
194
|
-
|
|
195
|
-
**Smart Integration:** All tools work together through intelligent workflows - from package discovery → repository analysis → commit history → file content, with automatic fallbacks and cross-referencing.
|
|
196
|
-
|
|
197
|
-
## Privacy & Security 🛡️
|
|
133
|
+
## Security & Privacy 🛡️
|
|
198
134
|
|
|
135
|
+
### Local-First Architecture
|
|
199
136
|
- **🏠 100% Local** - Runs entirely on your machine
|
|
200
|
-
- **🚫 Zero Data Collection** - No telemetry
|
|
201
|
-
- **🔑 No Token Management** - Uses
|
|
202
|
-
- **🛡️ Privacy by Design** - All API calls use your existing `gh` CLI permissions directly
|
|
203
|
-
|
|
204
|
-
### Command Execution Security 🔒
|
|
205
|
-
|
|
206
|
-
**Robust protection against prompt injections and malicious command execution:**
|
|
207
|
-
|
|
208
|
-
- **⚪ Allowlisted Commands Only** - Only pre-approved, safe NPM and GitHub CLI commands are executable
|
|
209
|
-
- NPM: `view`, `search`, `config`, `whoami`
|
|
210
|
-
- GitHub CLI: `search`, `api`, `auth`, `org`, `pr`
|
|
211
|
-
- **🛡️ Argument Sanitization** - All command arguments are properly escaped to prevent shell injection attacks
|
|
212
|
-
- **✅ Pre-execution Validation** - Every command is validated against allowed lists before execution
|
|
213
|
-
- **🔧 Controlled Environment** - Commands run in a secure, cross-platform shell environment with controlled variables
|
|
214
|
-
- **Cross-platform shells**: Uses `/bin/sh` on Unix/macOS, `cmd.exe` or `powershell.exe` on Windows - minimal, standard shells
|
|
215
|
-
- **PowerShell support**: Modern Windows environments can optionally use PowerShell with enhanced security
|
|
216
|
-
- **Why minimal shells are safe**: Avoids user's potentially customized shells with aliases, functions, plugins, or advanced features
|
|
217
|
-
- **Controlled variables**: Only essential environment variables (`PATH`, `SHELL`) are passed, preventing environment-based attacks
|
|
218
|
-
- **Platform-specific escaping**: Uses appropriate argument escaping for each platform (single quotes on Unix, double quotes for CMD, single quotes for PowerShell)
|
|
219
|
-
- **🚫 No Arbitrary Execution** - System cannot execute arbitrary shell commands or scripts
|
|
220
|
-
- **⏱️ Timeout Protection** - All commands have execution timeouts to prevent resource exhaustion
|
|
137
|
+
- **🚫 Zero Data Collection** - No telemetry or data transmission
|
|
138
|
+
- **🔑 No Token Management** - Uses GitHub CLI authentication
|
|
221
139
|
|
|
222
|
-
|
|
140
|
+
### Command Execution Security
|
|
141
|
+
- **⚪ Allowlisted Commands Only** - Pre-approved safe commands
|
|
142
|
+
- **🛡️ Argument Sanitization** - Prevents shell injection attacks
|
|
143
|
+
- **✅ Pre-execution Validation** - Every command is validated
|
|
144
|
+
- **🔧 Controlled Environment** - Cross-platform secure shell execution
|
|
145
|
+
- **⏱️ Timeout Protection** - Prevents resource exhaustion
|
|
223
146
|
|
|
224
|
-
|
|
225
|
-
- **Let AI guide you** - Start with natural language questions, the heuristic search will find relevant code
|
|
226
|
-
- **Trust the smart fallbacks** - If initial search doesn't work, AI automatically tries alternative strategies
|
|
227
|
-
- **Explore connections** - Ask about relationships between packages, libraries, and implementations
|
|
228
|
-
- **Use any privilege level** - Works seamlessly across public repos, private repos, and organization repositories
|
|
229
|
-
- **Keep research along the MCP** - Build upon previous searches and maintain context across multiple queries for deeper exploration
|
|
147
|
+
## Best Practices 💡
|
|
230
148
|
|
|
231
149
|
**Effective Questions:**
|
|
232
|
-
-
|
|
233
|
-
-
|
|
234
|
-
-
|
|
235
|
-
-
|
|
150
|
+
- Start with natural language - "How does authentication work?"
|
|
151
|
+
- Ask for connections - "What libraries use this pattern?"
|
|
152
|
+
- Cross-ecosystem queries - "NPM packages that implement X"
|
|
153
|
+
- Evolution questions - "How has this approach changed?"
|
|
236
154
|
|
|
237
|
-
**
|
|
238
|
-
-
|
|
239
|
-
-
|
|
240
|
-
-
|
|
241
|
-
-
|
|
155
|
+
**Pro Tips:**
|
|
156
|
+
- Let AI guide discovery - vague queries work great
|
|
157
|
+
- Trust smart fallbacks - automatic retry with alternatives
|
|
158
|
+
- Build on previous searches - maintain context for deeper exploration
|
|
159
|
+
- Works everywhere - public, private, and organization repositories
|
|
242
160
|
|
|
243
161
|
## Troubleshooting 🔧
|
|
244
162
|
|
|
245
|
-
**Authentication Issues:**
|
|
246
163
|
```bash
|
|
247
164
|
# Check GitHub CLI status
|
|
248
165
|
gh auth status
|
|
@@ -252,43 +169,24 @@ gh auth logout && gh auth login
|
|
|
252
169
|
|
|
253
170
|
# Check NPM access
|
|
254
171
|
npm whoami
|
|
172
|
+
|
|
173
|
+
# Clear NPX cache if needed
|
|
174
|
+
rm -rf ~/.npm/_npx
|
|
255
175
|
```
|
|
256
176
|
|
|
257
177
|
**Common Solutions:**
|
|
258
178
|
- No results? Try broader search terms
|
|
259
|
-
- Private repos not found? Check
|
|
260
|
-
-
|
|
261
|
-
|
|
262
|
-
**🏢 Organization & Private Repository Access:**
|
|
263
|
-
- **Automatic detection** - Octocode automatically discovers your GitHub organizations
|
|
264
|
-
- **No additional setup** - If you have access to private repos through your organization, they work immediately
|
|
265
|
-
- **Verify access** - Run `gh auth status` to see your organization memberships
|
|
266
|
-
|
|
267
|
-
**💻 Windows PowerShell Support:**
|
|
268
|
-
- **Modern shell support** - Optionally use PowerShell instead of cmd.exe on Windows
|
|
269
|
-
- **Enhanced security** - PowerShell provides better argument escaping and modern features
|
|
270
|
-
- **Automatic detection** - The system automatically detects Windows and applies appropriate shell configurations
|
|
271
|
-
- **Zero configuration** - Works seamlessly with existing setups, no additional configuration needed
|
|
272
|
-
|
|
273
|
-
**Why GitHub CLI Authentication?**
|
|
274
|
-
- ✅ **No token creation** - GitHub CLI handles OAuth flow automatically
|
|
275
|
-
- ✅ **Enterprise compatible** - Works with SSO, SAML, and 2FA out of the box
|
|
276
|
-
- ✅ **Organization auto-detection** - Automatically discovers your GitHub organizations and private repo access
|
|
277
|
-
- ✅ **Works out of the box** - If you work for an organization, private repositories are immediately accessible
|
|
278
|
-
- ❌ **vs Personal Access Tokens** - No manual creation, rotation, or security risks
|
|
179
|
+
- Private repos not found? Check `gh auth status` for organization membership
|
|
180
|
+
- Windows users? PowerShell is automatically supported
|
|
279
181
|
|
|
280
182
|
## Background 💭
|
|
281
183
|
|
|
282
|
-
This project started as a personal tool while working at Wix, born from the challenge of navigating large codebases and keeping up with rapidly evolving technology landscapes. What began as a side project
|
|
283
|
-
|
|
284
|
-
The goal was simple: **make code exploration as intelligent as having a senior developer guide you through any codebase.** Built specifically to understand connections between many repositories and NPM packages under any privilege the user has, with AI-powered heuristic search, smart fallbacks, and intelligent discovery.
|
|
184
|
+
This project started as a personal tool while working at Wix, born from the challenge of navigating large codebases and keeping up with rapidly evolving technology landscapes. What began as a side project evolved into **the perfect code assistant that can help understand anything**.
|
|
285
185
|
|
|
186
|
+
The goal: **make code exploration as intelligent as having a senior developer guide you through any codebase.**
|
|
286
187
|
|
|
287
188
|
## License 📄
|
|
288
189
|
|
|
289
190
|
MIT License - See [LICENSE](./LICENSE.md) for details.
|
|
290
191
|
|
|
291
|
-
---
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
192
|
+
---
|
package/build/index.js
CHANGED
|
@@ -112050,15 +112050,44 @@ async function fetchGitHubFileContent(params) {
|
|
|
112050
112050
|
});
|
|
112051
112051
|
}
|
|
112052
112052
|
}
|
|
112053
|
-
//
|
|
112054
|
-
if (errorMsg.includes('404')
|
|
112055
|
-
branch
|
|
112056
|
-
|
|
112057
|
-
|
|
112053
|
+
// Enhanced fallback strategy for 404 errors
|
|
112054
|
+
if (errorMsg.includes('404')) {
|
|
112055
|
+
// Get the actual default branch from the repo info we already fetched
|
|
112056
|
+
let defaultBranch = 'main';
|
|
112057
|
+
let repoDefaultBranchFound = false;
|
|
112058
|
+
if (!repoCheckResult.isError) {
|
|
112059
|
+
try {
|
|
112060
|
+
const repoData = JSON.parse(repoCheckResult.content[0].text);
|
|
112061
|
+
defaultBranch = repoData.default_branch || 'main';
|
|
112062
|
+
repoDefaultBranchFound = true;
|
|
112063
|
+
}
|
|
112064
|
+
catch (e) {
|
|
112065
|
+
// Keep default as 'main' if parsing fails
|
|
112066
|
+
}
|
|
112067
|
+
}
|
|
112068
|
+
// If we found the actual default branch, try it first
|
|
112069
|
+
if (repoDefaultBranchFound && defaultBranch !== branch) {
|
|
112070
|
+
const defaultBranchPath = `/repos/${owner}/${repo}/contents/${filePath}?ref=${defaultBranch}`;
|
|
112071
|
+
const defaultBranchResult = await executeGitHubCommand('api', [defaultBranchPath], {
|
|
112072
|
+
cache: false,
|
|
112073
|
+
});
|
|
112074
|
+
if (!defaultBranchResult.isError) {
|
|
112075
|
+
return await processFileContent(defaultBranchResult, owner, repo, defaultBranch, filePath, params.minified, params.startLine, params.endLine, params.contextLines);
|
|
112076
|
+
}
|
|
112077
|
+
}
|
|
112078
|
+
// Comprehensive fallback list (excluding default branch since we tried it)
|
|
112079
|
+
const fallbackBranches = [
|
|
112080
|
+
'main',
|
|
112081
|
+
'master',
|
|
112082
|
+
'develop',
|
|
112083
|
+
'dev',
|
|
112084
|
+
'trunk',
|
|
112085
|
+
].filter(b => b !== defaultBranch && b !== branch);
|
|
112058
112086
|
const triedBranches = [branch];
|
|
112087
|
+
if (repoDefaultBranchFound && defaultBranch !== branch) {
|
|
112088
|
+
triedBranches.push(`${defaultBranch} (default)`);
|
|
112089
|
+
}
|
|
112059
112090
|
for (const fallbackBranch of fallbackBranches) {
|
|
112060
|
-
if (triedBranches.includes(fallbackBranch))
|
|
112061
|
-
continue;
|
|
112062
112091
|
triedBranches.push(fallbackBranch);
|
|
112063
112092
|
const fallbackPath = `/repos/${owner}/${repo}/contents/${filePath}?ref=${fallbackBranch}`;
|
|
112064
112093
|
const fallbackResult = await executeGitHubCommand('api', [fallbackPath], {
|
|
@@ -112068,8 +112097,19 @@ async function fetchGitHubFileContent(params) {
|
|
|
112068
112097
|
return await processFileContent(fallbackResult, owner, repo, fallbackBranch, filePath, params.minified, params.startLine, params.endLine, params.contextLines);
|
|
112069
112098
|
}
|
|
112070
112099
|
}
|
|
112100
|
+
const defaultBranchInfo = repoDefaultBranchFound
|
|
112101
|
+
? `\nRepository default branch: "${defaultBranch}"`
|
|
112102
|
+
: `\nCould not determine default branch - repository info unavailable`;
|
|
112071
112103
|
return createResult({
|
|
112072
|
-
error: `File not found in any common branches (tried: ${triedBranches.join(', ')})
|
|
112104
|
+
error: `File not found in any common branches (tried: ${triedBranches.join(', ')}).${defaultBranchInfo}
|
|
112105
|
+
|
|
112106
|
+
Quick solution: Use the correct branch name:
|
|
112107
|
+
{"owner": "${owner}", "repo": "${repo}", "branch": "${defaultBranch}", "filePath": "${filePath}"}
|
|
112108
|
+
|
|
112109
|
+
Alternative solutions:
|
|
112110
|
+
• Check repository structure: github_view_repo_structure with {"owner": "${owner}", "repo": "${repo}", "branch": "main", "path": ""}
|
|
112111
|
+
• Search for file: github_search_code with query="filename:${filePath.split('/').pop()}" owner="${owner}"
|
|
112112
|
+
• Find file path: github_search_code with query="path:${filePath}"`,
|
|
112073
112113
|
});
|
|
112074
112114
|
}
|
|
112075
112115
|
// Handle common errors with more context
|
|
@@ -113754,125 +113794,78 @@ async function viewRepositoryStructure(params) {
|
|
|
113754
113794
|
try {
|
|
113755
113795
|
// Clean up path
|
|
113756
113796
|
const cleanPath = path.startsWith('/') ? path.substring(1) : path;
|
|
113757
|
-
// Try the requested branch first
|
|
113758
|
-
const
|
|
113759
|
-
|
|
113760
|
-
|
|
113761
|
-
|
|
113762
|
-
|
|
113763
|
-
|
|
113764
|
-
|
|
113765
|
-
|
|
113766
|
-
|
|
113767
|
-
|
|
113768
|
-
|
|
113769
|
-
|
|
113797
|
+
// Try the requested branch first
|
|
113798
|
+
const apiPath = `/repos/${owner}/${repo}/contents/${cleanPath}?ref=${branch}`;
|
|
113799
|
+
const result = await executeGitHubCommand('api', [apiPath], {
|
|
113800
|
+
cache: false,
|
|
113801
|
+
});
|
|
113802
|
+
if (!result.isError) {
|
|
113803
|
+
const execResult = JSON.parse(result.content[0].text);
|
|
113804
|
+
const apiItems = execResult.result;
|
|
113805
|
+
const items = Array.isArray(apiItems) ? apiItems : [apiItems];
|
|
113806
|
+
return formatRepositoryStructure(owner, repo, branch, cleanPath, items);
|
|
113807
|
+
}
|
|
113808
|
+
// If initial request failed, start enhanced fallback mechanism
|
|
113809
|
+
const errorMsg = result.content[0].text;
|
|
113810
|
+
// Check repository existence first
|
|
113811
|
+
const repoCheckResult = await executeGitHubCommand('api', [`/repos/${owner}/${repo}`], {
|
|
113812
|
+
cache: false,
|
|
113813
|
+
});
|
|
113814
|
+
if (repoCheckResult.isError) {
|
|
113815
|
+
return handleRepositoryNotFound(owner, repo, repoCheckResult.content[0].text);
|
|
113816
|
+
}
|
|
113817
|
+
// Enhanced fallback strategy for branch/path errors
|
|
113818
|
+
if (errorMsg.includes('404')) {
|
|
113819
|
+
// Get the actual default branch from the repo info we already fetched
|
|
113820
|
+
let defaultBranch = 'main';
|
|
113821
|
+
let repoDefaultBranchFound = false;
|
|
113770
113822
|
try {
|
|
113771
|
-
const
|
|
113772
|
-
|
|
113823
|
+
const repoData = JSON.parse(repoCheckResult.content[0].text);
|
|
113824
|
+
defaultBranch = repoData.default_branch || 'main';
|
|
113825
|
+
repoDefaultBranchFound = true;
|
|
113826
|
+
}
|
|
113827
|
+
catch (e) {
|
|
113828
|
+
// Keep default as 'main' if parsing fails
|
|
113829
|
+
}
|
|
113830
|
+
// If we found the actual default branch, try it first
|
|
113831
|
+
if (repoDefaultBranchFound && defaultBranch !== branch) {
|
|
113832
|
+
const defaultBranchPath = `/repos/${owner}/${repo}/contents/${cleanPath}?ref=${defaultBranch}`;
|
|
113833
|
+
const defaultBranchResult = await executeGitHubCommand('api', [defaultBranchPath], {
|
|
113773
113834
|
cache: false,
|
|
113774
113835
|
});
|
|
113775
|
-
if (!
|
|
113776
|
-
const execResult = JSON.parse(
|
|
113836
|
+
if (!defaultBranchResult.isError) {
|
|
113837
|
+
const execResult = JSON.parse(defaultBranchResult.content[0].text);
|
|
113777
113838
|
const apiItems = execResult.result;
|
|
113778
|
-
items = Array.isArray(apiItems) ? apiItems : [apiItems];
|
|
113779
|
-
|
|
113780
|
-
break;
|
|
113781
|
-
}
|
|
113782
|
-
else {
|
|
113783
|
-
lastError = new Error(result.content[0].text);
|
|
113784
|
-
}
|
|
113785
|
-
}
|
|
113786
|
-
catch (error) {
|
|
113787
|
-
lastError = error instanceof Error ? error : new Error(String(error));
|
|
113788
|
-
continue;
|
|
113789
|
-
}
|
|
113790
|
-
}
|
|
113791
|
-
if (items.length === 0) {
|
|
113792
|
-
// Check repository existence only after content fetch fails
|
|
113793
|
-
const repoCheckResult = await executeGitHubCommand('api', [`/repos/${owner}/${repo}`], {
|
|
113794
|
-
cache: false,
|
|
113795
|
-
});
|
|
113796
|
-
if (repoCheckResult.isError) {
|
|
113797
|
-
const repoErrorMsg = repoCheckResult.content[0].text;
|
|
113798
|
-
if (repoErrorMsg.includes('404')) {
|
|
113799
|
-
return createResult({
|
|
113800
|
-
error: `Repository "${owner}/${repo}" not found. It might have been deleted, renamed, or made private. Use github_search_code to find current location.`,
|
|
113801
|
-
});
|
|
113802
|
-
}
|
|
113803
|
-
else if (repoErrorMsg.includes('403')) {
|
|
113804
|
-
return createResult({
|
|
113805
|
-
error: `Repository "${owner}/${repo}" exists but access is denied. Repository might be private or archived. Use api_status_check to verify permissions.`,
|
|
113806
|
-
});
|
|
113839
|
+
const items = Array.isArray(apiItems) ? apiItems : [apiItems];
|
|
113840
|
+
return formatRepositoryStructure(owner, repo, defaultBranch, cleanPath, items);
|
|
113807
113841
|
}
|
|
113808
113842
|
}
|
|
113809
|
-
|
|
113810
|
-
|
|
113811
|
-
|
|
113812
|
-
|
|
113813
|
-
|
|
113814
|
-
error: `Path "${path}" not found in any branch (tried: ${triedBranches.join(', ')}).${searchSuggestion}`,
|
|
113815
|
-
});
|
|
113816
|
-
}
|
|
113817
|
-
else {
|
|
113818
|
-
return createResult({
|
|
113819
|
-
error: `Repository "${owner}/${repo}" structure not accessible. Repository might be empty, private, or you might not have sufficient permissions. Use github_search_code with owner="${owner}" to find accessible repositories.`,
|
|
113820
|
-
});
|
|
113821
|
-
}
|
|
113843
|
+
// Try additional common branches
|
|
113844
|
+
const commonBranches = ['main', 'master', 'develop'];
|
|
113845
|
+
const triedBranches = [branch];
|
|
113846
|
+
if (repoDefaultBranchFound) {
|
|
113847
|
+
triedBranches.push(defaultBranch);
|
|
113822
113848
|
}
|
|
113823
|
-
|
|
113824
|
-
|
|
113825
|
-
|
|
113826
|
-
}
|
|
113827
|
-
|
|
113828
|
-
|
|
113829
|
-
const searchSuggestion = path
|
|
113830
|
-
? await suggestPathSearchFallback(owner, path)
|
|
113831
|
-
: '';
|
|
113832
|
-
return createResult({
|
|
113833
|
-
error: `Failed to access "${owner}/${repo}": ${errorMsg}. Check network connection and repository permissions.${searchSuggestion}`,
|
|
113849
|
+
for (const tryBranch of commonBranches) {
|
|
113850
|
+
if (triedBranches.includes(tryBranch))
|
|
113851
|
+
continue;
|
|
113852
|
+
const tryBranchPath = `/repos/${owner}/${repo}/contents/${cleanPath}?ref=${tryBranch}`;
|
|
113853
|
+
const tryBranchResult = await executeGitHubCommand('api', [tryBranchPath], {
|
|
113854
|
+
cache: false,
|
|
113834
113855
|
});
|
|
113856
|
+
triedBranches.push(tryBranch);
|
|
113857
|
+
if (!tryBranchResult.isError) {
|
|
113858
|
+
const execResult = JSON.parse(tryBranchResult.content[0].text);
|
|
113859
|
+
const apiItems = execResult.result;
|
|
113860
|
+
const items = Array.isArray(apiItems) ? apiItems : [apiItems];
|
|
113861
|
+
return formatRepositoryStructure(owner, repo, tryBranch, cleanPath, items);
|
|
113862
|
+
}
|
|
113835
113863
|
}
|
|
113864
|
+
// All branches failed - return helpful error
|
|
113865
|
+
return handlePathNotFound(owner, repo, cleanPath, triedBranches, defaultBranch, repoDefaultBranchFound);
|
|
113836
113866
|
}
|
|
113837
|
-
//
|
|
113838
|
-
|
|
113839
|
-
// Sort: directories first, then alphabetically
|
|
113840
|
-
limitedItems.sort((a, b) => {
|
|
113841
|
-
if (a.type !== b.type) {
|
|
113842
|
-
return a.type === 'dir' ? -1 : 1;
|
|
113843
|
-
}
|
|
113844
|
-
return a.name.localeCompare(b.name);
|
|
113845
|
-
});
|
|
113846
|
-
// Create simplified, token-efficient structure
|
|
113847
|
-
const files = limitedItems
|
|
113848
|
-
.filter(item => item.type === 'file')
|
|
113849
|
-
.map(item => ({
|
|
113850
|
-
name: item.name,
|
|
113851
|
-
size: item.size,
|
|
113852
|
-
url: item.path, // Use path for fetching
|
|
113853
|
-
}));
|
|
113854
|
-
const folders = limitedItems
|
|
113855
|
-
.filter(item => item.type === 'dir')
|
|
113856
|
-
.map(item => ({
|
|
113857
|
-
name: item.name,
|
|
113858
|
-
url: item.path, // Use path for browsing
|
|
113859
|
-
}));
|
|
113860
|
-
return createResult({
|
|
113861
|
-
data: {
|
|
113862
|
-
repository: `${owner}/${repo}`,
|
|
113863
|
-
branch: usedBranch,
|
|
113864
|
-
path: cleanPath || '/',
|
|
113865
|
-
githubBasePath: `https://api.github.com/repos/${owner}/${repo}/contents/`,
|
|
113866
|
-
files: {
|
|
113867
|
-
count: files.length,
|
|
113868
|
-
files: files,
|
|
113869
|
-
},
|
|
113870
|
-
folders: {
|
|
113871
|
-
count: folders.length,
|
|
113872
|
-
folders: folders,
|
|
113873
|
-
},
|
|
113874
|
-
},
|
|
113875
|
-
});
|
|
113867
|
+
// Handle other errors (403, etc.)
|
|
113868
|
+
return handleOtherErrors(owner, repo, errorMsg);
|
|
113876
113869
|
}
|
|
113877
113870
|
catch (error) {
|
|
113878
113871
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
@@ -113883,62 +113876,114 @@ async function viewRepositoryStructure(params) {
|
|
|
113883
113876
|
});
|
|
113884
113877
|
}
|
|
113885
113878
|
/**
|
|
113886
|
-
*
|
|
113887
|
-
* Now includes more comprehensive branch detection and better error handling.
|
|
113879
|
+
* Format the repository structure response
|
|
113888
113880
|
*/
|
|
113889
|
-
|
|
113890
|
-
|
|
113891
|
-
|
|
113892
|
-
|
|
113893
|
-
|
|
113894
|
-
|
|
113881
|
+
function formatRepositoryStructure(owner, repo, branch, path, items) {
|
|
113882
|
+
// Limit total items to 100 for efficiency
|
|
113883
|
+
const limitedItems = items.slice(0, 100);
|
|
113884
|
+
// Sort: directories first, then alphabetically
|
|
113885
|
+
limitedItems.sort((a, b) => {
|
|
113886
|
+
if (a.type !== b.type) {
|
|
113887
|
+
return a.type === 'dir' ? -1 : 1;
|
|
113888
|
+
}
|
|
113889
|
+
return a.name.localeCompare(b.name);
|
|
113890
|
+
});
|
|
113891
|
+
// Create simplified, token-efficient structure
|
|
113892
|
+
const files = limitedItems
|
|
113893
|
+
.filter(item => item.type === 'file')
|
|
113894
|
+
.map(item => ({
|
|
113895
|
+
name: item.name,
|
|
113896
|
+
size: item.size,
|
|
113897
|
+
url: item.path, // Use path for fetching
|
|
113898
|
+
}));
|
|
113899
|
+
const folders = limitedItems
|
|
113900
|
+
.filter(item => item.type === 'dir')
|
|
113901
|
+
.map(item => ({
|
|
113902
|
+
name: item.name,
|
|
113903
|
+
url: item.path, // Use path for browsing
|
|
113904
|
+
}));
|
|
113905
|
+
return createResult({
|
|
113906
|
+
data: {
|
|
113907
|
+
repository: `${owner}/${repo}`,
|
|
113908
|
+
branch: branch,
|
|
113909
|
+
path: path || '/',
|
|
113910
|
+
githubBasePath: `https://api.github.com/repos/${owner}/${repo}/contents/`,
|
|
113911
|
+
files: {
|
|
113912
|
+
count: files.length,
|
|
113913
|
+
files: files,
|
|
113914
|
+
},
|
|
113915
|
+
folders: {
|
|
113916
|
+
count: folders.length,
|
|
113917
|
+
folders: folders,
|
|
113918
|
+
},
|
|
113919
|
+
},
|
|
113920
|
+
});
|
|
113921
|
+
}
|
|
113922
|
+
/**
|
|
113923
|
+
* Handle repository not found errors
|
|
113924
|
+
*/
|
|
113925
|
+
function handleRepositoryNotFound(owner, repo, errorMsg) {
|
|
113926
|
+
if (errorMsg.includes('404')) {
|
|
113927
|
+
return createResult({
|
|
113928
|
+
error: `Repository "${owner}/${repo}" not found. It might have been deleted, renamed, or made private. Use github_search_code to find current location.`,
|
|
113895
113929
|
});
|
|
113896
|
-
if (!repoInfoResult.isError) {
|
|
113897
|
-
const execResult = JSON.parse(repoInfoResult.content[0].text);
|
|
113898
|
-
const repoData = execResult.result;
|
|
113899
|
-
const defaultBranch = repoData.default_branch;
|
|
113900
|
-
if (defaultBranch) {
|
|
113901
|
-
branches.add(defaultBranch);
|
|
113902
|
-
}
|
|
113903
|
-
}
|
|
113904
113930
|
}
|
|
113905
|
-
|
|
113906
|
-
|
|
113907
|
-
|
|
113908
|
-
|
|
113909
|
-
|
|
113910
|
-
|
|
113911
|
-
|
|
113912
|
-
const branchesArray = Array.from(branches);
|
|
113913
|
-
branchesArray.sort((a, b) => {
|
|
113914
|
-
if (a === requestedBranch)
|
|
113915
|
-
return -1;
|
|
113916
|
-
if (b === requestedBranch)
|
|
113917
|
-
return 1;
|
|
113918
|
-
return 0;
|
|
113931
|
+
else if (errorMsg.includes('403')) {
|
|
113932
|
+
return createResult({
|
|
113933
|
+
error: `Repository "${owner}/${repo}" exists but access is denied. Repository might be private or archived. Use api_status_check to verify permissions.`,
|
|
113934
|
+
});
|
|
113935
|
+
}
|
|
113936
|
+
return createResult({
|
|
113937
|
+
error: `Failed to access repository "${owner}/${repo}": ${errorMsg}. Verify repository exists and is accessible.`,
|
|
113919
113938
|
});
|
|
113920
|
-
return branchesArray;
|
|
113921
113939
|
}
|
|
113922
|
-
|
|
113923
|
-
|
|
113924
|
-
|
|
113925
|
-
|
|
113926
|
-
|
|
113927
|
-
|
|
113928
|
-
|
|
113929
|
-
|
|
113930
|
-
|
|
113931
|
-
|
|
113932
|
-
|
|
113933
|
-
|
|
113934
|
-
|
|
113935
|
-
|
|
113936
|
-
|
|
113940
|
+
/**
|
|
113941
|
+
* Handle path not found errors with helpful suggestions
|
|
113942
|
+
*/
|
|
113943
|
+
function handlePathNotFound(owner, repo, path, triedBranches, defaultBranch, repoDefaultBranchFound) {
|
|
113944
|
+
const defaultBranchInfo = repoDefaultBranchFound
|
|
113945
|
+
? `\nRepository default branch: "${defaultBranch}"`
|
|
113946
|
+
: `\nCould not determine default branch - repository info unavailable`;
|
|
113947
|
+
if (path) {
|
|
113948
|
+
return createResult({
|
|
113949
|
+
error: `Path "${path}" not found in any branch (tried: ${triedBranches.join(', ')}).${defaultBranchInfo}
|
|
113950
|
+
|
|
113951
|
+
Quick solution: Use the correct branch name:
|
|
113952
|
+
{"owner": "${owner}", "repo": "${repo}", "branch": "${defaultBranch}", "path": "${path}"}
|
|
113953
|
+
|
|
113954
|
+
Alternative solutions:
|
|
113955
|
+
• Search for path: github_search_code with query="path:${path}" owner="${owner}"
|
|
113956
|
+
• Search for directory: github_search_code with query="${path.split('/').pop()}" owner="${owner}"
|
|
113957
|
+
• Check root structure: github_view_repo_structure with {"owner": "${owner}", "repo": "${repo}", "branch": "${defaultBranch}", "path": ""}`,
|
|
113958
|
+
});
|
|
113937
113959
|
}
|
|
113938
|
-
|
|
113939
|
-
|
|
113960
|
+
else {
|
|
113961
|
+
return createResult({
|
|
113962
|
+
error: `Repository "${owner}/${repo}" structure not accessible in any branch (tried: ${triedBranches.join(', ')}).${defaultBranchInfo}
|
|
113963
|
+
|
|
113964
|
+
Repository might be empty, private, or you might not have sufficient permissions.
|
|
113965
|
+
|
|
113966
|
+
Alternative solutions:
|
|
113967
|
+
• Verify permissions: api_status_check
|
|
113968
|
+
• Search accessible repos: github_search_code with owner="${owner}"
|
|
113969
|
+
• Try different branch: github_view_repo_structure with {"owner": "${owner}", "repo": "${repo}", "branch": "${defaultBranch}", "path": ""}`,
|
|
113970
|
+
});
|
|
113971
|
+
}
|
|
113972
|
+
}
|
|
113973
|
+
/**
|
|
113974
|
+
* Handle other types of errors (403, rate limits, etc.)
|
|
113975
|
+
*/
|
|
113976
|
+
function handleOtherErrors(owner, repo, errorMsg) {
|
|
113977
|
+
if (errorMsg.includes('403') || errorMsg.includes('Forbidden')) {
|
|
113978
|
+
return createResult({
|
|
113979
|
+
error: `Access denied to "${owner}/${repo}". Repository exists but might be private/archived. Use api_status_check to verify permissions, or github_search_code with owner="${owner}" to find accessible repositories.`,
|
|
113980
|
+
});
|
|
113981
|
+
}
|
|
113982
|
+
else {
|
|
113983
|
+
return createResult({
|
|
113984
|
+
error: `Failed to access "${owner}/${repo}": ${errorMsg}. Check network connection and repository permissions.`,
|
|
113985
|
+
});
|
|
113940
113986
|
}
|
|
113941
|
-
return ` Try these searches:\n1. github_search_code with query="${path.split('/').pop()}" owner="${owner}"\n2. github_search_code with query="path:${path}"`;
|
|
113942
113987
|
}
|
|
113943
113988
|
|
|
113944
113989
|
const GITHUB_SEARCH_ISSUES_TOOL_NAME = 'githubSearchIssues';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "octocode-mcp",
|
|
3
|
-
"version": "2.3.
|
|
3
|
+
"version": "2.3.11",
|
|
4
4
|
"description": "Model Context Protocol (MCP) server for advanced GitHub repository analysis, code discovery, and npm package exploration. Provides AI assistants with powerful tools to search, analyze, and understand codebases across GitHub and npm ecosystems.",
|
|
5
5
|
"author": "Guy Bary <guybary@gmail.com>",
|
|
6
6
|
"homepage": "https://octocode.ai",
|