packageSearch
Find NPM and Python packages with their repository URLs to locate code sources and research dependencies from imports or configuration files.
Instructions
Find NPM/Python packages & their repository URLs
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| queries | Yes | Research queries for packageSearch (1-3 queries per call for optimal resource management). Review schema before use for optimal results |
Implementation Reference
- Core execution logic for packageSearch tool: processes bulk queries, calls searchPackage API, handles errors, enriches results with repo info and deprecation status, generates contextual hints.async function searchPackages( queries: PackageSearchQuery[] ): Promise<CallToolResult> { return executeBulkOperation( queries, async (query: PackageSearchQuery, _index: number) => { try { const apiResult = await searchPackage(query); if (isPackageSearchError(apiResult)) { return createErrorResult(apiResult.error, query); } const packages = (apiResult.packages as PackageResult[]).map(pkg => { const repoUrl = getPackageRepo(pkg); const { owner, repo } = parseRepoInfo(repoUrl); if (owner && repo) { return { ...pkg, owner, repo }; } return pkg; }); const result = { packages, totalFound: apiResult.totalFound, }; const hasContent = result.packages.length > 0; let deprecationInfo: DeprecationInfo | null = null; if (hasContent && query.ecosystem === 'npm' && result.packages[0]) { deprecationInfo = await checkNpmDeprecation( getPackageName(result.packages[0]) ); } // Generate context-specific hints for package search const extraHints = hasContent ? generateSuccessHints(result, query.ecosystem, deprecationInfo) : generateEmptyHints(query); // Use unified pattern with extraHints for package-specific guidance return createSuccessResult( query, result, hasContent, TOOL_NAMES.PACKAGE_SEARCH, { extraHints } ); } catch (error) { return handleCatchError(error, query); } }, { toolName: TOOL_NAMES.PACKAGE_SEARCH, keysPriority: ['packages', 'totalFound', 'error'], } ); }
- packages/octocode-mcp/src/tools/package_search.ts:27-73 (registration)Registers the 'packageSearch' tool (TOOL_NAMES.PACKAGE_SEARCH) with MCP server, including input schema, description, annotations, and security-wrapped handler.export async function registerPackageSearchTool( server: McpServer, callback?: ToolInvocationCallback ): Promise<RegisteredTool | null> { const npmAvailable = await checkNpmAvailability(10000); if (!npmAvailable) { return null; } return server.registerTool( TOOL_NAMES.PACKAGE_SEARCH, { description: DESCRIPTIONS[TOOL_NAMES.PACKAGE_SEARCH], // Type assertion needed: Zod discriminatedUnion types don't fully align with MCP SDK's expected schema type inputSchema: PackageSearchBulkQuerySchema as Parameters< typeof server.registerTool >[1]['inputSchema'], annotations: { title: 'Package Search', readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true, }, }, withSecurityValidation( TOOL_NAMES.PACKAGE_SEARCH, async ( args: { queries: PackageSearchQuery[]; }, _authInfo, _sessionId ): Promise<CallToolResult> => { const queries = args.queries || []; await invokeCallbackSafely( callback, TOOL_NAMES.PACKAGE_SEARCH, queries ); return searchPackages(queries); } ) ); }
- Zod input schema: discriminated union for npm/python package queries (name, searchLimit, ecosystem-specific options), plus bulk query schema used in registration.export const PackageSearchQuerySchema = z.discriminatedUnion('ecosystem', [ NpmPackageQuerySchema, PythonPackageQuerySchema, ]); export type NpmPackageQuery = z.infer<typeof NpmPackageQuerySchema>; export type PythonPackageQuery = z.infer<typeof PythonPackageQuerySchema>; export type PackageSearchQuery = NpmPackageQuery | PythonPackageQuery; export type PackageSearchBulkParams = { queries: PackageSearchQuery[]; }; export const PackageSearchBulkQuerySchema = createBulkQuerySchema( TOOL_NAMES.PACKAGE_SEARCH, PackageSearchQuerySchema );
- packages/octocode-mcp/src/tools/toolConfig.ts:81-88 (registration)ToolConfig entry that wires registerPackageSearchTool into the ALL_TOOLS array for automatic registration via toolsManager.export const PACKAGE_SEARCH: ToolConfig = { name: TOOL_NAMES.PACKAGE_SEARCH, description: getDescription(TOOL_NAMES.PACKAGE_SEARCH), isDefault: true, isLocal: false, type: 'search', fn: registerPackageSearchTool, };
- packages/octocode-mcp/src/tools/toolsManager.ts:41-73 (registration)Generic registration loop in registerTools() that invokes each tool's fn (including packageSearch via toolConfig), with filtering based on config.for (const tool of ALL_TOOLS) { // Step 1: Check if tool should be enabled if (!isToolEnabled(tool, localEnabled, filterConfig)) { continue; } // Step 2: Check if tool exists in metadata try { if (!isToolInMetadata(tool.name)) { await logSessionError( tool.name, TOOL_METADATA_ERRORS.INVALID_FORMAT.code ); continue; } } catch { await logSessionError( tool.name, TOOL_METADATA_ERRORS.INVALID_API_RESPONSE.code ); continue; } // Step 3: Register the tool try { const result = await tool.fn(server, callback); if (result !== null) { successCount++; } } catch { failedTools.push(tool.name); } }