create-note
Create and attach notes to records in Attio CRM for companies, people, deals, tasks, and other resource types to document important information and updates.
Instructions
Create a note for any record type (companies, people, deals)
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| content | Yes | Content of the note | |
| record_id | Yes | ID of the record to attach the note to | |
| resource_type | Yes | Target resource type | |
| title | Yes | Title of the note |
Implementation Reference
- The core handler function that executes the create-note tool by posting to Attio's /v2/notes API endpoint.export async function handleCreateNote( client: HttpClient, params: { resource_type: 'companies' | 'people' | 'deals'; record_id: string; title: string; content: string; format?: 'plaintext' | 'markdown'; } ): Promise<ToolResult> { try { const { resource_type, record_id, title, content, format = 'plaintext', } = params; const response = await client.post<AttioApiResponse<AttioNote>>( '/v2/notes', { data: { parent_object: resource_type, parent_record_id: record_id, title, format, content, // API expects 'content', not 'content_plaintext' }, } ); const note = response.data.data; const noteId = note.id?.note_id || 'unknown'; return structuredResult( note, `Created note "${title}" (ID: ${noteId}) on ${resource_type} ${record_id}` ); } catch (error) { const { message, details } = extractErrorInfo(error); return errorResult(message || 'Failed to create note', details); } }
- The tool definition object containing the name, description, input schema, and annotations for create-note.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'], }, };
- packages/core/src/tools/handlers.ts:1032-1036 (registration)Registration of the create-note handler in the tool dispatch map within getToolHandler function.'create-note': async (client, params) => handleCreateNote( client, params as Parameters<typeof handleCreateNote>[1] ),
- src/handlers/tool-configs/universal/core/index.ts:35-35 (registration)MCP server registration of the create-note tool config in the core operations tool configs export.'create-note': createNoteConfig,
- MCP-specific wrapper handler config for create-note, including validation, error handling, and result formatting.export const createNoteConfig: UniversalToolConfig< Record<string, unknown>, Record<string, unknown> > = { name: 'create-note', handler: async ( params: Record<string, unknown> ): Promise<Record<string, unknown>> => { try { const sanitizedParams = validateUniversalToolParams( 'create-note', params ) as UniversalCreateNoteParams; if (!isValidUUID(sanitizedParams.record_id)) { throw new Error( `Invalid record_id: must be a UUID. Got: ${sanitizedParams.record_id}` ); } const result = await handleUniversalCreateNote(sanitizedParams); const { success, error } = result as Record<string, unknown> & { success?: boolean; error?: unknown; }; if (success === false) { throw new Error( typeof error === 'string' && error.length ? error : 'Universal note creation failed' ); } return result; } catch (err: unknown) { throw ErrorService.createUniversalError('create-note', 'notes', err); } }, formatResult: (note: Record<string, unknown>): string => { try { if (!note) { return 'No note created'; } const { title, content, id } = extractNoteFields(note); return `✅ Note created successfully: ${title} (ID: ${id})${ content ? `\n${content}` : '' }`; } catch (error) { const err = error instanceof Error ? error : new Error(String(error)); const fallback = createErrorResult( err, 'create-note#format', 'FORMAT' ) as McpErrorPayload; const message = fallback.content?.[0]?.text; return typeof message === 'string' ? message : 'Error formatting note result'; } }, structuredOutput: ( note: Record<string, unknown> ): Record<string, unknown> => { if (!note) return {}; // Normalize content fields to top-level, but preserve original id object const { title, content } = extractNoteFields(note); return { ...note, // Keep original id (object) - don't replace with extracted string title: title || note.title, content: content || note.content || note.content_markdown || note.content_plaintext, }; }, };