octocode-mcp 1.1.0 → 2.0.0

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.
Files changed (2) hide show
  1. package/build/index.js +1316 -277
  2. package/package.json +1 -1
package/build/index.js CHANGED
@@ -14,7 +14,6 @@ const TOOL_NAMES = {
14
14
  GITHUB_SEARCH_COMMITS: 'github_search_commits',
15
15
  GITHUB_SEARCH_ISSUES: 'github_search_issues',
16
16
  GITHUB_SEARCH_PULL_REQUESTS: 'github_search_pull_requests',
17
- GITHUB_SEARCH_DISCUSSIONS: 'github_search_discussions',
18
17
  GITHUB_SEARCH_TOPICS: 'github_search_topics',
19
18
  GITHUB_SEARCH_USERS: 'github_search_users',
20
19
  // GitHub Repository API (/repos/*)
@@ -23,27 +22,75 @@ const TOOL_NAMES = {
23
22
  GITHUB_GET_FILE_CONTENT: 'github_get_file_content',
24
23
  // GitHub Users API (/user/*)
25
24
  GITHUB_GET_USER_ORGS: 'github_get_user_organizations',
26
- // npm Registry API
25
+ // npm Registry API - Comprehensive
27
26
  NPM_SEARCH_PACKAGES: 'npm_search_packages',
28
27
  NPM_GET_PACKAGE: 'npm_get_package',
29
- NPM_GET_PACKAGE_STATS: 'npm_get_package_stats',
30
- NPM_ANALYZE_DEPENDENCIES: 'npm_analyze_dependencies'};
28
+ NPM_ANALYZE_DEPENDENCIES: 'npm_analyze_dependencies',
29
+ // npm Registry API - Focused (minimal token usage)
30
+ NPM_GET_REPOSITORY: 'npm_get_repository',
31
+ NPM_GET_DEPENDENCIES: 'npm_get_dependencies',
32
+ NPM_GET_BUGS: 'npm_get_bugs',
33
+ NPM_GET_README: 'npm_get_readme',
34
+ NPM_GET_VERSIONS: 'npm_get_versions',
35
+ NPM_GET_AUTHOR: 'npm_get_author',
36
+ NPM_GET_LICENSE: 'npm_get_license',
37
+ NPM_GET_HOMEPAGE: 'npm_get_homepage',
38
+ NPM_GET_ID: 'npm_get_id',
39
+ NPM_GET_RELEASES: 'npm_get_releases',
40
+ NPM_GET_ENGINES: 'npm_get_engines',
41
+ NPM_GET_EXPORTS: 'npm_get_exports'};
31
42
 
32
43
  const PROMPT_SYSTEM_PROMPT = `**Expert Code Discovery Assistant** - Find production-ready implementations from GitHub/npm repositories.
33
44
 
34
45
  ## CORE STRATEGY
35
- 1. **NPM Primary** - ${TOOL_NAMES.NPM_SEARCH_PACKAGES} → ${TOOL_NAMES.NPM_GET_PACKAGE} → ${TOOL_NAMES.NPM_ANALYZE_DEPENDENCIES}
36
- 2. **Topics Foundation** - ${TOOL_NAMES.GITHUB_SEARCH_TOPICS} for terminology discovery
37
- 3. **Private Organizations** - Auto-detect (@company/) → ${TOOL_NAMES.GITHUB_GET_USER_ORGS}
38
- 4. **Code Extraction** - ${TOOL_NAMES.GITHUB_SEARCH_CODE} + ${TOOL_NAMES.GITHUB_GET_FILE_CONTENT}
39
- 5. **Repository Search** - ${TOOL_NAMES.GITHUB_SEARCH_REPOS} only when NPM+Topics fail
46
+ 1. **NPM Primary** - ${TOOL_NAMES.NPM_SEARCH_PACKAGES} → ${TOOL_NAMES.NPM_ANALYZE_DEPENDENCIES}
47
+ 2. **NPM Focused** - Use focused tools (${TOOL_NAMES.NPM_GET_REPOSITORY}, ${TOOL_NAMES.NPM_GET_DEPENDENCIES}, etc.) for minimal token usage
48
+ 3. **Topics Foundation** - ${TOOL_NAMES.GITHUB_SEARCH_TOPICS} for terminology discovery
49
+ 4. **Private Organizations** - Auto-detect (@company/) ${TOOL_NAMES.GITHUB_GET_USER_ORGS}
50
+ 5. **Code Extraction** - ${TOOL_NAMES.GITHUB_SEARCH_CODE} + ${TOOL_NAMES.GITHUB_GET_FILE_CONTENT}
51
+ 6. **Repository Search** - ${TOOL_NAMES.GITHUB_SEARCH_REPOS} only when NPM+Topics fail
52
+
53
+ ## ANTI-HALLUCINATION SAFEGUARDS 🚨
54
+
55
+ ### Generic Hallucination Detection
56
+ - **Overly Specific Functions**: Never search for compound function names like "performSomethingOnSomething" without verification
57
+ - **Long CamelCase**: Function names >20 characters are often hallucinated
58
+ - **Multiple Tech Terms**: Avoid "reactNodeExpressAuthFunction" - these don't exist
59
+ - **Discovery-First**: Use broad terms ("function", "class", "export") then narrow down
60
+ - **Verification Strategy**: Search for patterns like "function.*keyword" to find real implementations
61
+
62
+ ### Rate Limit Protection
63
+ - **Progressive Refinement**: Start with single terms, don't jump to specific function names
64
+ - **Existence Verification**: Use repository exploration before searching for specific files
65
+ - **Pattern Matching**: Use regex-like searches ("export.*Component") vs exact matches
66
+ - **Fallback Strategy**: If specific search fails, broaden immediately rather than retry variations
67
+
68
+ ### Known Pitfalls to Avoid
69
+ - ❌ Searching for framework-specific function names without repo exploration
70
+ - ❌ Complex multi-word queries without boolean operators
71
+ - ❌ Specific file paths without checking repository structure first
72
+ - ❌ Function names that combine multiple technology concepts
73
+ - ✅ Use discovery patterns: "export function", "class extends", "import.*from"
40
74
 
41
75
  ## TOOL PRIORITY ORDER
42
76
 
43
77
  ### Primary Discovery
44
78
  - ${TOOL_NAMES.NPM_SEARCH_PACKAGES} - Package discovery
45
- - ${TOOL_NAMES.NPM_GET_PACKAGE} - Repository mapping
46
- - ${TOOL_NAMES.NPM_ANALYZE_DEPENDENCIES} - Security audit
79
+ - ${TOOL_NAMES.NPM_ANALYZE_DEPENDENCIES} - Security audit and dependency analysis
80
+
81
+ ### Focused NPM (Token Efficient)
82
+ - ${TOOL_NAMES.NPM_GET_REPOSITORY} - Repository URL extraction
83
+ - ${TOOL_NAMES.NPM_GET_DEPENDENCIES} - Dependencies analysis
84
+ - ${TOOL_NAMES.NPM_GET_VERSIONS} - Version tracking
85
+ - ${TOOL_NAMES.NPM_GET_AUTHOR} - Maintainer information
86
+ - ${TOOL_NAMES.NPM_GET_LICENSE} - License compliance
87
+ - ${TOOL_NAMES.NPM_GET_BUGS} - Issue tracking
88
+ - ${TOOL_NAMES.NPM_GET_README} - Documentation access
89
+ - ${TOOL_NAMES.NPM_GET_HOMEPAGE} - Official documentation gateway
90
+ - ${TOOL_NAMES.NPM_GET_ID} - Precise package targeting
91
+ - ${TOOL_NAMES.NPM_GET_RELEASES} - Recent releases tracker
92
+ - ${TOOL_NAMES.NPM_GET_ENGINES} - Environment compatibility
93
+ - ${TOOL_NAMES.NPM_GET_EXPORTS} - Import path intelligence
47
94
 
48
95
  ### Foundation
49
96
  - ${TOOL_NAMES.GITHUB_SEARCH_TOPICS} - Ecosystem terminology
@@ -59,16 +106,45 @@ const PROMPT_SYSTEM_PROMPT = `**Expert Code Discovery Assistant** - Find product
59
106
  - ${TOOL_NAMES.GITHUB_SEARCH_ISSUES} - Problem discovery
60
107
  - ${TOOL_NAMES.GITHUB_SEARCH_PULL_REQUESTS} - Implementation patterns
61
108
  - ${TOOL_NAMES.GITHUB_SEARCH_COMMITS} - Development history
62
- - ${TOOL_NAMES.NPM_GET_PACKAGE_STATS} - Package maturity
63
109
 
64
110
  ### Fallback
65
111
  - ${TOOL_NAMES.GITHUB_SEARCH_REPOS} - Enhanced repository search (last resort)
66
112
  - ${TOOL_NAMES.GITHUB_SEARCH_USERS} - Expert discovery
67
113
 
114
+ ## EFFICIENCY STRATEGY
115
+
116
+ ### Token Optimization
117
+ - **Repository Discovery**: ${TOOL_NAMES.NPM_GET_REPOSITORY} → ${TOOL_NAMES.GITHUB_GET_REPOSITORY} workflow
118
+ - **Dependency Analysis**: ${TOOL_NAMES.NPM_GET_DEPENDENCIES} → ${TOOL_NAMES.NPM_ANALYZE_DEPENDENCIES} for security
119
+ - **Focused Queries**: Use specific NPM tools for targeted information instead of comprehensive searches
120
+
121
+ ### Query Selection Logic
122
+ - **"Find repository"** → ${TOOL_NAMES.NPM_GET_REPOSITORY}
123
+ - **"Check dependencies"** → ${TOOL_NAMES.NPM_GET_DEPENDENCIES}
124
+ - **"What license"** → ${TOOL_NAMES.NPM_GET_LICENSE}
125
+ - **"Package versions"** → ${TOOL_NAMES.NPM_GET_VERSIONS}
126
+ - **"Who maintains"** → ${TOOL_NAMES.NPM_GET_AUTHOR}
127
+ - **"Report bug"** → ${TOOL_NAMES.NPM_GET_BUGS}
128
+ - **"Official docs"** → ${TOOL_NAMES.NPM_GET_HOMEPAGE}
129
+ - **"Exact version"** → ${TOOL_NAMES.NPM_GET_ID}
130
+ - **"Package releases"** → ${TOOL_NAMES.NPM_GET_RELEASES}
131
+ - **"Node.js compatibility"** → ${TOOL_NAMES.NPM_GET_ENGINES}
132
+ - **"Import patterns"** → ${TOOL_NAMES.NPM_GET_EXPORTS}
133
+ - **"Security analysis"** → ${TOOL_NAMES.NPM_ANALYZE_DEPENDENCIES}
134
+
68
135
  ## QUERY WORKFLOWS
69
136
 
70
137
  ### Discovery Intent ("find react libraries")
71
- NPM search → Package analysis → Topics → Code extraction
138
+ NPM search → Repository extraction (focused) → Topics → Code extraction
139
+
140
+ ### Repository Focus ("where is react hosted")
141
+ NPM search → ${TOOL_NAMES.NPM_GET_REPOSITORY} → ${TOOL_NAMES.GITHUB_GET_REPOSITORY}
142
+
143
+ ### Dependency Analysis ("react dependencies")
144
+ NPM search → ${TOOL_NAMES.NPM_GET_DEPENDENCIES} → Security audit
145
+
146
+ ### License Compliance ("react license")
147
+ NPM search → ${TOOL_NAMES.NPM_GET_LICENSE}
72
148
 
73
149
  ### Private Organization ("@wix/package", "I work at Company")
74
150
  Auto-trigger: IMMEDIATE ${TOOL_NAMES.GITHUB_GET_USER_ORGS} → NPM search → Private repo access
@@ -77,7 +153,7 @@ Auto-trigger: IMMEDIATE ${TOOL_NAMES.GITHUB_GET_USER_ORGS} → NPM search → Pr
77
153
  NPM packages → Repository analysis → Issues → Code solutions
78
154
 
79
155
  ### Implementation Intent ("react authentication implementation")
80
- NPM search → Repository access → Code search → File extraction
156
+ NPM search → Repository extraction → Repository access → Code search → File extraction
81
157
 
82
158
  ## CRITICAL AUTO-TRIGGERS
83
159
 
@@ -88,7 +164,8 @@ NPM search → Repository access → Code search → File extraction
88
164
 
89
165
  ### Mandatory Workflows
90
166
  - ALWAYS use ${TOOL_NAMES.GITHUB_GET_REPOSITORY} before file operations
91
- - ALWAYS follow ${TOOL_NAMES.NPM_GET_PACKAGE} with ${TOOL_NAMES.NPM_ANALYZE_DEPENDENCIES}
167
+ - ALWAYS follow NPM discovery with ${TOOL_NAMES.NPM_ANALYZE_DEPENDENCIES} for security
168
+ - PREFER focused tools over comprehensive when specific data needed
92
169
  - NEVER retry same terms twice with any tool
