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.
- package/build/index.js +1316 -277
- 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
|
-
|
|
30
|
-
|
|
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.
|
|
36
|
-
2. **
|
|
37
|
-
3. **
|
|
38
|
-
4. **
|
|
39
|
-
5. **
|
|
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.
|
|
46
|
-
|
|
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 →
|
|
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
|
|
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
|
-
**
|
|
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"}) →
|
|
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
|
|
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.
|
|
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
|
|
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}
|
|
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
|
-
**
|
|
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
|
-
**
|
|
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
|
-
**
|
|
285
|
-
|
|
388
|
+
**KNOWN LIMITATIONS:** Multi-term repository search breaks down (use NPM→Topics 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:**
|
|
410
|
+
**WHEN TO USE:** When users need to report issues or check known problems.
|
|
288
411
|
|
|
289
|
-
**
|
|
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
|
-
**
|
|
415
|
+
**MINIMAL OUTPUT:** Package name and readme filename - efficient documentation lookup.
|
|
292
416
|
|
|
293
|
-
**
|
|
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],
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
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(
|
|
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
|
-
|
|
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
|
-
|
|
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(
|
|
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
|
-
//
|
|
1200
|
-
const sortBy = params.sort || '
|
|
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
|
|
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 &&
|
|
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
|
|
1302
|
-
warnings.push('Stars filter must be
|
|
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
|
|
1342
|
-
.
|
|
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
|
|
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
|
|
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
|
|
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('
|
|
1387
|
-
.describe('Sort
|
|
1748
|
+
.default('best-match')
|
|
1749
|
+
.describe('Sort fetched repositories (default: best-match)'),
|
|
1388
1750
|
stars: z
|
|
1389
|
-
.
|
|
1751
|
+
.string()
|
|
1390
1752
|
.optional()
|
|
1391
|
-
.describe('Filter by stars count - TIP: Use >100 for established projects, >10 for active ones'),
|
|
1392
|
-
topic: z
|
|
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
|
|
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
|
-
|
|
1424
|
-
|
|
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:
|
|
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.
|
|
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
|
|
2295
|
-
.
|
|
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
|
|
2627
|
-
.
|
|
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
|
-
|
|
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) {
|