- 
                Notifications
    You must be signed in to change notification settings 
- Fork 0
feat: add bunx and pipx package version detection #3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
Add comprehensive support for bunx (Bun) and pipx (Python) package managers in MCP server version detection alongside existing npx/uvx support. Features: - Parse bunx commands (identical patterns to npx) - Parse pipx commands with --spec and --python flags - Query npm registry for JavaScript packages (npx/bunx) - Query PyPI registry for Python packages (pipx/uvx) - Extract versions directly from command strings when specified - Graceful fallback to "unknown" on network/parsing errors Testing: - 17 unit tests for command parsing (no external dependencies) - 10 integration tests with mocked API calls (CI-safe) - Separate test:integration command for local testing with real tools - All existing tests pass (202 total) CI Safety: - No external tool dependencies (npx/bunx/pipx/uvx not required) - Network requests mocked in tests for reliability - Main test command excludes integration directory - Version detection works purely through command parsing + HTTP APIs 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
| WalkthroughAdds package-version resolution for STDIO MCP servers by parsing invocation commands and querying npm or PyPI; integrates resolved version into MCP connect/verify. Introduces src/core/packageVersionUtils, updates mcpClient to use it, adds unit and integration tests, and splits test scripts with integration tests documented. Changes
 Sequence Diagram(s)sequenceDiagram
  autonumber
  participant Client
  participant MCP as MCP Client
  participant Utils as packageVersionUtils
  participant NPM as npm Registry
  participant PyPI as PyPI Registry
  participant Server as STDIO Server
  Client->>MCP: connectAndVerify(server)
  MCP->>Utils: parsePackageFromCommand(server.command, server.args)
  alt explicit version found
    Utils-->>MCP: PackageInfo {name, version}
  else no explicit version
    MCP->>Utils: getPackageVersion(server)
    alt npm-style manager
      Utils->>NPM: GET /-/package/<pkg>/dist-tags (with timeout)
      NPM-->>Utils: dist-tags.latest or error
    else python-style manager
      Utils->>PyPI: GET /pypi/<pkg>/json (with timeout)
      PyPI-->>Utils: info.version or error
    end
    Utils-->>MCP: resolved version or null
  end
  MCP->>MCP: set serverInfo.version (resolved or "unknown")
  MCP->>Server: Initialize / request capabilities
  Server-->>MCP: Capabilities / info
  MCP-->>Client: Verified connection (includes serverInfo.version)
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Poem
 Pre-merge checks and finishing touches✅ Passed checks (3 passed)
 ✨ Finishing touches
 🧪 Generate unit tests
 Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment  | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🧹 Nitpick comments (1)