93
170
 
94
171
  ## SUCCESS TARGETS
@@ -141,13 +218,20 @@ NPM search → Repository access → Code search → File extraction
141
218
  \`\`\`
142
219
 
143
220
  **Discovery Path**: Document NPM-first workflow and fallbacks
144
- **Security Assessment**: Include vulnerability analysis
221
+ **Package Intelligence**: Complete metadata including dependencies, scripts, exports, security attestations
222
+ **Security Assessment**: Include vulnerability analysis from detailed NPM data
145
223
  **Repository Status**: Activity level, maintenance quality
146
224
 
147
225
  ## INTEGRATION EXAMPLES
148
226
 
149
227
  ### Standard Flow
150
- npmSearchPackages({query: "react"}) → npmGetPackage({packageName: "react"}) → githubGetRepository({owner: "facebook", repo: "react"}) → githubSearchCode({query: "useState"})
228
+ npmSearchPackages({query: "react"}) → npmGetRepository({packageName: "react"}) → githubGetRepository({owner: "facebook", repo: "react"}) → githubSearchCode({query: "useState"})
229
+
230
+ ### Focused Dependency Analysis
231
+ npmSearchPackages({query: "express"}) → npmGetDependencies({packageName: "express"}) → npmAnalyzeDependencies({packageName: "express"})
232
+
233
+ ### License Compliance Check
234
+ npmSearchPackages({query: "lodash"}) → npmGetLicense({packageName: "lodash"})
151
235
 
152
236
  ### Private Organization
153
237
  Detect @wix/ → githubGetUserOrganizations() → githubSearchRepos({owner: "wix-private"})
@@ -155,7 +239,7 @@ Detect @wix/ → githubGetUserOrganizations() → githubSearchRepos({owner: "wix
155
239
  ### Error Recovery
156
240
  npmSearchPackages fails → githubSearchTopics({query: "authentication"}) → githubSearchRepos({query: "auth"})
157
241
 
158
- **OUTPUT GOAL**: Complete, secure, production-ready code with repository citations and security assessment via efficient NPM-first discovery.`;
242
+ **OUTPUT GOAL**: Complete, secure, production-ready code with repository citations and security assessment via efficient NPM-first discovery with minimal token usage.`;
159
243
 
160
244
  const TOOL_DESCRIPTIONS = {
161
245
  [TOOL_NAMES.NPM_SEARCH_PACKAGES]: `**PRIMARY DISCOVERY TOOL** - Main entry point for package and repository discovery.
