search_packages
Search npm registry for packages by keyword to find relevant dependencies and tools for your project.
Instructions
Search npm registry for packages by keyword
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| query | Yes | ||
| limit | No |
Implementation Reference
- src/index.ts:289-356 (handler)The handler function for the 'search_packages' tool. It takes a query and optional limit, fetches search results from the npm registry API, validates the response using PackageSearchSchema, formats a text summary of the results, and returns both text content and structured output.async ({ query, limit = 20 }) => { try { const encodedQuery = encodeURIComponent(query); const response = await fetch( `https://registry.npmjs.org/-/v1/search?text=${encodedQuery}&size=${limit}` ); if (!response.ok) { throw new Error(`Failed to search packages: ${response.statusText}`); } const rawData = await response.json(); const parseResult = PackageSearchSchema.safeParse(rawData); if (!parseResult.success) { throw new Error( `Invalid search results structure: ${parseResult.error.message}` ); } const data = parseResult.data; const packages = data.objects.map((obj) => obj.package); const formattedResults = packages .map( (pkg) => `Name: ${pkg.name}\nVersion: ${pkg.version}\nDescription: ${ pkg.description || "N/A" }\n${pkg.author ? `Author: ${pkg.author.name || "N/A"}\n` : ""}${ pkg.links?.npm ? `NPM: ${pkg.links.npm}\n` : "" }---` ) .join("\n\n"); const output = { total: data.total, results: packages.map((pkg) => ({ name: pkg.name, version: pkg.version, description: pkg.description, author: pkg.author?.name, npmUrl: pkg.links?.npm, })), }; return { content: [ { type: "text", text: `Found ${data.total} packages (showing ${packages.length}):\n\n${formattedResults}`, }, ], structuredContent: output, }; } catch (error) { return { content: [ { type: "text", text: `Error searching packages: ${ error instanceof Error ? error.message : "Unknown error" }`, }, ], isError: true, }; } }
- src/index.ts:21-46 (schema)Zod schema for validating the npm package search response from the registry API, used in the search_packages handler.const PackageSearchSchema = z.object({ objects: z.array( z.object({ package: z.object({ name: z.string(), version: z.string(), description: z.string().optional(), keywords: z.array(z.string()).optional(), author: z .object({ name: z.string().optional(), email: z.string().optional(), }) .optional(), links: z .object({ npm: z.string().optional(), homepage: z.string().optional(), repository: z.string().optional(), }) .optional(), }), }) ), total: z.number(), });
- src/index.ts:267-357 (registration)Registers the 'search_packages' tool with McpServer, defining title, description, input and output schemas, and references the handler function.server.registerTool( "search_packages", { title: "Search npm Packages", description: "Search npm registry for packages by keyword", inputSchema: { query: z.string(), limit: z.number().optional(), }, outputSchema: { total: z.number(), results: z.array( z.object({ name: z.string(), version: z.string(), description: z.string().optional(), author: z.string().optional(), npmUrl: z.string().optional(), }) ), }, }, async ({ query, limit = 20 }) => { try { const encodedQuery = encodeURIComponent(query); const response = await fetch( `https://registry.npmjs.org/-/v1/search?text=${encodedQuery}&size=${limit}` ); if (!response.ok) { throw new Error(`Failed to search packages: ${response.statusText}`); } const rawData = await response.json(); const parseResult = PackageSearchSchema.safeParse(rawData); if (!parseResult.success) { throw new Error( `Invalid search results structure: ${parseResult.error.message}` ); } const data = parseResult.data; const packages = data.objects.map((obj) => obj.package); const formattedResults = packages .map( (pkg) => `Name: ${pkg.name}\nVersion: ${pkg.version}\nDescription: ${ pkg.description || "N/A" }\n${pkg.author ? `Author: ${pkg.author.name || "N/A"}\n` : ""}${ pkg.links?.npm ? `NPM: ${pkg.links.npm}\n` : "" }---` ) .join("\n\n"); const output = { total: data.total, results: packages.map((pkg) => ({ name: pkg.name, version: pkg.version, description: pkg.description, author: pkg.author?.name, npmUrl: pkg.links?.npm, })), }; return { content: [ { type: "text", text: `Found ${data.total} packages (showing ${packages.length}):\n\n${formattedResults}`, }, ], structuredContent: output, }; } catch (error) { return { content: [ { type: "text", text: `Error searching packages: ${ error instanceof Error ? error.message : "Unknown error" }`, }, ], isError: true, }; } } );
- src/index.ts:270-287 (schema)Input and output schemas defined for the search_packages tool registration, specifying parameters like query and limit, and expected response structure.title: "Search npm Packages", description: "Search npm registry for packages by keyword", inputSchema: { query: z.string(), limit: z.number().optional(), }, outputSchema: { total: z.number(), results: z.array( z.object({ name: z.string(), version: z.string(), description: z.string().optional(), author: z.string().optional(), npmUrl: z.string().optional(), }) ), },