Skip to main content
Glama
definitions.ts12.7 kB
/** * Tool definitions for Attio MCP - edge-compatible * * These definitions follow the MCP Tool schema and can be used with any * MCP server implementation (stdio, HTTP, Cloudflare Workers, etc.) */ // Note: Commented out imports kept for documentation purposes // import type { ResourceType, ToolResult } from '../types/index.js'; /** * MCP Tool definition structure */ export interface ToolDefinition { name: string; description: string; inputSchema: { type: 'object'; properties: Record<string, unknown>; required?: string[]; additionalProperties?: boolean; }; annotations?: { readOnlyHint?: boolean; idempotentHint?: boolean; }; } /** * Standard resource type description for tool schemas. * * Supported resource types with automatic API routing: * - companies, people, deals, users, workspaces: /v2/objects/{slug}/records/query * - tasks: /v2/tasks (dedicated tasks API) * - workspace_members: /v2/workspace_members (dedicated members API) * * NOTE: 'notes' use create-note/list-notes tools (notes are attached to records, not searchable) */ const RESOURCE_TYPE_SCHEMA = { type: 'string', description: 'Type of Attio resource to query. Objects: companies, people, deals, users, workspaces. Also supports: tasks (list all tasks), workspace_members (list team members). Custom objects may also work.', enum: [ 'companies', 'people', 'deals', 'users', 'workspaces', 'tasks', 'workspace_members', ], }; /** * Standard pagination schema properties */ const PAGINATION_SCHEMA = { limit: { type: 'number', description: 'Maximum number of results to return', minimum: 1, maximum: 100, default: 10, }, offset: { type: 'number', description: 'Number of results to skip for pagination', minimum: 0, default: 0, }, }; /** * Format a tool description with capabilities, boundaries, constraints, and recovery hints */ function formatDescription(opts: { capability: string; boundaries: string; constraints: string; recoveryHint: string; }): string { return `${opts.capability} | Does not: ${opts.boundaries} | ${opts.constraints} | If errors occur: ${opts.recoveryHint}`; } /** * Health check tool - no authentication required */ export const healthCheckDefinition: ToolDefinition = { name: 'aaa-health-check', description: formatDescription({ capability: 'Run a lightweight health probe that echoes deployment metadata.', boundaries: 'query Attio APIs, mutate data, or require credentials.', constraints: 'Accepts optional echo text; returns JSON payload as text for MCP clients.', recoveryHint: 'If unavailable, review server logs or restart the server process.', }), inputSchema: { type: 'object', properties: { echo: { type: 'string', description: 'Optional text to echo back in the response', }, }, additionalProperties: true, }, annotations: { readOnlyHint: true, idempotentHint: true, }, }; /** * Search records tool */ export const searchRecordsDefinition: ToolDefinition = { name: 'records_search', description: formatDescription({ capability: 'Search across companies, people, deals, tasks, and lists', boundaries: 'create or modify records', constraints: 'Returns max 100 results (default: 10). ' + 'Filter operators: eq/equals, ne, gt, gte, lt, lte, contains, starts_with, ends_with. ' + 'Status fields (stage) only support "eq"; ' + 'actor-reference fields (owner) require actor IDs. ' + 'Use records_discover_attributes to check field types.', recoveryHint: 'use records_discover_attributes to find searchable fields and their types', }), annotations: { readOnlyHint: true, }, inputSchema: { type: 'object', properties: { resource_type: RESOURCE_TYPE_SCHEMA, query: { type: 'string', description: 'Search query string', }, filters: { type: 'object', description: 'Filter conditions for the search', properties: { filters: { type: 'array', items: { type: 'object', properties: { attribute: { type: 'object', properties: { slug: { type: 'string' } }, required: ['slug'], }, condition: { type: 'string' }, value: {}, }, required: ['attribute', 'condition'], }, }, matchAny: { type: 'boolean', description: 'Use OR logic between filters (default: AND)', }, }, }, ...PAGINATION_SCHEMA, }, required: ['resource_type'], }, }; /** * Get record details tool */ export const getRecordDetailsDefinition: ToolDefinition = { name: 'records_get_details', description: formatDescription({ capability: 'Fetch a single record with enriched attribute formatting', boundaries: 'search or filter result sets; use records_search instead', constraints: 'Requires resource_type and record_id; optional fields filter output', recoveryHint: 'Validate record IDs with records_search before retrying', }), inputSchema: { type: 'object', properties: { resource_type: RESOURCE_TYPE_SCHEMA, record_id: { type: 'string', description: 'Record ID to retrieve', }, fields: { type: 'array', items: { type: 'string' }, description: 'Fields to include in the response', }, }, required: ['resource_type', 'record_id'], }, annotations: { readOnlyHint: true, }, }; /** * Create record tool */ export const createRecordDefinition: ToolDefinition = { name: 'create-record', description: formatDescription({ capability: 'Create new Attio records (companies, people, deals, tasks)', boundaries: 'update existing records, attach files, or bypass required fields', constraints: 'Requires resource_type plus attributes map that matches records_discover_attributes output', recoveryHint: 'If validation fails, call records_discover_attributes to confirm required fields', }), inputSchema: { type: 'object', properties: { resource_type: RESOURCE_TYPE_SCHEMA, record_data: { type: 'object', description: 'Data to create the record with', additionalProperties: true, }, return_details: { type: 'boolean', description: 'Return full record details after creation', default: true, }, }, required: ['resource_type', 'record_data'], }, }; /** * Update record tool */ export const updateRecordDefinition: ToolDefinition = { name: 'update-record', description: formatDescription({ capability: 'Update existing Attio record fields across all supported resource types', boundaries: 'create new records, delete data, or manage list memberships', constraints: 'Requires record_id and attributes payload; supports partial updates', recoveryHint: 'Call records_get_details first to inspect the latest values before editing', }), inputSchema: { type: 'object', properties: { resource_type: RESOURCE_TYPE_SCHEMA, record_id: { type: 'string', description: 'Record ID to update', }, record_data: { type: 'object', description: 'Updated data for the record', additionalProperties: true, }, return_details: { type: 'boolean', description: 'Return full record details after update', default: true, }, }, required: ['resource_type', 'record_id', 'record_data'], }, }; /** * Delete record tool */ export const deleteRecordDefinition: ToolDefinition = { name: 'delete-record', description: formatDescription({ capability: 'Delete an Attio record from its object (company, person, deal, task)', boundaries: 'cascade delete related data or clean up list memberships automatically', constraints: 'Requires record_id and resource_type; operation is irreversible once confirmed', recoveryHint: 'If uncertain, fetch with records_get_details to confirm the target before deletion', }), inputSchema: { type: 'object', properties: { resource_type: RESOURCE_TYPE_SCHEMA, record_id: { type: 'string', description: 'Record ID to delete', }, }, required: ['resource_type', 'record_id'], }, }; /** * Discover attributes tool */ export const discoverAttributesDefinition: ToolDefinition = { name: 'records_discover_attributes', description: formatDescription({ capability: 'Discover available attributes (standard/custom) for a resource, including their types', boundaries: 'alter schema or create fields', constraints: 'Requires resource_type; optional categories selects subsets. Returns attribute types like text, select, actor-reference, record-reference, etc. Actor-reference fields (e.g., owner) require special filter handling.', recoveryHint: 'Use this tool first to understand attribute types before filtering', }), inputSchema: { type: 'object', properties: { resource_type: RESOURCE_TYPE_SCHEMA, categories: { type: 'array', items: { type: 'string' }, description: 'Attribute categories to filter by (e.g., standard, custom)', }, }, required: ['resource_type'], }, annotations: { readOnlyHint: true, }, }; /** * Create note tool */ export const createNoteDefinition: ToolDefinition = { name: 'create-note', description: formatDescription({ capability: 'Create note for companies, people, or deals with optional markdown formatting', boundaries: 'update or delete notes; creates only', constraints: 'Requires resource_type, record_id, title, content. Optional format (plaintext or markdown)', recoveryHint: 'If record not found, use records_search first', }), inputSchema: { type: 'object', properties: { resource_type: { type: 'string', enum: ['companies', 'people', 'deals'], description: 'Target resource type for the note', }, record_id: { type: 'string', description: 'ID of the record to attach the note to', }, title: { type: 'string', description: 'Title of the note', }, content: { type: 'string', description: 'Content of the note', }, format: { type: 'string', enum: ['plaintext', 'markdown'], description: 'Content format (default: plaintext)', default: 'plaintext', }, }, required: ['resource_type', 'record_id', 'title', 'content'], }, }; /** * List notes tool */ export const listNotesDefinition: ToolDefinition = { name: 'list-notes', description: formatDescription({ capability: 'Retrieve notes for a record with timestamps', boundaries: 'create or modify notes; read-only', constraints: 'Requires resource_type, record_id; sorted by creation date', recoveryHint: 'If empty, verify record has notes with records_get_details', }), inputSchema: { type: 'object', properties: { resource_type: { type: 'string', enum: ['companies', 'people', 'deals'], description: 'Type of resource to list notes for', }, record_id: { type: 'string', description: 'Record ID to list notes for', }, ...PAGINATION_SCHEMA, }, required: ['resource_type', 'record_id'], }, annotations: { readOnlyHint: true, }, }; /** * All core tool definitions */ export const coreToolDefinitions: Record<string, ToolDefinition> = { 'aaa-health-check': healthCheckDefinition, records_search: searchRecordsDefinition, records_get_details: getRecordDetailsDefinition, 'create-record': createRecordDefinition, 'update-record': updateRecordDefinition, 'delete-record': deleteRecordDefinition, records_discover_attributes: discoverAttributesDefinition, 'create-note': createNoteDefinition, 'list-notes': listNotesDefinition, }; /** * Get all tool definitions as an array (for MCP ListTools) */ export function getToolDefinitions(): ToolDefinition[] { return Object.values(coreToolDefinitions); } /** * Get a specific tool definition by name */ export function getToolDefinition(name: string): ToolDefinition | undefined { return coreToolDefinitions[name]; }

Implementation Reference

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