@goforgeit/mcp-apple-notes 0.5.2 → 0.5.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -6,6 +6,8 @@ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"
6
6
  import { z } from "zod";
7
7
  import { execFile } from "child_process";
8
8
  import { promisify } from "util";
9
+ import { realpathSync } from "fs";
10
+ import { fileURLToPath } from "url";
9
11
  var execFileAsync = promisify(execFile);
10
12
  async function runAppleScript(script) {
11
13
  const { stdout } = await execFileAsync("osascript", ["-e", script]);
@@ -234,7 +236,13 @@ function createAppleNotesMCPServer() {
234
236
  }
235
237
  };
236
238
  }
237
- var isMainModule = process.argv[1] && import.meta.url.endsWith(process.argv[1].replace(/\\/g, "/"));
239
+ var isMainModule = (() => {
240
+ try {
241
+ return process.argv[1] && fileURLToPath(import.meta.url) === realpathSync(process.argv[1]);
242
+ } catch {
243
+ return false;
244
+ }
245
+ })();
238
246
  if (isMainModule || process.env.FORGE_MCP_START === "true") {
239
247
  const mcpServer = createAppleNotesMCPServer();
240
248
  mcpServer.start().catch((err) => {
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * @goforgeit/mcp-apple-notes\n *\n * Forge MCP server for Apple Notes on macOS.\n * Lists, searches, reads, and creates notes via AppleScript.\n */\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport { z } from 'zod';\nimport { execFile } from 'child_process';\nimport { promisify } from 'util';\n\nconst execFileAsync = promisify(execFile);\n\nexport interface AppleNotesMCPServer {\n server: McpServer;\n getRegisteredTools(): string[];\n start(): Promise<void>;\n}\n\nexport async function runAppleScript(script: string): Promise<string> {\n const { stdout } = await execFileAsync('osascript', ['-e', script]);\n return stdout.trim();\n}\n\nexport function createAppleNotesMCPServer(): AppleNotesMCPServer {\n const server = new McpServer({\n name: '@goforgeit/mcp-apple-notes',\n version: '0.1.0',\n });\n\n const registeredTools: string[] = [];\n\n // --- list_notes ---\n server.tool(\n 'list_notes',\n 'List notes from Apple Notes app with optional folder filtering',\n {\n folder: z.string().optional().describe('Folder name to filter notes (e.g., \"Notes\", \"Work\")'),\n limit: z.number().optional().default(20).describe('Maximum number of notes to return'),\n },\n async ({ folder, limit }) => {\n const folderClause = folder ? `notes of folder ${JSON.stringify(folder)}` : 'notes';\n\n const script = `\n tell application \"Notes\"\n set notesList to {}\n set targetNotes to ${folderClause}\n set noteCount to 0\n repeat with aNote in targetNotes\n if noteCount < ${limit} then\n set noteInfo to \"{\\\\\"name\\\\\":\\\\\"\" & (name of aNote as string) & \"\\\\\",\\\\\"id\\\\\":\\\\\"\" & (id of aNote as string) & \"\\\\\",\\\\\"creation_date\\\\\":\\\\\"\" & (creation date of aNote as string) & \"\\\\\",\\\\\"modification_date\\\\\":\\\\\"\" & (modification date of aNote as string) & \"\\\\\"}\"\n set end of notesList to noteInfo\n set noteCount to noteCount + 1\n else\n exit repeat\n end if\n end repeat\n return \"[\" & my joinList(notesList, \",\") & \"]\"\n end tell\n\n on joinList(theList, delimiter)\n set AppleScript's text item delimiters to delimiter\n set theString to theList as string\n set AppleScript's text item delimiters to \"\"\n return theString\n end joinList\n `;\n\n try {\n const results = await runAppleScript(script);\n return { content: [{ type: 'text' as const, text: results }] };\n } catch (error) {\n return {\n content: [\n {\n type: 'text' as const,\n text: `Failed to list notes: ${error instanceof Error ? error.message : String(error)}`,\n },\n ],\n isError: true,\n };\n }\n },\n );\n registeredTools.push('list_notes');\n\n // --- get_note ---\n server.tool(\n 'get_note',\n 'Get the full content of a specific note by name',\n {\n note_name: z.string().describe('Name of the note to retrieve'),\n folder: z.string().optional().describe('Folder where the note is located'),\n },\n async ({ note_name, folder }) => {\n const targetClause = folder\n ? `first note of folder ${JSON.stringify(folder)} whose name is ${JSON.stringify(note_name)}`\n : `first note whose name is ${JSON.stringify(note_name)}`;\n\n const script = `\n tell application \"Notes\"\n set targetNote to ${targetClause}\n set noteName to name of targetNote as string\n set noteBody to body of targetNote as string\n set noteId to id of targetNote as string\n set noteCreated to creation date of targetNote as string\n set noteModified to modification date of targetNote as string\n return \"{\\\\\"name\\\\\":\\\\\"\" & noteName & \"\\\\\",\\\\\"id\\\\\":\\\\\"\" & noteId & \"\\\\\",\\\\\"creation_date\\\\\":\\\\\"\" & noteCreated & \"\\\\\",\\\\\"modification_date\\\\\":\\\\\"\" & noteModified & \"\\\\\",\\\\\"body\\\\\":\\\\\"\" & noteBody & \"\\\\\"}\"\n end tell\n `;\n\n try {\n const result = await runAppleScript(script);\n return { content: [{ type: 'text' as const, text: result }] };\n } catch (error) {\n return {\n content: [\n {\n type: 'text' as const,\n text: `Failed to get note: ${error instanceof Error ? error.message : String(error)}`,\n },\n ],\n isError: true,\n };\n }\n },\n );\n registeredTools.push('get_note');\n\n // --- search_notes ---\n server.tool(\n 'search_notes',\n 'Search notes by text query across all folders',\n {\n query: z.string().describe('Text to search for in note names and bodies'),\n limit: z.number().optional().default(10).describe('Maximum number of results to return'),\n },\n async ({ query, limit }) => {\n const script = `\n tell application \"Notes\"\n set notesList to {}\n set noteCount to 0\n repeat with aNote in notes\n if noteCount < ${limit} then\n set noteName to name of aNote as string\n set noteBody to plaintext of aNote as string\n if noteName contains ${JSON.stringify(query)} or noteBody contains ${JSON.stringify(query)} then\n set noteInfo to \"{\\\\\"name\\\\\":\\\\\"\" & noteName & \"\\\\\",\\\\\"id\\\\\":\\\\\"\" & (id of aNote as string) & \"\\\\\",\\\\\"creation_date\\\\\":\\\\\"\" & (creation date of aNote as string) & \"\\\\\",\\\\\"modification_date\\\\\":\\\\\"\" & (modification date of aNote as string) & \"\\\\\"}\"\n set end of notesList to noteInfo\n set noteCount to noteCount + 1\n end if\n else\n exit repeat\n end if\n end repeat\n return \"[\" & my joinList(notesList, \",\") & \"]\"\n end tell\n\n on joinList(theList, delimiter)\n set AppleScript's text item delimiters to delimiter\n set theString to theList as string\n set AppleScript's text item delimiters to \"\"\n return theString\n end joinList\n `;\n\n try {\n const results = await runAppleScript(script);\n return { content: [{ type: 'text' as const, text: results }] };\n } catch (error) {\n return {\n content: [\n {\n type: 'text' as const,\n text: `Failed to search notes: ${error instanceof Error ? error.message : String(error)}`,\n },\n ],\n isError: true,\n };\n }\n },\n );\n registeredTools.push('search_notes');\n\n // --- create_note ---\n server.tool(\n 'create_note',\n 'Create a new note in Apple Notes',\n {\n title: z.string().describe('Title of the new note'),\n body: z.string().describe('Content/body of the new note'),\n folder: z.string().optional().default('Notes').describe('Folder to create the note in'),\n },\n async ({ title, body, folder }) => {\n const script = `\n tell application \"Notes\"\n set targetFolder to folder ${JSON.stringify(folder)}\n set newNote to make new note at targetFolder with properties {name:${JSON.stringify(title)}, body:${JSON.stringify(body)}}\n return \"Note created successfully: \" & (name of newNote as string)\n end tell\n `;\n\n try {\n const result = await runAppleScript(script);\n return { content: [{ type: 'text' as const, text: result }] };\n } catch (error) {\n return {\n content: [\n {\n type: 'text' as const,\n text: `Failed to create note: ${error instanceof Error ? error.message : String(error)}`,\n },\n ],\n isError: true,\n };\n }\n },\n );\n registeredTools.push('create_note');\n\n // --- list_folders ---\n server.tool('list_folders', 'List all folders in Apple Notes', {}, async () => {\n const script = `\n tell application \"Notes\"\n set foldersList to {}\n repeat with aFolder in folders\n set folderInfo to \"{\\\\\"name\\\\\":\\\\\"\" & (name of aFolder as string) & \"\\\\\",\\\\\"id\\\\\":\\\\\"\" & (id of aFolder as string) & \"\\\\\",\\\\\"note_count\\\\\":\" & (count of notes of aFolder) & \"}\"\n set end of foldersList to folderInfo\n end repeat\n return \"[\" & my joinList(foldersList, \",\") & \"]\"\n end tell\n\n on joinList(theList, delimiter)\n set AppleScript's text item delimiters to delimiter\n set theString to theList as string\n set AppleScript's text item delimiters to \"\"\n return theString\n end joinList\n `;\n\n try {\n const results = await runAppleScript(script);\n return { content: [{ type: 'text' as const, text: results }] };\n } catch (error) {\n return {\n content: [\n {\n type: 'text' as const,\n text: `Failed to list folders: ${error instanceof Error ? error.message : String(error)}`,\n },\n ],\n isError: true,\n };\n }\n });\n registeredTools.push('list_folders');\n\n return {\n server,\n getRegisteredTools() {\n return [...registeredTools];\n },\n async start() {\n const transport = new StdioServerTransport();\n await server.connect(transport);\n },\n };\n}\n\n// CLI entry point\nconst isMainModule =\n process.argv[1] && import.meta.url.endsWith(process.argv[1].replace(/\\\\/g, '/'));\n\nif (isMainModule || process.env.FORGE_MCP_START === 'true') {\n const mcpServer = createAppleNotesMCPServer();\n mcpServer.start().catch((err) => {\n console.error('Failed to start Apple Notes MCP server:', err);\n process.exit(1);\n });\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * @goforgeit/mcp-apple-notes\n *\n * Forge MCP server for Apple Notes on macOS.\n * Lists, searches, reads, and creates notes via AppleScript.\n */\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport { z } from 'zod';\nimport { execFile } from 'child_process';\nimport { promisify } from 'util';\n\nconst execFileAsync = promisify(execFile);\n\nexport interface AppleNotesMCPServer {\n server: McpServer;\n getRegisteredTools(): string[];\n start(): Promise<void>;\n}\n\nexport async function runAppleScript(script: string): Promise<string> {\n const { stdout } = await execFileAsync('osascript', ['-e', script]);\n return stdout.trim();\n}\n\nexport function createAppleNotesMCPServer(): AppleNotesMCPServer {\n const server = new McpServer({\n name: '@goforgeit/mcp-apple-notes',\n version: '0.1.0',\n });\n\n const registeredTools: string[] = [];\n\n // --- list_notes ---\n server.tool(\n 'list_notes',\n 'List notes from Apple Notes app with optional folder filtering',\n {\n folder: z.string().optional().describe('Folder name to filter notes (e.g., \"Notes\", \"Work\")'),\n limit: z.number().optional().default(20).describe('Maximum number of notes to return'),\n },\n async ({ folder, limit }) => {\n const folderClause = folder ? `notes of folder ${JSON.stringify(folder)}` : 'notes';\n\n const script = `\n tell application \"Notes\"\n set notesList to {}\n set targetNotes to ${folderClause}\n set noteCount to 0\n repeat with aNote in targetNotes\n if noteCount < ${limit} then\n set noteInfo to \"{\\\\\"name\\\\\":\\\\\"\" & (name of aNote as string) & \"\\\\\",\\\\\"id\\\\\":\\\\\"\" & (id of aNote as string) & \"\\\\\",\\\\\"creation_date\\\\\":\\\\\"\" & (creation date of aNote as string) & \"\\\\\",\\\\\"modification_date\\\\\":\\\\\"\" & (modification date of aNote as string) & \"\\\\\"}\"\n set end of notesList to noteInfo\n set noteCount to noteCount + 1\n else\n exit repeat\n end if\n end repeat\n return \"[\" & my joinList(notesList, \",\") & \"]\"\n end tell\n\n on joinList(theList, delimiter)\n set AppleScript's text item delimiters to delimiter\n set theString to theList as string\n set AppleScript's text item delimiters to \"\"\n return theString\n end joinList\n `;\n\n try {\n const results = await runAppleScript(script);\n return { content: [{ type: 'text' as const, text: results }] };\n } catch (error) {\n return {\n content: [\n {\n type: 'text' as const,\n text: `Failed to list notes: ${error instanceof Error ? error.message : String(error)}`,\n },\n ],\n isError: true,\n };\n }\n },\n );\n registeredTools.push('list_notes');\n\n // --- get_note ---\n server.tool(\n 'get_note',\n 'Get the full content of a specific note by name',\n {\n note_name: z.string().describe('Name of the note to retrieve'),\n folder: z.string().optional().describe('Folder where the note is located'),\n },\n async ({ note_name, folder }) => {\n const targetClause = folder\n ? `first note of folder ${JSON.stringify(folder)} whose name is ${JSON.stringify(note_name)}`\n : `first note whose name is ${JSON.stringify(note_name)}`;\n\n const script = `\n tell application \"Notes\"\n set targetNote to ${targetClause}\n set noteName to name of targetNote as string\n set noteBody to body of targetNote as string\n set noteId to id of targetNote as string\n set noteCreated to creation date of targetNote as string\n set noteModified to modification date of targetNote as string\n return \"{\\\\\"name\\\\\":\\\\\"\" & noteName & \"\\\\\",\\\\\"id\\\\\":\\\\\"\" & noteId & \"\\\\\",\\\\\"creation_date\\\\\":\\\\\"\" & noteCreated & \"\\\\\",\\\\\"modification_date\\\\\":\\\\\"\" & noteModified & \"\\\\\",\\\\\"body\\\\\":\\\\\"\" & noteBody & \"\\\\\"}\"\n end tell\n `;\n\n try {\n const result = await runAppleScript(script);\n return { content: [{ type: 'text' as const, text: result }] };\n } catch (error) {\n return {\n content: [\n {\n type: 'text' as const,\n text: `Failed to get note: ${error instanceof Error ? error.message : String(error)}`,\n },\n ],\n isError: true,\n };\n }\n },\n );\n registeredTools.push('get_note');\n\n // --- search_notes ---\n server.tool(\n 'search_notes',\n 'Search notes by text query across all folders',\n {\n query: z.string().describe('Text to search for in note names and bodies'),\n limit: z.number().optional().default(10).describe('Maximum number of results to return'),\n },\n async ({ query, limit }) => {\n const script = `\n tell application \"Notes\"\n set notesList to {}\n set noteCount to 0\n repeat with aNote in notes\n if noteCount < ${limit} then\n set noteName to name of aNote as string\n set noteBody to plaintext of aNote as string\n if noteName contains ${JSON.stringify(query)} or noteBody contains ${JSON.stringify(query)} then\n set noteInfo to \"{\\\\\"name\\\\\":\\\\\"\" & noteName & \"\\\\\",\\\\\"id\\\\\":\\\\\"\" & (id of aNote as string) & \"\\\\\",\\\\\"creation_date\\\\\":\\\\\"\" & (creation date of aNote as string) & \"\\\\\",\\\\\"modification_date\\\\\":\\\\\"\" & (modification date of aNote as string) & \"\\\\\"}\"\n set end of notesList to noteInfo\n set noteCount to noteCount + 1\n end if\n else\n exit repeat\n end if\n end repeat\n return \"[\" & my joinList(notesList, \",\") & \"]\"\n end tell\n\n on joinList(theList, delimiter)\n set AppleScript's text item delimiters to delimiter\n set theString to theList as string\n set AppleScript's text item delimiters to \"\"\n return theString\n end joinList\n `;\n\n try {\n const results = await runAppleScript(script);\n return { content: [{ type: 'text' as const, text: results }] };\n } catch (error) {\n return {\n content: [\n {\n type: 'text' as const,\n text: `Failed to search notes: ${error instanceof Error ? error.message : String(error)}`,\n },\n ],\n isError: true,\n };\n }\n },\n );\n registeredTools.push('search_notes');\n\n // --- create_note ---\n server.tool(\n 'create_note',\n 'Create a new note in Apple Notes',\n {\n title: z.string().describe('Title of the new note'),\n body: z.string().describe('Content/body of the new note'),\n folder: z.string().optional().default('Notes').describe('Folder to create the note in'),\n },\n async ({ title, body, folder }) => {\n const script = `\n tell application \"Notes\"\n set targetFolder to folder ${JSON.stringify(folder)}\n set newNote to make new note at targetFolder with properties {name:${JSON.stringify(title)}, body:${JSON.stringify(body)}}\n return \"Note created successfully: \" & (name of newNote as string)\n end tell\n `;\n\n try {\n const result = await runAppleScript(script);\n return { content: [{ type: 'text' as const, text: result }] };\n } catch (error) {\n return {\n content: [\n {\n type: 'text' as const,\n text: `Failed to create note: ${error instanceof Error ? error.message : String(error)}`,\n },\n ],\n isError: true,\n };\n }\n },\n );\n registeredTools.push('create_note');\n\n // --- list_folders ---\n server.tool('list_folders', 'List all folders in Apple Notes', {}, async () => {\n const script = `\n tell application \"Notes\"\n set foldersList to {}\n repeat with aFolder in folders\n set folderInfo to \"{\\\\\"name\\\\\":\\\\\"\" & (name of aFolder as string) & \"\\\\\",\\\\\"id\\\\\":\\\\\"\" & (id of aFolder as string) & \"\\\\\",\\\\\"note_count\\\\\":\" & (count of notes of aFolder) & \"}\"\n set end of foldersList to folderInfo\n end repeat\n return \"[\" & my joinList(foldersList, \",\") & \"]\"\n end tell\n\n on joinList(theList, delimiter)\n set AppleScript's text item delimiters to delimiter\n set theString to theList as string\n set AppleScript's text item delimiters to \"\"\n return theString\n end joinList\n `;\n\n try {\n const results = await runAppleScript(script);\n return { content: [{ type: 'text' as const, text: results }] };\n } catch (error) {\n return {\n content: [\n {\n type: 'text' as const,\n text: `Failed to list folders: ${error instanceof Error ? error.message : String(error)}`,\n },\n ],\n isError: true,\n };\n }\n });\n registeredTools.push('list_folders');\n\n return {\n server,\n getRegisteredTools() {\n return [...registeredTools];\n },\n async start() {\n const transport = new StdioServerTransport();\n await server.connect(transport);\n },\n };\n}\n\n// CLI entry point\nimport { realpathSync } from 'node:fs';\nimport { fileURLToPath } from 'node:url';\nconst isMainModule = (() => {\n try {\n return process.argv[1] &&\n fileURLToPath(import.meta.url) === realpathSync(process.argv[1]);\n } catch { return false; }\n})();\n\nif (isMainModule || process.env.FORGE_MCP_START === 'true') {\n const mcpServer = createAppleNotesMCPServer();\n mcpServer.start().catch((err) => {\n console.error('Failed to start Apple Notes MCP server:', err);\n process.exit(1);\n });\n}\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@goforgeit/mcp-apple-notes",
3
- "version": "0.5.2",
3
+ "version": "0.5.3",
4
4
  "type": "module",
5
5
  "description": "Forge MCP server for Apple Notes — list, search, read, and create notes via macOS Notes app",
6
6
  "bin": {