workflow_contact_to_textedit
Extract contact details from macOS Contacts and generate a formatted TextEdit document with the information for easy reference or sharing.
Instructions
Get contact information and create formatted TextEdit document
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | Person name to look up | |
| title | No | Document title (optional) |
Implementation Reference
- src/index.ts:1821-1929 (handler)Handler implementation that fetches contact details from macOS Contacts app via AppleScript, formats them into a document, and creates a new TextEdit document with the information.case 'workflow_contact_to_textedit': try { const personName = (args?.name as string) || ''; const docTitle = (args?.title as string) || `Contact: ${personName}`; if (!personName) { return { content: [ { type: 'text', text: 'Error: name is required', }, ], }; } // Step 1: Get contact information const contactCommand = `osascript -e 'on run argv set personNameToFind to item 1 of argv tell application "Contacts" set thePerson to first person whose name is personNameToFind set emailList to {} repeat with anEmail in emails of thePerson set end of emailList to (value of anEmail & " (" & label of anEmail & ")") end repeat set phoneList to {} repeat with aPhone in phones of thePerson set end of phoneList to (value of aPhone & " (" & label of aPhone & ")") end repeat return "Name: " & name of thePerson & "\\nCompany: " & organization of thePerson & "\\nJob Title: " & job title of thePerson & "\\nEmails:\\n" & (emailList as string) & "\\nPhones:\\n" & (phoneList as string) end tell end run' -- "${personName}"`; const { stdout: contactInfo, stderr: contactError } = await execAsync(contactCommand); if (contactError.trim()) { return { content: [ { type: 'text', text: `Error getting contact info: ${contactError.trim()}`, }, ], }; } if (!contactInfo.trim()) { return { content: [ { type: 'text', text: `No contact found with name "${personName}"`, }, ], }; } // Step 2: Format data for document const formattedContent = `${docTitle} ================== ${contactInfo.trim()} Generated: ${new Date().toLocaleString()}`; // Step 3: Create TextEdit document const docCommand = `osascript -e 'on run argv set docContent to item 1 of argv tell application "TextEdit" set newDoc to make new document set text of newDoc to docContent set docName to name of newDoc return "Created document: " & docName end tell end run' -- "${formattedContent}"`; const { stdout: docResult, stderr: docError } = await execAsync(docCommand); if (docError.trim()) { return { content: [ { type: 'text', text: `Error creating document: ${docError.trim()}`, }, ], }; } return { content: [ { type: 'text', text: `Workflow completed: ${docResult.trim()}`, }, ], }; } catch (error: any) { return { content: [ { type: 'text', text: `Error executing workflow: ${error.message}`, }, ], }; }
- src/index.ts:279-295 (schema)Tool schema defining input parameters: required 'name' for the contact and optional 'title' for the document.name: 'workflow_contact_to_textedit', description: 'Get contact information and create formatted TextEdit document', inputSchema: { type: 'object', properties: { name: { type: 'string', description: 'Person name to look up', }, title: { type: 'string', description: 'Document title (optional)', }, }, required: ['name'], }, },
- src/index.ts:27-358 (registration)The tool is registered in the ListToolsRequestHandler by including it in the returned tools list.server.setRequestHandler(ListToolsRequestSchema, async () => { return { tools: [ { name: 'discover_apps', description: 'Discover AppleScript capabilities of a macOS application', inputSchema: { type: 'object', properties: { app_name: { type: 'string', description: 'Name of the macOS application to discover', }, method: { type: 'string', description: 'Discovery method: basic, dictionary, properties, system_events, comprehensive', }, destination: { type: 'string', description: 'Directory path to save discovery results', }, }, required: ['app_name', 'method', 'destination'], }, }, { name: 'finder_get_selection', description: 'Get currently selected files/folders in Finder', inputSchema: { type: 'object', properties: {}, }, }, { name: 'finder_get_current_folder', description: 'Get path of currently viewed folder in frontmost Finder window', inputSchema: { type: 'object', properties: {}, }, }, { name: 'mail_get_accounts', description: 'Get list of all Mail account names', inputSchema: { type: 'object', properties: {}, }, }, { name: 'mail_get_inbox_count', description: 'Get unread message count in inbox', inputSchema: { type: 'object', properties: {}, }, }, { name: 'mail_get_total_inbox_count', description: 'Get total message count in inbox', inputSchema: { type: 'object', properties: {}, }, }, { name: 'contacts_search_people', description: 'Search for people by name in Contacts', inputSchema: { type: 'object', properties: { search_term: { type: 'string', description: 'Name or part of name to search for', }, }, required: ['search_term'], }, }, { name: 'contacts_get_person_info', description: 'Get detailed information for a specific person', inputSchema: { type: 'object', properties: { person_name: { type: 'string', description: 'Full name of the person to get info for', }, }, required: ['person_name'], }, }, { name: 'reminders_get_lists', description: 'Get all reminder lists with reminder counts', inputSchema: { type: 'object', properties: {}, }, }, { name: 'reminders_get_incomplete_reminders', description: 'Get incomplete reminders across all lists', inputSchema: { type: 'object', properties: { limit: { type: 'number', description: 'Maximum number of reminders to return (default: 10)', }, }, }, }, { name: 'notes_get_folders', description: 'Get all note folders with note counts', inputSchema: { type: 'object', properties: {}, }, }, { name: 'notes_get_recent_notes', description: 'Get recently modified notes', inputSchema: { type: 'object', properties: { limit: { type: 'number', description: 'Maximum number of notes to return (default: 10)', }, }, }, }, { name: 'notes_search_notes', description: 'Search notes by title or content', inputSchema: { type: 'object', properties: { query: { type: 'string', description: 'Search query for note title or content', }, }, required: ['query'], }, }, { name: 'notes_create_note', description: 'Create new note with title and content', inputSchema: { type: 'object', properties: { title: { type: 'string', description: 'Note title', }, content: { type: 'string', description: 'Note content/body', }, folder: { type: 'string', description: 'Target folder name (optional, defaults to "Notes")', }, }, required: ['title', 'content'], }, }, { name: 'textedit_get_documents', description: 'Get list of open TextEdit documents', inputSchema: { type: 'object', properties: {}, }, }, { name: 'textedit_create_document', description: 'Create new TextEdit document with optional content', inputSchema: { type: 'object', properties: { content: { type: 'string', description: 'Optional initial content for the document', }, }, }, }, { name: 'calendar_get_calendars', description: 'Get all calendars with event counts', inputSchema: { type: 'object', properties: {}, }, }, { name: 'calendar_create_event', description: 'Create new calendar event', inputSchema: { type: 'object', properties: { title: { type: 'string', description: 'Event title/summary', }, start_datetime: { type: 'string', description: 'Start date and time (YYYY-MM-DD HH:MM format)', }, end_datetime: { type: 'string', description: 'End date and time (YYYY-MM-DD HH:MM format)', }, calendar: { type: 'string', description: 'Target calendar name (optional, defaults to "Calendar")', }, notes: { type: 'string', description: 'Event notes/description (optional)', }, }, required: ['title', 'start_datetime', 'end_datetime'], }, }, { name: 'calendar_get_today_events', description: 'Get today\'s events across all calendars', inputSchema: { type: 'object', properties: {}, }, }, { name: 'calendar_get_upcoming_events', description: 'Get upcoming events in date range', inputSchema: { type: 'object', properties: { days: { type: 'number', description: 'Number of days ahead to look (default: 7)', }, }, }, }, { name: 'workflow_contact_to_textedit', description: 'Get contact information and create formatted TextEdit document', inputSchema: { type: 'object', properties: { name: { type: 'string', description: 'Person name to look up', }, title: { type: 'string', description: 'Document title (optional)', }, }, required: ['name'], }, }, { name: 'mail_create_message', description: 'Create new email message with recipients, subject, and body', inputSchema: { type: 'object', properties: { to: { type: 'string', description: 'Recipient email address', }, subject: { type: 'string', description: 'Email subject', }, body: { type: 'string', description: 'Email body content', }, cc: { type: 'string', description: 'CC recipient email address (optional)', }, }, required: ['to', 'subject', 'body'], }, }, { name: 'mail_send_message', description: 'Send the most recently created message', inputSchema: { type: 'object', properties: {}, }, }, { name: 'reminders_create_reminder', description: 'Create new reminder with title, optional due date and list', inputSchema: { type: 'object', properties: { title: { type: 'string', description: 'Reminder title', }, due_date: { type: 'string', description: 'Due date in format YYYY-MM-DD (optional)', }, list: { type: 'string', description: 'Target reminder list name (optional, defaults to "Reminders")', }, notes: { type: 'string', description: 'Reminder notes/body (optional)', }, }, required: ['title'], }, }, ], }; });