/**
* Tool: update_company
* Update an existing company in Attio CRM
*/
import type { Tool, CallToolResult } from '@modelcontextprotocol/sdk/types.js';
import { createAttioClient } from '../attio-client.js';
import {
handleToolError,
createSuccessResponse,
} from '../utils/error-handler.js';
import { ConfigurationError, ValidationError } from '../utils/errors.js';
interface AttioCompanyUpdateResponse {
data: {
id: {
workspace_id: string;
object_id: string;
record_id: string;
};
created_at: string;
web_url: string;
values: {
name?: Array<{ value: string }>;
domains?: Array<{ domain: string; root_domain: string }>;
description?: Array<{ value: string }>;
linkedin?: Array<{ value: string }>;
[key: string]: unknown;
};
};
}
/**
* Tool definition for MCP
*/
export const updateCompanyTool: Tool = {
name: 'update_company',
description:
'Update an existing company in Attio CRM by record ID. You can update name, description, and/or LinkedIn URL. Only provided fields will be updated; omitted fields remain unchanged. To manage domains, use add_company_domain and remove_company_domain tools instead. Returns the updated company record.',
inputSchema: {
type: 'object',
properties: {
record_id: {
type: 'string',
description:
'The unique record ID of the company to update (e.g., from search_companies or get_company)',
},
name: {
type: 'string',
description: 'Updated company name',
},
description: {
type: 'string',
description: 'Updated company description or notes',
},
linkedin: {
type: 'string',
description:
'Updated LinkedIn URL (e.g., "https://linkedin.com/company/example")',
},
},
required: ['record_id'],
},
};
/**
* Handler function for update_company tool
*/
export async function handleUpdateCompany(args: {
record_id: string;
name?: string;
description?: string;
linkedin?: string;
}): Promise<CallToolResult> {
try {
const apiKey = process.env['ATTIO_API_KEY'];
if (!apiKey) {
throw new ConfigurationError('ATTIO_API_KEY not configured');
}
const { record_id, name, description, linkedin } = args;
// Validate required fields
if (!record_id || record_id.trim().length === 0) {
throw new ValidationError(
'record_id parameter is required and cannot be empty',
'record_id'
);
}
// Check that at least one field is being updated
if (!name && !description && !linkedin) {
throw new ValidationError(
'At least one field must be provided to update (name, description, or linkedin). To manage domains, use add_company_domain and remove_company_domain tools.'
);
}
const client = createAttioClient(apiKey);
// Build request body with only provided fields
const values: Record<string, unknown[]> = {};
if (name && name.trim().length > 0) {
values['name'] = [{ value: name.trim() }];
}
if (description !== undefined) {
// Allow empty string to clear description
if (description.trim().length > 0) {
values['description'] = [{ value: description.trim() }];
} else {
values['description'] = [];
}
}
if (linkedin !== undefined) {
// Allow empty string to clear linkedin
if (linkedin.trim().length > 0) {
values['linkedin'] = [{ value: linkedin.trim() }];
} else {
values['linkedin'] = [];
}
}
// Update company via Attio API
// Use PUT to replace fields (PATCH would add to arrays instead of replacing)
const response = await client.put<AttioCompanyUpdateResponse>(
`/objects/companies/records/${record_id}`,
{
data: {
values,
},
}
);
const company = response.data;
// Transform to clean format
const result = {
record_id: company.id.record_id,
workspace_id: company.id.workspace_id,
object_id: company.id.object_id,
created_at: company.created_at,
web_url: company.web_url,
name: company.values.name?.[0]?.value || null,
domains:
company.values.domains?.map((d) => d.domain).filter(Boolean) || [],
description: company.values.description?.[0]?.value || null,
linkedin: company.values.linkedin?.[0]?.value || null,
};
return createSuccessResponse(result);
} catch (error) {
return handleToolError(error, 'update_company');
}
}