UNPKG

npmplus-mcp-server

Version:

Production-ready MCP server for intelligent JavaScript package management. Works with Claude, Windsurf, Cursor, VS Code, and any MCP-compatible AI editor.

68 lines (56 loc) 2.16 kB
import { cache, CacheManager } from "../cache.js"; import { httpClient } from "../http-client.js"; import { SearchPackagesSchema } from "../validators/index.js"; import { createSuccessResponse, createErrorResponse, truncateText } from "../utils/index.js"; // Export tools and handlers export const tools = [ { name: "search_packages", description: "Search for packages in the npm registry", inputSchema: SearchPackagesSchema } ]; export const handlers = new Map([ ["search_packages", handleSearchPackages] ]); async function handleSearchPackages(args: unknown) { const input = SearchPackagesSchema.parse(args); // Check cache first const cacheKey = CacheManager.keys.searchResults(input.query, input.limit); const cached = await cache.get<any>(cacheKey); if (cached) { return createSuccessResponse(formatSearchResults(cached, input.query)); } try { const searchResults = await httpClient.npmSearch(input.query, { size: input.limit, from: input.from }); // Cache for 5 minutes await cache.set(cacheKey, searchResults, 300); return createSuccessResponse(formatSearchResults(searchResults, input.query)); } catch (error: any) { return createErrorResponse(error, 'Failed to search packages'); } } function formatSearchResults(results: any, query: string): string { const output: string[] = [ `🔍 Search results for "${query}":\n` ]; if (!results.objects || results.objects.length === 0) { output.push("No packages found matching your query."); return output.join("\n"); } results.objects.slice(0, 10).forEach((item: any, index: number) => { const pkg = item.package; output.push(`${index + 1}. 📦 **${pkg.name}**`); output.push(` Version: ${pkg.version}`); output.push(` Description: ${truncateText(pkg.description || 'No description', 100)}`); output.push(` Downloads: ${pkg.links?.npm ? '📊 Available' : 'N/A'}`); output.push(""); }); if (results.total > results.objects.length) { output.push(`Showing ${results.objects.length} of ${results.total} results`); } return output.join("\n"); }