Skip to main content
Glama
kesslerio

Attio MCP Server

by kesslerio

filter-list-entries-by-parent-id

Filter CRM list entries to find all lists containing a specific company or person by their parent record ID, enabling targeted data retrieval from your Attio database.

Instructions

Filter CRM list entries by parent record ID (find all lists containing a specific company or person)

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
limitNoMaximum number of entries to fetch (default: 20)
listIdYesID of the list to filter entries from
offsetNoNumber of entries to skip for pagination (default: 0)
recordIdYesID of the parent record to filter by

Implementation Reference

  • The handler function for the 'filter-list-entries-by-parent-id' tool. It wraps the general filterListEntriesByParent helper with fixed parameters to match entries by exact parent record ID.
    export async function filterListEntriesByParentId(
      listId: string,
      recordId: string,
      limit: number = 20,
      offset: number = 0
    ): Promise<AttioListEntry[]> {
      return filterListEntriesByParent(
        listId,
        'record',
        'record_id',
        'equals',
        recordId,
        limit,
        offset
      );
    }
  • Core helper implementing path-based filtering via Attio API POST to /lists/{listId}/entries/query, constructing path and constraints from parent attributes. Called by the tool handler.
    export async function filterListEntriesByParent(
      listId: string,
      parentObjectType: string,
      parentAttributeSlug: string,
      condition: string,
      value: unknown,
      limit: number = 20,
      offset: number = 0
    ): Promise<AttioListEntry[]> {
      if (!listId || typeof listId !== 'string') {
        throw new Error('Invalid list ID: Must be a non-empty string');
      }
    
      if (!parentObjectType || typeof parentObjectType !== 'string') {
        throw new Error('Invalid parent object type: Must be a non-empty string');
      }
    
      if (!parentAttributeSlug || typeof parentAttributeSlug !== 'string') {
        throw new Error(
          'Invalid parent attribute slug: Must be a non-empty string'
        );
      }
    
      if (!condition || typeof condition !== 'string') {
        throw new Error('Invalid condition: Must be a non-empty string');
      }
    
      try {
        const api = getLazyAttioClient();
        const { path, constraints } = createPathBasedFilter(
          listId,
          parentObjectType,
          parentAttributeSlug,
          condition,
          value
        );
    
        const payload = {
          limit,
          offset,
          expand: ['record'],
          path,
          constraints,
        };
    
        if (process.env.NODE_ENV === 'development') {
          const log = createScopedLogger(
            'objects.lists',
            'filterListEntriesByParent'
          );
          log.info('Filtering with path-based filter', {
            listId,
            parentObjectType,
            parentAttributeSlug,
            condition,
            value,
            payload,
          });
        }
    
        const endpoint = `/lists/${listId}/entries/query`;
        const response = await api.post(endpoint, payload);
        const entries = processListEntries(response.data.data || []);
    
        if (process.env.NODE_ENV === 'development') {
          createScopedLogger('objects.lists', 'filterListEntriesByParent').info(
            'Matching entries found',
            { count: entries.length }
          );
        }
    
        return entries;
      } catch (error) {
        if (process.env.NODE_ENV === 'development') {
          const log = createScopedLogger(
            'objects.lists',
            'filterListEntriesByParent'
          );
          log.warn('Error filtering list entries', {
            message: error instanceof Error ? error.message : 'Unknown error',
            status: hasErrorResponse(error) ? error.response?.status : undefined,
            data: hasErrorResponse(error) ? error.response?.data || {} : undefined,
          });
        }
    
        if (hasErrorResponse(error) && error.response?.status === 400) {
          throw new Error(
            `Invalid filter parameters: ${
              error instanceof Error ? error.message : 'Bad request'
            }`
          );
        } else if (hasErrorResponse(error) && error.response?.status === 404) {
          throw new Error(`List ${listId} not found`);
        }
    
        throw error;
      }
    }
  • Registers the tool configuration, linking the name to the handler function and defining JSON result formatting.
    filterListEntriesByParentId: {
      name: 'filter-list-entries-by-parent-id',
      handler: filterListEntriesByParentId,
      formatResult: (results: AttioListEntry[]) => {
        // Return JSON string
        return JSON.stringify(Array.isArray(results) ? results : []);
      },
    } as ToolConfig,
  • Defines the tool's JSON Schema for input validation, including required listId and recordId UUIDs, optional pagination.
    {
      name: 'filter-list-entries-by-parent-id',
      description: formatToolDescription({
        capability: 'Filter entries by exact parent record UUID.',
        boundaries: 'search multiple lists.',
        constraints:
          'Requires list UUID, record UUID; faster than attribute filtering.',
        recoveryHint:
          'Use get-record-list-memberships for workspace-wide search.',
      }),
      inputSchema: {
        type: 'object',
        properties: {
          listId: {
            type: 'string',
            description: 'UUID of the list to filter entries from',
            example: '550e8400-e29b-41d4-a716-446655440000',
          },
          recordId: {
            type: 'string',
            description: 'UUID of the parent record to filter by',
            example: '660e8400-e29b-41d4-a716-446655440001',
          },
          limit: {
            type: 'number',
            description: 'Maximum number of entries to fetch (default: 20)',
            example: 50,
          },
          offset: {
            type: 'number',
            description: 'Number of entries to skip for pagination (default: 0)',
            example: 0,
          },
        },
        required: ['listId', 'recordId'],
        additionalProperties: false,
      },
    },

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/kesslerio/attio-mcp-server'

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