Skip to main content
Glama

process_note_request

Submit text requests to create, update, delete, or search Apple Notes through the NotesY MCP server, enabling streamlined note management via natural language commands.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
textYes

Implementation Reference

  • Main MCP tool handler for 'process_note_request'. Parses natural language input, uses helpers to generate and execute AppleScript for Apple Notes operations, and formats MCP response.
    server.tool("process_note_request", { text: z.string().min(1) }, async ({ text }) => { try { // Handle JSON input if present let processedText = text; if (text.trim().startsWith('{') && text.includes('text')) { try { const jsonData = JSON.parse(text); if (jsonData.text) { processedText = jsonData.text; } } catch (err) { // Continue with original text } } // Process the text request const parsedRequest = parseNaturalLanguage(processedText); if (!parsedRequest) { return { content: [{ type: "text", text: "I couldn't understand your request. Try phrasing it like:\n- Create a note titled 'shopping list' with items: milk, eggs, bread\n- Add meeting notes to my 'work' note\n- Delete my 'old tasks' note\n- Search for notes with 'project'" }] }; } // Execute the AppleScript const script = generateAppleScript(parsedRequest); const result = await executeAppleScript(script); // Format the response based on action type let responseText = ""; switch (parsedRequest.action) { case 'create': responseText = `Successfully created note "${parsedRequest.title}"`; break; case 'update': responseText = `Successfully updated note "${parsedRequest.title}"`; break; case 'delete': responseText = `Successfully deleted note "${parsedRequest.title}"`; break; case 'search': if (result && result.trim()) { const notes = result.split(',').map(note => note.trim()); responseText = `Found ${notes.length} note(s) matching "${parsedRequest.title}":\n${notes.map(note => `- ${note}`).join('\n')}`; } else { responseText = `No notes found matching "${parsedRequest.title}"`; } break; } return { content: [{ type: "text", text: responseText }] }; } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); return { content: [{ type: "text", text: `Error: ${errorMessage}` }] }; } });
  • Zod schema for internal NoteRequest structure used by parseNaturalLanguage and other functions.
    const NoteRequestSchema = z.object({ action: z.enum(['create', 'update', 'delete', 'search']), title: z.string().min(1), content: z.array(z.string()).optional(), folder: z.string().optional(), }); export type NoteRequest = z.infer<typeof NoteRequestSchema>;
  • src/index.ts:16-80 (registration)
    MCP tool registration including schema and handler reference.
    server.tool("process_note_request", { text: z.string().min(1) }, async ({ text }) => { try { // Handle JSON input if present let processedText = text; if (text.trim().startsWith('{') && text.includes('text')) { try { const jsonData = JSON.parse(text); if (jsonData.text) { processedText = jsonData.text; } } catch (err) { // Continue with original text } } // Process the text request const parsedRequest = parseNaturalLanguage(processedText); if (!parsedRequest) { return { content: [{ type: "text", text: "I couldn't understand your request. Try phrasing it like:\n- Create a note titled 'shopping list' with items: milk, eggs, bread\n- Add meeting notes to my 'work' note\n- Delete my 'old tasks' note\n- Search for notes with 'project'" }] }; } // Execute the AppleScript const script = generateAppleScript(parsedRequest); const result = await executeAppleScript(script); // Format the response based on action type let responseText = ""; switch (parsedRequest.action) { case 'create': responseText = `Successfully created note "${parsedRequest.title}"`; break; case 'update': responseText = `Successfully updated note "${parsedRequest.title}"`; break; case 'delete': responseText = `Successfully deleted note "${parsedRequest.title}"`; break; case 'search': if (result && result.trim()) { const notes = result.split(',').map(note => note.trim()); responseText = `Found ${notes.length} note(s) matching "${parsedRequest.title}":\n${notes.map(note => `- ${note}`).join('\n')}`; } else { responseText = `No notes found matching "${parsedRequest.title}"`; } break; } return { content: [{ type: "text", text: responseText }] }; } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); return { content: [{ type: "text", text: `Error: ${errorMessage}` }] }; } });
  • Helper function that parses natural language text into structured NoteRequest object.
    export function parseNaturalLanguage(text: string): NoteRequest | null { const lowerText = text.toLowerCase(); // Handle long text content as note creation if (text.length > 100 && !text.includes('"') && !text.includes("'")) { const firstLine = text.split('\n')[0].trim(); const title = firstLine.split(' ').slice(0, 5).join(' '); try { return NoteRequestSchema.parse({ action: 'create', title: title, content: [text] }); } catch (e) { // Continue to other patterns } } // Handle trip planning specifically if (lowerText.includes('trip') || lowerText.includes('travel') || lowerText.includes('vacation')) { const locationMatch = text.match(/(?:trip|travel|vacation)(?:\s+(?:to|for|in))?\s+([A-Za-z\s,]+)/) || text.match(/([A-Za-z\s,]+)(?:\s+(?:trip|travel|vacation))/); if (locationMatch) { const location = locationMatch[1].trim(); const title = `Trip plan: ${location}`; try { return NoteRequestSchema.parse({ action: 'create', title, content: [text] }); } catch (e) { // Continue to other patterns } } } // Handle note creation commands const createPatterns = [ /create\s+(?:a\s+)?note\s+(?:titled|called|named)\s+['"](.+?)['"](?:\s+with\s+(?:items|content|text)(?:\s*:|:|\s+of)?)?(?:\s+(.+))?/i, /(?:make|add)\s+(?:a\s+)?(?:new\s+)?note\s+(?:titled|called|named)\s+['"](.+?)['"](?:\s+with\s+(?:items|content|text)(?:\s*:|:|\s+of)?)?(?:\s+(.+))?/i, /(?:take|write)\s+(?:a\s+)?note\s+(?:titled|called|named)\s+['"](.+?)['"](?:\s+with\s+(?:items|content|text)(?:\s*:|:|\s+of)?)?(?:\s+(.+))?/i ]; for (const pattern of createPatterns) { const match = text.match(pattern); if (match) { const title = match[1]; let content: string[] = []; if (match[2]) { if (match[2].includes(',')) { content = match[2].split(',').map(item => item.trim()); } else if (match[2].includes('\n')) { content = match[2].split('\n').map(item => item.trim().replace(/^[-•*]\s*/, '')); } else { content = [match[2].trim()]; } } try { return NoteRequestSchema.parse({ action: 'create', title, content }); } catch (e) { return null; } } } // Handle update commands const updatePatterns = [ /add\s+(.+?)\s+to\s+(?:my\s+)?['"](.+?)['"](?:\s+note)?/i, /update\s+(?:my\s+)?['"](.+?)['"](?:\s+note)?\s+(?:with|to(?:\s+add)?)\s+(.+)/i, /append\s+(.+?)\s+to\s+(?:my\s+)?['"](.+?)['"](?:\s+note)?/i ]; for (const pattern of updatePatterns) { const match = text.match(pattern); if (match) { let content: string, title: string; if (lowerText.includes("update") && match[1]) { title = match[1]; content = match[2]; } else { content = match[1]; title = match[2]; } if (title && content) { try { return NoteRequestSchema.parse({ action: 'update', title, content: [content.trim()] }); } catch (e) { return null; } } } } // Handle delete commands const deletePatterns = [ /delete\s+(?:my\s+)?(?:note\s+)?['"](.+?)['"](?:\s+note)?/i, /remove\s+(?:my\s+)?(?:note\s+)?['"](.+?)['"](?:\s+note)?/i, /trash\s+(?:my\s+)?(?:note\s+)?['"](.+?)['"](?:\s+note)?/i, /get\s+rid\s+of\s+(?:my\s+)?(?:note\s+)?['"](.+?)['"](?:\s+note)?/i ]; for (const pattern of deletePatterns) { const match = text.match(pattern); if (match) { const title = match[1]; try { return NoteRequestSchema.parse({ action: 'delete', title }); } catch (e) { return null; } } } // Handle search commands const searchPatterns = [ /(?:search|find|look\s+for)\s+(?:my\s+)?(?:note\s+)?['"](.+?)['"](?:\s+note)?/i, /(?:search|find|look)\s+(?:for\s+)?(?:notes?\s+)?(?:with|containing|about)\s+['"](.+?)['"](?:\s+note)?/i ]; for (const pattern of searchPatterns) { const match = text.match(pattern); if (match) { const title = match[1]; try { return NoteRequestSchema.parse({ action: 'search', title }); } catch (e) { return null; } } } // Handle simple creation with quoted title if (lowerText.includes('create') || lowerText.includes('new') || lowerText.includes('make')) { const titleMatch = text.match(/['"](.+?)['"]/) || text.match(/note\s+(?:about|on|for)\s+(.+?)(?:\s|$)/i); if (titleMatch) { try { return NoteRequestSchema.parse({ action: 'create', title: titleMatch[1], content: [] }); } catch (e) { return null; } } } return null; }
  • Helper function that generates AppleScript based on parsed NoteRequest.
    export function generateAppleScript(request: NoteRequest): string { const safeTitle = request.title.replace(/"/g, '\\"'); const safeContent = request.content?.map(item => item.replace(/"/g, '\\"')) || []; switch (request.action) { case 'create': return ` tell application "Notes" set newNote to make new note with properties {name:"${safeTitle}"} ${safeContent.map(item => `tell newNote to make new paragraph at the end with data "${item}"`).join('\n') || ''} end tell `; case 'update': return ` tell application "Notes" set noteFound to false repeat with theNote in notes if name of theNote is "${safeTitle}" then set noteFound to true tell theNote ${safeContent.map(item => `make new paragraph at the end with data "${item}"`).join('\n') || ''} end tell exit repeat end if end repeat if not noteFound then set newNote to make new note with properties {name:"${safeTitle}"} ${safeContent.map(item => `tell newNote to make new paragraph at the end with data "${item}"`).join('\n') || ''} end if end tell `; case 'delete': return ` tell application "Notes" set noteFound to false repeat with theNote in notes if name of theNote is "${safeTitle}" then set noteFound to true delete theNote exit repeat end if end repeat end tell `; case 'search': return ` tell application "Notes" set matchingNotes to {} repeat with theNote in notes if name of theNote contains "${safeTitle}" then set end of matchingNotes to name of theNote end if end repeat return matchingNotes end tell `; default: return ''; } }
  • Helper function to execute generated AppleScript.
    export function executeAppleScript(script: string): Promise<string> { return new Promise((resolve, reject) => { const tempFile = `/tmp/notescript_${Date.now()}.scpt`; const writeCmd = `echo '${script.replace(/'/g, "'\\''")}' > ${tempFile}`; exec(writeCmd, writeErr => { if (writeErr) { return reject(`Error writing script: ${writeErr}`); } exec(`osascript ${tempFile}`, (execErr, stdout, stderr) => { exec(`rm ${tempFile}`); if (execErr) { return reject(`AppleScript execution error: ${stderr}`); } resolve(stdout); }); }); }); }

Other Tools

Related 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/Rish-it/Notes-MCP'

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