src/core/mcpClient.ts (1)
33-91: Consider extracting regex patterns as constants for maintainability.The regex patterns are complex and repeated across multiple files. Consider extracting them as named constants to improve readability and maintainability.
+const PACKAGE_PATTERNS = { + NPX_VERSION: /npx\s+(?:-[ygc]\s+)?(?:--\S+\s+)*([^@\s]+)@([^\s]+)/, + NPX_SCOPED: /npx\s+(?:-[ygc]\s+)?(?:--\S+\s+)*(@[^/]+\/[^@\s]+)(?:@([^\s]+))?/, + NPX_BASIC: /npx\s+(?:-[ygc]\s+)?(?:--\S+\s+)*([^@\s]+)/, + BUNX_VERSION: /bunx\s+(?:-[ygc]\s+)?(?:--\S+\s+)*([^@\s]+)@([^\s]+)/, + BUNX_SCOPED: /bunx\s+(?:-[ygc]\s+)?(?:--\S+\s+)*(@[^/]+\/[^@\s]+)(?:@([^\s]+))?/, + BUNX_BASIC: /bunx\s+(?:-[ygc]\s+)?(?:--\S+\s+)*([^@\s]+)/, + PIPX_SPEC: /pipx\s+run\s+--spec\s+([^=\s]+)==([^\s]+)/, + PIPX_RUN: /pipx\s+run\s+(?:--python\s+[^\s]+\s+)?([^@\s]+)/, + UVX_BASIC: /uvx\s+(?:--from\s+[^\s]+\s+)?([^@\s]+)/ +}; function parsePackageFromCommand(command: string, args: string[] = []): PackageInfo | null { const fullCommand = [command, ...args].join(' '); // Pattern 1: npx package-name@version - const npxVersionMatch = fullCommand.match(/npx\s+(?:-[ygc]\s+)?(?:--\S+\s+)*([^@\s]+)@([^\s]+)/); + const npxVersionMatch = fullCommand.match(PACKAGE_PATTERNS.NPX_VERSION); // ... apply similar changes to other patterns
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (5)
- package.json(1 hunks)
- src/core/mcpClient.ts(2 hunks)
- tests/core/packageVersion.test.ts(1 hunks)
- tests/core/packageVersionIntegration.test.ts(1 hunks)
- tests/integration/README.md(1 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.{ts,tsx}: Write clean, maintainable code following TypeScript best practices
Use TypeScript for type safety when applicable
Follow consistent naming conventions
Add comments for complex logic
Maintain consistency with existing code style
Add appropriate error handling
Never expose sensitive information in code or logs
Follow security best practices for TypeScript
Validate all inputs
Use environment variables for configuration
Document all public APIs, functions, and classes with clear descriptions
Files:
- tests/core/packageVersion.test.ts
- tests/core/packageVersionIntegration.test.ts
- src/core/mcpClient.ts
**/*.{test,spec}.ts
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.{test,spec}.ts: Write unit tests for all business logic using Jest
Test edge cases and error scenarios
Update tests when modifying functionality
Files:
- tests/core/packageVersion.test.ts
- tests/core/packageVersionIntegration.test.ts
package.json
📄 CodeRabbit inference engine (CLAUDE.md)
Use npm for dependency management
Files:
- package.json
🧠 Learnings (4)
📚 Learning: 2025-09-24T11:44:03.031Z
Learnt from: CR
PR: agentinit/agentinit#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-24T11:44:03.031Z
Learning: Include integration tests for critical paths
Applied to files:
- tests/integration/README.md
📚 Learning: 2025-09-19T20:17:12.331Z
Learnt from: CR
PR: agentinit/agentinit#0
File: .cursorrules:0-0
Timestamp: 2025-09-19T20:17:12.331Z
Learning: Write both unit tests for individual components and integration tests
Applied to files:
- tests/integration/README.md
📚 Learning: 2025-09-24T11:44:03.031Z
Learnt from: CR
PR: agentinit/agentinit#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-24T11:44:03.031Z
Learning: Applies to **/*.{test,spec}.ts : Update tests when modifying functionality
Applied to files:
- tests/core/packageVersion.test.ts
- package.json
📚 Learning: 2025-09-24T11:44:03.031Z
Learnt from: CR
PR: agentinit/agentinit#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-24T11:44:03.031Z
Learning: Applies to **/*.{test,spec}.ts : Test edge cases and error scenarios
Applied to files:
- tests/core/packageVersion.test.ts
🧬 Code graph analysis (2)
tests/core/packageVersion.test.ts (1)
tests/core/packageVersionIntegration.test.ts (1)
parsePackageFromCommand(11-69)
src/core/mcpClient.ts (2)
tests/core/packageVersionIntegration.test.ts (5)
parsePackageFromCommand(11-69)
fetchPackageVersionFromNpm(71-93)
fetchPackageVersionFromPyPI(95-117)
isPythonPackageManager(119-122)
getPackageVersion(124-146)src/types/index.ts (1)
MCPServerConfig(80-88)
🔇 Additional comments (14)
tests/core/packageVersion.test.ts (2)
6-63: LGTM! Comprehensive pattern matching for package managers.The parsing logic correctly handles all the different package manager patterns including npx, bunx, pipx, and uvx with their various flag combinations and version specifications.
65-154: LGTM! Thorough test coverage for command parsing.Excellent test coverage including edge cases, scoped packages, version specifications, and different flag combinations across all supported package managers.
src/core/mcpClient.ts (4)
96-118: LGTM! Robust npm registry integration.The implementation includes proper timeout handling, error handling, and graceful fallback to null on failures.
123-145: LGTM! Clean PyPI registry integration.Good implementation with proper error handling and consistent structure with the npm version.
156-191: LGTM! Well-documented version resolution logic.The function has clear documentation explaining the resolution strategy and gracefully handles all edge cases. The comment explicitly notes that no external tools are required, which is important for CI compatibility.
414-419: LGTM! Clean integration into the MCP verification flow.The package version resolution is properly integrated into the server connection flow, replacing the hardcoded "unknown" value with the actual resolved version.
tests/core/packageVersionIntegration.test.ts (6)
149-157: LGTM! Proper test setup and teardown.Good practice using
beforeEachto clear mocks andafterEachto restore all mocks.
158-225: LGTM! Comprehensive npm registry integration tests.Excellent coverage of npm registry interactions including success cases, error handling, and proper URL construction verification.
227-290: LGTM! Thorough PyPI registry integration tests.Good coverage of PyPI interactions including both pipx and uvx commands, with proper error handling tests.
292-318: LGTM! Version extraction tests validate command parsing.Good tests confirming that versions specified in commands are used directly without API calls.
320-346: LGTM! Edge case handling for non-package commands.Properly tests that non-package manager commands and non-STDIO servers return "unknown" without making unnecessary API calls.
8-10: Consider using a more robust approach for testing internal functions.Similar to the unit tests, this creates another duplicate implementation of the parsing logic. This triples the maintenance burden.
package.json (1)
13-18: LGTM! Well-organized test script structure.The test scripts are properly organized to separate unit and integration tests, with sensible defaults that exclude integration tests from CI runs. This aligns well with the goal of keeping CI fast while allowing comprehensive local testing.
tests/integration/README.md (1)
1-30: LGTM! Clear documentation for test organization.The README clearly explains the rationale for separating integration tests and provides helpful commands for running different test suites. The categorization and goals are well-defined.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🧹 Nitpick comments (8)
src/core/mcpClient.ts (1)
247-253: Avoid blocking server verification on registry lookups; add abort-aware, short-circuit fallback.Fetching the package version here can add up to 5s latency and ignores the provided abortSignal. Prefer racing it with a short timeout and the abortSignal so verification isn't delayed by registry slowness.
Apply this diff to make version resolution non-blocking and abort-aware:
- // Get server info and fetch package version - const packageVersion = await getPackageVersion(server); + // Get server info and fetch package version with a short cap and abort awareness + const packageVersion = await Promise.race<string>([ + getPackageVersion(server), + new Promise<string>(resolve => setTimeout(() => resolve('unknown'), 1500)), + new Promise<string>(resolve => { + if (abortSignal?.aborted) return resolve('unknown'); + abortSignal?.addEventListener('abort', () => resolve('unknown'), { once: true }); + }), + ]);If you want fuller cancellation, consider extending getPackageVersion to accept an AbortSignal and propagate it downstream. As per coding guidelines.
tests/core/packageVersion.test.ts (1)
1-92: Solid unit coverage; add UVX flag variants.Great breadth across managers and scoped packages. Consider adding a UVX case with extra flags to guard future regex tweaks.
Apply this diff to extend coverage:
it('should parse uvx with --from flag', () => { const result = parsePackageFromCommand('uvx', ['--from', 'git+https://github.com/user/repo.git', 'package-name']); expect(result).toEqual({ name: 'package-name' }); }); + + it('should parse uvx with additional flags', () => { + const result = parsePackageFromCommand('uvx', ['-q', '--isolated', 'black']); + expect(result).toEqual({ name: 'black' }); + });Based on learnings
tests/core/packageVersionIntegration.test.ts (2)
1-8: Prefer stubbing globals via Vitest helpers.Direct assignment works but is brittle across environments. Use vi.stubGlobal/vi.unstubAllGlobals for safer setup/teardown.
Example:
const mockFetch = vi.fn(); beforeAll(() => { vi.stubGlobal('fetch', mockFetch); }); afterAll(() => { vi.unstubAllGlobals(); });Based on learnings
18-88: Nice npm-path coverage; add ‘latest’ deref case.You test direct versions and error paths. Add a case where the command specifies @latest to assert the registry is consulted.
Proposed test:
it('should dereference @latest via npm registry', async () => { mockFetch.mockResolvedValueOnce({ ok: true, json: async () => ({ 'dist-tags': { latest: '9.9.9' } }) }); const server = { name: 'x', type: MCPServerType.STDIO, command: 'npx', args: ['pkg@latest'] }; const version = await getPackageVersion(server); expect(version).toBe('9.9.9'); });src/core/packageVersionUtils.ts (4)
129-132: Stricter manager detection to avoid false positives.includes('uvx') could mis-route if 'uvx' appears in args. Check the first token instead.
Apply this diff:
-export function isPythonPackageManager(command: string, args: string[] = []): boolean { - const fullCommand = [command, ...args].join(' '); - return fullCommand.includes('pipx') || fullCommand.includes('uvx'); -} +export function isPythonPackageManager(command: string, _args: string[] = []): boolean { + const firstToken = String(command || '').trim().split(/\s+/)[0]; + return firstToken === 'pipx' || firstToken === 'uvx'; +}
63-67: UVX regex doesn’t handle additional flags.Support generic long/short flags (with or without values) before the package name.
Apply this diff:
- const uvxMatch = fullCommand.match(/uvx\s+(?:--from\s+[^\s]+\s+)?([^@\s]+)/); + const uvxMatch = fullCommand.match(/uvx\s+(?:--\S+(?:\s+[^\s]+)?\s+|-{1}\S+\s+)*([^@\s]+)/);This skips sequences like: uvx -q --isolated --from https://... package-name
12-70: Reduce regex duplication for npx/bunx patterns (optional).npx and bunx branches are identical. Consider a small helper to apply one set of patterns for a given manager to ease maintenance.
Sketch:
function matchJsManager(full: string, manager: 'npx'|'bunx'): PackageInfo | null { /* shared regex with variable */ }
158-169: Tag semantics: consider dereferencing non-semver tags (e.g., next, beta).Current logic returns non-'latest' tags verbatim. Optionally, detect non-semver tags and resolve via registry for a concrete version.
Example:
const isSemver = /^\d+\.\d+\.\d+(-[\w.-]+)?$/.test(packageInfo.version); if (packageInfo.version && isSemver) return packageInfo.version; // else fall through to registry lookup
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
- src/core/mcpClient.ts(2 hunks)
- src/core/packageVersionUtils.ts(1 hunks)
- tests/core/packageVersion.test.ts(1 hunks)
- tests/core/packageVersionIntegration.test.ts(1 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.{ts,tsx}: Write clean, maintainable code following TypeScript best practices
Use TypeScript for type safety when applicable
Follow consistent naming conventions
Add comments for complex logic
Maintain consistency with existing code style
Add appropriate error handling
Never expose sensitive information in code or logs
Follow security best practices for TypeScript
Validate all inputs
Use environment variables for configuration
Document all public APIs, functions, and classes with clear descriptions
Files:
- src/core/mcpClient.ts
- tests/core/packageVersion.test.ts
- src/core/packageVersionUtils.ts
- tests/core/packageVersionIntegration.test.ts
**/*.{test,spec}.ts
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.{test,spec}.ts: Write unit tests for all business logic using Jest
Test edge cases and error scenarios
Update tests when modifying functionality
Files:
- tests/core/packageVersion.test.ts
- tests/core/packageVersionIntegration.test.ts
🧠 Learnings (2)
📚 Learning: 2025-09-24T11:44:03.031Z
Learnt from: CR
PR: agentinit/agentinit#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-24T11:44:03.031Z
Learning: Applies to **/*.{test,spec}.ts : Update tests when modifying functionality
Applied to files:
- tests/core/packageVersion.test.ts
- tests/core/packageVersionIntegration.test.ts
📚 Learning: 2025-09-24T11:44:03.046Z
Learnt from: CR
PR: agentinit/agentinit#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-24T11:44:03.046Z
Learning: Applies to **/*.{test,spec}.ts : Test edge cases and error scenarios
Applied to files:
- tests/core/packageVersion.test.ts
🧬 Code graph analysis (4)
src/core/mcpClient.ts (1)
src/core/packageVersionUtils.ts (1)
getPackageVersion(148-170)
tests/core/packageVersion.test.ts (1)
src/core/packageVersionUtils.ts (1)
parsePackageFromCommand(12-70)
src/core/packageVersionUtils.ts (1)
src/types/index.ts (1)
MCPServerConfig(80-88)
tests/core/packageVersionIntegration.test.ts (1)
src/core/packageVersionUtils.ts (1)
getPackageVersion(148-170)
🔇 Additional comments (1)
src/core/mcpClient.ts (1)
9-12: Import looks good.Brings in the new utility cleanly with correct type import grouping.
- Fix timer cleanup in fetchPackageVersionFromNpm/PyPI using try/finally blocks - Add non-blocking version resolution with 1.5s timeout and abort awareness in mcpClient - Improve isPythonPackageManager detection to avoid false positives - Fix UVX regex to handle additional flags properly - Reduce code duplication by creating shared matchJsManager helper for npx/bunx - Add semver detection for better tag handling (resolve non-semver tags via registry) - Add comprehensive tests for all changes 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
- src/core/mcpClient.ts(2 hunks)
- src/core/packageVersionUtils.ts(1 hunks)
- tests/core/packageVersion.test.ts(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- src/core/mcpClient.ts
- tests/core/packageVersion.test.ts
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.{ts,tsx}: Write clean, maintainable code following TypeScript best practices
Use TypeScript for type safety when applicable
Follow consistent naming conventions
Add comments for complex logic
Maintain consistency with existing code style
Add appropriate error handling
Never expose sensitive information in code or logs
Follow security best practices for TypeScript
Validate all inputs
Use environment variables for configuration
Document all public APIs, functions, and classes with clear descriptions
Files:
- src/core/packageVersionUtils.ts
🧬 Code graph analysis (1)
src/core/packageVersionUtils.ts (1)
src/types/index.ts (1)
MCPServerConfig(80-88)
🪛 ast-grep (0.39.5)
src/core/packageVersionUtils.ts
[warning] 13-13: Regular expression constructed from variable input detected. This can lead to Regular Expression Denial of Service (ReDoS) attacks if the variable contains malicious patterns. Use libraries like 'recheck' to validate regex safety or use static patterns.
Context: new RegExp(${manager}\\s+(?:-[ygc]\\s+)?(?:--\\S+\\s+)*([^@\\s]+)@([^\\s]+))
Note: [CWE-1333] Inefficient Regular Expression Complexity [REFERENCES]
- https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS
- https://cwe.mitre.org/data/definitions/1333.html
(regexp-from-variable)
[warning] 19-19: Regular expression constructed from variable input detected. This can lead to Regular Expression Denial of Service (ReDoS) attacks if the variable contains malicious patterns. Use libraries like 'recheck' to validate regex safety or use static patterns.
Context: new RegExp(${manager}\\s+(?:-[ygc]\\s+)?(?:--\\S+\\s+)*(@[^/]+\\/[^@\\s]+)(?:@([^\\s]+))?)
Note: [CWE-1333] Inefficient Regular Expression Complexity [REFERENCES]
- https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS
- https://cwe.mitre.org/data/definitions/1333.html
(regexp-from-variable)
[warning] 25-25: Regular expression constructed from variable input detected. This can lead to Regular Expression Denial of Service (ReDoS) attacks if the variable contains malicious patterns. Use libraries like 'recheck' to validate regex safety or use static patterns.
Context: new RegExp(${manager}\\s+(?:-[ygc]\\s+)?(?:--\\S+\\s+)*([^@\\s]+))
Note: [CWE-1333] Inefficient Regular Expression Complexity [REFERENCES]
- https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS
- https://cwe.mitre.org/data/definitions/1333.html
(regexp-from-variable)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (6)
tests/core/packageVersionIntegration.test.ts (2)
1-1: Stabilize fetch mocking: type-safe assignment and restore original fetchAvoid leaking the mocked fetch across files and fix TS typing by assigning/restoring in hooks.
Apply this diff:
-import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'; +import { describe, it, expect, vi, beforeEach, afterEach, beforeAll, afterAll } from 'vitest'; @@ -// Mock fetch globally -const mockFetch = vi.fn(); -global.fetch = mockFetch; +// Mock fetch globally +const mockFetch = vi.fn() as unknown as typeof fetch; +let originalFetch: typeof global.fetch; + +beforeAll(() => { + originalFetch = global.fetch; +}); @@ afterEach(() => { vi.restoreAllMocks(); }); + +afterAll(() => { + // Restore original fetch to avoid leaking mocks to other test files + global.fetch = originalFetch; +});And ensure we set the mock per test run (so we don’t rely on file-load timing):
beforeEach(() => { - mockFetch.mockClear(); + mockFetch.mockClear(); + global.fetch = mockFetch; });As per coding guidelines
Also applies to: 5-8, 14-16
261-273: Add a scoped package test for npx -p to verify encodingWe currently don’t cover scoped packages for the npm registry path. Add a case like @scope/cli to ensure encodeURIComponent handling is correct.
Example test to add after this block:
it('should handle scoped packages with npx -p without API calls', async () => { const server = { name: 'test-server', type: MCPServerType.STDIO, command: 'npx', args: ['-p', '@scope/[email protected]', 'cli', '--help'] }; const version = await getPackageVersion(server); expect(mockFetch).not.toHaveBeenCalled(); expect(version).toBe('2.1.0'); });src/core/packageVersionUtils.ts (4)
90-115: Broaden timeout type for Node/browser parityUse ReturnType instead of NodeJS.Timeout to keep types portable across environments.
Apply this diff in both functions:
-export async function fetchPackageVersionFromNpm(packageName: string, timeoutMs = 5000): Promise<string | null> { - let timeoutId: NodeJS.Timeout | undefined; +export async function fetchPackageVersionFromNpm(packageName: string, timeoutMs = 5000): Promise<string | null> { + let timeoutId: ReturnType<typeof setTimeout> | undefined; @@ export async function fetchPackageVersionFromPyPI(packageName: string, timeoutMs = 5000): Promise<string | null> { - let timeoutId: NodeJS.Timeout | undefined; + let timeoutId: ReturnType<typeof setTimeout> | undefined;As per coding guidelines
Also applies to: 120-145
150-153: Detect Python managers from args too (env wrappers, absolute paths)When command is an interpreter or env shim, we may still have pipx/uvx in args. Check both for robustness.
Apply this diff:
-export function isPythonPackageManager(command: string, _args: string[] = []): boolean { - const firstToken = String(command || '').trim().split(/\s+/)[0]; - return firstToken === 'pipx' || firstToken === 'uvx'; -} +export function isPythonPackageManager(command: string, args: string[] = []): boolean { + const tokens = [String(command || '').trim(), ...(args ?? [])].filter(Boolean); + // Match exact tokens only to avoid false positives on similarly named binaries + return tokens.some(t => t === 'pipx' || t === 'uvx'); +}
169-207: Prefer cached lookups for “latest” registry queriesRepeated same-package lookups can be memoized to reduce latency and registry load. Cache only when we perform a registry fetch (i.e., when no version is specified or it’s a dist tag).
Apply this diff around the fetch call:
- const usePyPI = isPythonPackageManager(server.command, server.args); - const latestVersion = usePyPI - ? await fetchPackageVersionFromPyPI(packageInfo.name) - : await fetchPackageVersionFromNpm(packageInfo.name); - - return latestVersion || "unknown"; + const usePyPI = isPythonPackageManager(server.command, server.args); + const cacheKey = `${usePyPI ? 'pypi' : 'npm'}:${packageInfo.name}`; + const cached = versionCache.get(cacheKey); + if (cached) return cached; + + const latestVersion = usePyPI + ? await fetchPackageVersionFromPyPI(packageInfo.name) + : await fetchPackageVersionFromNpm(packageInfo.name); + + if (latestVersion) { + versionCache.set(cacheKey, latestVersion); + return latestVersion; + } + return "unknown";Add this at module scope:
const versionCache = new Map<string, string>();Note: For long-running processes, consider a small TTL or size cap if package churn is expected.
27-41: Dynamic RegExp is safe here but consider literals for clarityThe interpolated manager is a closed union ('npx' | 'bunx'), so ReDoS risk is negligible. If you want to quiet scanners and improve readability, duplicate the patterns as regex literals for each manager or prebuild them once.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
- src/core/packageVersionUtils.ts(1 hunks)
- tests/core/packageVersion.test.ts(1 hunks)
- tests/core/packageVersionIntegration.test.ts(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- tests/core/packageVersion.test.ts
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.{ts,tsx}: Write clean, maintainable code following TypeScript best practices
Use TypeScript for type safety when applicable
Follow consistent naming conventions
Add comments for complex logic
Maintain consistency with existing code style
Add appropriate error handling
Never expose sensitive information in code or logs
Follow security best practices for TypeScript
Validate all inputs
Use environment variables for configuration
Document all public APIs, functions, and classes with clear descriptions
Files:
- src/core/packageVersionUtils.ts
- tests/core/packageVersionIntegration.test.ts
**/*.{test,spec}.ts
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.{test,spec}.ts: Write unit tests for all business logic using Jest
Test edge cases and error scenarios
Update tests when modifying functionality
Files:
- tests/core/packageVersionIntegration.test.ts
🧠 Learnings (1)
📚 Learning: 2025-09-24T11:44:03.046Z
Learnt from: CR
PR: agentinit/agentinit#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-24T11:44:03.046Z
Learning: Applies to **/*.{test,spec}.ts : Update tests when modifying functionality
Applied to files:
- tests/core/packageVersionIntegration.test.ts
🧬 Code graph analysis (2)
src/core/packageVersionUtils.ts (1)
src/types/index.ts (1)
MCPServerConfig(80-88)
tests/core/packageVersionIntegration.test.ts (1)
src/core/packageVersionUtils.ts (1)
getPackageVersion(169-207)
🪛 ast-grep (0.39.5)
src/core/packageVersionUtils.ts
[warning] 13-13: Regular expression constructed from variable input detected. This can lead to Regular Expression Denial of Service (ReDoS) attacks if the variable contains malicious patterns. Use libraries like 'recheck' to validate regex safety or use static patterns.
Context: new RegExp(${manager}\\s+(?:-[ygc]\\s+)?(?:--\\S+\\s+)*-p\\s+([^\\s]+))
Note: [CWE-1333] Inefficient Regular Expression Complexity [REFERENCES]
- https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS
- https://cwe.mitre.org/data/definitions/1333.html
(regexp-from-variable)
[warning] 27-27: Regular expression constructed from variable input detected. This can lead to Regular Expression Denial of Service (ReDoS) attacks if the variable contains malicious patterns. Use libraries like 'recheck' to validate regex safety or use static patterns.
Context: new RegExp(${manager}\\s+(?:-[ygc]\\s+)?(?:--\\S+\\s+)*([^@\\s]+)@([^\\s]+))
Note: [CWE-1333] Inefficient Regular Expression Complexity [REFERENCES]
- https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS
- https://cwe.mitre.org/data/definitions/1333.html
(regexp-from-variable)
[warning] 33-33: Regular expression constructed from variable input detected. This can lead to Regular Expression Denial of Service (ReDoS) attacks if the variable contains malicious patterns. Use libraries like 'recheck' to validate regex safety or use static patterns.
Context: new RegExp(${manager}\\s+(?:-[ygc]\\s+)?(?:--\\S+\\s+)*(@[^/]+\\/[^@\\s]+)(?:@([^\\s]+))?)
Note: [CWE-1333] Inefficient Regular Expression Complexity [REFERENCES]
- https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS
- https://cwe.mitre.org/data/definitions/1333.html
(regexp-from-variable)
[warning] 39-39: Regular expression constructed from variable input detected. This can lead to Regular Expression Denial of Service (ReDoS) attacks if the variable contains malicious patterns. Use libraries like 'recheck' to validate regex safety or use static patterns.
Context: new RegExp(${manager}\\s+(?:-[ygc]\\s+)?(?:--\\S+\\s+)*([^@\\s]+))
Note: [CWE-1333] Inefficient Regular Expression Complexity [REFERENCES]
- https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS
- https://cwe.mitre.org/data/definitions/1333.html
(regexp-from-variable)
🔇 Additional comments (3)
tests/core/packageVersionIntegration.test.ts (1)
289-301: Good coverage for pipx global flags with --pythonThis validates the relaxed regex for pipx global flags. Looks solid.
src/core/packageVersionUtils.ts (2)
12-45: JS manager parsing covers -p and scoped/inline specs wellThe preinstall -p pattern and scoped package handling close the gap for npx/bunx flows. Nice.
67-75: pipx regex now tolerates global flags before run — addressed prior reviewThe relaxed patterns handle --python and other globals correctly. This resolves the earlier match failure.
Also applies to: 79-82
Add comprehensive support for bunx (Bun) and pipx (Python) package managers in MCP server version detection alongside existing npx/uvx support.
Features:
Testing:
CI Safety:
🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
Tests
Documentation
Chores