octocode-mcp 2.3.2 → 2.3.4
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 +53 -20
- package/build/index.js +281 -156
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
<div>
|
|
6
6
|
<img src="./assets/logo.png">
|
|
7
7
|
|
|
8
|
-
[](./package.json)
|
|
9
9
|
[](./package.json)
|
|
10
10
|
[](https://modelcontextprotocol.io/)
|
|
11
11
|
</div>
|
|
@@ -55,7 +55,7 @@ It's the tool you reach for when you need to understand *"how does this work?"*
|
|
|
55
55
|
|
|
56
56
|
### 1. Install Prerequisites
|
|
57
57
|
```bash
|
|
58
|
-
# Install Node.js
|
|
58
|
+
# Install Node.js 18.12+
|
|
59
59
|
brew install node # macOS
|
|
60
60
|
# or download from https://nodejs.org/
|
|
61
61
|
|
|
@@ -93,35 +93,44 @@ npm login
|
|
|
93
93
|
|
|
94
94
|
**That's it!** No personal access tokens, no config files, no complex setup. Octocode leverages [GitHub CLI](https://cli.github.com/) authentication behind the scenes and **automatically works with your organization's private repositories**.
|
|
95
95
|
|
|
96
|
-
|
|
96
|
+

|
|
97
97
|
|
|
98
|
-
**Learning & Research:**
|
|
99
|
-
- *"How do popular libraries implement rate limiting?"*
|
|
100
|
-
- *"Show me Server Actions patterns in Next.js applications"*
|
|
101
|
-
- *"What are the differences between Vue and React rendering?"*
|
|
102
98
|
|
|
103
|
-
|
|
104
|
-
- *"How is authentication handled in enterprise applications?"*
|
|
105
|
-
- *"Show me microservices communication patterns"*
|
|
106
|
-
- *"Find examples of event-driven architecture implementations"*
|
|
99
|
+
## How Octocode Works 🔄
|
|
107
100
|
|
|
108
|
-
**
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
101
|
+
**Smart Discovery Flow:**
|
|
102
|
+
1. **🔍 Query Analysis** → AI determines the best search strategy based on your question
|
|
103
|
+
2. **⚡ Multi-Tool Orchestration** → Combines GitHub + NPM searches intelligently
|
|
104
|
+
3. **🔄 Smart Fallbacks** → Automatically retries with different approaches if initial search fails
|
|
105
|
+
4. **🔗 Cross-Reference Discovery** → Links packages to repositories, finds related implementations
|
|
106
|
+
5. **🎯 Context Synthesis** → Provides comprehensive understanding across multiple sources
|
|
112
107
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
108
|
+
## Example Flows
|
|
109
|
+
|
|
110
|
+
### Example 1: LangGraph Node.js Implementation Tutorial
|
|
111
|
+
**Query:** "Show implementations of langgraph in node js. Make a tutorial for how to implement a simple agent using OpenAI API."
|
|
112
|
+
|
|
113
|
+

|
|
114
|
+
|
|
115
|
+
### Example 2: Zustand React State Management
|
|
116
|
+
**Query:** "Show me how to add zustand to react application. Show examples and best practices"
|
|
117
|
+
|
|
118
|
+

|
|
119
|
+
|
|
120
|
+
### Example 3: React vs Vue.js Rendering Comparison
|
|
121
|
+
**Query:** "How did React implement their concurrent rendering flows? How is it different from Vue.js rendering mechanism? Which is better?"
|
|
122
|
+
|
|
123
|
+

|
|
117
124
|
|
|
118
125
|
## Core Features 🛠️
|
|
119
126
|
|
|
120
127
|
### 🧠 AI-Powered Advanced Search
|
|
121
128
|
- **Heuristic Pattern Recognition** - Finds relevant code even with vague or incomplete queries
|
|
122
|
-
- **Smart Fallback Strategies** - Automatically tries alternative approaches when searches fail
|
|
129
|
+
- **Smart Fallback Strategies** - Automatically tries alternative approaches when searches fail with actionable suggestions
|
|
130
|
+
- **Boolean Search Intelligence** - Automatic query optimization with smart boolean operators (3-5x performance improvement)
|
|
123
131
|
- **Context-Aware Discovery** - Understands code relationships and suggests related implementations
|
|
124
132
|
- **Multi-Strategy Search** - Combines semantic, syntactic, and dependency-based search methods
|
|
133
|
+
- **Graceful Error Recovery** - Comprehensive error handling with intelligent retry mechanisms
|
|
125
134
|
|
|
126
135
|
### 🔗 Connection Intelligence
|
|
127
136
|
- **Repository-Package Mapping** - Automatically links NPM packages to their GitHub repositories
|
|
@@ -148,6 +157,24 @@ npm login
|
|
|
148
157
|
- **🔑 No Token Management** - Uses [GitHub CLI](https://cli.github.com/) authentication, no personal access tokens needed
|
|
149
158
|
- **🛡️ Privacy by Design** - All API calls use your existing `gh` CLI permissions directly
|
|
150
159
|
|
|
160
|
+
### Command Execution Security 🔒
|
|
161
|
+
|
|
162
|
+
**Robust protection against prompt injections and malicious command execution:**
|
|
163
|
+
|
|
164
|
+
- **⚪ Allowlisted Commands Only** - Only pre-approved, safe NPM and GitHub CLI commands are executable
|
|
165
|
+
- NPM: `view`, `search`, `ping`, `config`, `whoami`
|
|
166
|
+
- GitHub CLI: `search`, `api`, `auth`, `org`
|
|
167
|
+
- **🛡️ Argument Sanitization** - All command arguments are properly escaped to prevent shell injection attacks
|
|
168
|
+
- **✅ Pre-execution Validation** - Every command is validated against allowed lists before execution
|
|
169
|
+
- **🔧 Controlled Environment** - Commands run in a secure, cross-platform shell environment with controlled variables
|
|
170
|
+
- **Cross-platform shells**: Uses `/bin/sh` on Unix/macOS, `cmd.exe` or `powershell.exe` on Windows - minimal, standard shells
|
|
171
|
+
- **PowerShell support**: Modern Windows environments can optionally use PowerShell with enhanced security
|
|
172
|
+
- **Why minimal shells are safe**: Avoids user's potentially customized shells with aliases, functions, plugins, or advanced features
|
|
173
|
+
- **Controlled variables**: Only essential environment variables (`PATH`, `SHELL`) are passed, preventing environment-based attacks
|
|
174
|
+
- **Platform-specific escaping**: Uses appropriate argument escaping for each platform (single quotes on Unix, double quotes for CMD, single quotes for PowerShell)
|
|
175
|
+
- **🚫 No Arbitrary Execution** - System cannot execute arbitrary shell commands or scripts
|
|
176
|
+
- **⏱️ Timeout Protection** - All commands have execution timeouts to prevent resource exhaustion
|
|
177
|
+
|
|
151
178
|
## Best Practices 💡
|
|
152
179
|
|
|
153
180
|
**AI-Powered Search Tips:**
|
|
@@ -193,6 +220,12 @@ npm whoami
|
|
|
193
220
|
- **No additional setup** - If you have access to private repos through your organization, they work immediately
|
|
194
221
|
- **Verify access** - Run `gh auth status` to see your organization memberships
|
|
195
222
|
|
|
223
|
+
**💻 Windows PowerShell Support:**
|
|
224
|
+
- **Modern shell support** - Optionally use PowerShell instead of cmd.exe on Windows
|
|
225
|
+
- **Enhanced security** - PowerShell provides better argument escaping and modern features
|
|
226
|
+
- **Automatic detection** - The system automatically detects Windows and applies appropriate shell configurations
|
|
227
|
+
- **Zero configuration** - Works seamlessly with existing setups, no additional configuration needed
|
|
228
|
+
|
|
196
229
|
**Why GitHub CLI Authentication?**
|
|
197
230
|
- ✅ **No token creation** - GitHub CLI handles OAuth flow automatically
|
|
198
231
|
- ✅ **Enterprise compatible** - Works with SSO, SAML, and 2FA out of the box
|
package/build/index.js
CHANGED
|
@@ -3,40 +3,44 @@ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
|
3
3
|
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
4
4
|
import { exec } from 'child_process';
|
|
5
5
|
import { promisify } from 'util';
|
|
6
|
+
import { platform } from 'os';
|
|
6
7
|
import NodeCache from 'node-cache';
|
|
7
8
|
import crypto from 'crypto';
|
|
8
9
|
import z from 'zod';
|
|
9
10
|
|
|
10
|
-
const PROMPT_SYSTEM_PROMPT = `
|
|
11
|
-
You leverage powerful semantic search using GitHub (gh) and NPM CLI for code discovery.
|
|
11
|
+
const PROMPT_SYSTEM_PROMPT = `Expert code research assistant for GitHub/NPM ecosystems (public/private). Use powerful semantic search for efficient code discovery.
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
CORE TOOLS:
|
|
14
|
+
GitHub: Code, repos, issues, PRs, commits - supports boolean logic (AND/OR/NOT) and exact phrases
|
|
15
|
+
NPM: Package search (fuzzy only, no boolean) + metadata (repo URLs, exports, dependencies)
|
|
16
|
+
API Status: Check connectivity + user's GitHub organizations for private access
|
|
14
17
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
18
|
+
SEARCH STRATEGIES:
|
|
19
|
+
GitHub Code/Issues/PRs/Commits:
|
|
20
|
+
OR (broad): "useState OR setState" - finds alternatives
|
|
21
|
+
AND (precise): "react AND hooks" - requires both terms
|
|
22
|
+
NOT (filter): "auth NOT test" - excludes noise
|
|
23
|
+
Quotes (exact): "useEffect cleanup" - literal phrases
|
|
24
|
+
Combine with filters: language, path, owner for focus
|
|
19
25
|
|
|
20
|
-
|
|
21
|
-
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
- Prioritize efficient, targeted searches with smart fallbacks
|
|
25
|
-
- Use strategic tool combinations for comprehensive results an
|
|
26
|
-
- Balance speed vs throughness based on query type
|
|
26
|
+
NPM Search:
|
|
27
|
+
Space-separated keywords only: "react state management"
|
|
28
|
+
No boolean operators supported
|
|
29
|
+
Use npm_view_package for direct package metadata → GitHub repo URL
|
|
27
30
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
31
|
+
OPTIMIZATION:
|
|
32
|
+
Check user's GitHub orgs for private repo access
|
|
33
|
+
npm_view_package gives repo URL instantly - avoid GitHub repo search
|
|
34
|
+
Use targeted searches, avoid redundant tool calls
|
|
35
|
+
Combine tools strategically: NPM → GitHub file content
|
|
36
|
+
Discovery: comprehensive multi-tool approach
|
|
37
|
+
Direct queries: quick targeted approach
|
|
34
38
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
39
|
+
CLI Help using CLI (use when needed to check failures)
|
|
40
|
+
gh <command> --help
|
|
41
|
+
npm <command> --help
|
|
42
|
+
|
|
43
|
+
Always provide code snippets and documentation references.`;
|
|
40
44
|
|
|
41
45
|
function createResult(data, isError = false, suggestions) {
|
|
42
46
|
const text = isError
|
|
@@ -133,6 +137,86 @@ function isValidNpmCommand(command) {
|
|
|
133
137
|
function isValidGhCommand(command) {
|
|
134
138
|
return ALLOWED_GH_COMMANDS.includes(command);
|
|
135
139
|
}
|
|
140
|
+
/**
|
|
141
|
+
* Get platform-specific shell configuration with PowerShell support
|
|
142
|
+
*/
|
|
143
|
+
function getShellConfig(preferredWindowsShell) {
|
|
144
|
+
const isWindows = platform() === 'win32';
|
|
145
|
+
if (!isWindows) {
|
|
146
|
+
return {
|
|
147
|
+
shell: '/bin/sh',
|
|
148
|
+
shellEnv: '/bin/sh',
|
|
149
|
+
type: 'unix',
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
// Windows shell selection
|
|
153
|
+
const usesPowerShell = preferredWindowsShell === 'powershell';
|
|
154
|
+
if (usesPowerShell) {
|
|
155
|
+
return {
|
|
156
|
+
shell: 'powershell.exe',
|
|
157
|
+
shellEnv: 'powershell.exe',
|
|
158
|
+
type: 'powershell',
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
return {
|
|
162
|
+
shell: 'cmd.exe',
|
|
163
|
+
shellEnv: 'cmd.exe',
|
|
164
|
+
type: 'cmd',
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Escape shell arguments to prevent shell injection and handle special characters
|
|
169
|
+
* Cross-platform compatible escaping for Windows CMD, PowerShell, and Unix shells
|
|
170
|
+
*/
|
|
171
|
+
function escapeShellArg(arg, shellType) {
|
|
172
|
+
// Auto-detect shell type if not provided
|
|
173
|
+
if (!shellType) {
|
|
174
|
+
const isWindows = platform() === 'win32';
|
|
175
|
+
shellType = isWindows ? 'cmd' : 'unix';
|
|
176
|
+
}
|
|
177
|
+
switch (shellType) {
|
|
178
|
+
case 'powershell':
|
|
179
|
+
return escapePowerShellArg(arg);
|
|
180
|
+
case 'cmd':
|
|
181
|
+
return escapeWindowsCmdArg(arg);
|
|
182
|
+
case 'unix':
|
|
183
|
+
default:
|
|
184
|
+
return escapeUnixShellArg(arg);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Escape arguments for PowerShell
|
|
189
|
+
* PowerShell uses single quotes for literal strings and has special escaping rules
|
|
190
|
+
*/
|
|
191
|
+
function escapePowerShellArg(arg) {
|
|
192
|
+
// PowerShell special characters that need escaping
|
|
193
|
+
if (/[\s&<>|;`$@"'()[\]{}]/.test(arg)) {
|
|
194
|
+
// Use single quotes for literal strings in PowerShell
|
|
195
|
+
// Escape single quotes by doubling them
|
|
196
|
+
return `'${arg.replace(/'/g, "''")}'`;
|
|
197
|
+
}
|
|
198
|
+
return arg;
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* Escape arguments for Windows CMD
|
|
202
|
+
*/
|
|
203
|
+
function escapeWindowsCmdArg(arg) {
|
|
204
|
+
// Windows CMD escaping
|
|
205
|
+
if (/[\s&<>|^"]/.test(arg)) {
|
|
206
|
+
return `"${arg.replace(/"/g, '""')}"`;
|
|
207
|
+
}
|
|
208
|
+
return arg;
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Escape arguments for Unix shells (/bin/sh, bash, etc.)
|
|
212
|
+
*/
|
|
213
|
+
function escapeUnixShellArg(arg) {
|
|
214
|
+
// Unix shell escaping
|
|
215
|
+
if (/[^\w\-._/:=@]/.test(arg)) {
|
|
216
|
+
return `'${arg.replace(/'/g, "'\"'\"'")}'`;
|
|
217
|
+
}
|
|
218
|
+
return arg;
|
|
219
|
+
}
|
|
136
220
|
/**
|
|
137
221
|
* Execute NPM commands safely by validating against allowed commands
|
|
138
222
|
* Security: Only executes commands that start with "npm {ALLOWED_COMMAND}"
|
|
@@ -142,27 +226,22 @@ async function executeNpmCommand(command, args = [], options = {}) {
|
|
|
142
226
|
if (!isValidNpmCommand(command)) {
|
|
143
227
|
return createErrorResult('Command not registered', new Error(`NPM command '${command}' is not in the allowed list`));
|
|
144
228
|
}
|
|
229
|
+
// Get shell configuration
|
|
230
|
+
const shellConfig = getShellConfig(options.windowsShell);
|
|
145
231
|
// Build command with validated prefix and properly escaped arguments
|
|
146
|
-
const escapedArgs = args.map(escapeShellArg);
|
|
232
|
+
const escapedArgs = args.map(arg => escapeShellArg(arg, shellConfig.type));
|
|
147
233
|
const fullCommand = `npm ${command} ${escapedArgs.join(' ')}`;
|
|
148
|
-
const executeNpmCommand = () => executeCommand(fullCommand, 'npm', options);
|
|
234
|
+
const executeNpmCommand = () => executeCommand(fullCommand, 'npm', options, shellConfig);
|
|
149
235
|
if (options.cache) {
|
|
150
|
-
const cacheKey = generateCacheKey('npm-exec', {
|
|
236
|
+
const cacheKey = generateCacheKey('npm-exec', {
|
|
237
|
+
command,
|
|
238
|
+
args,
|
|
239
|
+
shell: shellConfig.type,
|
|
240
|
+
});
|
|
151
241
|
return withCache(cacheKey, executeNpmCommand);
|
|
152
242
|
}
|
|
153
243
|
return executeNpmCommand();
|
|
154
244
|
}
|
|
155
|
-
/**
|
|
156
|
-
* Escape shell arguments to prevent shell injection and handle special characters
|
|
157
|
-
*/
|
|
158
|
-
function escapeShellArg(arg) {
|
|
159
|
-
// If the argument contains special characters, wrap it in single quotes
|
|
160
|
-
// and escape any single quotes within the argument
|
|
161
|
-
if (/[^\w\-._/:=@]/.test(arg)) {
|
|
162
|
-
return `'${arg.replace(/'/g, "'\"'\"'")}'`;
|
|
163
|
-
}
|
|
164
|
-
return arg;
|
|
165
|
-
}
|
|
166
245
|
/**
|
|
167
246
|
* Execute GitHub CLI commands safely by validating against allowed commands
|
|
168
247
|
* Security: Only executes commands that start with "gh {ALLOWED_COMMAND}"
|
|
@@ -172,12 +251,18 @@ async function executeGitHubCommand(command, args = [], options = {}) {
|
|
|
172
251
|
if (!isValidGhCommand(command)) {
|
|
173
252
|
return createErrorResult('Command not registered', new Error(`GitHub command '${command}' is not in the allowed list`));
|
|
174
253
|
}
|
|
254
|
+
// Get shell configuration
|
|
255
|
+
const shellConfig = getShellConfig(options.windowsShell);
|
|
175
256
|
// Build command with validated prefix and properly escaped arguments
|
|
176
|
-
const escapedArgs = args.map(escapeShellArg);
|
|
257
|
+
const escapedArgs = args.map(arg => escapeShellArg(arg, shellConfig.type));
|
|
177
258
|
const fullCommand = `gh ${command} ${escapedArgs.join(' ')}`;
|
|
178
|
-
const executeGhCommand = () => executeCommand(fullCommand, 'github', options);
|
|
259
|
+
const executeGhCommand = () => executeCommand(fullCommand, 'github', options, shellConfig);
|
|
179
260
|
if (options.cache) {
|
|
180
|
-
const cacheKey = generateCacheKey('gh-exec', {
|
|
261
|
+
const cacheKey = generateCacheKey('gh-exec', {
|
|
262
|
+
command,
|
|
263
|
+
args,
|
|
264
|
+
shell: shellConfig.type,
|
|
265
|
+
});
|
|
181
266
|
return withCache(cacheKey, executeGhCommand);
|
|
182
267
|
}
|
|
183
268
|
return executeGhCommand();
|
|
@@ -186,21 +271,23 @@ async function executeGitHubCommand(command, args = [], options = {}) {
|
|
|
186
271
|
* Execute shell commands with timeout and error handling
|
|
187
272
|
* Security: Should only be called with pre-validated command prefixes
|
|
188
273
|
*/
|
|
189
|
-
async function executeCommand(fullCommand, type, options = {}) {
|
|
274
|
+
async function executeCommand(fullCommand, type, options = {}, shellConfig) {
|
|
190
275
|
try {
|
|
191
276
|
const defaultTimeout = type === 'npm' ? 30000 : 60000;
|
|
277
|
+
const config = shellConfig || getShellConfig(options.windowsShell);
|
|
192
278
|
const execOptions = {
|
|
193
279
|
timeout: options.timeout || defaultTimeout,
|
|
280
|
+
maxBuffer: 5 * 1024 * 1024, // 5MB buffer limit (increased from default 1MB)
|
|
194
281
|
cwd: options.cwd,
|
|
195
282
|
env: {
|
|
196
283
|
...process.env,
|
|
197
284
|
...options.env,
|
|
198
|
-
// Ensure clean shell environment
|
|
199
|
-
SHELL:
|
|
285
|
+
// Ensure clean shell environment - cross-platform compatible
|
|
286
|
+
SHELL: config.shellEnv,
|
|
200
287
|
PATH: process.env.PATH,
|
|
201
288
|
},
|
|
202
289
|
encoding: 'utf-8',
|
|
203
|
-
shell:
|
|
290
|
+
shell: config.shell, // Use platform-appropriate shell
|
|
204
291
|
};
|
|
205
292
|
const { stdout, stderr } = await safeExecAsync(fullCommand, execOptions);
|
|
206
293
|
// Handle different warning patterns for npm vs gh
|
|
@@ -220,6 +307,9 @@ async function executeCommand(fullCommand, type, options = {}) {
|
|
|
220
307
|
result: stdout,
|
|
221
308
|
timestamp: new Date().toISOString(),
|
|
222
309
|
type,
|
|
310
|
+
platform: platform(),
|
|
311
|
+
shell: config.shell,
|
|
312
|
+
shellType: config.type,
|
|
223
313
|
...(stderr && { warning: stderr }), // Include warnings but don't treat as error
|
|
224
314
|
});
|
|
225
315
|
}
|
|
@@ -359,32 +449,16 @@ function registerApiStatusCheckTool(server) {
|
|
|
359
449
|
}
|
|
360
450
|
|
|
361
451
|
const TOOL_NAME$8 = 'github_search_code';
|
|
362
|
-
const DESCRIPTION$8 = `Search code across GitHub repositories using strategic boolean operators and filters
|
|
363
|
-
|
|
364
|
-
STRATEGIC SEARCH PATTERNS:
|
|
365
|
-
|
|
366
|
-
OR LOGIC (Exploratory Discovery):
|
|
367
|
-
• Auto-applied to multi-word queries: "useState hook" → "useState OR hook"
|
|
368
|
-
• Best for: Learning, finding alternatives, casting wide nets
|
|
369
|
-
• Scope: BROADEST - finds files with ANY of the terms
|
|
370
|
-
|
|
371
|
-
AND LOGIC (Precise Intersection):
|
|
372
|
-
• Explicit requirement: "react AND hooks" requires BOTH terms present
|
|
373
|
-
• Best for: Finding specific combinations, technology intersections
|
|
374
|
-
• Scope: RESTRICTIVE - only files containing ALL terms
|
|
375
|
-
|
|
376
|
-
EXACT PHRASE (Laser Targeting):
|
|
377
|
-
• Escaped quotes: "useState hook" finds literal "useState hook" sequence
|
|
378
|
-
• Best for: Documentation titles, specific API calls, exact implementations
|
|
379
|
-
• Scope: MOST PRECISE - only exact sequence matches
|
|
380
|
-
|
|
381
|
-
NOT LOGIC (Noise Filtering):
|
|
382
|
-
• Exclude unwanted results: "authentication NOT test NOT mock"
|
|
383
|
-
• Best for: Removing examples, tests, deprecated code
|
|
452
|
+
const DESCRIPTION$8 = `Search code across GitHub repositories using strategic boolean operators and filters with "gh code search" command.
|
|
384
453
|
|
|
385
|
-
|
|
454
|
+
SEARCH PATTERNS:
|
|
455
|
+
OR (broad): "useState hook" → "useState OR hook" (auto-default for multi-word)
|
|
456
|
+
AND (precise): "react AND hooks" (both terms required)
|
|
457
|
+
NOT (filter): "auth NOT test" (exclude unwanted)
|
|
458
|
+
Exact phrases: "useState hook" (quoted for literal match)
|
|
459
|
+
Combine with filters: language, owner, path for laser focus
|
|
386
460
|
|
|
387
|
-
|
|
461
|
+
RESTRICTIVENESS: OR (broadest) < AND < Exact Phrase (most precise)`;
|
|
388
462
|
function registerGitHubSearchCodeTool(server) {
|
|
389
463
|
server.tool(TOOL_NAME$8, DESCRIPTION$8, {
|
|
390
464
|
query: z
|
|
@@ -444,8 +518,10 @@ function registerGitHubSearchCodeTool(server) {
|
|
|
444
518
|
openWorldHint: true,
|
|
445
519
|
}, async (args) => {
|
|
446
520
|
try {
|
|
447
|
-
|
|
448
|
-
|
|
521
|
+
// Validate parameter combinations
|
|
522
|
+
const validationError = validateSearchParameters(args);
|
|
523
|
+
if (validationError) {
|
|
524
|
+
return createResult(validationError, true);
|
|
449
525
|
}
|
|
450
526
|
const result = await searchGitHubCode(args);
|
|
451
527
|
if (result.isError) {
|
|
@@ -469,7 +545,12 @@ function registerGitHubSearchCodeTool(server) {
|
|
|
469
545
|
});
|
|
470
546
|
}
|
|
471
547
|
catch (error) {
|
|
472
|
-
|
|
548
|
+
const errorMessage = error.message || '';
|
|
549
|
+
// Handle JSON parsing errors
|
|
550
|
+
if (errorMessage.includes('JSON')) {
|
|
551
|
+
return createErrorResult$1('GitHub CLI returned invalid response - check if GitHub CLI is up to date with "gh version" and try again', error);
|
|
552
|
+
}
|
|
553
|
+
return createErrorResult$1('GitHub code search failed - verify parameters and try with simpler query or specific filters (language, owner, path)', error);
|
|
473
554
|
}
|
|
474
555
|
});
|
|
475
556
|
}
|
|
@@ -489,10 +570,12 @@ function parseSearchQuery(query, filters) {
|
|
|
489
570
|
exactPhrases.push(match);
|
|
490
571
|
processedQuery = processedQuery.replace(match, placeholder);
|
|
491
572
|
});
|
|
492
|
-
// Step 3:
|
|
573
|
+
// Step 3: Check complexity BEFORE adding auto-OR logic
|
|
574
|
+
const originalHasComplexLogic = hasComplexBooleanLogic(processedQuery);
|
|
575
|
+
// Step 4: Smart boolean logic - default to OR between terms if no explicit operators
|
|
493
576
|
let searchQuery = processedQuery;
|
|
494
577
|
// Check if query already has explicit boolean operators
|
|
495
|
-
if (!
|
|
578
|
+
if (!originalHasComplexLogic) {
|
|
496
579
|
// Split by whitespace and join with OR for better search results
|
|
497
580
|
const terms = processedQuery
|
|
498
581
|
.trim()
|
|
@@ -502,21 +585,22 @@ function parseSearchQuery(query, filters) {
|
|
|
502
585
|
searchQuery = terms.join(' OR ');
|
|
503
586
|
}
|
|
504
587
|
}
|
|
505
|
-
// Step
|
|
588
|
+
// Step 5: Handle filters differently based on ORIGINAL query complexity
|
|
506
589
|
const githubFilters = [];
|
|
590
|
+
// Always add path and visibility to query string (they don't have CLI equivalents)
|
|
507
591
|
if (filters.path) {
|
|
508
592
|
githubFilters.push(`path:${filters.path}`);
|
|
509
593
|
}
|
|
510
594
|
if (filters.visibility) {
|
|
511
595
|
githubFilters.push(`visibility:${filters.visibility}`);
|
|
512
596
|
}
|
|
513
|
-
// For complex boolean queries, add
|
|
514
|
-
|
|
515
|
-
if (hasComplexLogic) {
|
|
597
|
+
// For complex boolean queries, add ALL filters to query string to avoid CLI conflicts
|
|
598
|
+
if (originalHasComplexLogic) {
|
|
516
599
|
if (filters.language) {
|
|
517
600
|
githubFilters.push(`language:${filters.language}`);
|
|
518
601
|
}
|
|
519
|
-
|
|
602
|
+
// For complex queries with both language and extension, prioritize language
|
|
603
|
+
if (filters.extension && !filters.language) {
|
|
520
604
|
githubFilters.push(`extension:${filters.extension}`);
|
|
521
605
|
}
|
|
522
606
|
if (filters.filename) {
|
|
@@ -526,11 +610,11 @@ function parseSearchQuery(query, filters) {
|
|
|
526
610
|
githubFilters.push(`size:${filters.size}`);
|
|
527
611
|
}
|
|
528
612
|
}
|
|
529
|
-
// Step
|
|
613
|
+
// Step 6: Combine query with GitHub filters using proper spacing
|
|
530
614
|
if (githubFilters.length > 0) {
|
|
531
615
|
searchQuery = `${searchQuery} ${githubFilters.join(' ')}`;
|
|
532
616
|
}
|
|
533
|
-
// Step
|
|
617
|
+
// Step 7: Restore exact phrases
|
|
534
618
|
exactPhrases.forEach((phrase, index) => {
|
|
535
619
|
const placeholder = `__EXACT_PHRASE_${index}__`;
|
|
536
620
|
searchQuery = searchQuery.replace(placeholder, phrase);
|
|
@@ -545,19 +629,17 @@ function hasComplexBooleanLogic(query) {
|
|
|
545
629
|
return booleanOperators.test(query);
|
|
546
630
|
}
|
|
547
631
|
/**
|
|
548
|
-
* Build command line arguments for GitHub CLI
|
|
632
|
+
* Build command line arguments for GitHub CLI with improved parameter handling
|
|
549
633
|
*/
|
|
550
634
|
function buildGitHubCliArgs(params) {
|
|
551
635
|
const args = ['code'];
|
|
552
636
|
// Parse and add the main search query
|
|
553
637
|
const searchQuery = parseSearchQuery(params.query, params);
|
|
554
638
|
args.push(searchQuery);
|
|
555
|
-
//
|
|
556
|
-
const hasComplexLogic = hasComplexBooleanLogic(
|
|
557
|
-
// For
|
|
558
|
-
if (hasComplexLogic)
|
|
559
|
-
else {
|
|
560
|
-
// Simple queries: use CLI flags for better performance
|
|
639
|
+
// Determine strategy based on ORIGINAL query complexity, not processed query
|
|
640
|
+
const hasComplexLogic = hasComplexBooleanLogic(params.query);
|
|
641
|
+
// For simple queries, use CLI flags for better performance and validation
|
|
642
|
+
if (!hasComplexLogic) {
|
|
561
643
|
if (params.language) {
|
|
562
644
|
args.push(`--language=${params.language}`);
|
|
563
645
|
}
|
|
@@ -571,15 +653,16 @@ function buildGitHubCliArgs(params) {
|
|
|
571
653
|
args.push(`--size=${params.size}`);
|
|
572
654
|
}
|
|
573
655
|
}
|
|
656
|
+
// For complex queries, filters are already in the query string (handled by parseSearchQuery)
|
|
657
|
+
// Always add limit
|
|
574
658
|
if (params.limit) {
|
|
575
659
|
args.push(`--limit=${params.limit}`);
|
|
576
660
|
}
|
|
577
|
-
// Handle match parameter
|
|
661
|
+
// Handle match parameter with conflict resolution
|
|
578
662
|
if (params.match) {
|
|
579
663
|
const matchValues = Array.isArray(params.match)
|
|
580
664
|
? params.match
|
|
581
665
|
: [params.match];
|
|
582
|
-
// GitHub API limitation: can't use both in:file and in:path in same query
|
|
583
666
|
// Use the first match type when multiple are provided
|
|
584
667
|
const matchValue = matchValues[0];
|
|
585
668
|
args.push(`--match=${matchValue}`);
|
|
@@ -591,7 +674,7 @@ function buildGitHubCliArgs(params) {
|
|
|
591
674
|
: [params.owner];
|
|
592
675
|
ownerValues.forEach(owner => args.push(`--owner=${owner}`));
|
|
593
676
|
}
|
|
594
|
-
// Handle repository filters
|
|
677
|
+
// Handle repository filters with improved validation
|
|
595
678
|
if (params.owner && params.repo) {
|
|
596
679
|
const owners = Array.isArray(params.owner) ? params.owner : [params.owner];
|
|
597
680
|
const repos = Array.isArray(params.repo) ? params.repo : [params.repo];
|
|
@@ -623,10 +706,65 @@ async function searchGitHubCode(params) {
|
|
|
623
706
|
return result;
|
|
624
707
|
}
|
|
625
708
|
catch (error) {
|
|
626
|
-
|
|
709
|
+
const errorMessage = error.message || '';
|
|
710
|
+
// Parse specific GitHub CLI error types
|
|
711
|
+
if (errorMessage.includes('authentication')) {
|
|
712
|
+
return createErrorResult$1('GitHub CLI authentication required - run the api_status_check tool to verify authentication and available organizations', error);
|
|
713
|
+
}
|
|
714
|
+
if (errorMessage.includes('rate limit')) {
|
|
715
|
+
return createErrorResult$1('GitHub API rate limit exceeded - wait a few minutes before searching again or use more specific filters to reduce results', error);
|
|
716
|
+
}
|
|
717
|
+
if (errorMessage.includes('validation failed') ||
|
|
718
|
+
errorMessage.includes('Invalid query')) {
|
|
719
|
+
return createErrorResult$1('Invalid search query syntax - check boolean operators (AND/OR/NOT), quotes for exact phrases, and filter formats. Try simplifying your query', error);
|
|
720
|
+
}
|
|
721
|
+
if (errorMessage.includes('repository not found') ||
|
|
722
|
+
errorMessage.includes('owner not found')) {
|
|
723
|
+
return createErrorResult$1('Repository or owner not found - run api_status_check tool to verify available organizations and access permissions', error);
|
|
724
|
+
}
|
|
725
|
+
if (errorMessage.includes('timeout')) {
|
|
726
|
+
return createErrorResult$1('Search timeout - query too broad or complex. Try adding filters like language, owner, or path to narrow results', error);
|
|
727
|
+
}
|
|
728
|
+
// Generic fallback with helpful guidance
|
|
729
|
+
return createErrorResult$1('GitHub code search failed - run api_status_check tool to verify authentication and permissions, or try simplifying your query', error);
|
|
627
730
|
}
|
|
628
731
|
});
|
|
629
732
|
}
|
|
733
|
+
/**
|
|
734
|
+
* Validate parameter combinations to prevent conflicts
|
|
735
|
+
*/
|
|
736
|
+
function validateSearchParameters(params) {
|
|
737
|
+
// Query validation
|
|
738
|
+
if (!params.query.trim()) {
|
|
739
|
+
return 'Empty search query - provide a search term like "useState", "function init", or "api AND endpoint"';
|
|
740
|
+
}
|
|
741
|
+
if (params.query.length > 1000) {
|
|
742
|
+
return 'Search query too long - limit to 1000 characters. Try breaking into smaller, focused searches';
|
|
743
|
+
}
|
|
744
|
+
// Repository validation
|
|
745
|
+
if (params.repo && !params.owner) {
|
|
746
|
+
return 'Missing owner parameter - when searching specific repositories, format as owner/repo (e.g., "microsoft/vscode") or provide both owner and repo parameters';
|
|
747
|
+
}
|
|
748
|
+
// Invalid characters in query
|
|
749
|
+
if (params.query.includes('\\') && !params.query.includes('\\"')) {
|
|
750
|
+
return 'Invalid escape characters in query - use quotes for exact phrases: "exact phrase" instead of escaping';
|
|
751
|
+
}
|
|
752
|
+
// Boolean operator validation
|
|
753
|
+
const invalidBooleans = params.query.match(/\b(and|or|not)\b/g);
|
|
754
|
+
if (invalidBooleans) {
|
|
755
|
+
return `Boolean operators must be uppercase - use ${invalidBooleans.map(op => op.toUpperCase()).join(', ')} instead of ${invalidBooleans.join(', ')}`;
|
|
756
|
+
}
|
|
757
|
+
// Unmatched quotes
|
|
758
|
+
const quoteCount = (params.query.match(/"/g) || []).length;
|
|
759
|
+
if (quoteCount % 2 !== 0) {
|
|
760
|
+
return 'Unmatched quotes in query - ensure all quotes are properly paired for exact phrase matching';
|
|
761
|
+
}
|
|
762
|
+
// Size parameter validation
|
|
763
|
+
if (params.size && !/^[<>]=?\d+$|^\d+\.\.\d+$|^\d+$/.test(params.size)) {
|
|
764
|
+
return 'Invalid size format - use ">100", "<50", "10..100", or "100" for file size filtering';
|
|
765
|
+
}
|
|
766
|
+
return null; // No validation errors
|
|
767
|
+
}
|
|
630
768
|
|
|
631
769
|
const TOOL_NAME$7 = 'github_get_file_content';
|
|
632
770
|
const DESCRIPTION$7 = `Read file content. This tool REQUIRES exact path verification from github_get_contents or package view exports. If fetching fails, re-check file existence with github_get_contents or branch name.`;
|
|
@@ -729,6 +867,13 @@ async function fetchGitHubFileContent(params) {
|
|
|
729
867
|
else if (errorMsg.includes('403')) {
|
|
730
868
|
return createErrorResult$1('Access denied - repository may be private or require authentication', new Error(`${owner}/${repo}`));
|
|
731
869
|
}
|
|
870
|
+
else if (errorMsg.includes('maxBuffer') ||
|
|
871
|
+
errorMsg.includes('stdout maxBuffer length exceeded')) {
|
|
872
|
+
return createErrorResult$1(` File too large to fetch (buffer limit exceeded)\n\n` +
|
|
873
|
+
`This usually happens with files >300KB. Consider:\n` +
|
|
874
|
+
` Use github_search_code to find specific patterns\n` +
|
|
875
|
+
` Browse directory structure with github_get_contents`, new Error(`Buffer overflow: ${filePath}`));
|
|
876
|
+
}
|
|
732
877
|
else {
|
|
733
878
|
return createErrorResult$1('Fetch failed - check repository and file path', new Error(errorMsg));
|
|
734
879
|
}
|
|
@@ -736,6 +881,15 @@ async function fetchGitHubFileContent(params) {
|
|
|
736
881
|
return await processFileContent(result, owner, repo, branch, filePath);
|
|
737
882
|
}
|
|
738
883
|
catch (error) {
|
|
884
|
+
const errorMessage = error.message;
|
|
885
|
+
// Handle maxBuffer errors that escape the main try-catch
|
|
886
|
+
if (errorMessage.includes('maxBuffer') ||
|
|
887
|
+
errorMessage.includes('stdout maxBuffer length exceeded')) {
|
|
888
|
+
return createErrorResult$1(` File too large to fetch (buffer limit exceeded)\n\n` +
|
|
889
|
+
`This usually happens with files >300KB. Consider:\n` +
|
|
890
|
+
` Use github_search_code to find specific patterns instead of fetching the whole file\n` +
|
|
891
|
+
` Browse directory structure with github_get_contents`, error);
|
|
892
|
+
}
|
|
739
893
|
return createErrorResult$1('Unexpected error during file fetch - check connection and permissions', error);
|
|
740
894
|
}
|
|
741
895
|
});
|
|
@@ -749,10 +903,15 @@ async function processFileContent(result, owner, repo, branch, filePath) {
|
|
|
749
903
|
return createErrorResult$1('Path is directory - use github_get_contents to browse directory structure', new Error(filePath));
|
|
750
904
|
}
|
|
751
905
|
const fileSize = fileData.size || 0;
|
|
752
|
-
const MAX_FILE_SIZE =
|
|
753
|
-
// Check file size
|
|
906
|
+
const MAX_FILE_SIZE = 300 * 1024; // 300KB limit for better performance and reliability
|
|
907
|
+
// Check file size with helpful message
|
|
754
908
|
if (fileSize > MAX_FILE_SIZE) {
|
|
755
|
-
|
|
909
|
+
const fileSizeKB = Math.round(fileSize / 1024);
|
|
910
|
+
const maxSizeKB = Math.round(MAX_FILE_SIZE / 1024);
|
|
911
|
+
return createErrorResult$1(` File too large to display (${fileSizeKB}KB > ${maxSizeKB}KB limit)\n\n` +
|
|
912
|
+
`For large files like this, consider:\n` +
|
|
913
|
+
` Use github_get_contents to browse directory structure\n` +
|
|
914
|
+
` Search specific code patterns with github_search_code`, new Error(`File: ${filePath} (${fileSizeKB}KB)`));
|
|
756
915
|
}
|
|
757
916
|
// Get and decode content
|
|
758
917
|
const base64Content = fileData.content?.replace(/\s/g, ''); // Remove all whitespace
|
|
@@ -1011,44 +1170,16 @@ async function searchGitHubRepos(params) {
|
|
|
1011
1170
|
function buildGitHubReposSearchCommand(params) {
|
|
1012
1171
|
// Build query following GitHub CLI patterns
|
|
1013
1172
|
const query = params.query?.trim() || '';
|
|
1014
|
-
// Handle complex queries (with qualifiers, operators, or --) differently
|
|
1015
|
-
const hasComplexSyntax = query.includes('--') ||
|
|
1016
|
-
query.includes(':') ||
|
|
1017
|
-
query.includes('OR') ||
|
|
1018
|
-
query.includes('AND') ||
|
|
1019
|
-
query.includes('(') ||
|
|
1020
|
-
query.includes(')') ||
|
|
1021
|
-
query.startsWith('-');
|
|
1022
1173
|
const args = ['repos'];
|
|
1023
|
-
// Only add query if it exists
|
|
1174
|
+
// Only add query if it exists and handle it properly
|
|
1024
1175
|
if (query) {
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
queryParts.forEach(part => {
|
|
1030
|
-
// If part contains shell special characters, quote it
|
|
1031
|
-
if (/[><=&|$`(){}[\];\\]/.test(part) && !part.includes('"')) {
|
|
1032
|
-
args.push(`"${part}"`);
|
|
1033
|
-
}
|
|
1034
|
-
else {
|
|
1035
|
-
args.push(part);
|
|
1036
|
-
}
|
|
1037
|
-
});
|
|
1176
|
+
// For repository search, treat multi-word queries as a single quoted string
|
|
1177
|
+
// This matches GitHub CLI expected behavior for repo searches
|
|
1178
|
+
if (query.includes(' ')) {
|
|
1179
|
+
args.push(query); // Let GitHub CLI handle the quoting
|
|
1038
1180
|
}
|
|
1039
1181
|
else {
|
|
1040
|
-
|
|
1041
|
-
// "cli shell" becomes separate args: cli shell
|
|
1042
|
-
const queryParts = query.split(/\s+/).filter(part => part.length > 0);
|
|
1043
|
-
queryParts.forEach(part => {
|
|
1044
|
-
// Only quote if the part contains special characters
|
|
1045
|
-
if (needsQuoting(part)) {
|
|
1046
|
-
args.push(`"${part}"`);
|
|
1047
|
-
}
|
|
1048
|
-
else {
|
|
1049
|
-
args.push(part);
|
|
1050
|
-
}
|
|
1051
|
-
});
|
|
1182
|
+
args.push(query);
|
|
1052
1183
|
}
|
|
1053
1184
|
}
|
|
1054
1185
|
// Add JSON output with specific fields for structured data parsing
|
|
@@ -1077,14 +1208,15 @@ function buildGitHubReposSearchCommand(params) {
|
|
|
1077
1208
|
const starsValue = params.stars.trim();
|
|
1078
1209
|
const isValidStars = /^(\d+|>\d+|<\d+|\d+\.\.\d+|>=\d+|<=\d+)$/.test(starsValue);
|
|
1079
1210
|
if (isValidStars) {
|
|
1080
|
-
|
|
1211
|
+
// Don't add quotes around the stars value - GitHub CLI handles this internally
|
|
1212
|
+
args.push(`--stars=${starsValue}`);
|
|
1081
1213
|
}
|
|
1082
1214
|
}
|
|
1083
1215
|
// SECONDARY FILTERS - only add if we have primary filters
|
|
1084
1216
|
if (params.archived !== undefined)
|
|
1085
1217
|
args.push(`--archived=${params.archived}`);
|
|
1086
1218
|
if (params.created)
|
|
1087
|
-
args.push(`--created
|
|
1219
|
+
args.push(`--created=${params.created}`);
|
|
1088
1220
|
if (params.includeForks)
|
|
1089
1221
|
args.push(`--include-forks=${params.includeForks}`);
|
|
1090
1222
|
if (params.license && params.license.length > 0)
|
|
@@ -1092,7 +1224,7 @@ function buildGitHubReposSearchCommand(params) {
|
|
|
1092
1224
|
if (params.match)
|
|
1093
1225
|
args.push(`--match=${params.match}`);
|
|
1094
1226
|
if (params.updated)
|
|
1095
|
-
args.push(`--updated
|
|
1227
|
+
args.push(`--updated=${params.updated}`);
|
|
1096
1228
|
if (params.visibility)
|
|
1097
1229
|
args.push(`--visibility=${params.visibility}`);
|
|
1098
1230
|
if (params.goodFirstIssues)
|
|
@@ -1391,15 +1523,13 @@ function buildGitHubCommitsSearchCommand(params) {
|
|
|
1391
1523
|
|
|
1392
1524
|
// TODO: add PR commeents. e.g, gh pr view <PR_NUMBER_OR_URL_OR_BRANCH> --comments
|
|
1393
1525
|
const TOOL_NAME$4 = 'github_search_pull_requests';
|
|
1394
|
-
const DESCRIPTION$4 = `Find pull requests and implementations with detailed metadata. Discover
|
|
1526
|
+
const DESCRIPTION$4 = `Find pull requests and implementations with detailed metadata. Discover feature implementations, code review patterns, and development workflows.
|
|
1395
1527
|
|
|
1396
|
-
SEARCH PATTERNS
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
Filter by state, author, reviewer, or merge status for comprehensive development workflow analysis.`;
|
|
1528
|
+
SEARCH PATTERNS:
|
|
1529
|
+
Boolean: "fix AND bug", "refactor OR cleanup", "feature NOT draft"
|
|
1530
|
+
Exact phrases: "initial commit" (quoted)
|
|
1531
|
+
GitHub qualifiers: "is:merged review:approved base:main"
|
|
1532
|
+
Combine with filters for targeted PR discovery`;
|
|
1403
1533
|
function registerSearchGitHubPullRequestsTool(server) {
|
|
1404
1534
|
server.tool(TOOL_NAME$4, DESCRIPTION$4, {
|
|
1405
1535
|
query: z
|
|
@@ -1600,9 +1730,9 @@ const TOOL_NAME$3 = 'npm_package_search';
|
|
|
1600
1730
|
const DESCRIPTION$3 = `Search npm packages by keywords using fuzzy matching.
|
|
1601
1731
|
|
|
1602
1732
|
IMPORTANT LIMITATIONS:
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1733
|
+
NO BOOLEAN OPERATORS: NPM search does NOT support AND/OR/NOT - use space-separated keywords for broader search
|
|
1734
|
+
FUZZY MATCHING ONLY: No exact phrase matching - searches are approximate keyword matching
|
|
1735
|
+
KEYWORD-BASED: Best results with simple, space-separated terms like "react hooks" or "cli typescript"
|
|
1606
1736
|
|
|
1607
1737
|
Required when package name is unknown. If you have the exact package name, use npm_view_package directly. This reduces the need to use GitHub search when packages are found.`;
|
|
1608
1738
|
const MAX_DESCRIPTION_LENGTH = 100;
|
|
@@ -1930,15 +2060,13 @@ async function getSmartBranchFallback(owner, repo, requestedBranch) {
|
|
|
1930
2060
|
}
|
|
1931
2061
|
|
|
1932
2062
|
const TOOL_NAME$1 = 'github_search_issues';
|
|
1933
|
-
const DESCRIPTION$1 = `Find GitHub issues
|
|
1934
|
-
|
|
1935
|
-
SEARCH PATTERNS SUPPORTED:
|
|
1936
|
-
• BOOLEAN OPERATORS: "bug AND crash" (both required), "feature OR enhancement" (either term), "error NOT test" (excludes test)
|
|
1937
|
-
• EXACT PHRASES: "memory leak" (precise phrase matching)
|
|
1938
|
-
• GITHUB QUALIFIERS: Built-in support for "is:open", "label:bug", "author:username", etc.
|
|
1939
|
-
• COMBINABLE: Mix search terms with filters for surgical precision
|
|
2063
|
+
const DESCRIPTION$1 = `Find GitHub issues with rich metadata (labels, reactions, comments, state). Discover pain points, feature requests, and bug patterns with boolean logic and GitHub qualifiers.
|
|
1940
2064
|
|
|
1941
|
-
|
|
2065
|
+
SEARCH PATTERNS:
|
|
2066
|
+
Boolean: "bug AND crash", "feature OR enhancement", "error NOT test"
|
|
2067
|
+
Exact phrases: "memory leak" (quoted)
|
|
2068
|
+
GitHub qualifiers: "is:open label:bug author:username"
|
|
2069
|
+
Combine with filters for precision`;
|
|
1942
2070
|
function registerSearchGitHubIssuesTool(server) {
|
|
1943
2071
|
server.tool(TOOL_NAME$1, DESCRIPTION$1, {
|
|
1944
2072
|
query: z
|
|
@@ -2150,10 +2278,7 @@ function buildGitHubIssuesAPICommand(params) {
|
|
|
2150
2278
|
}
|
|
2151
2279
|
|
|
2152
2280
|
const TOOL_NAME = 'npm_view_package';
|
|
2153
|
-
const DESCRIPTION = `
|
|
2154
|
-
name from search results or user input. This tool is effieicnt since it gets important package metadata
|
|
2155
|
-
on a package fast to optimize tools calls. get package git repository path easily without need to search it (using repo/code search tools),
|
|
2156
|
-
exported files of a package are there, along with dependencies and version history.`;
|
|
2281
|
+
const DESCRIPTION = `Get comprehensive NPM package metadata efficiently. Returns repository URL, exports, dependencies, and version history without needing GitHub searches. Essential for finding package source code and understanding project structure.`;
|
|
2157
2282
|
function registerNpmViewPackageTool(server) {
|
|
2158
2283
|
server.tool(TOOL_NAME, DESCRIPTION, {
|
|
2159
2284
|
packageName: z
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "octocode-mcp",
|
|
3
|
-
"version": "2.3.
|
|
3
|
+
"version": "2.3.4",
|
|
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://github.com/bgauryy/octocode-mcp#readme",
|