UNPKG

mcp-package-version

Version:

An MCP server to provide LLMs the latest (stable) version of packages in package.json and requirements.txt files

89 lines (88 loc) 3.82 kB
import axios from 'axios'; import { McpError, ErrorCode } from '@modelcontextprotocol/sdk/types.js'; export class NpmHandler { registry = 'https://registry.npmjs.org'; async getPackageVersion(packageName, currentVersion, constraints) { // Check if package should be excluded if (constraints?.excludePackage) { return { name: packageName, currentVersion: currentVersion?.replace(/^[\^~]/, ''), latestVersion: currentVersion?.replace(/^[\^~]/, '') || 'unknown', registry: 'npm', skipped: true, skipReason: 'Package excluded from updates' }; } try { const response = await axios.get(`${this.registry}/${encodeURIComponent(packageName)}`); let latestVersion = response.data['dist-tags']?.latest; if (!latestVersion) { throw new Error('Latest version not found'); } // If major version constraint exists, find the latest version within that major if (constraints?.majorVersion !== undefined) { const versions = Object.keys(response.data.versions || {}); const constrainedVersions = versions.filter(v => { const major = parseInt(v.split('.')[0]); return major === constraints.majorVersion; }); if (constrainedVersions.length > 0) { // Sort versions and get the latest within the major version latestVersion = constrainedVersions.sort((a, b) => { const [aMajor, aMinor, aPatch] = a.split('.').map(Number); const [bMajor, bMinor, bPatch] = b.split('.').map(Number); if (aMajor !== bMajor) return bMajor - aMajor; if (aMinor !== bMinor) return bMinor - aMinor; return bPatch - aPatch; })[0]; } } const result = { name: packageName, latestVersion, registry: 'npm' }; if (currentVersion) { // Remove any leading ^ or ~ from the current version const cleanCurrentVersion = currentVersion.replace(/^[\^~]/, ''); result.currentVersion = cleanCurrentVersion; } if (constraints?.majorVersion !== undefined) { result.skipReason = `Limited to major version ${constraints.majorVersion}`; } return result; } catch (error) { console.error(`Error fetching npm package ${packageName}:`, error); throw new McpError(ErrorCode.InternalError, `Failed to fetch npm package ${packageName}`); } } async getLatestVersion(args) { if (!args.dependencies || typeof args.dependencies !== 'object') { throw new McpError(ErrorCode.InvalidParams, 'Invalid dependencies object'); } const results = []; for (const [name, version] of Object.entries(args.dependencies)) { if (typeof version !== 'string') continue; try { const result = await this.getPackageVersion(name, version, args.constraints?.[name]); results.push(result); } catch (error) { console.error(`Error checking npm package ${name}:`, error); } } return { content: [ { type: 'text', text: JSON.stringify(results, null, 2), }, ], }; } }