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 CHANGED
@@ -8,11 +8,14 @@
8
8
  [![Version](https://img.shields.io/badge/version-2.3.2-blue.svg)](./package.json)
9
9
  [![License](https://img.shields.io/badge/license-MIT-green.svg)](./package.json)
10
10
  [![MCP](https://img.shields.io/badge/MCP-Compatible-purple.svg)](https://modelcontextprotocol.io/)
11
- [![Buy me a coffee](https://img.shields.io/badge/Buy%20me%20a%20coffee-☕-orange.svg)](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
Binary file
Binary file
Binary file
@@ -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, isGitHubQuery);
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 (/[^a-zA-Z0-9\-_./=@:]/.test(arg)) {
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
- const escapedArgs = args.map(arg => escapeShellArg(arg, shellConfig.type));
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 distinguish between:
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
- const isGitHubQualifier = command === 'search' &&
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
- return escapeShellArg(arg, shellConfig.type, false);
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
- // GitHub search qualifiers need special handling
288
- // Most qualifiers can be passed as-is, but those with shell metacharacters need escaping
289
- if (isGitHubQualifier) {
290
- // Check if the qualifier contains shell metacharacters that need escaping
291
- if (/[<>&|;`$\\]/.test(arg)) {
292
- // Escape qualifiers that contain shell metacharacters like size:<1000, size:>500
293
- return escapeShellArg(arg, shellConfig.type, false);
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
- return escapeShellArg(arg, shellConfig.type, isMainQueryArgument);
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 with quotes for literal matching
1359
- args.push(`"${params.exactQuery}"`);
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 topic for discovering repositories by technology/purpose
112317
- - Use query for searching by repository name
112318
- - Use owner to explore specific organizations
112319
- - Use language to filter by programming language
112320
- - Use quality filters (stars, forks) for refinement
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
- Separate searches for different topics and use minimal filters to get the most relevant results`;
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
- query: z
112347
+ exactQuery: z
112358
112348
  .string()
112359
112349
  .optional()
112360
- .describe('Search by repository name. Use minimal words for repository names or specific projects. For topic discovery, use topic parameter instead.'),
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('Discover repositories by topic. Use for exploring unknown domains and finding projects by technology or purpose.'),
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.query
112508
- ? extractOwnerRepoFromQuery(args.query)
112509
- : {
112510
- cleanedQuery: '',
112511
- extractedOwner: undefined,
112512
- extractedRepo: undefined,
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
- query: queryInfo.cleanedQuery || args.query,
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.query?.trim() ||
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 these patterns:
112535
- • Topic exploration: { topic: ["react", "typescript"] }
112536
- Organization search: { owner: "microsoft", visibility: "public" }
112537
- Language + quality: { language: "go", "good-first-issues": ">=10" }
112538
- Simple query: { query: "cli shell" }`,
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. Smart alternatives:
112549
- Try npm package search for package discovery
112550
- Use broader filters (remove stars/forks constraints)
112551
- • Search fewer organizations at once
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. Quick fix:
112558
- 1. Run: gh auth login
112559
- 2. For private repos: use api_status_check to verify access
112560
- 3. Public repos should work without auth - check query`,
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 fallbackSuggestions = [];
112571
- if (enhancedArgs.query) {
112572
- fallbackSuggestions.push('• Try broader search terms or remove query filter');
112585
+ const suggestions = [];
112586
+ if (enhancedArgs.exactQuery) {
112587
+ suggestions.push('• Try broader search terms');
112573
112588
  }
112574
112589
  if (enhancedArgs.language) {
112575
- fallbackSuggestions.push('• Remove language filter for broader discovery');
112590
+ suggestions.push('• Remove language filter');
112576
112591
  }
112577
112592
  if (enhancedArgs.stars || enhancedArgs.forks) {
112578
- fallbackSuggestions.push('• Lower quality thresholds (stars/forks)');
112593
+ suggestions.push('• Lower quality thresholds');
112579
112594
  }
112580
112595
  if (!enhancedArgs.topic) {
112581
- fallbackSuggestions.push('• 🎯 Try topic exploration: { topic: ["web", "api"] }');
112596
+ suggestions.push('• Try topic search: { topic: "react" }');
112582
112597
  }
112583
112598
  if (enhancedArgs.owner) {
112584
- fallbackSuggestions.push('• Search without owner filter for global discovery');
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 these alternatives:
112589
- ${fallbackSuggestions.join('\n')}
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
- const hasEmbeddedQualifiers = query &&
112727
- /\b(stars|language|org|repo|topic|user|created|updated|size|license|archived|fork|good-first-issues|help-wanted-issues):/i.test(query);
112728
- if (query) {
112729
- args.push(query);
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
- CAPABILITIES:
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
- SEARCH STRATEGY:
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
- - Results include package names, versions, descriptions, and repository links
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
- CAPABILITIES:
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> (e.g., version, description, license)
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.12",
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": "build/index.js",
17
+ "main": "dist/index.js",
18
18
  "license": "MIT",
19
19
  "type": "module",
20
- "bin": "./build/index.js",
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 build/index.js",
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
- "build"
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
  }