Skip to main content
Glama
lusha-oss

Lusha MCP Server

Official
by lusha-oss

companyBulkLookup

Perform bulk or single company lookups using name, domain, or ID to retrieve detailed company information from Lusha's API.

Instructions

Look up multiple or single companies information from Lusha API. REQUIREMENTS: Each company must provide at least one of: 1. Company name, 2. Company domain, 3. Fully qualified domain name (fqdn), or 4. Lusha companyId. Each company must have a unique 'id' field for identification in the response.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
companiesYes
metadataNo

Implementation Reference

  • Main handler function for the companyBulkLookup tool. Validates input, calls Lusha API POST /v2/company, and returns company data.
    export const companyBulkLookupHandler = async (params: CompanyBulkLookupParams): Promise<ToolResponse> => {
      const requestId = generateRequestId();
      
      const context: ErrorContext = {
        requestId,
        toolName: 'companyBulkLookup',
        operation: 'bulk_company_lookup',
        inputParams: { companyCount: params.companies?.length, metadata: params.metadata }
      };
    
      try {
        logger.info('Starting bulk company lookup request', { 
          requestId,
          toolName: 'companyBulkLookup',
          companyCount: params.companies?.length,
          inputParams: params 
        });
        
        const validatedParams = companyBulkLookupSchema.parse(params);
        logger.debug('Input validation passed', { requestId, toolName: 'companyBulkLookup' });
        
        const client = createLushaClient();
        context.apiEndpoint = '/v2/company';
        
        logger.debug('Making bulk company API request', { 
          requestId,
          toolName: 'companyBulkLookup',
          companyCount: validatedParams.companies.length,
          endpoint: context.apiEndpoint
        });
    
        const companiesForApi = validatedParams.companies.map(company => ({
          id: company.id,
          name: company.name,
          domain: company.domain,
          fqdn: company.fqdn,
          companyId: company.companyId
        }));
        
        const response = await client.post('/v2/company', {
          companies: companiesForApi
        });
        
        logger.info('Bulk company lookup completed successfully', { 
          requestId,
          toolName: 'companyBulkLookup',
          responseStatus: response.status,
          processedCompanies: Object.keys(response.data || {}).length
        });
        
        return {
          type: "success",
          data: {
            ...response.data,
            requestId,
            timestamp: new Date().toISOString()
          }
        };
        
      } catch (error) {
        logger.error('Bulk company lookup failed', { 
          error: (error as Error).message,
          stack: (error as Error).stack,
          requestId,
          toolName: 'companyBulkLookup'
        });
        return handleApiError(error, context);
      }
    }; 
  • Zod schema for companyBulkLookup: expects an array of 1-100 companies, each requiring at least one of name, domain, fqdn, or companyId, with optional metadata.filterBy.
    export const companyBulkLookupSchema = z.object({
      companies: z.array(z.object({
        id: z.string().min(1, "Company ID is required").describe("Unique ID for the company in the request"),
        name: z.string().optional().describe("Company name"),
        domain: z.string().optional().describe("Company domain"),
        fqdn: z.string().optional().describe("Fully qualified domain name of the company"),
        companyId: z.string().optional().describe("A unique identifier for a Lusha company")
      }).refine((company) => {
        const hasName = company.name && company.name.trim();
        const hasDomain = company.domain && company.domain.trim();
        const hasFqdn = company.fqdn && company.fqdn.trim();
        const hasCompanyId = company.companyId && company.companyId.trim();
    
        return hasName || hasDomain || hasFqdn || hasCompanyId;
      }, {
        message: "Each company must have at least one of: name, domain, fqdn, or companyId"
      }))
      .min(1, "Companies array cannot be empty")
      .max(100, "Companies array cannot exceed 100 items"),
      metadata: z.object({
        filterBy: z.string().optional()
      }).optional()
    });
  • TypeScript type derived from companyBulkLookupSchema for type safety.
    export type CompanyBulkLookupParams = z.infer<typeof companyBulkLookupSchema>;
  • Registration of companyBulkLookup tool with its name, description, schema, and handler.
    {
      name: "companyBulkLookup",
      description: `Look up multiple or single companies information from Lusha API.
          REQUIREMENTS: Each company must provide at least one of:
          1. Company name,
          2. Company domain,
          3. Fully qualified domain name (fqdn), or
          4. Lusha companyId.
          Each company must have a unique 'id' field for identification in the response.`,
      schema: companyBulkLookupSchema,
      handler: companyBulkLookupHandler
    },
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description implies a read-only operation ('look up') but does not disclose behavioral traits beyond input requirements. No annotations are provided, so the description carries the full burden, yet it omits details like rate limits, authentication, or response behavior when a company is not found.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is concise (two sentences plus bullet list) and front-loaded with the action. It efficiently states the purpose and requirements without unnecessary words. Minor improvement would be better formatting.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the complexity (nested objects, no output schema, no annotations), the description lacks completeness. It does not mention the max limit of 100 companies (though schema has maxItems), return format, error handling, or what happens if a lookup fails. The tool requires more context for an agent to use correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0%, so the description must compensate. It adds meaning by specifying that each company must have a unique id and at least one of the four identifiers, and mentions the metadata parameter exists (though not explained). However, it does not fully explain all parameters or the purpose of metadata.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states it looks up companies information from Lusha API, with a specific verb 'look up' and resource 'companies information'. It distinguishes from sibling tools like companySearch (search) and companyEnrich (enrich) by focusing on bulk lookup by known identifiers.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides explicit requirements for what each company must provide (name, domain, fqdn, or companyId) and a unique id field. Does not explicitly state when not to use or list alternatives, but the context of sibling tools implies use cases.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/lusha-oss/lusha-public-api-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server