Skip to main content
Glama
kesslerio

Attio MCP Server

by kesslerio

get-detailed-info

Read-onlyIdempotent

Retrieve comprehensive details for Attio CRM records including contacts, companies, lists, tasks, deals, and notes using specific record identifiers.

Instructions

Get specific types of detailed information (contact, business, social)

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
record_idYesUnique identifier of the record
resource_typeYesType of resource

Implementation Reference

  • Alias registration that maps the tool name 'get-detailed-info' to the canonical tool 'records_get_info'.
    'get-detailed-info': {
      target: 'records_get_info',
      reason: 'Phase 1 search tool rename (#776)',
      since: SINCE_PHASE_1,
      removal: 'v1.x (TBD)',
    },
  • Input schema definition for the records_get_info tool, specifying required resource_type and record_id.
    export const getDetailedInfoSchema = {
      type: 'object' as const,
      properties: {
        resource_type: {
          type: 'string' as const,
          enum: Object.values(UniversalResourceType),
          description: 'Type of resource',
        },
        record_id: {
          type: 'string' as const,
          description: 'Unique identifier of the record',
        },
      },
      required: ['resource_type' as const, 'record_id' as const],
      additionalProperties: false,
      examples: [
        {
          resource_type: 'companies',
          record_id: 'company_123456',
        },
      ],
    };
  • Handler configuration for 'records_get_info' tool (aliased from 'get-detailed-info'), including parameter validation and call to core retrieval logic.
    > = {
      name: 'records_get_info',
      handler: async (params: UniversalDetailedInfoParams) => {
        validateUniversalToolParams('records_get_info', params);
        return await handleUniversalGetDetailedInfo(params);
      },
      formatResult: (info: Record<string, unknown>, ...args: unknown[]): string => {
        const resourceType = args[0] as UniversalResourceType | undefined;
        const detailedInfoType = args[1] as string | undefined;
        if (!info) {
          return 'No detailed information found';
        }
    
        const resourceTypeName = resourceType
          ? getSingularResourceType(resourceType)
          : 'record';
    
        let infoTypeLabel = 'detailed';
        if (detailedInfoType) {
          switch (detailedInfoType) {
            case 'contact':
              infoTypeLabel = 'contact';
              break;
            case 'business':
              infoTypeLabel = 'business';
              break;
            case 'social':
              infoTypeLabel = 'social';
              break;
            default:
              infoTypeLabel = 'detailed';
          }
        }
    
        let result = `${resourceTypeName.charAt(0).toUpperCase() + resourceTypeName.slice(1)} ${infoTypeLabel} information:\n\n`;
    
        if (typeof info === 'object' && info.values) {
          Object.entries(info.values as Record<string, unknown>).forEach(
            ([field, values]: [string, unknown]) => {
              if (Array.isArray(values) && values.length > 0) {
                const value = (values[0] as { value: string }).value;
                if (value) {
                  const displayField =
                    field.charAt(0).toUpperCase() + field.slice(1);
                  result += `${displayField}: ${value}\n`;
                }
              }
            }
          );
        } else if (typeof info === 'object') {
          Object.entries(info).forEach(([key, value]: [string, unknown]) => {
            if (value && typeof value === 'string' && value.length < 200) {
              const displayKey = key.charAt(0).toUpperCase() + key.slice(1);
              result += `${displayKey}: ${value}\n`;
            }
          });
        } else {
          result += JSON.stringify(info, null, 2);
        }
    
        return result;
      },
    };
  • Core handler function that implements the tool logic by dispatching to resource-specific record retrieval functions based on resource_type.
    export async function handleUniversalGetDetailedInfo(
      params: UniversalDetailedInfoParams
    ): Promise<JsonObject> {
      const { resource_type, record_id } = params;
    
      // Return the full record for all resource types using standard endpoints
      switch (resource_type) {
        case UniversalResourceType.COMPANIES:
          return getObjectRecord('companies', record_id);
        case UniversalResourceType.PEOPLE:
          return getPersonDetails(record_id);
        case UniversalResourceType.LISTS: {
          const list = await getListDetails(record_id);
          // Convert AttioList to AttioRecord format with robust shape handling
          // Handle all documented Attio API list response shapes
          const raw = list;
          const listId =
            raw?.id?.list_id ?? // nested shape from some endpoints
            raw?.list_id ?? // flat shape from "Get a list" endpoint
            raw?.id ?? // some responses use a flat id
            record_id; // final fallback when caller already knows it
    
          return {
            id: {
              record_id: listId,
              list_id: listId,
            },
            values: {
              name: list.name || list.title,
              description: list.description,
              parent_object: list.object_slug || list.parent_object,
              api_slug: list.api_slug,
              workspace_id: list.workspace_id,
              workspace_member_access: list.workspace_member_access,
              created_at: list.created_at,
            },
          } as unknown as AttioRecord;
        }
        case UniversalResourceType.DEALS:
          return getObjectRecord('deals', record_id);
        case UniversalResourceType.TASKS:
          return getTask(record_id);
        case UniversalResourceType.RECORDS:
          return getObjectRecord('records', record_id);
        default:
          throw new Error(
            `Unsupported resource type for detailed info: ${resource_type}`
          );
      }
    }
  • Global tool registry that includes universalToolConfigs (containing records_get_info) under the UNIVERSAL category, enabling tool discovery and execution.
    export const TOOL_CONFIGS = USE_UNIVERSAL_TOOLS_ONLY
      ? {
          // Universal tools for consolidated operations (Issue #352)
          UNIVERSAL: universalToolConfigs,
          // Lists are relationship containers - always expose them (Issue #470)
          [ResourceType.LISTS]: listsToolConfigs,
          // Workspace members for user discovery (Issue #684)
          [ResourceType.WORKSPACE_MEMBERS]: workspaceMembersToolConfigs,
        }
Behavior3/5

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

Annotations already declare readOnlyHint=true and idempotentHint=true, indicating safe, repeatable read operations. The description adds no behavioral context beyond this, such as rate limits, authentication needs, or data format specifics. It doesn't contradict annotations, but offers minimal additional value.

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 a single, efficient sentence that directly states the tool's purpose without unnecessary words. It's appropriately front-loaded, though it could be slightly more structured to highlight key distinctions.

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

Completeness3/5

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

Given the annotations cover safety and idempotency, and the schema fully documents parameters, the description is minimally adequate. However, without an output schema, it doesn't explain return values or error handling, leaving gaps in completeness for a tool that fetches detailed data.

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 description coverage is 100%, fully documenting both parameters (record_id and resource_type with enum values). The description mentions 'specific types of detailed information' but doesn't add meaning beyond the schema's enum list or clarify how parameters interact, so it meets the baseline.

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

Purpose4/5

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

The description clearly states the verb 'Get' and specifies the types of detailed information (contact, business, social), making the purpose understandable. However, it doesn't explicitly distinguish this tool from similar siblings like 'get-record-details' or 'fetch', which limits its differentiation.

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

Usage Guidelines2/5

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

The description provides no guidance on when to use this tool versus alternatives. With many sibling tools like 'get-record-details' and 'fetch' that might overlap in functionality, the absence of explicit usage context or exclusions leaves the agent without clear direction.

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

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