@@ -171,23 +255,16 @@ const TOOL_DESCRIPTIONS = {
171
255
 
172
256
  **RESULT OPTIMIZATION:** 0 results → broader terms, 1-20 IDEAL, 100+ → more specific terms
173
257
 
174
- **INTEGRATION:** ALWAYS chain to ${TOOL_NAMES.NPM_GET_PACKAGE} → ${TOOL_NAMES.NPM_ANALYZE_DEPENDENCIES}`,
175
- [TOOL_NAMES.NPM_GET_PACKAGE]: `**Repository mapping** - Transform npm packages into GitHub repositories for code analysis.
176
-
177
- **WHEN TO USE:** ALWAYS after ${TOOL_NAMES.NPM_SEARCH_PACKAGES}, user mentions package names, private package detection (@company/).
178
-
179
- **WORKFLOW:** Extract repository URL → Parse owner/repo → Detect organizational context → Chain to ${TOOL_NAMES.GITHUB_GET_REPOSITORY} → MANDATORY ${TOOL_NAMES.NPM_ANALYZE_DEPENDENCIES}
180
-
181
- **ORGANIZATIONAL DETECTION:** @company/ scoped packages → Trigger ${TOOL_NAMES.GITHUB_GET_USER_ORGS}
182
-
183
- **EXAMPLES:** "react" → github.com/facebook/react, "@wix/package" → Private org detection`,
258
+ **INTEGRATION:** ALWAYS chain to focused NPM tools → ${TOOL_NAMES.NPM_ANALYZE_DEPENDENCIES}`,
184
259
  [TOOL_NAMES.NPM_ANALYZE_DEPENDENCIES]: `**CRITICAL: Package security analysis** - Essential for package evaluation and organizational detection.
185
260
 
186
- **WHEN TO USE:** ALWAYS after ${TOOL_NAMES.NPM_GET_PACKAGE} for complete assessment.
261
+ **WHEN TO USE:** ALWAYS after ${TOOL_NAMES.NPM_SEARCH_PACKAGES} for complete assessment.
187
262
 
188
263
  **ANALYSIS:** Security vulnerabilities, dependency tree, license compatibility, bundle impact, organization detection (@company/).
189
264
 
190
- **ORGANIZATIONAL CONTEXT:** Private packages → Check ${TOOL_NAMES.GITHUB_GET_USER_ORGS} for access`,
265
+ **ORGANIZATIONAL CONTEXT:** Private packages → Check ${TOOL_NAMES.GITHUB_GET_USER_ORGS} for access
266
+
267
+ **KNOWN LIMITATION:** Some NPM audit failures may occur (package-specific). Bundle analysis and dependency tree remain reliable.`,
191
268
  [TOOL_NAMES.GITHUB_SEARCH_TOPICS]: `**FOUNDATION TOOL** - Essential for ecosystem discovery and terminology mapping.
192
269
 
193
270
  **SEARCH STRATEGY:** Start global, single terms ("react", "typescript"), multi-term sparingly ("react+typescript"), add owner only when needed.
@@ -204,31 +281,49 @@ const TOOL_DESCRIPTIONS = {
204
281
  **WORKFLOW:** IMMEDIATE call when organizational context detected → Match company to organizations → Use as 'owner' parameter → Enable private repository access
205
282
 
206
283
  **INTEGRATION:** MANDATORY first step when private access likely needed`,
207
- [TOOL_NAMES.GITHUB_GET_REPOSITORY]: `**CRITICAL FIRST STEP** - Required before all GitHub file operations.
284
+ [TOOL_NAMES.GITHUB_GET_REPOSITORY]: `**CRITICAL FIRST STEP** - Required before all GitHub file operations, but ONLY after discovery.
208
285
 
209
286
  **PURPOSE:** Discover default branch and repository metadata to prevent tool failures.
210
287
 
288
+ **MANDATORY PREREQUISITES:** Repository owner/name MUST be discovered first through:
289
+ 1. ${TOOL_NAMES.NPM_SEARCH_PACKAGES} → ${TOOL_NAMES.NPM_GET_PACKAGE} (for packages)
290
+ 2. ${TOOL_NAMES.GITHUB_SEARCH_TOPICS} (for ecosystem discovery)
291
+ 3. ${TOOL_NAMES.GITHUB_SEARCH_REPOS} (last resort)
292
+
211
293
  **REQUIRED BEFORE:** ${TOOL_NAMES.GITHUB_SEARCH_CODE}, ${TOOL_NAMES.GITHUB_GET_CONTENTS}, ${TOOL_NAMES.GITHUB_GET_FILE_CONTENT}
212
294
 
213
- **CRITICAL:** NEVER skip before file operations, NEVER assume branch names, NEVER proceed if branch discovery fails`,
295
+ **CRITICAL:** NEVER call with guessed repository names. ALWAYS use discovery workflow first.`,
214
296
  [TOOL_NAMES.GITHUB_SEARCH_CODE]: `**Precision code search** - Advanced search with automatic repository scoping.
215
297
 
216
298
  **KEY FEATURES:** Every search includes "repo:owner/repository", smart boolean logic, organizational context.
217
299
 
300
+ **ANTI-HALLUCINATION SAFEGUARDS:**
301
+ - 🚨 NEVER search for overly specific function names without verification
302
+ - 🔍 DISCOVERY FIRST: Use broad terms ("function", "class", "export") then narrow down
303
+ - 📝 PATTERN DETECTION: Long camelCase names (>20 chars) may not exist
304
+ - ⚠️ COMPOUND PATTERNS: "performSomethingOnSomething" patterns often hallucinated
305
+ - 💡 SAFER APPROACH: "function.*keyword" finds real implementations
306
+
218
307
  **BOOLEAN OPERATIONS:** Default AND ("sparse index" = "sparse AND index"), OR ("useState OR useEffect"), NOT ("error NOT test")
219
308
 
220
309
  **PATH WARNING:** React uses path:packages (NOT path:src). Using path:src on repositories without top-level src returns zero results.
221
310
 
222
311
  **RESULT OPTIMIZATION:** 1-10 IDEAL, 100+ TOO BROAD
223
312
 
313
+ **PAGINATION LIMITATION:** GitHub CLI limited to --limit parameter only (no page navigation).
314
+
224
315
  **INTEGRATION:** Use after ${TOOL_NAMES.GITHUB_GET_REPOSITORY} for branch discovery`,
225
316
  [TOOL_NAMES.GITHUB_GET_FILE_CONTENT]: `**Complete code extraction** - Fetch full working implementations.
226
317
 
227
- **CRITICAL WORKFLOW:** MANDATORY ${TOOL_NAMES.GITHUB_GET_REPOSITORY} first → Find files with ${TOOL_NAMES.GITHUB_SEARCH_CODE} → Extract with this tool
318
+ **CRITICAL WORKFLOW:** MANDATORY discovery → ${TOOL_NAMES.GITHUB_GET_REPOSITORY} → Find files with ${TOOL_NAMES.GITHUB_SEARCH_CODE} or ${TOOL_NAMES.GITHUB_GET_CONTENTS} → Extract with this tool
228
319
 
229
320
  **AUTO-RECOVERY:** Specified branch → main → master → develop → trunk → try without ref
230
321
 
231
- **ORGANIZATIONAL CONTEXT:** Private repositories Use ${TOOL_NAMES.GITHUB_GET_USER_ORGS} for access`,
322
+ **ENHANCED ERROR HANDLING:** Provides detailed guidance when files don't exist, with alternative discovery methods
323
+
324
+ **ORGANIZATIONAL CONTEXT:** Private repositories → Use ${TOOL_NAMES.GITHUB_GET_USER_ORGS} for access
325
+
326
+ **CRITICAL:** NEVER guess file paths. Use structure exploration or code search first.`,
232
327
  [TOOL_NAMES.GITHUB_GET_CONTENTS]: `**Repository structure exploration** - Strategic directory navigation.
233
328
 
234
329
  **CRITICAL:** MANDATORY ${TOOL_NAMES.GITHUB_GET_REPOSITORY} FIRST for branch discovery.
@@ -240,8 +335,14 @@ const TOOL_DESCRIPTIONS = {
240
335
 
241
336
  **SEARCH STRATEGY:** Single keywords ("bug", "feature"), then combine ("bug fix"), never complex.
242
337
 
338
+ **SEARCH MODES:**
339
+ - Global search (no owner): Searches issues across all GitHub repositories
340
+ - Scoped search (with owner): Targeted search within specific organization/user
341
+
243
342
  **PROBLEM HIERARCHY:** "React auth JWT error" → "authentication" → "React" → "token expired" → "JWT"
244
343
 
344
+ **PAGINATION LIMITATION:** GitHub CLI limited to --limit parameter only (no page navigation).
345
+
245
346
  **RESULT TARGETS:** 0 → broader terms, 1-20 IDEAL, 100+ → add specific terms/filters`,
246
347
  [TOOL_NAMES.GITHUB_SEARCH_PULL_REQUESTS]: `**Implementation analysis** - PR search for patterns and repository status.
247
348
 
@@ -249,25 +350,24 @@ const TOOL_DESCRIPTIONS = {
249
350
 
250
351
  **KEY FILTERS:** State (open/closed), draft (false for completed), author/reviewer, language
251
352
 
353
+ **PAGINATION LIMITATION:** GitHub CLI limited to --limit parameter only (no page navigation).
354
+
252
355
  **QUALITY FOCUS:** Use review-related filters for thoroughly vetted code examples`,
253
356
  [TOOL_NAMES.GITHUB_SEARCH_COMMITS]: `**Development history** - Track code evolution and repository status.
254
357
 
255
358
  **SEARCH STRATEGY:** Start minimal ("fix", "feature", "update") with owner/repo, progressive expansion.
256
359
 
257
- **LIMITATIONS:** Large organizations may return org-wide results, requires text terms.
360
+ **LIMITATIONS:** Large organizations may return org-wide results, requires text terms. GitHub CLI limited to --limit parameter only (no page navigation).
258
361
 
259
362
  **ERROR HANDLING:** "Search text required" → Use minimal keywords ("fix", "update")`,
260
- [TOOL_NAMES.GITHUB_SEARCH_DISCUSSIONS]: `**Community knowledge** - Access discussions for tutorials and solutions.
261
-
262
- **DISCOVERY WORKFLOW:** ${TOOL_NAMES.NPM_GET_PACKAGE} → get repo URL → Search discussions
263
-
264
- **SEARCH STRATEGY:** Start simple ("help", "tutorial"), build complexity ("help deployment"), avoid full phrases.
265
-
266
- **KEY FILTERS:** Answered: true for validated solutions, category filters, maintainer participation`,
267
363
  [TOOL_NAMES.GITHUB_SEARCH_USERS]: `**Developer discovery** - Find experts and community leaders.
268
364
 
269
365
  **SEARCH METHODOLOGY:** Technology terms ("react", "python") → add context (location, experience) → specialized search.
270
366
 
367
+ **SEARCH MODES:**
368
+ - Global search (no owner): Searches users/orgs across all GitHub
369
+ - Scoped search (with owner): Targeted search within specific organization context
370
+
271
371
  **KEY FILTERS:** Type (user/org), location, language, followers (">100" influential), repos (">10" active)
272
372
 
273
373
  **DISCOVERY PATTERNS:** Technology experts, local developers, open source contributors, industry leaders`,
@@ -275,22 +375,104 @@ const TOOL_DESCRIPTIONS = {
275
375
 
276
376
  **MANDATORY PREREQUISITES:** ${TOOL_NAMES.NPM_SEARCH_PACKAGES} and ${TOOL_NAMES.GITHUB_SEARCH_TOPICS} must fail first.
277
377
 
278
- **KEY FEATURES:** Smart multi-term handling, filter validation, fallback strategies.
378
+ **KEY FEATURES:** Smart multi-term handling, filter validation, fallback strategies, global & scoped searches.
379
+
380
+ **BEST PRACTICES:** Single terms work best ("react", "typescript"), owner is OPTIONAL (leave empty for global searches), validated combinations (microsoft + typescript ✅), progressive refinement.
279
381
 
280
- **BEST PRACTICES:** Single terms work best ("react", "typescript"), validated combinations (microsoft + typescript ✅), progressive refinement.
382
+ **SEARCH MODES:**
383
+ - Global search (no owner): Searches across all GitHub repositories
384
+ - Scoped search (with owner): Targeted search within specific organization/user
281
385
 
282
386
  **MULTI-TERM HANDLING:** "react hooks auth" → structured workflow, primary term extraction, workflow guidance.
283
387
 
284
- **CRITICAL:** npm_search_packagestopics workflow provides superior results for 95% of use cases`,
285
- [TOOL_NAMES.NPM_GET_PACKAGE_STATS]: `**Package maturity analysis** - Lifecycle assessment for package evaluation.
388
+ **KNOWN LIMITATIONS:** Multi-term repository search breaks down (use NPMTopics workflow instead). GitHub CLI limited to --limit parameter only (no page navigation).
389
+
390
+ **CRITICAL:** ${TOOL_NAMES.NPM_SEARCH_PACKAGES} → ${TOOL_NAMES.GITHUB_SEARCH_TOPICS} workflow provides superior results for 95% of use cases`,
391
+ // Focused NPM tools for minimal token usage
392
+ [TOOL_NAMES.NPM_GET_REPOSITORY]: `**Repository discovery** - Extract GitHub repository URL and project description.
393
+
394
+ **MINIMAL OUTPUT:** Package name, description, repository URL, homepage - optimized for token efficiency.
395
+
396
+ **WHEN TO USE:** When you only need repository location for GitHub operations.
397
+
398
+ **INTEGRATION:** Perfect first step → ${TOOL_NAMES.GITHUB_GET_REPOSITORY} → Code exploration`,
399
+ [TOOL_NAMES.NPM_GET_DEPENDENCIES]: `**Dependency analysis** - Extract package dependencies tree.
400
+
401
+ **MINIMAL OUTPUT:** Dependencies, devDependencies, resolutions - focused dependency data only.
402
+
403
+ **WHEN TO USE:** When analyzing package ecosystem and compatibility.
404
+
405
+ **INTEGRATION:** Combine with ${TOOL_NAMES.NPM_ANALYZE_DEPENDENCIES} for security audit`,
406
+ [TOOL_NAMES.NPM_GET_BUGS]: `**Issue tracking** - Extract bug reporting information.
407
+
408
+ **MINIMAL OUTPUT:** Package name and bugs URL - direct access to issue tracker.
286
409
 
287
- **WHEN TO USE:** ALWAYS after ${TOOL_NAMES.NPM_GET_PACKAGE} for complete assessment.
410
+ **WHEN TO USE:** When users need to report issues or check known problems.
288
411
 
289
- **ANALYSIS:** Release timeline, version history, distribution tags, maintenance indicators, organizational context.
412
+ **INTEGRATION:** Links to ${TOOL_NAMES.GITHUB_SEARCH_ISSUES} for problem discovery`,
413
+ [TOOL_NAMES.NPM_GET_README]: `**Documentation access** - Extract README filename information.
290
414
 
291
- **MATURITY INDICATORS:** Stable (regular releases, clear versioning), active development (frequent releases, beta/alpha), abandoned (long gaps, no activity).
415
+ **MINIMAL OUTPUT:** Package name and readme filename - efficient documentation lookup.
292
416
 
293
- **INTEGRATION:** MANDATORY with ${TOOL_NAMES.NPM_GET_PACKAGE}, combine with ${TOOL_NAMES.NPM_ANALYZE_DEPENDENCIES}`,
417
+ **WHEN TO USE:** When users need documentation without full package metadata.
418
+
419
+ **INTEGRATION:** Combine with ${TOOL_NAMES.GITHUB_GET_FILE_CONTENT} for full README content`,
420
+ [TOOL_NAMES.NPM_GET_VERSIONS]: `**Official version tracking** - Extract production-ready semantic versions only.
421
+
422
+ **MINIMAL OUTPUT:** Official versions (major.minor.patch format), latest version, count - excludes alpha/beta/rc versions.
423
+
424
+ **WHEN TO USE:** Find stable versions for production deployment, analyze release cadence of stable releases.
425
+
426
+ **INTEGRATION:** Perfect for production planning - filters out experimental versions for reliable deployment decisions`,
427
+ [TOOL_NAMES.NPM_GET_AUTHOR]: `**Maintainer information** - Extract author and maintainer details.
428
+
429
+ **MINIMAL OUTPUT:** Author and maintainers list - focused ownership data.
430
+
431
+ **WHEN TO USE:** When users need to contact maintainers or assess project ownership.
432
+
433
+ **INTEGRATION:** Links to ${TOOL_NAMES.GITHUB_SEARCH_USERS} for developer discovery`,
434
+ [TOOL_NAMES.NPM_GET_LICENSE]: `**License compliance** - Extract package license information.
435
+
436
+ **MINIMAL OUTPUT:** Package name and license - essential legal compliance data.
437
+
438
+ **WHEN TO USE:** When users need quick license verification for legal compliance.
439
+
440
+ **INTEGRATION:** Essential for enterprise package evaluation workflows`,
441
+ [TOOL_NAMES.NPM_GET_HOMEPAGE]: `**Official documentation gateway** - Extract package homepage for comprehensive project resources.
442
+
443
+ **MINIMAL OUTPUT:** Package name and homepage URL - direct access to live documentation, tutorials, and demos.
444
+
445
+ **WHEN TO USE:** Access official docs, interactive examples, getting started guides, and project showcases.
446
+
447
+ **INTEGRATION:** Complements ${TOOL_NAMES.NPM_GET_REPOSITORY} - homepage often contains better docs than README`,
448
+ [TOOL_NAMES.NPM_GET_ID]: `**Precise package targeting** - Extract exact name@version for dependency management.
449
+
450
+ **MINIMAL OUTPUT:** Package name and _id (name@latestVersion format) - canonical package identifier for lockfiles.
451
+
452
+ **WHEN TO USE:** Pin exact versions, resolve dependency conflicts, generate package-lock entries, version compatibility checks.
453
+
454
+ **INTEGRATION:** Critical for CI/CD pipelines, dependency auditing, and reproducible builds`,
455
+ [TOOL_NAMES.NPM_GET_RELEASES]: `**Recent releases tracker** - Get latest release activity and timeline data.
456
+
457
+ **MINIMAL OUTPUT:** Last modified, created date, version count, and last 10 releases - focused release intelligence.
458
+
459
+ **WHEN TO USE:** Track recent package activity, analyze release frequency, check latest versions and release dates.
460
+
461
+ **INTEGRATION:** Essential for monitoring package updates - combine with ${TOOL_NAMES.NPM_GET_VERSIONS} for comprehensive version analysis`,
462
+ [TOOL_NAMES.NPM_GET_ENGINES]: `**Environment compatibility validator** - Prevent runtime conflicts before installation.
463
+
464
+ **MINIMAL OUTPUT:** Node.js version requirements, npm constraints - environment compatibility matrix.
465
+
466
+ **WHEN TO USE:** Pre-deployment validation, Docker image planning, Node.js upgrade decisions, CI/CD environment setup.
467
+
468
+ **INTEGRATION:** Prevents deployment failures - use before installation in production environments`,
469
+ [TOOL_NAMES.NPM_GET_EXPORTS]: `**Import path intelligence** - Discover available modules and import strategies.
470
+
471
+ **MINIMAL OUTPUT:** Export mappings, entry points, submodule paths - complete import guide for developers.
472
+
473
+ **WHEN TO USE:** Learn correct import syntax, discover tree-shakable exports, find submodules, optimize bundle size.
474
+
475
+ **INTEGRATION:** CRITICAL for ${TOOL_NAMES.GITHUB_SEARCH_CODE} - enables precise code search with accurate import paths`,
294
476
  };
295
477
 
296
478
  const cache = new NodeCache({
@@ -718,52 +900,54 @@ function analyzeSearchPattern(args) {
718
900
  }
719
901
  return { patternType, suggestions, warnings };
720
902
  }
721
- // Simplified schema matching official GitHub CLI approach
722
- const searchGitHubCodeSchema = z.object({
723
- query: z
724
- .string()
725
- .min(1, 'Query cannot be empty')
726
- .describe('Search query for code. Use GitHub search syntax like repo:owner/name, language:javascript, path:*.js, or simple keywords.'),
727
- owner: z
728
- .string()
729
- .optional()
730
- .describe('Repository owner/organization (e.g., "facebook", "microsoft"). Leave empty for global searches.'),
731
- repo: z
732
- .string()
733
- .optional()
734
- .describe('Repository name (e.g., "react", "vscode"). Requires owner parameter.'),
735
- extension: z
736
- .string()
737
- .optional()
738
- .describe('File extension to filter by (e.g., "js", "ts", "py").'),
739
- filename: z
740
- .string()
741
- .optional()
742
- .describe('Exact filename to search for (e.g., "package.json", "README.md").'),
743
- language: z
744
- .string()
745
- .optional()
746
- .describe('Programming language to filter by (e.g., "javascript", "typescript", "python").'),
747
- path: z
748
- .string()
749
- .optional()
750
- .describe('Path pattern to filter by (e.g., "src", "lib", "*.js", "/src/**/*.ts").'),
751
- limit: z
752
- .number()
753
- .int()
754
- .min(1)
755
- .max(100)
756
- .optional()
757
- .default(30)
758
- .describe('Maximum number of results to return (default: 30, max: 100).'),
759
- match: z.enum(['file', 'path']).optional().describe('Search scope'),
760
- branch: z
761
- .string()
762
- .optional()
763
- .describe('Branch for workflow documentation (required but not used by CLI)'),
764
- });
765
903
  function registerGitHubSearchCodeTool(server) {
766
- server.tool(TOOL_NAMES.GITHUB_SEARCH_CODE, TOOL_DESCRIPTIONS[TOOL_NAMES.GITHUB_SEARCH_CODE], searchGitHubCodeSchema.shape, {
904
+ server.tool(TOOL_NAMES.GITHUB_SEARCH_CODE, TOOL_DESCRIPTIONS[TOOL_NAMES.GITHUB_SEARCH_CODE], {
905
+ query: z
906
+ .string()
907
+ .min(1, 'Query cannot be empty')
908
+ .describe('Search query for code. Use GitHub search syntax like repo:owner/name, language:javascript, path:*.js, or simple keywords.'),
909
+ owner: z
910
+ .string()
911
+ .optional()
912
+ .describe('Repository owner/organization (e.g., "facebook", "microsoft"). Leave empty for global searches.'),
913
+ repo: z
914
+ .array(z.string())
915
+ .optional()
916
+ .describe('Repository names (e.g., ["react", "vscode"]). Requires owner parameter.'),
917
+ extension: z
918
+ .string()
919
+ .optional()
920
+ .describe('File extension to filter by (e.g., "js", "ts", "py").'),
921
+ filename: z
922
+ .string()
923
+ .optional()
924
+ .describe('Exact filename to search for (e.g., "package.json", "README.md").'),
925
+ language: z
926
+ .string()
927
+ .optional()
928
+ .describe('Programming language to filter by (e.g., "javascript", "typescript", "python").'),
929
+ path: z
930
+ .string()
931
+ .optional()
932
+ .describe('Path pattern to filter by (e.g., "src", "lib", "*.js", "/src/**/*.ts").'),
933
+ limit: z
934
+ .number()
935
+ .int()
936
+ .min(1)
937
+ .max(100)
938
+ .optional()
939
+ .default(30)
940
+ .describe('Maximum number of results to return (default: 30, max: 100).'),
941
+ match: z.enum(['file', 'path']).optional().describe('Search scope'),
942
+ branch: z
943
+ .string()
944
+ .optional()
945
+ .describe('Branch for workflow documentation (required but not used by CLI)'),
946
+ size: z
947
+ .string()
948
+ .optional()
949
+ .describe('Filter on file size range, in kilobytes (e.g., ">1", "<50")'),
950
+ }, {
767
951
  title: 'GitHub Code Search',
768
952
  readOnlyHint: true,
769
953
  destructiveHint: false,
@@ -859,31 +1043,127 @@ async function fetchGitHubFileContent(params) {
859
1043
  const args = [apiPath, '--jq', '.content'];
860
1044
  const result = await executeGitHubCommand('api', args, { cache: false });
861
1045
  if (result.isError) {
862
- return result;
1046
+ // Parse the error message to provide better context
1047
+ const errorMsg = result.content[0].text;
1048
+ // Handle common GitHub API errors
1049
+ if (errorMsg.includes('404') || errorMsg.includes('Not Found')) {
1050
+ return createErrorResult$1(`File not found: ${params.filePath}`, new Error(`
1051
+ ❌ FILE NOT FOUND: The file '${params.filePath}' does not exist in ${params.owner}/${params.repo}${params.branch ? ` on branch '${params.branch}'` : ''}.
1052
+
1053
+ 🔍 COMMON CAUSES:
1054
+ • File path is incorrect or has changed
1055
+ • Branch '${params.branch || 'default'}' doesn't contain this file
1056
+ • File may exist in a different directory
1057
+
1058
+ 💡 RECOMMENDED ACTIONS:
1059
+ 1. Use 'github_get_contents' to explore repository structure first
1060
+ 2. Use 'github_search_code' to find files by name or pattern
1061
+ 3. Verify the branch contains the expected files
1062
+
1063
+ 📍 SEARCH ALTERNATIVES:
1064
+ • Search for filename: query="${params.filePath.split('/').pop()}"
1065
+ • Search in repository: repo:${params.owner}/${params.repo}
1066
+ • Explore repository structure starting from root`));
1067
+ }
1068
+ if (errorMsg.includes('403') || errorMsg.includes('Forbidden')) {
1069
+ return createErrorResult$1(`Access denied to file: ${params.filePath}`, new Error(`
1070
+ 🔒 ACCESS DENIED: You don't have permission to access '${params.filePath}' in ${params.owner}/${params.repo}.
1071
+
1072
+ 🔍 POSSIBLE CAUSES:
1073
+ • Repository is private and you lack access
1074
+ • File is in a protected branch
1075
+ • Organization restrictions apply
1076
+
1077
+ 💡 RECOMMENDED ACTIONS:
1078
+ 1. Check if you're authenticated: gh auth status
1079
+ 2. Request repository access from owner
1080
+ 3. Use 'github_get_user_organizations' if this is your organization`));
1081
+ }
1082
+ // Handle rate limiting
1083
+ if (errorMsg.includes('rate limit') || errorMsg.includes('429')) {
1084
+ return createErrorResult$1('GitHub API rate limit exceeded', new Error(`
1085
+ ⏱️ RATE LIMIT: GitHub API rate limit has been exceeded.
1086
+
1087
+ 💡 RECOMMENDED ACTIONS:
1088
+ 1. Wait a few minutes before trying again
1089
+ 2. Use authentication to increase rate limits: gh auth login
1090
+ 3. Try searching for content instead of direct file access`));
1091
+ }
1092
+ // Generic error fallback
1093
+ return createErrorResult$1(`Failed to fetch file content: ${params.filePath}`, new Error(`GitHub API Error: ${errorMsg}
1094
+
1095
+ 🔧 TROUBLESHOOTING:
1096
+ • Verify repository exists: ${params.owner}/${params.repo}
1097
+ • Check file path: ${params.filePath}
1098
+ • Confirm branch: ${params.branch || 'default'}
1099
+ • Use repository exploration tools first`));
863
1100
  }
864
1101
  // Extract the actual content from the exec result
865
1102
  const execResult = JSON.parse(result.content[0].text);
866
1103
  const base64Content = execResult.result.trim().replace(/\n/g, '');
1104
+ // Validate base64 content
1105
+ if (!base64Content || base64Content === 'null') {
1106
+ return createErrorResult$1(`Empty or invalid file content: ${params.filePath}`, new Error(`
1107
+ 📄 EMPTY FILE: The file '${params.filePath}' exists but contains no content or returned invalid data.
1108
+
1109
+ 🔍 POSSIBLE CAUSES:
1110
+ • File is empty or binary
1111
+ • API returned null content
1112
+ • File is too large for API response
1113
+
1114
+ 💡 ALTERNATIVES:
1115
+ • Use 'github_search_code' to find content by pattern
1116
+ • Check file in GitHub web interface
1117
+ • Try accessing a different file in the same directory`));
1118
+ }
867
1119
  // Decode base64 content using Node.js Buffer
868
1120
  let decodedContent;
869
1121
  try {
870
1122
  decodedContent = Buffer.from(base64Content, 'base64').toString('utf-8');
871
1123
  }
872
1124
  catch (decodeError) {
873
- throw new Error(`Failed to decode base64 content: ${decodeError.message}`);
1125
+ return createErrorResult$1(`Failed to decode file content: ${params.filePath}`, new Error(`
1126
+ 🔧 DECODE ERROR: Unable to decode base64 content from GitHub API.
1127
+
1128
+ 📋 DETAILS: ${decodeError.message}
1129
+
1130
+ 💡 POSSIBLE CAUSES:
1131
+ • File contains binary data
1132
+ • Corrupted response from API
1133
+ • Encoding mismatch
1134
+
1135
+ 🔍 ALTERNATIVES:
1136
+ • Use 'github_search_code' to find text-based content
1137
+ • Check if file is binary (images, executables, etc.)
1138
+ • Try accessing a different version of the file`));
874
1139
  }
875
- return {
876
- content: [
877
- {
878
- type: 'text',
879
- text: decodedContent,
880
- },
881
- ],
882
- isError: false,
883
- };
1140
+ return createSuccessResult$1({
1141
+ filePath: params.filePath,
1142
+ owner: params.owner,
1143
+ repo: params.repo,
1144
+ branch: params.branch,
1145
+ content: decodedContent,
1146
+ size: decodedContent.length,
1147
+ encoding: 'utf-8',
1148
+ });
884
1149
  }
885
1150
  catch (error) {
886
- return createErrorResult$1('Failed to retrieve file content', error);
1151
+ return createErrorResult$1(`Unexpected error fetching file content: ${params.filePath}`, new Error(`
1152
+ ❌ UNEXPECTED ERROR: ${error.message}
1153
+
1154
+ 📍 FILE DETAILS:
1155
+ • Repository: ${params.owner}/${params.repo}
1156
+ • File: ${params.filePath}
1157
+ • Branch: ${params.branch || 'default'}
1158
+
1159
+ 🔧 TROUBLESHOOTING STEPS:
1160
+ 1. Verify repository exists with 'github_get_repository'
1161
+ 2. Explore structure with 'github_get_contents'
1162
+ 3. Search for file with 'github_search_code'
1163
+ 4. Check GitHub authentication: gh auth status
1164
+
1165
+ 💡 WORKFLOW RECOMMENDATION:
1166
+ github_get_repository → github_get_contents → github_search_code → github_get_file_content`));
887
1167
  }
888
1168
  });
889
1169
  }
@@ -932,21 +1212,160 @@ async function viewGitHubRepositoryInfo(params) {
932
1212
  const args = ['view', `${owner}/${params.repo}`];
933
1213
  const result = await executeGitHubCommand('repo', args, { cache: false });
934
1214
  if (result.isError) {
935
- return result;
1215
+ // Parse the error message to provide better context
1216
+ const errorMsg = result.content[0].text;
1217
+ // Handle repository not found
1218
+ if (errorMsg.includes('404') ||
1219
+ errorMsg.includes('Not Found') ||
1220
+ errorMsg.includes('could not resolve to a Repository')) {
1221
+ return createErrorResult$1(`Repository not found: ${owner}/${params.repo}`, new Error(`
1222
+ ❌ REPOSITORY NOT FOUND: The repository '${owner}/${params.repo}' does not exist or is not accessible.
1223
+
1224
+ 🔍 COMMON CAUSES:
1225
+ • Repository name is incorrect
1226
+ • Repository is private and you lack access
1227
+ • Owner/organization name is wrong
1228
+ • Repository has been deleted or moved
1229
+
1230
+ 🎯 RECOMMENDED DISCOVERY WORKFLOW (in this order):
1231
+
1232
+ 1️⃣ **NPM PACKAGE DISCOVERY** (if this is a package):
1233
+ • Use 'npm_search_packages' with keywords: "${params.repo}"
1234
+ • Then 'npm_get_package' to find the GitHub repository URL
1235
+ • This automatically discovers the correct owner/repo
1236
+
1237
+ 2️⃣ **GITHUB TOPICS SEARCH** (for broader discovery):
1238
+ • Use 'github_search_topics' with terms: "${params.repo}"
1239
+ • Discover related repositories and ecosystems
1240
+ • Find the correct repository among similar projects
1241
+
1242
+ 3️⃣ **REPOSITORY SEARCH** (last resort):
1243
+ • Use 'github_search_repositories' with query: "${params.repo}"
1244
+ • Add filters like language, stars, etc.
1245
+ • Manual selection from search results
1246
+
1247
+ 💡 ORGANIZATION ACCESS:
1248
+ If this should be a private repository, try:
1249
+ • 'github_get_user_organizations' to see your available orgs
1250
+ • Use the correct organization name as owner
1251
+
1252
+ 🔧 VERIFICATION:
1253
+ • Check repository exists at: https://github.com/${owner}/${params.repo}
1254
+ • Verify spelling and case sensitivity`));
1255
+ }
1256
+ // Handle access denied
1257
+ if (errorMsg.includes('403') || errorMsg.includes('Forbidden')) {
1258
+ return createErrorResult$1(`Access denied to repository: ${owner}/${params.repo}`, new Error(`
1259
+ 🔒 ACCESS DENIED: You don't have permission to access '${owner}/${params.repo}'.
1260
+
1261
+ 🔍 POSSIBLE CAUSES:
1262
+ • Repository is private
1263
+ • Organization restrictions
1264
+ • Invalid authentication
1265
+
1266
+ 💡 RECOMMENDED ACTIONS:
1267
+ 1. Check authentication: gh auth status
1268
+ 2. Request repository access from owner: ${owner}
1269
+ 3. Use 'github_get_user_organizations' if this is your org
1270
+ 4. Verify you're logged into the correct GitHub account
1271
+
1272
+ 🎯 ALTERNATIVE DISCOVERY:
1273
+ If you're looking for similar repositories, try:
1274
+ • 'npm_search_packages' for packages
1275
+ • 'github_search_topics' for general discovery
1276
+ • 'github_search_repositories' with broader terms`));
1277
+ }
1278
+ // Handle rate limiting
1279
+ if (errorMsg.includes('rate limit') || errorMsg.includes('429')) {
1280
+ return createErrorResult$1('GitHub API rate limit exceeded', new Error(`
1281
+ ⏱️ RATE LIMIT: GitHub API rate limit has been exceeded.
1282
+
1283
+ 💡 RECOMMENDED ACTIONS:
1284
+ 1. Wait a few minutes before trying again
1285
+ 2. Use authentication to increase rate limits: gh auth login
1286
+ 3. Try discovery tools instead: npm_search_packages or github_search_topics`));
1287
+ }
1288
+ // Generic error fallback
1289
+ return createErrorResult$1(`Failed to access repository: ${owner}/${params.repo}`, new Error(`GitHub CLI Error: ${errorMsg}
1290
+
1291
+ 🔧 TROUBLESHOOTING:
1292
+ • Verify repository exists: https://github.com/${owner}/${params.repo}
1293
+ • Check spelling and case sensitivity
1294
+ • Confirm authentication: gh auth status
1295
+
1296
+ 🎯 DISCOVERY WORKFLOW:
1297
+ 1. npm_search_packages → npm_get_package
1298
+ 2. github_search_topics
1299
+ 3. github_search_repositories
1300
+ 4. github_get_repository (current step)`));
936
1301
  }
937
1302
  // Extract the actual content from the exec result
938
1303
  const execResult = JSON.parse(result.content[0].text);
939
1304
  const content = execResult.result;
1305
+ // Parse repository info to extract key details
940
1306
  const viewResult = {
941
1307
  owner,
942
1308
  repo: params.repo,
943
1309
  repositoryInfo: content,
944
1310
  rawOutput: content,
945
1311
  };
946
- return createSuccessResult$1(viewResult);
1312
+ // Try to extract branch information from the output
1313
+ let defaultBranch = 'main'; // fallback
1314
+ try {
1315
+ // The content is usually YAML-like output from gh repo view
1316
+ const lines = content.split('\n');
1317
+ for (const line of lines) {
1318
+ if (line.includes('default branch:') ||
1319
+ line.includes('Default branch:')) {
1320
+ const branchMatch = line.split(':')[1]?.trim();
1321
+ if (branchMatch) {
1322
+ defaultBranch = branchMatch;
1323
+ break;
1324
+ }
1325
+ }
1326
+ }
1327
+ }
1328
+ catch (parseError) {
1329
+ // If we can't parse the branch, keep the fallback
1330
+ }
1331
+ return createSuccessResult$1({
1332
+ ...viewResult,
1333
+ defaultBranch,
1334
+ success: true,
1335
+ message: `✅ Repository found: ${owner}/${params.repo}
1336
+
1337
+ 📋 REPOSITORY DETAILS:
1338
+ • Default branch: ${defaultBranch}
1339
+ • Ready for file operations
1340
+
1341
+ 🔄 NEXT RECOMMENDED STEPS:
1342
+ 1. Explore structure: github_get_contents
1343
+ 2. Search for code: github_search_code
1344
+ 3. Fetch specific files: github_get_file_content
1345
+
1346
+ ⚠️ IMPORTANT: Use branch '${defaultBranch}' in subsequent file operations.`,
1347
+ });
947
1348
  }
948
1349
  catch (error) {
949
- return createErrorResult$1('Failed to view GitHub repository', error);
1350
+ return createErrorResult$1(`Unexpected error accessing repository: ${params.owner}/${params.repo}`, new Error(`
1351
+ ❌ UNEXPECTED ERROR: ${error.message}
1352
+
1353
+ 📍 REPOSITORY DETAILS:
1354
+ • Owner: ${params.owner}
1355
+ • Repository: ${params.repo}
1356
+
1357
+ 🔧 TROUBLESHOOTING STEPS:
1358
+ 1. Verify GitHub CLI is installed and authenticated
1359
+ 2. Check network connectivity
1360
+ 3. Try discovery workflow instead:
1361
+
1362
+ 🎯 DISCOVERY WORKFLOW:
1363
+ 1. npm_search_packages "${params.repo}"
1364
+ 2. github_search_topics "${params.repo}"
1365
+ 3. github_search_repositories query="${params.repo}" owner="${params.owner}"
1366
+ 4. github_get_repository (retry after discovery)
1367
+
1368
+ 💡 This ensures you have the correct owner/repo before attempting direct access.`));
950
1369
  }
951
1370
  });
952
1371
  }
@@ -983,79 +1402,6 @@ function registerViewRepositoryTool(server) {
983
1402
  });
984
1403
  }
