octocode-mcp 2.3.12 → 2.3.15
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 +60 -2
- package/assets/langchainTutorial.gif +0 -0
- package/assets/logo.png +0 -0
- package/assets/reactVSVueJS.gif +0 -0
- package/assets/reactZustand.gif +0 -0
- package/{build → dist}/index.js +157 -143
- package/manifest.json +110 -0
- package/package.json +19 -7
package/README.md
CHANGED
|
@@ -8,11 +8,14 @@
|
|
|
8
8
|
[](./package.json)
|
|
9
9
|
[](./package.json)
|
|
10
10
|
[](https://modelcontextprotocol.io/)
|
|
11
|
-
[](https://buymeacoffee.com/bgauryy)
|
|
12
11
|
</div>
|
|
13
12
|
|
|
13
|
+
|
|
14
|
+
|
|
14
15
|
## What is Octocode? 🐙
|
|
15
16
|
|
|
17
|
+
**For more details, visit [octocode.ai](https://octocode.ai)**
|
|
18
|
+
|
|
16
19
|
**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.
|
|
17
20
|
|
|
18
21
|
Instead of manually browsing repositories, ask questions like:
|
|
@@ -73,6 +76,61 @@ npm login
|
|
|
73
76
|
|
|
74
77
|
**That's it!** Octocode automatically works with your organization's private repositories.
|
|
75
78
|
|
|
79
|
+
## DXT Extension 📦
|
|
80
|
+
|
|
81
|
+
This project is available as a **Desktop Extension (DXT)** for easy installation in AI applications like Claude Desktop.
|
|
82
|
+
|
|
83
|
+
### For Developers
|
|
84
|
+
|
|
85
|
+
**Building the DXT Package:**
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
# Install dependencies
|
|
89
|
+
yarn install
|
|
90
|
+
|
|
91
|
+
# Build the DXT package
|
|
92
|
+
yarn dxt:pack
|
|
93
|
+
|
|
94
|
+
# Validate the manifest
|
|
95
|
+
yarn dxt:validate
|
|
96
|
+
|
|
97
|
+
# View package information
|
|
98
|
+
yarn dxt:info
|
|
99
|
+
|
|
100
|
+
# Sign the package (optional)
|
|
101
|
+
yarn dxt:sign
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
**DXT Scripts:**
|
|
105
|
+
- `yarn dxt:validate` - Validate the manifest.json file
|
|
106
|
+
- `yarn dxt:pack` - Build and package the extension as a .dxt file
|
|
107
|
+
- `yarn dxt:info` - Show information about the packaged extension
|
|
108
|
+
- `yarn dxt:sign` - Sign the package with a self-signed certificate
|
|
109
|
+
- `yarn dxt:verify` - Verify the signature of a signed package
|
|
110
|
+
|
|
111
|
+
**The DXT package includes:**
|
|
112
|
+
- Compiled MCP server (`dist/index.js`)
|
|
113
|
+
- Extension manifest (`manifest.json`)
|
|
114
|
+
- Package metadata (`package.json`)
|
|
115
|
+
- Logo and assets (`assets/logo.png`)
|
|
116
|
+
- Documentation (`README.md`)
|
|
117
|
+
|
|
118
|
+
**Building DXT from Source:**
|
|
119
|
+
To build the DXT package locally from this repository:
|
|
120
|
+
```bash
|
|
121
|
+
# Clone the repository
|
|
122
|
+
git clone https://github.com/bgauryy/octocode-mcp.git
|
|
123
|
+
cd octocode-mcp
|
|
124
|
+
|
|
125
|
+
# Install dependencies and build
|
|
126
|
+
yarn install
|
|
127
|
+
yarn build
|
|
128
|
+
yarn dxt:pack
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
The generated `octocode-mcp.dxt` file can then be installed in Claude Desktop (just click on it and it will open claude desktop with the extension)
|
|
132
|
+
|
|
133
|
+
|
|
76
134
|
## How It Works 🔄
|
|
77
135
|
|
|
78
136
|
**Smart Discovery Flow:**
|
|
@@ -189,4 +247,4 @@ The goal: **make code exploration as intelligent as having a senior developer gu
|
|
|
189
247
|
|
|
190
248
|
MIT License - See [LICENSE](./LICENSE.md) for details.
|
|
191
249
|
|
|
192
|
-
---
|
|
250
|
+
---
|
|
Binary file
|
package/assets/logo.png
ADDED
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/{build → dist}/index.js
RENAMED
|
@@ -144,29 +144,6 @@ function escapeShellArg(arg, shellType, isGitHubQuery // Flag to indicate if thi
|
|
|
144
144
|
const isWindows = platform() === 'win32';
|
|
145
145
|
shellType = isWindows ? 'cmd' : 'unix';
|
|
146
146
|
}
|
|
147
|
-
// Special handling for GitHub search queries to preserve AND logic
|
|
148
|
-
if (isGitHubQuery) {
|
|
149
|
-
// If the argument already contains quotes, preserve them for exact phrases
|
|
150
|
-
if (arg.includes('"')) {
|
|
151
|
-
// For Unix-like shells, wrap the entire argument in single quotes
|
|
152
|
-
if (shellType === 'unix') {
|
|
153
|
-
return `'${arg.replace(/'/g, "'\"'\"'")}'`;
|
|
154
|
-
}
|
|
155
|
-
// For Windows CMD
|
|
156
|
-
if (shellType === 'cmd') {
|
|
157
|
-
return `"${arg.replace(/"/g, '""')}"`;
|
|
158
|
-
}
|
|
159
|
-
// For PowerShell
|
|
160
|
-
return `'${arg.replace(/'/g, "''")}'`;
|
|
161
|
-
}
|
|
162
|
-
// For space-separated terms (AND search), minimize escaping
|
|
163
|
-
if (arg.includes(' ') && shellType === 'unix') {
|
|
164
|
-
// Only escape if contains dangerous shell characters
|
|
165
|
-
if (!/[;&|<>$`\\]/.test(arg)) {
|
|
166
|
-
return `"${arg}"`;
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
147
|
switch (shellType) {
|
|
171
148
|
case 'powershell':
|
|
172
149
|
return escapePowerShellArg(arg);
|
|
@@ -174,7 +151,7 @@ function escapeShellArg(arg, shellType, isGitHubQuery // Flag to indicate if thi
|
|
|
174
151
|
return escapeWindowsCmdArg(arg);
|
|
175
152
|
case 'unix':
|
|
176
153
|
default:
|
|
177
|
-
return escapeUnixShellArg(arg
|
|
154
|
+
return escapeUnixShellArg(arg);
|
|
178
155
|
}
|
|
179
156
|
}
|
|
180
157
|
/**
|
|
@@ -205,30 +182,10 @@ function escapeWindowsCmdArg(arg) {
|
|
|
205
182
|
* Preserves AND search logic by not over-escaping space-separated terms
|
|
206
183
|
*/
|
|
207
184
|
function escapeUnixShellArg(arg, isGitHubQuery) {
|
|
208
|
-
// For GitHub search queries, we need to preserve AND logic and quoted phrases
|
|
209
|
-
if (isGitHubQuery) {
|
|
210
|
-
// If the query contains quotes, we need to preserve them for GitHub CLI
|
|
211
|
-
// but escape the entire argument for the shell
|
|
212
|
-
if (arg.includes('"')) {
|
|
213
|
-
// Use single quotes to wrap the entire query while preserving internal quotes
|
|
214
|
-
// This allows GitHub CLI to see: "quoted phrase" other terms
|
|
215
|
-
return `'${arg.replace(/'/g, "'\"'\"'")}'`;
|
|
216
|
-
}
|
|
217
|
-
// For space-separated terms (AND search), only escape if absolutely necessary
|
|
218
|
-
// GitHub CLI expects space-separated terms for AND logic
|
|
219
|
-
if (arg.includes(' ') && !/[;&|<>$`\\]/.test(arg)) {
|
|
220
|
-
// Only wrap in quotes if it contains shell metacharacters beyond spaces
|
|
221
|
-
return `"${arg}"`;
|
|
222
|
-
}
|
|
223
|
-
// For single terms or terms with special chars, escape normally
|
|
224
|
-
if (/[;&|<>$`\\]/.test(arg)) {
|
|
225
|
-
return `'${arg.replace(/'/g, "'\"'\"'")}'`;
|
|
226
|
-
}
|
|
227
|
-
// Simple terms don't need escaping
|
|
228
|
-
return arg;
|
|
229
|
-
}
|
|
230
185
|
// Standard Unix shell escaping for other arguments
|
|
231
|
-
if
|
|
186
|
+
// Only escape if contains dangerous shell metacharacters
|
|
187
|
+
// Allow common safe characters: alphanumeric, dash, underscore, dot, slash, equals, at, colon, comma
|
|
188
|
+
if (/[;&|<>$`\\*?()[\]{}^~]/.test(arg)) {
|
|
232
189
|
return `'${arg.replace(/'/g, "'\"'\"'")}'`;
|
|
233
190
|
}
|
|
234
191
|
return arg;
|
|
@@ -245,7 +202,28 @@ async function executeNpmCommand(command, args = [], options = {}) {
|
|
|
245
202
|
// Get shell configuration
|
|
246
203
|
const shellConfig = getShellConfig(options.windowsShell);
|
|
247
204
|
// Build command with validated prefix and properly escaped arguments
|
|
248
|
-
|
|
205
|
+
// NPM commands need minimal escaping - most arguments are package names or CLI flags
|
|
206
|
+
const escapedArgs = args.map(arg => {
|
|
207
|
+
const isCliFlag = arg.startsWith('--');
|
|
208
|
+
// CLI flags like --searchlimit=20, --json need minimal escaping
|
|
209
|
+
if (isCliFlag) {
|
|
210
|
+
// Only escape CLI flags if they contain dangerous shell characters
|
|
211
|
+
if (/[;&|<>$`\\]/.test(arg)) {
|
|
212
|
+
return escapeShellArg(arg, shellConfig.type);
|
|
213
|
+
}
|
|
214
|
+
return arg;
|
|
215
|
+
}
|
|
216
|
+
// Package names and search terms need minimal escaping
|
|
217
|
+
// Only escape if contains shell metacharacters that could be dangerous
|
|
218
|
+
if (/[;&|<>$`\\*?[\]{}]/.test(arg)) {
|
|
219
|
+
return escapeShellArg(arg, shellConfig.type);
|
|
220
|
+
}
|
|
221
|
+
// For arguments with spaces, use minimal quoting
|
|
222
|
+
if (/\s/.test(arg)) {
|
|
223
|
+
return `"${arg}"`;
|
|
224
|
+
}
|
|
225
|
+
return arg;
|
|
226
|
+
});
|
|
249
227
|
const fullCommand = `npm ${command} ${escapedArgs.join(' ')}`;
|
|
250
228
|
const executeNpmCommand = () => executeCommand(fullCommand, 'npm', options, shellConfig);
|
|
251
229
|
if (options.cache) {
|
|
@@ -269,33 +247,40 @@ async function executeGitHubCommand(command, args = [], options = {}) {
|
|
|
269
247
|
// Get shell configuration
|
|
270
248
|
const shellConfig = getShellConfig(options.windowsShell);
|
|
271
249
|
// Build command with validated prefix and properly escaped arguments
|
|
272
|
-
// For GitHub search commands, we need to
|
|
273
|
-
// 1. Main query (index 1) - needs special escaping for AND logic
|
|
274
|
-
// 2. CLI flags (--flag=value) - standard escaping
|
|
275
|
-
// 3. Search qualifiers (key:value) - minimal escaping
|
|
250
|
+
// For GitHub search commands, we need minimal escaping to avoid interfering with GitHub CLI
|
|
276
251
|
const escapedArgs = args.map((arg, index) => {
|
|
277
252
|
const isMainQueryArgument = command === 'search' && index === 1;
|
|
278
253
|
const isCliFlag = arg.startsWith('--');
|
|
279
|
-
|
|
280
|
-
index > 1 &&
|
|
281
|
-
!isCliFlag &&
|
|
282
|
-
(arg.includes(':') || arg.startsWith('('));
|
|
283
|
-
// CLI flags like --language=javascript, --repo=owner/repo need standard escaping
|
|
254
|
+
// CLI flags like --language=javascript, --repo=owner/repo need minimal escaping
|
|
284
255
|
if (isCliFlag) {
|
|
285
|
-
|
|
256
|
+
// Only escape CLI flags if they contain dangerous shell characters
|
|
257
|
+
if (/[;&|<>$`\\*?[\]{}]/.test(arg)) {
|
|
258
|
+
return escapeShellArg(arg, shellConfig.type);
|
|
259
|
+
}
|
|
260
|
+
return arg;
|
|
286
261
|
}
|
|
287
|
-
//
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
262
|
+
// For search queries, only escape if absolutely necessary for shell safety
|
|
263
|
+
if (isMainQueryArgument) {
|
|
264
|
+
// Only escape if the argument contains shell metacharacters that could be dangerous
|
|
265
|
+
if (/[;&|<>$`\\*?[\]{}]/.test(arg)) {
|
|
266
|
+
return escapeShellArg(arg, shellConfig.type);
|
|
267
|
+
}
|
|
268
|
+
// For simple queries with spaces or special chars, use minimal quoting
|
|
269
|
+
if (/\s/.test(arg)) {
|
|
270
|
+
return `"${arg}"`;
|
|
294
271
|
}
|
|
295
|
-
// Safe qualifiers like "language:typescript", "user:microsoft" can be passed as-is
|
|
296
272
|
return arg;
|
|
297
273
|
}
|
|
298
|
-
|
|
274
|
+
// For other arguments, use minimal escaping
|
|
275
|
+
// Only escape if contains shell metacharacters that could be dangerous
|
|
276
|
+
if (/[;&|<>$`\\*?[\]{}]/.test(arg)) {
|
|
277
|
+
return escapeShellArg(arg, shellConfig.type);
|
|
278
|
+
}
|
|
279
|
+
// For arguments with spaces, use minimal quoting
|
|
280
|
+
if (/\s/.test(arg)) {
|
|
281
|
+
return `"${arg}"`;
|
|
282
|
+
}
|
|
283
|
+
return arg;
|
|
299
284
|
});
|
|
300
285
|
const fullCommand = `gh ${command} ${escapedArgs.join(' ')}`;
|
|
301
286
|
const executeGhCommand = () => executeCommand(fullCommand, 'github', options, shellConfig);
|
|
@@ -1355,8 +1340,8 @@ function buildGitHubCliArgs(params) {
|
|
|
1355
1340
|
const args = ['code'];
|
|
1356
1341
|
// Build search query (either exactQuery OR queryTerms, never both)
|
|
1357
1342
|
if (params.exactQuery) {
|
|
1358
|
-
// Add exact query
|
|
1359
|
-
args.push(
|
|
1343
|
+
// Add exact query - let GitHub CLI handle the quoting
|
|
1344
|
+
args.push(params.exactQuery);
|
|
1360
1345
|
}
|
|
1361
1346
|
else if (params.queryTerms && params.queryTerms.length > 0) {
|
|
1362
1347
|
// Add query terms as separate arguments (for AND logic)
|
|
@@ -112312,14 +112297,19 @@ async function suggestCodeSearchFallback(owner, filePath) {
|
|
|
112312
112297
|
const GITHUB_SEARCH_REPOSITORIES_TOOL_NAME = 'githubSearchRepositories';
|
|
112313
112298
|
const DESCRIPTION$6 = `Search GitHub repositories using gh search repos CLI.
|
|
112314
112299
|
|
|
112300
|
+
THREE SEARCH APPROACHES:
|
|
112301
|
+
- exactQuery: Single exact phrase/word search
|
|
112302
|
+
- queryTerms: Multiple search terms (broader coverage)
|
|
112303
|
+
- topic: Find repositories by technology/subject
|
|
112304
|
+
|
|
112315
112305
|
BEST PRACTICES:
|
|
112316
|
-
- Use
|
|
112317
|
-
- Use
|
|
112318
|
-
- Use
|
|
112319
|
-
- Use
|
|
112320
|
-
- Use
|
|
112306
|
+
- Use exactQuery for specific repository names
|
|
112307
|
+
- Use queryTerms with minimal words for broader results
|
|
112308
|
+
- Use topic for technology/subject discovery
|
|
112309
|
+
- Use owner for organization exploration
|
|
112310
|
+
- Use filters (language, stars, forks) for refinement
|
|
112321
112311
|
|
|
112322
|
-
|
|
112312
|
+
Multiple focused searches work better than complex single queries.`;
|
|
112323
112313
|
/**
|
|
112324
112314
|
* Extract owner/repo information from various query formats
|
|
112325
112315
|
*/
|
|
@@ -112354,10 +112344,14 @@ function registerSearchGitHubReposTool(server) {
|
|
|
112354
112344
|
server.registerTool(GITHUB_SEARCH_REPOSITORIES_TOOL_NAME, {
|
|
112355
112345
|
description: DESCRIPTION$6,
|
|
112356
112346
|
inputSchema: {
|
|
112357
|
-
|
|
112347
|
+
exactQuery: z
|
|
112358
112348
|
.string()
|
|
112359
112349
|
.optional()
|
|
112360
|
-
.describe('
|
|
112350
|
+
.describe('Single exact phrase/word search'),
|
|
112351
|
+
queryTerms: z
|
|
112352
|
+
.array(z.string())
|
|
112353
|
+
.optional()
|
|
112354
|
+
.describe('Multiple search terms for broader coverage'),
|
|
112361
112355
|
// CORE FILTERS (GitHub CLI flags)
|
|
112362
112356
|
owner: z
|
|
112363
112357
|
.union([z.string(), z.array(z.string())])
|
|
@@ -112379,7 +112373,7 @@ function registerSearchGitHubReposTool(server) {
|
|
|
112379
112373
|
topic: z
|
|
112380
112374
|
.union([z.string(), z.array(z.string())])
|
|
112381
112375
|
.optional()
|
|
112382
|
-
.describe('
|
|
112376
|
+
.describe('Find repositories by technology/subject'),
|
|
112383
112377
|
forks: z
|
|
112384
112378
|
.union([
|
|
112385
112379
|
z.number().int().min(0),
|
|
@@ -112502,15 +112496,29 @@ function registerSearchGitHubReposTool(server) {
|
|
|
112502
112496
|
openWorldHint: true,
|
|
112503
112497
|
},
|
|
112504
112498
|
}, async (args) => {
|
|
112499
|
+
// Validate that exactly one search parameter is provided (not both)
|
|
112500
|
+
const hasExactQuery = !!args.exactQuery;
|
|
112501
|
+
const hasQueryTerms = args.queryTerms && args.queryTerms.length > 0;
|
|
112502
|
+
if (hasExactQuery && hasQueryTerms) {
|
|
112503
|
+
return createResult({
|
|
112504
|
+
error: 'Use either exactQuery OR queryTerms, not both. Choose one search approach.',
|
|
112505
|
+
});
|
|
112506
|
+
}
|
|
112505
112507
|
try {
|
|
112506
112508
|
// Extract owner/repo from query if present
|
|
112507
|
-
const queryInfo = args.
|
|
112508
|
-
? extractOwnerRepoFromQuery(args.
|
|
112509
|
-
:
|
|
112510
|
-
|
|
112511
|
-
|
|
112512
|
-
|
|
112513
|
-
|
|
112509
|
+
const queryInfo = args.exactQuery
|
|
112510
|
+
? extractOwnerRepoFromQuery(args.exactQuery)
|
|
112511
|
+
: args.queryTerms
|
|
112512
|
+
? {
|
|
112513
|
+
cleanedQuery: args.queryTerms.join(' '),
|
|
112514
|
+
extractedOwner: undefined,
|
|
112515
|
+
extractedRepo: undefined,
|
|
112516
|
+
}
|
|
112517
|
+
: {
|
|
112518
|
+
cleanedQuery: '',
|
|
112519
|
+
extractedOwner: undefined,
|
|
112520
|
+
extractedRepo: undefined,
|
|
112521
|
+
};
|
|
112514
112522
|
// Merge extracted owner with explicit owner parameter
|
|
112515
112523
|
let finalOwner = args.owner;
|
|
112516
112524
|
if (queryInfo.extractedOwner && !finalOwner) {
|
|
@@ -112519,11 +112527,13 @@ function registerSearchGitHubReposTool(server) {
|
|
|
112519
112527
|
// Update parameters with extracted information
|
|
112520
112528
|
const enhancedArgs = {
|
|
112521
112529
|
...args,
|
|
112522
|
-
|
|
112530
|
+
exactQuery: args.exactQuery ? queryInfo.cleanedQuery : undefined,
|
|
112531
|
+
queryTerms: args.queryTerms,
|
|
112523
112532
|
owner: finalOwner,
|
|
112524
112533
|
};
|
|
112525
112534
|
// Enhanced validation logic for primary filters
|
|
112526
|
-
const hasPrimaryFilter = enhancedArgs.
|
|
112535
|
+
const hasPrimaryFilter = enhancedArgs.exactQuery?.trim() ||
|
|
112536
|
+
(enhancedArgs.queryTerms && enhancedArgs.queryTerms.length > 0) ||
|
|
112527
112537
|
enhancedArgs.owner ||
|
|
112528
112538
|
enhancedArgs.language ||
|
|
112529
112539
|
enhancedArgs.topic ||
|
|
@@ -112531,11 +112541,14 @@ function registerSearchGitHubReposTool(server) {
|
|
|
112531
112541
|
enhancedArgs.forks;
|
|
112532
112542
|
if (!hasPrimaryFilter) {
|
|
112533
112543
|
return createResult({
|
|
112534
|
-
error: `Repository search requires at least one filter. Try
|
|
112535
|
-
• Topic
|
|
112536
|
-
•
|
|
112537
|
-
•
|
|
112538
|
-
•
|
|
112544
|
+
error: `Repository search requires at least one filter. Try:
|
|
112545
|
+
• Topic search: { topic: "react" }
|
|
112546
|
+
• Exact search: { exactQuery: "cli shell" }
|
|
112547
|
+
• Multiple terms: { queryTerms: ["react", "hooks"] }
|
|
112548
|
+
• Organization: { owner: "microsoft" }
|
|
112549
|
+
• Language filter: { language: "go" }
|
|
112550
|
+
|
|
112551
|
+
Alternative: Use npm search for package discovery.`,
|
|
112539
112552
|
});
|
|
112540
112553
|
}
|
|
112541
112554
|
// First attempt: Search with current parameters
|
|
@@ -112545,19 +112558,21 @@ function registerSearchGitHubReposTool(server) {
|
|
|
112545
112558
|
// Smart fallbacks based on error type
|
|
112546
112559
|
if (errorMsg.includes('rate limit')) {
|
|
112547
112560
|
return createResult({
|
|
112548
|
-
error: `GitHub API rate limit.
|
|
112549
|
-
•
|
|
112550
|
-
•
|
|
112551
|
-
• Search fewer organizations
|
|
112561
|
+
error: `GitHub API rate limit exceeded. Alternatives:
|
|
112562
|
+
• Use npm search for package discovery
|
|
112563
|
+
• Remove quality filters (stars/forks)
|
|
112564
|
+
• Search fewer organizations
|
|
112552
112565
|
• Wait 5-10 minutes and retry`,
|
|
112553
112566
|
});
|
|
112554
112567
|
}
|
|
112555
112568
|
if (errorMsg.includes('authentication')) {
|
|
112556
112569
|
return createResult({
|
|
112557
|
-
error: `Authentication required
|
|
112558
|
-
|
|
112559
|
-
|
|
112560
|
-
|
|
112570
|
+
error: `Authentication required:
|
|
112571
|
+
• Run: gh auth login
|
|
112572
|
+
• For private repos: use api_status_check tool
|
|
112573
|
+
• Public repos work without auth
|
|
112574
|
+
|
|
112575
|
+
Alternative: Use npm search for packages.`,
|
|
112561
112576
|
});
|
|
112562
112577
|
}
|
|
112563
112578
|
return result; // Return original error for other cases
|
|
@@ -112567,31 +112582,26 @@ function registerSearchGitHubReposTool(server) {
|
|
|
112567
112582
|
const hasResults = resultData.total_count > 0;
|
|
112568
112583
|
// Smart fallback strategies for no results
|
|
112569
112584
|
if (!hasResults) {
|
|
112570
|
-
const
|
|
112571
|
-
if (enhancedArgs.
|
|
112572
|
-
|
|
112585
|
+
const suggestions = [];
|
|
112586
|
+
if (enhancedArgs.exactQuery) {
|
|
112587
|
+
suggestions.push('• Try broader search terms');
|
|
112573
112588
|
}
|
|
112574
112589
|
if (enhancedArgs.language) {
|
|
112575
|
-
|
|
112590
|
+
suggestions.push('• Remove language filter');
|
|
112576
112591
|
}
|
|
112577
112592
|
if (enhancedArgs.stars || enhancedArgs.forks) {
|
|
112578
|
-
|
|
112593
|
+
suggestions.push('• Lower quality thresholds');
|
|
112579
112594
|
}
|
|
112580
112595
|
if (!enhancedArgs.topic) {
|
|
112581
|
-
|
|
112596
|
+
suggestions.push('• Try topic search: { topic: "react" }');
|
|
112582
112597
|
}
|
|
112583
112598
|
if (enhancedArgs.owner) {
|
|
112584
|
-
|
|
112585
|
-
fallbackSuggestions.push('• Use npm package search if looking for packages');
|
|
112599
|
+
suggestions.push('• Remove owner filter for global search');
|
|
112586
112600
|
}
|
|
112601
|
+
suggestions.push('• Use npm search for package discovery');
|
|
112587
112602
|
return createResult({
|
|
112588
|
-
error: `No repositories found. Try
|
|
112589
|
-
${
|
|
112590
|
-
|
|
112591
|
-
Quick discovery patterns:
|
|
112592
|
-
• 🎯 Topic exploration: { topic: ["react"] }
|
|
112593
|
-
• Organization search: { owner: "microsoft" }
|
|
112594
|
-
• Quality filter: { stars: ">100", language: "python" }`,
|
|
112603
|
+
error: `No repositories found. Try:
|
|
112604
|
+
${suggestions.join('\n')}`,
|
|
112595
112605
|
});
|
|
112596
112606
|
}
|
|
112597
112607
|
// Fallback for private repositories: If no results and owner is specified, try with private visibility
|
|
@@ -112721,13 +112731,19 @@ async function searchGitHubRepos(params) {
|
|
|
112721
112731
|
});
|
|
112722
112732
|
}
|
|
112723
112733
|
function buildGitHubReposSearchCommand(params) {
|
|
112724
|
-
const query = params.query?.trim() || '';
|
|
112725
112734
|
const args = ['repos'];
|
|
112726
|
-
|
|
112727
|
-
|
|
112728
|
-
|
|
112729
|
-
|
|
112735
|
+
let queryForQualifierCheck = '';
|
|
112736
|
+
if (params.exactQuery) {
|
|
112737
|
+
args.push(params.exactQuery.trim());
|
|
112738
|
+
queryForQualifierCheck = params.exactQuery.trim();
|
|
112730
112739
|
}
|
|
112740
|
+
else if (params.queryTerms && params.queryTerms.length > 0) {
|
|
112741
|
+
// Add each term as separate argument for AND logic
|
|
112742
|
+
params.queryTerms.forEach(term => args.push(term.trim()));
|
|
112743
|
+
queryForQualifierCheck = params.queryTerms.join(' ');
|
|
112744
|
+
}
|
|
112745
|
+
const hasEmbeddedQualifiers = queryForQualifierCheck &&
|
|
112746
|
+
/\b(stars|language|org|repo|topic|user|created|updated|size|license|archived|fork|good-first-issues|help-wanted-issues):/i.test(queryForQualifierCheck);
|
|
112731
112747
|
args.push('--json=name,fullName,description,language,stargazersCount,forksCount,updatedAt,createdAt,url,owner,isPrivate,license,hasIssues,openIssuesCount,isArchived,isFork,visibility');
|
|
112732
112748
|
const addArg = (paramName, cliFlag, condition = true, formatter) => {
|
|
112733
112749
|
const value = params[paramName];
|
|
@@ -113434,23 +113450,19 @@ function buildGitHubPullRequestsListCommand(params) {
|
|
|
113434
113450
|
const NPM_PACKAGE_SEARCH_TOOL_NAME = 'npmPackageSearch';
|
|
113435
113451
|
const DESCRIPTION$3 = `Search NPM packages using 'npm search' command. Discover packages by functionality keywords and explore alternatives.
|
|
113436
113452
|
|
|
113437
|
-
|
|
113438
|
-
- Package discovery: npm search <term> --json --searchlimit=<n>
|
|
113439
|
-
- Multiple search terms: searches each term separately and combines results
|
|
113440
|
-
- Functional keyword search: "testing", "validation", "http client"
|
|
113441
|
-
- Repository URL extraction for GitHub integration
|
|
113442
|
-
- Deduplication and result optimization
|
|
113453
|
+
**WHEN TO USE**: Use when users ask questions about npm packages or need to discover packages - provides package discovery and ecosystem insights.
|
|
113443
113454
|
|
|
113444
|
-
|
|
113455
|
+
**KEY INSIGHTS**:
|
|
113456
|
+
- Another code search mechanism for npm packages (along github repository search)
|
|
113457
|
+
- Repo discovery by npm packages search
|
|
113458
|
+
- Package descriptions, keywords, and version information
|
|
113459
|
+
- Can be used undesrsant npm depndencies better
|
|
113460
|
+
|
|
113461
|
+
**SEARCH STRATEGY**:
|
|
113445
113462
|
- Use broad functional terms for best discovery
|
|
113446
113463
|
- Single keywords work better than complex phrases
|
|
113447
113464
|
- Multiple searches reveal ecosystem alternatives
|
|
113448
|
-
-
|
|
113449
|
-
|
|
113450
|
-
USAGE EXAMPLES:
|
|
113451
|
-
- Single search: queries="testing"
|
|
113452
|
-
- Multiple searches: queries=["react", "hooks", "typescript"]
|
|
113453
|
-
- Limit results: searchLimit=10`;
|
|
113465
|
+
- Combine with npm_view_package for detailed analysis of discovered packages`;
|
|
113454
113466
|
const MAX_DESCRIPTION_LENGTH = 100;
|
|
113455
113467
|
const MAX_KEYWORDS = 10;
|
|
113456
113468
|
function registerNpmSearchTool(server) {
|
|
@@ -114317,18 +114329,20 @@ function buildGitHubIssuesAPICommand(params) {
|
|
|
114317
114329
|
const NPM_VIEW_PACKAGE_TOOL_NAME = 'npmViewPackage';
|
|
114318
114330
|
const DESCRIPTION = `View NPM package information using 'npm view' command. Supports field-specific queries and GitHub repository discovery.
|
|
114319
114331
|
|
|
114320
|
-
|
|
114332
|
+
**WHEN TO USE**: Use when users ask questions about npm packages - provides comprehensive package data and insights.
|
|
114333
|
+
|
|
114334
|
+
**KEY INSIGHTS**:
|
|
114335
|
+
- Git repository URL for source code exploration
|
|
114336
|
+
- Package exports structure (understand API surface and dependencies)
|
|
114337
|
+
- Dependencies/devDependencies for ecosystem analysis
|
|
114338
|
+
- Version history, size, performance metrics
|
|
114339
|
+
- License and author information
|
|
114340
|
+
|
|
114341
|
+
**CAPABILITIES**:
|
|
114321
114342
|
- Full package info: npm view <package> --json (optimized format)
|
|
114322
|
-
- Single field: npm view <package> <field> (
|
|
114343
|
+
- Single field: npm view <package> <field> (version, description, license)
|
|
114323
114344
|
- Multiple fields: filtered JSON response for specific fields
|
|
114324
|
-
- Repository URLs for GitHub integration and source code analysis
|
|
114325
|
-
- Version history, dependencies, and package metadata
|
|
114326
|
-
|
|
114327
|
-
USAGE EXAMPLES:
|
|
114328
|
-
- Get version: field="version"
|
|
114329
|
-
- Get repository: field="repository" or match="repository"
|
|
114330
|
-
- Get multiple: match=["version", "description", "license"]
|
|
114331
|
-
- Get all info: no parameters (returns optimized package data)`;
|
|
114345
|
+
- Repository URLs for GitHub integration and source code analysis`;
|
|
114332
114346
|
function registerNpmViewPackageTool(server) {
|
|
114333
114347
|
server.registerTool(NPM_VIEW_PACKAGE_TOOL_NAME, {
|
|
114334
114348
|
description: DESCRIPTION,
|
package/manifest.json
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
{
|
|
2
|
+
"dxt_version": "0.1",
|
|
3
|
+
"name": "octocode-mcp",
|
|
4
|
+
"display_name": "Octocode MCP Extension",
|
|
5
|
+
"version": "1.0.0",
|
|
6
|
+
"description": "GitHub code search and npm package exploration MCP server",
|
|
7
|
+
"long_description": "A comprehensive MCP server that provides GitHub code search, repository exploration, commit history, pull requests, issues, and npm package search capabilities. This extension enables AI assistants to efficiently search and analyze code across GitHub repositories and npm packages with advanced filtering and content retrieval features.",
|
|
8
|
+
"author": {
|
|
9
|
+
"name": "Octocode Team",
|
|
10
|
+
"email": "support@octocode.dev",
|
|
11
|
+
"url": "https://github.com/octocode-dev"
|
|
12
|
+
},
|
|
13
|
+
"repository": {
|
|
14
|
+
"type": "git",
|
|
15
|
+
"url": "https://github.com/guybary/octocode-mcp"
|
|
16
|
+
},
|
|
17
|
+
"homepage": "https://github.com/guybary/octocode-mcp",
|
|
18
|
+
"documentation": "https://github.com/guybary/octocode-mcp#readme",
|
|
19
|
+
"support": "https://github.com/guybary/octocode-mcp/issues",
|
|
20
|
+
"icon": "assets/logo.png",
|
|
21
|
+
"server": {
|
|
22
|
+
"type": "node",
|
|
23
|
+
"entry_point": "dist/index.js",
|
|
24
|
+
"mcp_config": {
|
|
25
|
+
"command": "node",
|
|
26
|
+
"args": ["${__dirname}/dist/index.js"],
|
|
27
|
+
"env": {
|
|
28
|
+
"NODE_ENV": "production"
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
"tools": [
|
|
33
|
+
{
|
|
34
|
+
"name": "mcp_octocode_apiStatusCheck",
|
|
35
|
+
"description": "Check GitHub and npm login status"
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
"name": "mcp_octocode_githubSearchCode",
|
|
39
|
+
"description": "Search code across GitHub repositories"
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
"name": "mcp_octocode_githubGetFileContent",
|
|
43
|
+
"description": "Fetch file content from GitHub repositories"
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
"name": "mcp_octocode_githubSearchRepositories",
|
|
47
|
+
"description": "Search GitHub repositories"
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
"name": "mcp_octocode_githubSearchCommits",
|
|
51
|
+
"description": "Search commit history across GitHub repositories"
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
"name": "mcp_octocode_githubSearchPullRequests",
|
|
55
|
+
"description": "Search GitHub pull requests"
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
"name": "mcp_octocode_githubSearchIssues",
|
|
59
|
+
"description": "Search GitHub issues"
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
"name": "mcp_octocode_githubViewRepoStructure",
|
|
63
|
+
"description": "View GitHub repository structure"
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
"name": "mcp_octocode_npmPackageSearch",
|
|
67
|
+
"description": "Search npm packages"
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
"name": "mcp_octocode_npmViewPackage",
|
|
71
|
+
"description": "View npm package information"
|
|
72
|
+
}
|
|
73
|
+
],
|
|
74
|
+
"keywords": [
|
|
75
|
+
"github",
|
|
76
|
+
"npm",
|
|
77
|
+
"code-search",
|
|
78
|
+
"repository",
|
|
79
|
+
"package-manager",
|
|
80
|
+
"development",
|
|
81
|
+
"api",
|
|
82
|
+
"search",
|
|
83
|
+
"mcp",
|
|
84
|
+
"octocode"
|
|
85
|
+
],
|
|
86
|
+
"license": "MIT",
|
|
87
|
+
"compatibility": {
|
|
88
|
+
"claude_desktop": ">=0.10.0",
|
|
89
|
+
"platforms": ["darwin", "win32", "linux"],
|
|
90
|
+
"runtimes": {
|
|
91
|
+
"node": ">=18.0.0"
|
|
92
|
+
}
|
|
93
|
+
},
|
|
94
|
+
"user_config": {
|
|
95
|
+
"github_token": {
|
|
96
|
+
"type": "string",
|
|
97
|
+
"title": "GitHub Token",
|
|
98
|
+
"description": "Personal access token for GitHub API (optional, increases rate limits)",
|
|
99
|
+
"sensitive": true,
|
|
100
|
+
"required": false
|
|
101
|
+
},
|
|
102
|
+
"npm_registry": {
|
|
103
|
+
"type": "string",
|
|
104
|
+
"title": "NPM Registry",
|
|
105
|
+
"description": "NPM registry URL",
|
|
106
|
+
"default": "https://registry.npmjs.org",
|
|
107
|
+
"required": false
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "octocode-mcp",
|
|
3
|
-
"version": "2.3.
|
|
3
|
+
"version": "2.3.15",
|
|
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",
|
|
@@ -14,10 +14,10 @@
|
|
|
14
14
|
"engines": {
|
|
15
15
|
"node": ">=18.12.0"
|
|
16
16
|
},
|
|
17
|
-
"main": "
|
|
17
|
+
"main": "dist/index.js",
|
|
18
18
|
"license": "MIT",
|
|
19
19
|
"type": "module",
|
|
20
|
-
"bin": "./
|
|
20
|
+
"bin": "./dist/index.js",
|
|
21
21
|
"scripts": {
|
|
22
22
|
"build": "yarn lint && rollup -c",
|
|
23
23
|
"build:watch": "rollup -c --watch",
|
|
@@ -26,14 +26,23 @@
|
|
|
26
26
|
"test:watch": "vitest --watch",
|
|
27
27
|
"test:coverage": "vitest run --coverage",
|
|
28
28
|
"test:ui": "vitest --ui",
|
|
29
|
-
"debug": "npx @modelcontextprotocol/inspector node
|
|
29
|
+
"debug": "npx @modelcontextprotocol/inspector node dist/index.js",
|
|
30
30
|
"lint": "eslint src/**/*.ts tests/**/*.ts",
|
|
31
31
|
"lint:fix": "eslint src/**/*.ts tests/**/*.ts --fix",
|
|
32
32
|
"format": "prettier --write \"src/**/*.{ts,js,json}\"",
|
|
33
|
-
"format:check": "prettier --check \"src/**/*.{ts,js,json}\""
|
|
33
|
+
"format:check": "prettier --check \"src/**/*.{ts,js,json}\"",
|
|
34
|
+
"dxt:validate": "dxt validate manifest.json",
|
|
35
|
+
"dxt:pack": "yarn build && dxt pack . octocode-mcp.dxt",
|
|
36
|
+
"dxt:pack:dev": "yarn build && dxt pack . octocode-mcp-dev.dxt",
|
|
37
|
+
"dxt:info": "dxt info octocode-mcp.dxt",
|
|
38
|
+
"dxt:sign": "dxt sign octocode-mcp.dxt --self-signed",
|
|
39
|
+
"dxt:verify": "dxt verify octocode-mcp.dxt",
|
|
40
|
+
"release:dxt": "yarn build && dxt pack . octocode-mcp.dxt && dxt sign octocode-mcp.dxt --self-signed"
|
|
34
41
|
},
|
|
35
42
|
"files": [
|
|
36
|
-
"
|
|
43
|
+
"dist",
|
|
44
|
+
"manifest.json",
|
|
45
|
+
"assets"
|
|
37
46
|
],
|
|
38
47
|
"dependencies": {
|
|
39
48
|
"@babel/core": "^7.28.0",
|
|
@@ -47,6 +56,7 @@
|
|
|
47
56
|
"zod": "^3.25.26"
|
|
48
57
|
},
|
|
49
58
|
"devDependencies": {
|
|
59
|
+
"@anthropic-ai/dxt": "^0.2.1",
|
|
50
60
|
"@rollup/plugin-commonjs": "^28.0.3",
|
|
51
61
|
"@rollup/plugin-json": "^6.1.0",
|
|
52
62
|
"@rollup/plugin-node-resolve": "^16.0.1",
|
|
@@ -87,6 +97,8 @@
|
|
|
87
97
|
"semantic-search",
|
|
88
98
|
"typescript",
|
|
89
99
|
"nodejs",
|
|
90
|
-
"cli-tool"
|
|
100
|
+
"cli-tool",
|
|
101
|
+
"dxt",
|
|
102
|
+
"desktop-extension"
|
|
91
103
|
]
|
|
92
104
|
}
|