985
1404
 
986
- async function npmView(packageName) {
987
- const cacheKey = generateCacheKey('npm-view', { packageName });
988
- return withCache(cacheKey, async () => {
989
- try {
990
- const result = await executeNpmCommand('view', [packageName, '--json'], {
991
- cache: true,
992
- });
993
- if (result.isError) {
994
- return result;
995
- }
996
- // Parse the result from the executed command
997
- const commandOutput = JSON.parse(result.content[0].text);
998
- const npmData = commandOutput.result;
999
- let popularityData = '';
1000
- try {
1001
- // Get version count as popularity indicator
1002
- const versionsResult = await executeNpmCommand('view', [
1003
- packageName,
1004
- 'time',
1005
- '--json',
1006
- ]);
1007
- if (!versionsResult.isError) {
1008
- const versionsOutput = JSON.parse(versionsResult.content[0].text);
1009
- const timeData = versionsOutput.result;
1010
- const versionCount = Object.keys(timeData).length - 2; // Subtract 'created' and 'modified'
1011
- popularityData = `Package versions released: ${versionCount}`;
1012
- }
1013
- }
1014
- catch {
1015
- // Popularity data is optional
1016
- }
1017
- const enhancedResult = {
1018
- npmData: JSON.parse(JSON.stringify(npmData)),
1019
- popularityInfo: popularityData,
1020
- lastAnalyzed: new Date().toISOString(),
1021
- };
1022
- return createSuccessResult$1(enhancedResult);
1023
- }
1024
- catch (error) {
1025
- return createErrorResult$1('Failed to get npm repository information', error);
1026
- }
1027
- });
1028
- }
1029
-
1030
- function registerNpmViewTool(server) {
1031
- server.tool(TOOL_NAMES.NPM_GET_PACKAGE, TOOL_DESCRIPTIONS[TOOL_NAMES.NPM_GET_PACKAGE], {
1032
- packageName: z
1033
- .string()
1034
- .describe("The name of the npm package to analyze (e.g., 'react', '@types/node', 'lodash')"),
1035
- }, {
1036
- title: 'View NPM Package',
1037
- readOnlyHint: true,
1038
- destructiveHint: false,
1039
- idempotentHint: true,
1040
- openWorldHint: true,
1041
- }, async (args) => {
1042
- try {
1043
- return await npmView(args.packageName);
1044
- }
1045
- catch (error) {
1046
- return {
1047
- content: [
1048
- {
1049
- type: 'text',
1050
- text: `Failed to get npm package info: ${error.message}`,
1051
- },
1052
- ],
1053
- isError: true,
1054
- };
1055
- }
1056
- });
1057
- }
1058
-
1059
1405
  async function searchGitHubRepos(params) {
1060
1406
  const cacheKey = generateCacheKey('gh-repos', params);
1061
1407
  return withCache(cacheKey, async () => {
@@ -1184,8 +1530,8 @@ function buildGitHubReposSearchCommand(params) {
1184
1530
  args.push(`--include-forks=${params.includeForks}`);
1185
1531
  if (params.language)
1186
1532
  args.push(`--language=${params.language}`);
1187
- if (params.license)
1188
- args.push(`--license=${params.license}`);
1533
+ if (params.license && params.license.length > 0)
1534
+ args.push(`--license=${params.license.join(',')}`);
1189
1535
  if (params.limit)
1190
1536
  args.push(`--limit=${params.limit}`);
1191
1537
  if (params.match)
@@ -1196,15 +1542,15 @@ function buildGitHubReposSearchCommand(params) {
1196
1542
  args.push(`--order=${params.order}`);
1197
1543
  if (params.size)
1198
1544
  args.push(`--size="${params.size}"`);
1199
- // DEFAULT TO UPDATED SORTING for recency prioritization
1200
- const sortBy = params.sort || 'updated';
1545
+ // Use best-match as default, only specify sort if different from default
1546
+ const sortBy = params.sort || 'best-match';
1201
1547
  if (sortBy !== 'best-match') {
1202
1548
  args.push(`--sort=${sortBy}`);
1203
1549
  }
1204
1550
  if (params.stars !== undefined)
1205
- args.push(`--stars=${params.stars}`);
1206
- if (params.topic)
1207
- args.push(`--topic=${params.topic}`);
1551
+ args.push(`--stars="${params.stars}"`);
1552
+ if (params.topic && params.topic.length > 0)
1553
+ args.push(`--topic=${params.topic.join(',')}`);
1208
1554
  if (params.updated)
1209
1555
  args.push(`--updated="${params.updated}"`);
1210
1556
  if (params.visibility)
@@ -1264,7 +1610,13 @@ function validateFilterCombinations(args) {
1264
1610
  suggestion: 'PROVEN: owner=facebook + query=react without language filter → React (236K⭐), React Native (119K⭐), Create React App',
1265
1611
  },
1266
1612
  {
1267
- condition: args.language && args.stars !== undefined && args.stars > 10000,
1613
+ condition: args.language &&
1614
+ args.stars &&
1615
+ ((args.stars.includes('>') &&
1616
+ parseInt(args.stars.replace(/[><]/g, '')) > 10000) ||
1617
+ (!args.stars.includes('>') &&
1618
+ !args.stars.includes('<') &&
1619
+ parseInt(args.stars) > 10000)),
1268
1620
  warning: 'High star threshold with specific language may be too restrictive (TESTING-VALIDATED)',
1269
1621
  suggestion: 'PROVEN: Use >1000 stars for established projects, >100 for active ones. Language filters often miss major projects.',
1270
1622
  },
@@ -1298,8 +1650,8 @@ function validateFilterCombinations(args) {
1298
1650
  if (args.limit && (args.limit < 1 || args.limit > 100)) {
1299
1651
  warnings.push('Limit must be between 1 and 100');
1300
1652
  }
1301
- if (args.stars !== undefined && args.stars < 0) {
1302
- warnings.push('Stars filter must be non-negative');
1653
+ if (args.stars && !/^[><]=?\d+$|^\d+$|^\d+\.\.\d+$/.test(args.stars)) {
1654
+ warnings.push('Stars filter must be in format ">100", ">=500", "<1000", "<=200", "50..200" or a simple number');
1303
1655
  }
1304
1656
  if (args.forks !== undefined && args.forks < 0) {
1305
1657
  warnings.push('Forks filter must be non-negative');
@@ -1338,8 +1690,9 @@ function registerSearchGitHubReposTool(server) {
1338
1690
  .describe('Search query for repositories. PRODUCTION TIP: Single terms work best (e.g., "react", "typescript"). Multi-term queries will be auto-decomposed with suggestions.'),
1339
1691
  owner: z
1340
1692
  .string()
1341
- .min(1, 'Owner is required and cannot be empty')
1342
- .describe('Repository owner/organization - REQUIRED for scoped, reliable results'),
1693
+ .min(1)
1694
+ .optional()
1695
+ .describe('Repository owner/organization (e.g., "facebook", "microsoft"). OPTIONAL: Leave empty for global searches across all of GitHub. Recommended for scoped, reliable results.'),
1343
1696
  archived: z.boolean().optional().describe('Filter archived state'),
1344
1697
  created: z
1345
1698
  .string()
@@ -1363,7 +1716,10 @@ function registerSearchGitHubReposTool(server) {
1363
1716
  .string()
1364
1717
  .optional()
1365
1718
  .describe('Filter by programming language - WARNING: Can cause empty results with restrictive combinations'),
1366
- license: z.string().optional().describe('Filter by license type'),
1719
+ license: z
1720
+ .array(z.string())
1721
+ .optional()
1722
+ .describe('Filter based on license type (e.g., ["mit", "apache-2.0"])'),
1367
1723
  limit: z
1368
1724
  .number()
1369
1725
  .optional()
@@ -1373,28 +1729,37 @@ function registerSearchGitHubReposTool(server) {
1373
1729
  .enum(['name', 'description', 'readme'])
1374
1730
  .optional()
1375
1731
  .describe('Search scope restriction'),
1376
- numberTopics: z.number().optional().describe('Filter by topics count'),
1732
+ numberTopics: z
1733
+ .number()
1734
+ .optional()
1735
+ .describe('Filter on number of topics'),
1377
1736
  order: z
1378
1737
  .enum(['asc', 'desc'])
1379
1738
  .optional()
1380
1739
  .default('desc')
1381
1740
  .describe('Result order (default: desc for newest first)'),
1382
- size: z.string().optional().describe('Filter by size in KB'),
1741
+ size: z
1742
+ .string()
1743
+ .optional()
1744
+ .describe('Filter on size range, in kilobytes (e.g., ">1000", "50..120")'),
1383
1745
  sort: z
1384
1746
  .enum(['forks', 'help-wanted-issues', 'stars', 'updated', 'best-match'])
1385
1747
  .optional()
1386
- .default('updated')
1387
- .describe('Sort criteria (default: updated for recent activity)'),
1748
+ .default('best-match')
1749
+ .describe('Sort fetched repositories (default: best-match)'),
1388
1750
  stars: z
1389
- .number()
1751
+ .string()
1390
1752
  .optional()
1391
- .describe('Filter by stars count - TIP: Use >100 for established projects, >10 for active ones'),
1392
- topic: z.string().optional().describe('Filter by topic/tag'),
1753
+ .describe('Filter by stars count (e.g., ">100", "<1000", ">=500", "50..200" for range queries) - TIP: Use >100 for established projects, >10 for active ones'),
1754
+ topic: z
1755
+ .array(z.string())
1756
+ .optional()
1757
+ .describe('Filter on topic (e.g., ["react", "javascript"])'),
1393
1758
  updated: z.string().optional().describe('Filter by last update date'),
1394
1759
  visibility: z
1395
1760
  .enum(['public', 'private', 'internal'])
1396
1761
  .optional()
1397
- .describe('Filter by visibility'),
1762
+ .describe('Filter based on repository visibility'),
1398
1763
  }, {
1399
1764
  title: 'Search GitHub Repositories',
1400
1765
  readOnlyHint: true,
@@ -1420,8 +1785,26 @@ function registerSearchGitHubReposTool(server) {
1420
1785
  const result = await searchGitHubRepos(searchArgs);
1421
1786
  // Check if we got empty results and provide helpful guidance
1422
1787
  const resultText = result.content[0].text;
1423
- const parsedResults = JSON.parse(resultText);
1424
- const resultCount = JSON.parse(parsedResults.rawOutput).length;
1788
+ // Handle non-JSON responses gracefully
1789
+ let parsedResults;
1790
+ let resultCount = 0;
1791
+ try {
1792
+ parsedResults = JSON.parse(resultText);
1793
+ if (parsedResults.rawOutput) {
1794
+ const rawData = JSON.parse(parsedResults.rawOutput);
1795
+ resultCount = Array.isArray(rawData) ? rawData.length : 0;
1796
+ }
1797
+ }
1798
+ catch (parseError) {
1799
+ // If parsing fails, it might be an error message from GitHub CLI
1800
+ if (resultText.includes('Failed to') ||
1801
+ resultText.includes('Error:')) {
1802
+ throw new Error(`GitHub CLI error: ${resultText}`);
1803
+ }
1804
+ // For other parsing issues, set reasonable defaults
1805
+ resultCount = 0;
1806
+ parsedResults = { rawOutput: '[]' };
1807
+ }
1425
1808
  let responseText = resultText;
1426
1809
  // Add guidance for multi-term queries
1427
1810
  if (queryAnalysis.shouldDecompose) {
@@ -1462,6 +1845,10 @@ function registerSearchGitHubReposTool(server) {
1462
1845
  responseText += `\n• SCOPED SEARCH SUCCESS: owner + single term pattern proven effective`;
1463
1846
  responseText += `\n• PROVEN EXAMPLES: microsoft+typescript→VSCode(173K⭐), facebook+react→React(236K⭐)`;
1464
1847
  }
1848
+ else if (!args.owner) {
1849
+ responseText += `\n• GLOBAL SEARCH: Searching across all GitHub repositories`;
1850
+ responseText += `\n• TIP: Add owner filter for more targeted results if you know specific organizations`;
1851
+ }
1465
1852
  // Add caching recommendations for testing-validated popular searches
1466
1853
  const validatedPopularTerms = [
1467
1854
  'react', // 236K⭐ confirmed
@@ -1494,11 +1881,12 @@ function registerSearchGitHubReposTool(server) {
1494
1881
  🔄 RECOMMENDED FALLBACK WORKFLOW:
1495
1882
  ${fallbacks.map(f => `• ${f}`).join('\n')}
1496
1883
 
1497
- 💡 PRODUCTION NOTE: This tool is a last resort. For reliable discovery:
1884
+ 💡 PRODUCTION NOTE: For reliable discovery:
1498
1885
  1. Start with npm_search_packages for package-based discovery
1499
1886
  2. Use github_search_topics for ecosystem terminology
1500
1887
  3. Use npm_get_package to extract repository URLs
1501
- 4. Only use repository search when NPM + Topics completely fail`;
1888
+ 4. Use global repository search (without owner) for broad discovery
1889
+ 5. Use scoped search (with owner) when you know specific organizations`;
1502
1890
  return {
1503
1891
  content: [
1504
1892
  {
@@ -2291,8 +2679,9 @@ function registerSearchGitHubIssuesTool(server) {
2291
2679
  .describe("The search query to find issues (e.g., 'bug fix', 'feature request', 'documentation')"),
2292
2680
  owner: z
2293
2681
  .string()
2294
- .min(1, 'Owner is required and cannot be empty')
2295
- .describe("Filter by repository owner/organization (e.g., 'example-org')"),
2682
+ .min(1)
2683
+ .optional()
2684
+ .describe("Filter by repository owner/organization (e.g., 'example-org'). OPTIONAL: Leave empty for global searches across all of GitHub."),
2296
2685
  repo: z
2297
2686
  .string()
2298
2687
  .optional()
@@ -2605,6 +2994,8 @@ function buildGitHubUsersAPICommand(params) {
2605
2994
  // Add pagination parameters
2606
2995
  const limit = params.limit || 30;
2607
2996
  queryParams.push(`per_page=${limit}`);
2997
+ const page = params.page || 1;
2998
+ queryParams.push(`page=${page}`);
2608
2999
  if (params.sort)
2609
3000
  queryParams.push(`sort=${params.sort}`);
2610
3001
  if (params.order)
@@ -2623,8 +3014,9 @@ function registerSearchGitHubUsersTool(server) {
2623
3014
  .describe("The search query to find users/organizations (e.g., 'react developer', 'python', 'machine learning')"),
2624
3015
  owner: z
2625
3016
  .string()
2626
- .min(1, 'Owner is required and cannot be empty')
2627
- .describe("Filter by repository owner/organization (e.g., 'example-org') obtained from the appropriate tool for fetching user organizations"),
3017
+ .min(1)
3018
+ .optional()
3019
+ .describe("Filter by repository owner/organization (e.g., 'example-org'). OPTIONAL: Leave empty for global searches across all of GitHub."),
2628
3020
  type: z
2629
3021
  .enum(['user', 'org'])
2630
3022
  .optional()
@@ -2663,6 +3055,11 @@ function registerSearchGitHubUsersTool(server) {
2663
3055
  .optional()
2664
3056
  .default(50)
2665
3057
  .describe('Maximum number of users to return (default: 50)'),
3058
+ page: z
3059
+ .number()
3060
+ .optional()
3061
+ .default(1)
3062
+ .describe('The page number of the results to fetch (default: 1)'),
2666
3063
  }, {
2667
3064
  title: 'Search GitHub Users',
2668
3065
  readOnlyHint: true,
@@ -2687,67 +3084,6 @@ function registerSearchGitHubUsersTool(server) {
2687
3084
  });
2688
3085
  }
2689
3086
 
2690
- async function npmPackageStats(packageName) {
2691
- const cacheKey = generateCacheKey('npm-stats', { packageName });
2692
- return withCache(cacheKey, async () => {
2693
- try {
2694
- // Execute multiple commands in parallel using executeNpmCommand
2695
- const commands = [
2696
- executeNpmCommand('view', [packageName, 'time', '--json']),
2697
- executeNpmCommand('view', [packageName, 'versions', '--json']),
2698
- executeNpmCommand('view', [packageName, 'dist-tags', '--json']),
2699
- ];
2700
- const results = await Promise.allSettled(commands);
2701
- const stats = {
2702
- packageName,
2703
- releaseHistory: results[0].status === 'fulfilled' && !results[0].value.isError
2704
- ? JSON.parse(results[0].value.content[0].text).result
2705
- : null,
2706
- versions: results[1].status === 'fulfilled' && !results[1].value.isError
2707
- ? JSON.parse(results[1].value.content[0].text).result
2708
- : null,
2709
- distTags: results[2].status === 'fulfilled' && !results[2].value.isError
2710
- ? JSON.parse(results[2].value.content[0].text).result
2711
- : null,
2712
- analyzedAt: new Date().toISOString(),
2713
- };
2714
- return createSuccessResult$1(stats);
2715
- }
2716
- catch (error) {
2717
- return createErrorResult$1('Failed to get npm package statistics', error);
2718
- }
2719
- });
2720
- }
2721
-
2722
- function registerNpmPackageStatsTool(server) {
2723
- server.tool(TOOL_NAMES.NPM_GET_PACKAGE_STATS, TOOL_DESCRIPTIONS[TOOL_NAMES.NPM_GET_PACKAGE_STATS], {
2724
- packageName: z
2725
- .string()
2726
- .describe("The name of the npm package to analyze (e.g., 'react', '@types/node', 'lodash')"),
2727
- }, {
2728
- title: 'NPM Package Statistics',
2729
- readOnlyHint: true,
2730
- destructiveHint: false,
2731
- idempotentHint: true,
2732
- openWorldHint: true,
2733
- }, async (args) => {
2734
- try {
2735
- return await npmPackageStats(args.packageName);
2736
- }
2737
- catch (error) {
2738
- return {
2739
- content: [
2740
- {
2741
- type: 'text',
2742
- text: `Failed to get npm package statistics: ${error.message}`,
2743
- },
2744
- ],
2745
- isError: true,
2746
- };
2747
- }
2748
- });
2749
- }
2750
-
2751
3087
  async function analyzeDependencies(packageName) {
2752
3088
  const cacheKey = generateCacheKey('npm-dep-analysis', { packageName });
2753
3089
  return withCache(cacheKey, async () => {
@@ -2874,6 +3210,699 @@ function registerNpmDependencyAnalysisTool(server) {
2874
3210
  });
2875
3211
  }
2876
3212
 
3213
+ async function npmGetRepository(packageName) {
3214
+ const cacheKey = generateCacheKey('npm-get-repository', { packageName });
3215
+ return withCache(cacheKey, async () => {
3216
+ try {
3217
+ const result = await executeNpmCommand('view', [packageName, '--json'], {
3218
+ cache: true,
3219
+ });
3220
+ if (result.isError) {
3221
+ return result;
3222
+ }
3223
+ // Parse the result from the executed command
3224
+ const commandOutput = JSON.parse(result.content[0].text);
3225
+ // The result is a JSON string from npm that needs to be parsed again
3226
+ const npmData = JSON.parse(commandOutput.result);
3227
+ // Extract only repository-related data
3228
+ const repositoryResult = {
3229
+ packageName: npmData.name,
3230
+ description: npmData.description,
3231
+ repository: npmData.repository,
3232
+ homepage: npmData.homepage,
3233
+ };
3234
+ return createSuccessResult$1(repositoryResult);
3235
+ }
3236
+ catch (error) {
3237
+ return createErrorResult$1('Failed to get npm repository information', error);
3238
+ }
3239
+ });
3240
+ }
3241
+
3242
+ function registerNpmGetRepositoryTool(server) {
3243
+ server.tool(TOOL_NAMES.NPM_GET_REPOSITORY, TOOL_DESCRIPTIONS[TOOL_NAMES.NPM_GET_REPOSITORY], {
3244
+ packageName: z
3245
+ .string()
3246
+ .describe("The name of the npm package to get repository information for (e.g., 'react', 'express', 'lodash'). Returns minimal repository data: package name, description, repository URL, and homepage - optimized for token efficiency."),
3247
+ }, {
3248
+ title: 'NPM Repository Discovery - Extract GitHub Repository URL',
3249
+ readOnlyHint: true,
3250
+ destructiveHint: false,
3251
+ idempotentHint: true,
3252
+ openWorldHint: true,
3253
+ }, async (args) => {
3254
+ try {
3255
+ return await npmGetRepository(args.packageName);
3256
+ }
3257
+ catch (error) {
3258
+ return {
3259
+ content: [
3260
+ {
3261
+ type: 'text',
3262
+ text: `Failed to get npm repository info: ${error.message}`,
3263
+ },
3264
+ ],
3265
+ isError: true,
3266
+ };
3267
+ }
3268
+ });
3269
+ }
3270
+
3271
+ async function npmGetDependencies(packageName) {
3272
+ const cacheKey = generateCacheKey('npm-get-dependencies', { packageName });
3273
+ return withCache(cacheKey, async () => {
3274
+ try {
3275
+ const result = await executeNpmCommand('view', [packageName, '--json'], {
3276
+ cache: true,
3277
+ });
3278
+ if (result.isError) {
3279
+ return result;
3280
+ }
3281
+ // Parse the result from the executed command
3282
+ const commandOutput = JSON.parse(result.content[0].text);
3283
+ // The result is a JSON string from npm that needs to be parsed again
3284
+ const npmData = JSON.parse(commandOutput.result);
3285
+ // Extract only dependencies data
3286
+ const dependenciesResult = {
3287
+ packageName: npmData.name,
3288
+ dependencies: npmData.dependencies || {},
3289
+ devDependencies: npmData.devDependencies || {},
3290
+ resolutions: npmData.resolutions || {},
3291
+ };
3292
+ return createSuccessResult$1(dependenciesResult);
3293
+ }
3294
+ catch (error) {
3295
+ return createErrorResult$1('Failed to get npm dependencies information', error);
3296
+ }
3297
+ });
3298
+ }
3299
+
3300
+ function registerNpmGetDependenciesTool(server) {
3301
+ server.tool(TOOL_NAMES.NPM_GET_DEPENDENCIES, TOOL_DESCRIPTIONS[TOOL_NAMES.NPM_GET_DEPENDENCIES], {
3302
+ packageName: z
3303
+ .string()
3304
+ .describe("The name of the npm package to analyze dependencies for (e.g., 'react', 'express', 'lodash'). Returns focused dependency data: dependencies, devDependencies, and resolutions - optimized for token efficiency."),
3305
+ }, {
3306
+ title: 'NPM Dependency Analysis - Extract Package Dependencies',
3307
+ readOnlyHint: true,
3308
+ destructiveHint: false,
3309
+ idempotentHint: true,
3310
+ openWorldHint: true,
3311
+ }, async (args) => {
3312
+ try {
3313
+ return await npmGetDependencies(args.packageName);
3314
+ }
3315
+ catch (error) {
3316
+ return {
3317
+ content: [
3318
+ {
3319
+ type: 'text',
3320
+ text: `Failed to get npm dependencies: ${error.message}`,
3321
+ },
3322
+ ],
3323
+ isError: true,
3324
+ };
3325
+ }
3326
+ });
3327
+ }
3328
+
3329
+ async function npmGetBugs(packageName) {
3330
+ const cacheKey = generateCacheKey('npm-get-bugs', { packageName });
3331
+ return withCache(cacheKey, async () => {
3332
+ try {
3333
+ const result = await executeNpmCommand('view', [packageName, '--json'], {
3334
+ cache: true,
3335
+ });
3336
+ if (result.isError) {
3337
+ return result;
3338
+ }
3339
+ // Parse the result from the executed command
3340
+ const commandOutput = JSON.parse(result.content[0].text);
3341
+ // The result is a JSON string from npm that needs to be parsed again
3342
+ const npmData = JSON.parse(commandOutput.result);
3343
+ // Extract only bugs data
3344
+ const bugsResult = {
3345
+ packageName: npmData.name,
3346
+ bugs: npmData.bugs,
3347
+ };
3348
+ return createSuccessResult$1(bugsResult);
3349
+ }
3350
+ catch (error) {
3351
+ return createErrorResult$1('Failed to get npm bugs information', error);
3352
+ }
3353
+ });
3354
+ }
3355
+
3356
+ function registerNpmGetBugsTool(server) {
3357
+ server.tool(TOOL_NAMES.NPM_GET_BUGS, TOOL_DESCRIPTIONS[TOOL_NAMES.NPM_GET_BUGS], {
3358
+ packageName: z
3359
+ .string()
3360
+ .describe("The name of the npm package to get bug tracking information for (e.g., 'react', 'express', 'lodash'). Returns minimal bug data: package name and bugs URL - optimized for token efficiency."),
3361
+ }, {
3362
+ title: 'NPM Bug Tracking - Extract Issue Tracker URL',
3363
+ readOnlyHint: true,
3364
+ destructiveHint: false,
3365
+ idempotentHint: true,
3366
+ openWorldHint: true,
3367
+ }, async (args) => {
3368
+ try {
3369
+ return await npmGetBugs(args.packageName);
3370
+ }
3371
+ catch (error) {
3372
+ return {
3373
+ content: [
3374
+ {
3375
+ type: 'text',
3376
+ text: `Failed to get npm bugs info: ${error.message}`,
3377
+ },
3378
+ ],
3379
+ isError: true,
3380
+ };
3381
+ }
3382
+ });
3383
+ }
3384
+
3385
+ async function npmGetReadme(packageName) {
3386
+ const cacheKey = generateCacheKey('npm-get-readme', { packageName });
3387
+ return withCache(cacheKey, async () => {
3388
+ try {
3389
+ const result = await executeNpmCommand('view', [packageName, '--json'], {
3390
+ cache: true,
3391
+ });
3392
+ if (result.isError) {
3393
+ return result;
3394
+ }
3395
+ // Parse the result from the executed command
3396
+ const commandOutput = JSON.parse(result.content[0].text);
3397
+ // The result is a JSON string from npm that needs to be parsed again
3398
+ const npmData = JSON.parse(commandOutput.result);
3399
+ // Extract only readme data
3400
+ const readmeResult = {
3401
+ packageName: npmData.name,
3402
+ readmeFilename: npmData.readmeFilename,
3403
+ };
3404
+ return createSuccessResult$1(readmeResult);
3405
+ }
3406
+ catch (error) {
3407
+ return createErrorResult$1('Failed to get npm readme information', error);
3408
+ }
3409
+ });
3410
+ }
3411
+
3412
+ function registerNpmGetReadmeTool(server) {
3413
+ server.tool(TOOL_NAMES.NPM_GET_README, TOOL_DESCRIPTIONS[TOOL_NAMES.NPM_GET_README], {
3414
+ packageName: z
3415
+ .string()
3416
+ .describe("The name of the npm package to get README information for (e.g., 'react', 'express', 'lodash'). Returns minimal README data: package name and readme filename - optimized for token efficiency."),
3417
+ }, {
3418
+ title: 'NPM Documentation Access - Extract README Filename',
3419
+ readOnlyHint: true,
3420
+ destructiveHint: false,
3421
+ idempotentHint: true,
3422
+ openWorldHint: true,
3423
+ }, async (args) => {
3424
+ try {
3425
+ return await npmGetReadme(args.packageName);
3426
+ }
3427
+ catch (error) {
3428
+ return {
3429
+ content: [
3430
+ {
3431
+ type: 'text',
3432
+ text: `Failed to get npm readme info: ${error.message}`,
3433
+ },
3434
+ ],
3435
+ isError: true,
3436
+ };
3437
+ }
3438
+ });
3439
+ }
3440
+
3441
+ async function npmGetVersions(packageName) {
3442
+ const cacheKey = generateCacheKey('npm-get-versions', { packageName });
3443
+ return withCache(cacheKey, async () => {
3444
+ try {
3445
+ const result = await executeNpmCommand('view', [packageName, '--json'], {
3446
+ cache: true,
3447
+ });
3448
+ if (result.isError) {
3449
+ return result;
3450
+ }
3451
+ // Parse the result from the executed command
3452
+ const commandOutput = JSON.parse(result.content[0].text);
3453
+ // The result is a JSON string from npm that needs to be parsed again
3454
+ const npmData = JSON.parse(commandOutput.result);
3455
+ // Filter versions to include only official semantic versions (major.minor.patch)
3456
+ // Excludes pre-release versions like alpha, beta, rc, dev, experimental, etc.
3457
+ const semanticVersionRegex = /^\d+\.\d+\.\d+$/;
3458
+ const officialVersions = npmData.versions.filter(version => semanticVersionRegex.test(version));
3459
+ // Extract only versions data with filtered official versions
3460
+ const versionsResult = {
3461
+ packageName: npmData.name,
3462
+ versions: officialVersions,
3463
+ latestVersion: npmData['dist-tags'].latest,
3464
+ versionCount: officialVersions.length,
3465
+ };
3466
+ return createSuccessResult$1(versionsResult);
3467
+ }
3468
+ catch (error) {
3469
+ return createErrorResult$1('Failed to get npm versions information', error);
3470
+ }
3471
+ });
3472
+ }
3473
+
3474
+ function registerNpmGetVersionsTool(server) {
3475
+ server.tool(TOOL_NAMES.NPM_GET_VERSIONS, TOOL_DESCRIPTIONS[TOOL_NAMES.NPM_GET_VERSIONS], {
3476
+ packageName: z
3477
+ .string()
3478
+ .describe("The name of the npm package to get version information for (e.g., 'react', 'express', 'lodash'). Returns only official semantic versions (major.minor.patch format), excluding pre-release versions like alpha, beta, rc - optimized for production planning."),
3479
+ }, {
3480
+ title: 'NPM Version Tracking - Extract Package Versions',
3481
+ readOnlyHint: true,
3482
+ destructiveHint: false,
3483
+ idempotentHint: true,
3484
+ openWorldHint: true,
3485
+ }, async (args) => {
3486
+ try {
3487
+ return await npmGetVersions(args.packageName);
3488
+ }
3489
+ catch (error) {
3490
+ return {
3491
+ content: [
3492
+ {
3493
+ type: 'text',
3494
+ text: `Failed to get npm versions: ${error.message}`,
3495
+ },
3496
+ ],
3497
+ isError: true,
3498
+ };
3499
+ }
3500
+ });
3501
+ }
3502
+
3503
+ async function npmGetAuthor(packageName) {
3504
+ const cacheKey = generateCacheKey('npm-get-author', { packageName });
3505
+ return withCache(cacheKey, async () => {
3506
+ try {
3507
+ const result = await executeNpmCommand('view', [packageName, '--json'], {
3508
+ cache: true,
3509
+ });
3510
+ if (result.isError) {
3511
+ return result;
3512
+ }
3513
+ // Parse the result from the executed command
3514
+ const commandOutput = JSON.parse(result.content[0].text);
3515
+ // The result is a JSON string from npm that needs to be parsed again
3516
+ const npmData = JSON.parse(commandOutput.result);
3517
+ // Extract only author data
3518
+ const authorResult = {
3519
+ packageName: npmData.name,
3520
+ author: npmData.author,
3521
+ maintainers: npmData.maintainers,
3522
+ };
3523
+ return createSuccessResult$1(authorResult);
3524
+ }
3525
+ catch (error) {
3526
+ return createErrorResult$1('Failed to get npm author information', error);
3527
+ }
3528
+ });
3529
+ }
3530
+
3531
+ function registerNpmGetAuthorTool(server) {
3532
+ server.tool(TOOL_NAMES.NPM_GET_AUTHOR, TOOL_DESCRIPTIONS[TOOL_NAMES.NPM_GET_AUTHOR], {
3533
+ packageName: z
3534
+ .string()
3535
+ .describe("The name of the npm package to get author information for (e.g., 'react', 'express', 'lodash'). Returns focused author data: author and maintainers list - optimized for token efficiency."),
3536
+ }, {
3537
+ title: 'NPM Maintainer Information - Extract Author and Maintainers',
3538
+ readOnlyHint: true,
3539
+ destructiveHint: false,
3540
+ idempotentHint: true,
3541
+ openWorldHint: true,
3542
+ }, async (args) => {
3543
+ try {
3544
+ return await npmGetAuthor(args.packageName);
3545
+ }
3546
+ catch (error) {
3547
+ return {
3548
+ content: [
3549
+ {
3550
+ type: 'text',
3551
+ text: `Failed to get npm author info: ${error.message}`,
3552
+ },
3553
+ ],
3554
+ isError: true,
3555
+ };
3556
+ }
3557
+ });
3558
+ }
3559
+
3560
+ async function npmGetLicense(packageName) {
3561
+ const cacheKey = generateCacheKey('npm-get-license', { packageName });
3562
+ return withCache(cacheKey, async () => {
3563
+ try {
3564
+ const result = await executeNpmCommand('view', [packageName, '--json'], {
3565
+ cache: true,
3566
+ });
3567
+ if (result.isError) {
3568
+ return result;
3569
+ }
3570
+ // Parse the result from the executed command
3571
+ const commandOutput = JSON.parse(result.content[0].text);
3572
+ // The result is a JSON string from npm that needs to be parsed again
3573
+ const npmData = JSON.parse(commandOutput.result);
3574
+ // Extract only license data
3575
+ const licenseResult = {
3576
+ packageName: npmData.name,
3577
+ license: npmData.license,
3578
+ };
3579
+ return createSuccessResult$1(licenseResult);
3580
+ }
3581
+ catch (error) {
3582
+ return createErrorResult$1('Failed to get npm license information', error);
3583
+ }
3584
+ });
3585
+ }
3586
+
3587
+ function registerNpmGetLicenseTool(server) {
3588
+ server.tool(TOOL_NAMES.NPM_GET_LICENSE, TOOL_DESCRIPTIONS[TOOL_NAMES.NPM_GET_LICENSE], {
3589
+ packageName: z
3590
+ .string()
3591
+ .describe("The name of the npm package to get license information for (e.g., 'react', 'express', 'lodash'). Returns minimal license data: package name and license - optimized for token efficiency."),
3592
+ }, {
3593
+ title: 'NPM License Compliance - Extract Package License',
3594
+ readOnlyHint: true,
3595
+ destructiveHint: false,
3596
+ idempotentHint: true,
3597
+ openWorldHint: true,
3598
+ }, async (args) => {
3599
+ try {
3600
+ return await npmGetLicense(args.packageName);
3601
+ }
3602
+ catch (error) {
3603
+ return {
3604
+ content: [
3605
+ {
3606
+ type: 'text',
3607
+ text: `Failed to get npm license info: ${error.message}`,
3608
+ },
3609
+ ],
3610
+ isError: true,
3611
+ };
3612
+ }
3613
+ });
3614
+ }
3615
+
3616
+ async function npmGetHomepage(packageName) {
3617
+ const cacheKey = generateCacheKey('npm-get-homepage', { packageName });
3618
+ return withCache(cacheKey, async () => {
3619
+ try {
3620
+ const result = await executeNpmCommand('view', [packageName, '--json'], {
3621
+ cache: true,
3622
+ });
3623
+ if (result.isError) {
3624
+ return result;
3625
+ }
3626
+ // Parse the result from the executed command
3627
+ const commandOutput = JSON.parse(result.content[0].text);
3628
+ // The result is a JSON string from npm that needs to be parsed again
3629
+ const npmData = JSON.parse(commandOutput.result);
3630
+ // Extract only homepage data
3631
+ const homepageResult = {
3632
+ packageName: npmData.name,
3633
+ homepage: npmData.homepage,
3634
+ };
3635
+ return createSuccessResult$1(homepageResult);
3636
+ }
3637
+ catch (error) {
3638
+ return createErrorResult$1('Failed to get npm homepage information', error);
3639
+ }
3640
+ });
3641
+ }
3642
+
3643
+ function registerNpmGetHomepageTool(server) {
3644
+ server.tool(TOOL_NAMES.NPM_GET_HOMEPAGE, TOOL_DESCRIPTIONS[TOOL_NAMES.NPM_GET_HOMEPAGE], {
3645
+ packageName: z
3646
+ .string()
3647
+ .describe("The name of the npm package to get homepage information for (e.g., 'react', 'express', 'lodash'). Returns direct access to official documentation, interactive examples, and comprehensive project resources - optimized for token efficiency."),
3648
+ }, {
3649
+ title: 'NPM Homepage Discovery - Extract Project Website URL',
3650
+ readOnlyHint: true,
3651
+ destructiveHint: false,
3652
+ idempotentHint: true,
3653
+ openWorldHint: true,
3654
+ }, async (args) => {
3655
+ try {
3656
+ return await npmGetHomepage(args.packageName);
3657
+ }
3658
+ catch (error) {
3659
+ return {
3660
+ content: [
3661
+ {
3662
+ type: 'text',
3663
+ text: `Failed to get npm homepage info: ${error.message}`,
3664
+ },
3665
+ ],
3666
+ isError: true,
3667
+ };
3668
+ }
3669
+ });
3670
+ }
3671
+
3672
+ async function npmGetId(packageName) {
3673
+ const cacheKey = generateCacheKey('npm-get-id', { packageName });
3674
+ return withCache(cacheKey, async () => {
3675
+ try {
3676
+ const result = await executeNpmCommand('view', [packageName, '--json'], {
3677
+ cache: true,
3678
+ });
3679
+ if (result.isError) {
3680
+ return result;
3681
+ }
3682
+ // Parse the result from the executed command
3683
+ const commandOutput = JSON.parse(result.content[0].text);
3684
+ // The result is a JSON string from npm that needs to be parsed again
3685
+ const npmData = JSON.parse(commandOutput.result);
3686
+ // Extract only _id data (name@latestVersion format)
3687
+ const idResult = {
3688
+ packageName: npmData.name,
3689
+ id: npmData._id,
3690
+ };
3691
+ return createSuccessResult$1(idResult);
3692
+ }
3693
+ catch (error) {
3694
+ return createErrorResult$1('Failed to get npm ID information', error);
3695
+ }
3696
+ });
3697
+ }
3698
+
3699
+ function registerNpmGetIdTool(server) {
3700
+ server.tool(TOOL_NAMES.NPM_GET_ID, TOOL_DESCRIPTIONS[TOOL_NAMES.NPM_GET_ID], {
3701
+ packageName: z
3702
+ .string()
3703
+ .describe("The name of the npm package to get ID information for (e.g., 'react', 'express', 'lodash'). Returns precise version identifier for dependency management, lockfiles, and reproducible builds - optimized for token efficiency."),
3704
+ }, {
3705
+ title: 'NPM Package Identification - Extract Name@Version ID',
3706
+ readOnlyHint: true,
3707
+ destructiveHint: false,
3708
+ idempotentHint: true,
3709
+ openWorldHint: true,
3710
+ }, async (args) => {
3711
+ try {
3712
+ return await npmGetId(args.packageName);
3713
+ }
3714
+ catch (error) {
3715
+ return {
3716
+ content: [
3717
+ {
3718
+ type: 'text',
3719
+ text: `Failed to get npm ID info: ${error.message}`,
3720
+ },
3721
+ ],
3722
+ isError: true,
3723
+ };
3724
+ }
3725
+ });
3726
+ }
3727
+
3728
+ async function npmGetReleases(packageName) {
3729
+ const cacheKey = generateCacheKey('npm-get-releases', { packageName });
3730
+ return withCache(cacheKey, async () => {
3731
+ try {
3732
+ const result = await executeNpmCommand('view', [packageName, '--json'], {
3733
+ cache: true,
3734
+ });
3735
+ if (result.isError) {
3736
+ return result;
3737
+ }
3738
+ // Parse the result from the executed command
3739
+ const commandOutput = JSON.parse(result.content[0].text);
3740
+ // The result is a JSON string from npm that needs to be parsed again
3741
+ const npmData = JSON.parse(commandOutput.result);
3742
+ // Extract only version entries (exclude 'created' and 'modified')
3743
+ const versionEntries = Object.entries(npmData.time).filter(([key]) => key !== 'created' && key !== 'modified');
3744
+ // Sort by release date (most recent first) and take last 10
3745
+ const sortedVersions = versionEntries
3746
+ .sort(([, dateA], [, dateB]) => new Date(dateB).getTime() - new Date(dateA).getTime())
3747
+ .slice(0, 10)
3748
+ .map(([version, releaseDate]) => ({ version, releaseDate }));
3749
+ // Create efficient result with only requested data
3750
+ const timeResult = {
3751
+ packageName: npmData.name,
3752
+ lastModified: npmData.time.modified,
3753
+ created: npmData.time.created,
3754
+ versionCount: versionEntries.length,
3755
+ last10Releases: sortedVersions,
3756
+ };
3757
+ return createSuccessResult$1(timeResult);
3758
+ }
3759
+ catch (error) {
3760
+ return createErrorResult$1('Failed to get npm time information', error);
3761
+ }
3762
+ });
3763
+ }
3764
+
3765
+ function registerNpmGetReleasesTool(server) {
3766
+ server.tool(TOOL_NAMES.NPM_GET_RELEASES, TOOL_DESCRIPTIONS[TOOL_NAMES.NPM_GET_RELEASES], {
3767
+ packageName: z
3768
+ .string()
3769
+ .describe("The name of the npm package to get release information for (e.g., 'react', 'express', 'lodash'). Returns focused release data: last modified, created date, version count, and last 10 releases - optimized for token efficiency."),
3770
+ }, {
3771
+ title: 'NPM Package Releases - Extract Recent Release Data',
3772
+ readOnlyHint: true,
3773
+ destructiveHint: false,
3774
+ idempotentHint: true,
3775
+ openWorldHint: true,
3776
+ }, async (args) => {
3777
+ try {
3778
+ return await npmGetReleases(args.packageName);
3779
+ }
3780
+ catch (error) {
3781
+ return {
3782
+ content: [
3783
+ {
3784
+ type: 'text',
3785
+ text: `Failed to get npm release info: ${error.message}`,
3786
+ },
3787
+ ],
3788
+ isError: true,
3789
+ };
3790
+ }
3791
+ });
3792
+ }
3793
+
3794
+ async function npmGetEngines(packageName) {
3795
+ const cacheKey = generateCacheKey('npm-get-engines', { packageName });
3796
+ return withCache(cacheKey, async () => {
3797
+ try {
3798
+ const result = await executeNpmCommand('view', [packageName, '--json'], {
3799
+ cache: true,
3800
+ });
3801
+ if (result.isError) {
3802
+ return result;
3803
+ }
3804
+ // Parse the result from the executed command
3805
+ const commandOutput = JSON.parse(result.content[0].text);
3806
+ // The result is a JSON string from npm that needs to be parsed again
3807
+ const npmData = JSON.parse(commandOutput.result);
3808
+ // Extract only engines data
3809
+ const enginesResult = {
3810
+ packageName: npmData.name,
3811
+ engines: npmData.engines || {},
3812
+ };
3813
+ return createSuccessResult$1(enginesResult);
3814
+ }
3815
+ catch (error) {
3816
+ return createErrorResult$1('Failed to get npm engines information', error);
3817
+ }
3818
+ });
3819
+ }
3820
+
3821
+ function registerNpmGetEnginesTool(server) {
3822
+ server.tool(TOOL_NAMES.NPM_GET_ENGINES, TOOL_DESCRIPTIONS[TOOL_NAMES.NPM_GET_ENGINES], {
3823
+ packageName: z
3824
+ .string()
3825
+ .describe("The name of the npm package to get engines information for (e.g., 'react', 'express', 'lodash'). Returns environment compatibility requirements to prevent deployment failures and runtime conflicts - optimized for token efficiency."),
3826
+ }, {
3827
+ title: 'NPM Runtime Compatibility - Extract Engine Requirements',
3828
+ readOnlyHint: true,
3829
+ destructiveHint: false,
3830
+ idempotentHint: true,
3831
+ openWorldHint: true,
3832
+ }, async (args) => {
3833
+ try {
3834
+ return await npmGetEngines(args.packageName);
3835
+ }
3836
+ catch (error) {
3837
+ return {
3838
+ content: [
3839
+ {
3840
+ type: 'text',
3841
+ text: `Failed to get npm engines info: ${error.message}`,
3842
+ },
3843
+ ],
3844
+ isError: true,
3845
+ };
3846
+ }
3847
+ });
3848
+ }
3849
+
3850
+ async function npmGetExports(packageName) {
3851
+ const cacheKey = generateCacheKey('npm-get-exports', { packageName });
3852
+ return withCache(cacheKey, async () => {
3853
+ try {
3854
+ const result = await executeNpmCommand('view', [packageName, '--json'], {
3855
+ cache: true,
3856
+ });
3857
+ if (result.isError) {
3858
+ return result;
3859
+ }
3860
+ // Parse the result from the executed command
3861
+ const commandOutput = JSON.parse(result.content[0].text);
3862
+ // The result is a JSON string from npm that needs to be parsed again
3863
+ const npmData = JSON.parse(commandOutput.result);
3864
+ // Extract only exports data
3865
+ const exportsResult = {
3866
+ packageName: npmData.name,
3867
+ exports: npmData.exports || {},
3868
+ };
3869
+ return createSuccessResult$1(exportsResult);
3870
+ }
3871
+ catch (error) {
3872
+ return createErrorResult$1('Failed to get npm exports information', error);
3873
+ }
3874
+ });
3875
+ }
3876
+
3877
+ function registerNpmGetExportsTool(server) {
3878
+ server.tool(TOOL_NAMES.NPM_GET_EXPORTS, TOOL_DESCRIPTIONS[TOOL_NAMES.NPM_GET_EXPORTS], {
3879
+ packageName: z
3880
+ .string()
3881
+ .describe("The name of the npm package to get exports information for (e.g., 'react', 'express', 'lodash'). Returns import path intelligence: available modules, entry points, and tree-shakable exports for optimal code search - optimized for token efficiency."),
3882
+ }, {
3883
+ title: 'NPM Module Structure - Extract Package Export Mappings',
3884
+ readOnlyHint: true,
3885
+ destructiveHint: false,
3886
+ idempotentHint: true,
3887
+ openWorldHint: true,
3888
+ }, async (args) => {
3889
+ try {
3890
+ return await npmGetExports(args.packageName);
3891
+ }
3892
+ catch (error) {
3893
+ return {
3894
+ content: [
3895
+ {
3896
+ type: 'text',
3897
+ text: `Failed to get npm exports info: ${error.message}`,
3898
+ },
3899
+ ],
3900
+ isError: true,
3901
+ };
3902
+ }
3903
+ });
3904
+ }
3905
+
2877
3906
  function registerUsageGuideResource(server) {
2878
3907
  server.resource('usage-guide', 'help://usage', async (uri) => ({
2879
3908
  contents: [
@@ -3601,7 +4630,7 @@ function registerAllTools(server) {
3601
4630
  registerGitHubSearchCodeTool(server);
3602
4631
  registerFetchGitHubFileContentTool(server);
3603
4632
  registerViewRepositoryTool(server);
3604
- registerNpmViewTool(server);
4633
+ //Tools.registerNpmViewTool(server);
3605
4634
  registerSearchGitHubReposTool(server);
3606
4635
  registerSearchGitHubCommitsTool(server);
3607
4636
  registerSearchGitHubPullRequestsTool(server);
@@ -3609,12 +4638,22 @@ function registerAllTools(server) {
3609
4638
  registerNpmSearchTool(server);
3610
4639
  registerViewRepositoryStructureTool(server);
3611
4640
  registerSearchGitHubIssuesTool(server);
3612
- // TODO: add discussions tool after fixing API
3613
- //Tools.registerSearchGitHubDiscussionsTool(server);
3614
4641
  registerSearchGitHubTopicsTool(server);
3615
4642
  registerSearchGitHubUsersTool(server);
3616
- registerNpmPackageStatsTool(server);
4643
+ // Focused NPM tools for minimal token usage
3617
4644
  registerNpmDependencyAnalysisTool(server);
4645
+ registerNpmGetRepositoryTool(server);
4646
+ registerNpmGetDependenciesTool(server);
4647
+ registerNpmGetBugsTool(server);
4648
+ registerNpmGetReadmeTool(server);
4649
+ registerNpmGetVersionsTool(server);
4650
+ registerNpmGetAuthorTool(server);
4651
+ registerNpmGetLicenseTool(server);
4652
+ registerNpmGetHomepageTool(server);
4653
+ registerNpmGetIdTool(server);
4654
+ registerNpmGetReleasesTool(server);
4655
+ registerNpmGetEnginesTool(server);
4656
+ registerNpmGetExportsTool(server);
3618
4657
  }
3619
4658
  // Register all resources
3620
4659
  function registerResources(server) {