@heznpc/imcp 1.1.0 → 1.3.0
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/README.md +197 -212
- package/dist/cli/doctor.d.ts +7 -0
- package/dist/cli/doctor.js +135 -0
- package/dist/cli/doctor.js.map +1 -0
- package/dist/cli/init.d.ts +8 -0
- package/dist/cli/init.js +145 -0
- package/dist/cli/init.js.map +1 -0
- package/dist/cross/tools.d.ts +7 -0
- package/dist/cross/tools.js +81 -0
- package/dist/cross/tools.js.map +1 -0
- package/dist/finder/tools.js +1 -1
- package/dist/finder/tools.js.map +1 -1
- package/dist/index.js +21 -2
- package/dist/index.js.map +1 -1
- package/dist/mail/scripts.d.ts +2 -0
- package/dist/mail/scripts.js +42 -0
- package/dist/mail/scripts.js.map +1 -1
- package/dist/mail/tools.d.ts +1 -1
- package/dist/mail/tools.js +45 -4
- package/dist/mail/tools.js.map +1 -1
- package/dist/semantic/embeddings.d.ts +10 -0
- package/dist/semantic/embeddings.js +112 -0
- package/dist/semantic/embeddings.js.map +1 -0
- package/dist/semantic/store.d.ts +47 -0
- package/dist/semantic/store.js +101 -0
- package/dist/semantic/store.js.map +1 -0
- package/dist/semantic/tools.d.ts +7 -0
- package/dist/semantic/tools.js +287 -0
- package/dist/semantic/tools.js.map +1 -0
- package/dist/shared/config.d.ts +1 -1
- package/dist/shared/config.js +1 -0
- package/dist/shared/config.js.map +1 -1
- package/dist/shared/resources.d.ts +10 -1
- package/dist/shared/resources.js +199 -45
- package/dist/shared/resources.js.map +1 -1
- package/dist/shared/setup.js +1 -0
- package/dist/shared/setup.js.map +1 -1
- package/dist/system/tools.js +2 -2
- package/dist/system/tools.js.map +1 -1
- package/dist/tv/scripts.d.ts +6 -0
- package/dist/tv/scripts.js +121 -0
- package/dist/tv/scripts.js.map +1 -0
- package/dist/tv/tools.d.ts +3 -0
- package/dist/tv/tools.js +95 -0
- package/dist/tv/tools.js.map +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -4,21 +4,99 @@ MCP server for the entire Apple ecosystem — Notes, Reminders, Calendar, Contac
|
|
|
4
4
|
|
|
5
5
|
> [한국어](README.ko.md)
|
|
6
6
|
|
|
7
|
-
##
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
7
|
+
## Get Started (2 minutes)
|
|
8
|
+
|
|
9
|
+
### 1. Install Node.js
|
|
10
|
+
|
|
11
|
+
If you don't have Node.js, install it first:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
# Using Homebrew (recommended)
|
|
15
|
+
brew install node
|
|
16
|
+
|
|
17
|
+
# Or download from https://nodejs.org (LTS version)
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
### 2. Run the Setup Wizard
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
npx @heznpc/imcp init
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
This will:
|
|
27
|
+
- Let you choose which Apple apps to connect (Notes, Calendar, Reminders, etc.)
|
|
28
|
+
- Automatically configure Claude Desktop
|
|
29
|
+
- Save your preferences to `~/.config/imcp/config.json`
|
|
30
|
+
|
|
31
|
+
### 3. Restart Claude Desktop
|
|
32
|
+
|
|
33
|
+
That's it! Claude can now read your notes, manage reminders, check your calendar, and more.
|
|
34
|
+
|
|
35
|
+
### Troubleshooting
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
npx @heznpc/imcp doctor
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Checks Node.js version, config files, Claude Desktop setup, macOS permissions, and module status — all in one command.
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
## What Can It Do?
|
|
46
|
+
|
|
47
|
+
**122 tools** across 14 Apple app modules + semantic search, **9 MCP resources**, and **20 prompts**:
|
|
48
|
+
|
|
49
|
+
| Module | What it does | Tools |
|
|
50
|
+
|--------|-------------|-------|
|
|
51
|
+
| **Notes** | Read, create, search, organize notes and folders | 12 |
|
|
52
|
+
| **Reminders** | Create tasks, set due dates, manage lists | 11 |
|
|
53
|
+
| **Calendar** | View events, create meetings, check schedule | 10 |
|
|
54
|
+
| **Contacts** | Look up people, manage contact info | 10 |
|
|
55
|
+
| **Mail** | Read, search, send, reply to emails | 11 |
|
|
56
|
+
| **Music** | Control playback, search tracks, manage playlists | 9 |
|
|
57
|
+
| **Finder** | Browse files, search with Spotlight, organize | 8 |
|
|
58
|
+
| **Safari** | Read web pages, manage tabs | 8 |
|
|
59
|
+
| **System** | Clipboard, volume, dark mode, screenshots, notifications | 10 |
|
|
60
|
+
| **Photos** | Browse albums, import/delete photos | 9 |
|
|
61
|
+
| **Messages** | View chats, send iMessages | 6 |
|
|
62
|
+
| **Shortcuts** | Run Siri Shortcuts from AI | 4 |
|
|
63
|
+
| **Intelligence** | On-device summarize, rewrite, proofread (macOS 26+) | 3 |
|
|
64
|
+
| **TV** | Browse library, control playback, search content | 6 |
|
|
65
|
+
| **Semantic** | On-device cross-app semantic search (Swift bridge) | 4 |
|
|
66
|
+
|
|
67
|
+
All tools include MCP annotations (`readOnlyHint`, `destructiveHint`, `openWorldHint`) for client-side safety UI.
|
|
68
|
+
|
|
69
|
+
## Module Presets
|
|
70
|
+
|
|
71
|
+
By default, new installations start with 5 core modules (Notes, Reminders, Calendar, Shortcuts, System) to keep things simple. You can enable more anytime:
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
# Re-run the setup wizard to change modules
|
|
75
|
+
npx @heznpc/imcp init
|
|
76
|
+
|
|
77
|
+
# Or enable all modules at once
|
|
78
|
+
npx @heznpc/imcp --full
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
Or edit `~/.config/imcp/config.json` directly:
|
|
82
|
+
|
|
83
|
+
```json
|
|
84
|
+
{
|
|
85
|
+
"disabledModules": ["messages", "intelligence"]
|
|
86
|
+
}
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## CLI Commands
|
|
90
|
+
|
|
91
|
+
| Command | Description |
|
|
92
|
+
|---------|-------------|
|
|
93
|
+
| `npx @heznpc/imcp init` | Interactive setup wizard |
|
|
94
|
+
| `npx @heznpc/imcp doctor` | Diagnose installation issues |
|
|
95
|
+
| `npx @heznpc/imcp` | Start MCP server (stdio, default) |
|
|
96
|
+
| `npx @heznpc/imcp --full` | Start with all 13 modules enabled |
|
|
97
|
+
| `npx @heznpc/imcp --http` | Start as HTTP server (port 3847) |
|
|
98
|
+
|
|
99
|
+
## Alternative Setup (Manual)
|
|
22
100
|
|
|
23
101
|
### Claude Desktop
|
|
24
102
|
|
|
@@ -48,37 +126,100 @@ git clone https://github.com/heznpc/iMcp.git
|
|
|
48
126
|
cd iMcp
|
|
49
127
|
npm install
|
|
50
128
|
npm run build
|
|
129
|
+
node dist/index.js
|
|
51
130
|
```
|
|
52
131
|
|
|
53
|
-
|
|
132
|
+
## Configuration
|
|
54
133
|
|
|
55
|
-
|
|
134
|
+
### Environment Variables
|
|
56
135
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
136
|
+
| Variable | Default | Description |
|
|
137
|
+
|----------|---------|-------------|
|
|
138
|
+
| `IMCP_INCLUDE_SHARED` | `false` | Include shared notes/folders |
|
|
139
|
+
| `IMCP_ALLOW_SEND_MESSAGES` | `true` | Allow sending iMessages |
|
|
140
|
+
| `IMCP_ALLOW_SEND_MAIL` | `true` | Allow sending emails |
|
|
141
|
+
| `IMCP_FULL` | `false` | Enable all modules (ignores preset) |
|
|
142
|
+
| `IMCP_DISABLE_{MODULE}` | — | Disable a specific module (e.g. `IMCP_DISABLE_MUSIC=true`) |
|
|
143
|
+
| `GEMINI_API_KEY` | — | Google Gemini API key for higher-quality embeddings (optional) |
|
|
144
|
+
|
|
145
|
+
### Config File
|
|
146
|
+
|
|
147
|
+
`~/.config/imcp/config.json`:
|
|
148
|
+
|
|
149
|
+
```json
|
|
150
|
+
{
|
|
151
|
+
"disabledModules": ["messages", "intelligence"],
|
|
152
|
+
"includeShared": false,
|
|
153
|
+
"allowSendMessages": true,
|
|
154
|
+
"allowSendMail": true,
|
|
155
|
+
"hitl": {
|
|
156
|
+
"level": "destructive-only",
|
|
157
|
+
"timeout": 30
|
|
158
|
+
}
|
|
159
|
+
}
|
|
60
160
|
```
|
|
61
161
|
|
|
62
|
-
|
|
162
|
+
## Advanced Features
|
|
63
163
|
|
|
64
164
|
### HTTP Mode
|
|
65
165
|
|
|
66
|
-
Run iMcp as an HTTP server for remote agents
|
|
166
|
+
Run iMcp as an HTTP server for remote agents or multi-client setups:
|
|
67
167
|
|
|
68
168
|
```bash
|
|
69
169
|
npx @heznpc/imcp --http --port 3847
|
|
70
170
|
```
|
|
71
171
|
|
|
72
|
-
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
172
|
+
### Human-in-the-Loop (HITL)
|
|
173
|
+
|
|
174
|
+
Require manual approval before destructive operations:
|
|
175
|
+
|
|
176
|
+
```json
|
|
177
|
+
{
|
|
178
|
+
"hitl": {
|
|
179
|
+
"level": "destructive-only",
|
|
180
|
+
"timeout": 30
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
Levels: `off`, `destructive-only`, `all-writes`, `all`
|
|
186
|
+
|
|
187
|
+
### Menubar App (Optional)
|
|
188
|
+
|
|
189
|
+
A native SwiftUI companion app for server status monitoring and permission setup:
|
|
190
|
+
|
|
191
|
+
```bash
|
|
192
|
+
cd app && swift build -c release
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
### Semantic Search (Optional)
|
|
196
|
+
|
|
197
|
+
On-device cross-app semantic search powered by Apple's NLContextualEmbedding. Find related notes, events, reminders, and emails by meaning — not just keywords.
|
|
198
|
+
|
|
199
|
+
```bash
|
|
200
|
+
npm run swift-build # Build the Swift bridge first
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
Then use the tools:
|
|
204
|
+
1. `semantic_index` — Index data from enabled Apple apps into a local vector store
|
|
205
|
+
2. `semantic_search` — Search by meaning across all indexed data
|
|
206
|
+
3. `find_related` — Find items related to a specific note/event/reminder
|
|
207
|
+
4. `semantic_status` — Check index status
|
|
208
|
+
|
|
209
|
+
Supports Korean, English, Japanese, Chinese with automatic language detection. Optionally set `GEMINI_API_KEY` for higher-quality Google Gemini embeddings.
|
|
210
|
+
|
|
211
|
+
### Swift Bridge (Optional)
|
|
212
|
+
|
|
213
|
+
For semantic search, recurring events/reminders (EventKit), photo import/delete (PhotoKit), and Apple Intelligence — requires macOS 26+:
|
|
76
214
|
|
|
77
|
-
|
|
215
|
+
```bash
|
|
216
|
+
npm run swift-build
|
|
217
|
+
```
|
|
78
218
|
|
|
79
|
-
## Tools
|
|
219
|
+
## Tools Reference
|
|
80
220
|
|
|
81
|
-
|
|
221
|
+
<details>
|
|
222
|
+
<summary>Notes (12 tools)</summary>
|
|
82
223
|
|
|
83
224
|
| Tool | Description | Type |
|
|
84
225
|
|------|-------------|------|
|
|
@@ -94,8 +235,10 @@ Useful for Mac Mini "always-on AI hub" setups where remote agents connect over t
|
|
|
94
235
|
| `scan_notes` | Bulk scan with metadata and preview | read |
|
|
95
236
|
| `compare_notes` | Compare 2-5 notes side by side | read |
|
|
96
237
|
| `bulk_move_notes` | Move multiple notes at once | destructive |
|
|
238
|
+
</details>
|
|
97
239
|
|
|
98
|
-
|
|
240
|
+
<details>
|
|
241
|
+
<summary>Reminders (11 tools)</summary>
|
|
99
242
|
|
|
100
243
|
| Tool | Description | Type |
|
|
101
244
|
|------|-------------|------|
|
|
@@ -110,8 +253,10 @@ Useful for Mac Mini "always-on AI hub" setups where remote agents connect over t
|
|
|
110
253
|
| `create_reminder_list` | Create a new reminder list | write |
|
|
111
254
|
| `delete_reminder_list` | Delete a reminder list | destructive |
|
|
112
255
|
| `create_recurring_reminder` | Create with recurrence rule (Swift/EventKit) | write |
|
|
256
|
+
</details>
|
|
113
257
|
|
|
114
|
-
|
|
258
|
+
<details>
|
|
259
|
+
<summary>Calendar (10 tools)</summary>
|
|
115
260
|
|
|
116
261
|
| Tool | Description | Type |
|
|
117
262
|
|------|-------------|------|
|
|
@@ -125,8 +270,10 @@ Useful for Mac Mini "always-on AI hub" setups where remote agents connect over t
|
|
|
125
270
|
| `get_upcoming_events` | Next N events from now | read |
|
|
126
271
|
| `today_events` | All events for today | read |
|
|
127
272
|
| `create_recurring_event` | Create with recurrence rule (Swift/EventKit) | write |
|
|
273
|
+
</details>
|
|
128
274
|
|
|
129
|
-
|
|
275
|
+
<details>
|
|
276
|
+
<summary>Contacts (10 tools)</summary>
|
|
130
277
|
|
|
131
278
|
| Tool | Description | Type |
|
|
132
279
|
|------|-------------|------|
|
|
@@ -140,8 +287,10 @@ Useful for Mac Mini "always-on AI hub" setups where remote agents connect over t
|
|
|
140
287
|
| `add_contact_email` | Add email to existing contact | write |
|
|
141
288
|
| `add_contact_phone` | Add phone to existing contact | write |
|
|
142
289
|
| `list_group_members` | List contacts in a group | read |
|
|
290
|
+
</details>
|
|
143
291
|
|
|
144
|
-
|
|
292
|
+
<details>
|
|
293
|
+
<summary>Mail (9 tools)</summary>
|
|
145
294
|
|
|
146
295
|
| Tool | Description | Type |
|
|
147
296
|
|------|-------------|------|
|
|
@@ -154,8 +303,10 @@ Useful for Mac Mini "always-on AI hub" setups where remote agents connect over t
|
|
|
154
303
|
| `get_unread_count` | Total unread across all mailboxes | read |
|
|
155
304
|
| `move_message` | Move message to another mailbox | destructive |
|
|
156
305
|
| `list_accounts` | List all mail accounts | read |
|
|
306
|
+
</details>
|
|
157
307
|
|
|
158
|
-
|
|
308
|
+
<details>
|
|
309
|
+
<summary>Music (9 tools)</summary>
|
|
159
310
|
|
|
160
311
|
| Tool | Description | Type |
|
|
161
312
|
|------|-------------|------|
|
|
@@ -168,102 +319,13 @@ Useful for Mac Mini "always-on AI hub" setups where remote agents connect over t
|
|
|
168
319
|
| `play_playlist` | Start playing a playlist | write |
|
|
169
320
|
| `get_track_info` | Detailed track metadata | read |
|
|
170
321
|
| `set_shuffle` | Set shuffle and repeat mode | write |
|
|
322
|
+
</details>
|
|
171
323
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
| Tool | Description | Type |
|
|
175
|
-
|------|-------------|------|
|
|
176
|
-
| `search_files` | Spotlight search in a folder | read |
|
|
177
|
-
| `get_file_info` | File size, dates, kind, tags | read |
|
|
178
|
-
| `set_file_tags` | Set Finder tags on a file | destructive |
|
|
179
|
-
| `recent_files` | Recently modified files | read |
|
|
180
|
-
| `list_directory` | List files in a directory | read |
|
|
181
|
-
| `move_file` | Move or rename a file | destructive |
|
|
182
|
-
| `trash_file` | Move file to Trash | destructive |
|
|
183
|
-
| `create_directory` | Create a new directory | write |
|
|
184
|
-
|
|
185
|
-
### Safari (8 tools)
|
|
186
|
-
|
|
187
|
-
| Tool | Description | Type |
|
|
188
|
-
|------|-------------|------|
|
|
189
|
-
| `list_tabs` | List all open tabs across windows | read |
|
|
190
|
-
| `read_page_content` | Read text content of a page | read |
|
|
191
|
-
| `get_current_tab` | Get the active tab URL and title | read |
|
|
192
|
-
| `open_url` | Open a URL in Safari | write |
|
|
193
|
-
| `close_tab` | Close a specific tab | destructive |
|
|
194
|
-
| `activate_tab` | Switch to a specific tab | write |
|
|
195
|
-
| `run_javascript` | Execute JavaScript in a tab | write |
|
|
196
|
-
| `search_tabs` | Search tabs by title or URL | read |
|
|
197
|
-
|
|
198
|
-
### System (10 tools)
|
|
199
|
-
|
|
200
|
-
| Tool | Description | Type |
|
|
201
|
-
|------|-------------|------|
|
|
202
|
-
| `get_clipboard` | Read clipboard contents | read |
|
|
203
|
-
| `set_clipboard` | Write to clipboard | write |
|
|
204
|
-
| `get_volume` | Get system volume level | read |
|
|
205
|
-
| `set_volume` | Set system volume level | write |
|
|
206
|
-
| `toggle_dark_mode` | Toggle dark/light mode | write |
|
|
207
|
-
| `get_frontmost_app` | Get the frontmost application | read |
|
|
208
|
-
| `list_running_apps` | List all running applications | read |
|
|
209
|
-
| `get_screen_info` | Get display information | read |
|
|
210
|
-
| `show_notification` | Display a system notification | write |
|
|
211
|
-
| `capture_screenshot` | Take a screenshot (fullscreen/window/selection) | write |
|
|
212
|
-
|
|
213
|
-
### Photos (9 tools)
|
|
214
|
-
|
|
215
|
-
| Tool | Description | Type |
|
|
216
|
-
|------|-------------|------|
|
|
217
|
-
| `list_albums` | List photo albums | read |
|
|
218
|
-
| `list_photos` | List photos in an album | read |
|
|
219
|
-
| `search_photos` | Search photos by keyword | read |
|
|
220
|
-
| `get_photo_info` | Detailed photo metadata | read |
|
|
221
|
-
| `list_favorites` | List favorite photos | read |
|
|
222
|
-
| `create_album` | Create a new album | write |
|
|
223
|
-
| `add_to_album` | Add photos to an album | write |
|
|
224
|
-
| `import_photo` | Import from file path (Swift/PhotoKit) | write |
|
|
225
|
-
| `delete_photos` | Delete photos by ID (Swift/PhotoKit) | destructive |
|
|
226
|
-
|
|
227
|
-
### Messages (6 tools)
|
|
228
|
-
|
|
229
|
-
| Tool | Description | Type |
|
|
230
|
-
|------|-------------|------|
|
|
231
|
-
| `list_chats` | List recent chats with participants | read |
|
|
232
|
-
| `read_chat` | Read chat details including participants and last update | read |
|
|
233
|
-
| `search_chats` | Search by name, participant, or handle | read |
|
|
234
|
-
| `send_message` | Send text via iMessage/SMS | write |
|
|
235
|
-
| `send_file` | Send file attachment via iMessage/SMS | write |
|
|
236
|
-
| `list_participants` | List participants in a chat | read |
|
|
324
|
+
<details>
|
|
325
|
+
<summary>Finder, Safari, System, Photos, Messages, Shortcuts, Intelligence</summary>
|
|
237
326
|
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
| Tool | Description | Type |
|
|
241
|
-
|------|-------------|------|
|
|
242
|
-
| `list_shortcuts` | List available Shortcuts | read |
|
|
243
|
-
| `run_shortcut` | Run a Shortcut by name | write |
|
|
244
|
-
| `search_shortcuts` | Search shortcuts by name | read |
|
|
245
|
-
| `get_shortcut_detail` | Get shortcut details/actions | read |
|
|
246
|
-
|
|
247
|
-
### Apple Intelligence (3 tools)
|
|
248
|
-
|
|
249
|
-
Requires macOS 26+ with Apple Silicon. Graceful error on unsupported systems.
|
|
250
|
-
|
|
251
|
-
| Tool | Description | Type |
|
|
252
|
-
|------|-------------|------|
|
|
253
|
-
| `summarize_text` | On-device summarization | read |
|
|
254
|
-
| `rewrite_text` | Rewrite in specified tone | read |
|
|
255
|
-
| `proofread_text` | Grammar/spelling correction | read |
|
|
256
|
-
|
|
257
|
-
## Resources
|
|
258
|
-
|
|
259
|
-
MCP Resources expose live data from Apple apps as URIs.
|
|
260
|
-
|
|
261
|
-
| URI | Description |
|
|
262
|
-
|-----|-------------|
|
|
263
|
-
| `notes://recent` | 10 most recent notes |
|
|
264
|
-
| `notes://recent/{count}` | Recent notes (configurable count) |
|
|
265
|
-
| `calendar://today` | Today's calendar events |
|
|
266
|
-
| `reminders://due` | Overdue reminders |
|
|
327
|
+
See the full tool list in the [Tools Reference](https://github.com/heznpc/iMcp/wiki/Tools-Reference) or run the server to explore via your AI client.
|
|
328
|
+
</details>
|
|
267
329
|
|
|
268
330
|
## Prompts
|
|
269
331
|
|
|
@@ -281,103 +343,26 @@ MCP Resources expose live data from Apple apps as URIs.
|
|
|
281
343
|
- **weekly-digest** — Past N days: events + notes + reminders combined
|
|
282
344
|
- **meeting-notes-to-reminders** — Extract action items from meeting notes, create reminders
|
|
283
345
|
- **event-follow-up** — Create follow-up note and reminders after a meeting
|
|
284
|
-
- **research-with-safari** — Browse with Safari + save findings to Notes
|
|
285
|
-
- **focus-session** — Calendar + Reminders + Music for focused work
|
|
286
|
-
- **file-organizer** — Organize files with Finder + track in Notes
|
|
287
346
|
|
|
288
347
|
### Developer Workflows
|
|
289
348
|
- **dev-session** — Scan project, check specs, research docs, create session notes
|
|
290
|
-
- **debug-loop** — Capture errors from Safari/clipboard, locate code, log bugs
|
|
291
|
-
- **screen-capture-flow** — Screenshot → Photos import → annotated note
|
|
292
|
-
- **app-release-prep** — Calendar dates + changelog from Notes + Reminders checklist
|
|
349
|
+
- **debug-loop** — Capture errors from Safari/clipboard, locate code, log bugs
|
|
293
350
|
- **idea-to-task** — Break idea into tasks → Reminders + Calendar time blocks
|
|
294
|
-
- **build-log** — Analyze build output, log errors or celebrate success
|
|
295
|
-
|
|
296
|
-
## Developer Agent Pipeline
|
|
297
|
-
|
|
298
|
-
iMcp's developer prompts chain Apple apps into autonomous agent workflows. Each prompt orchestrates multiple tools across modules — the AI reads your actual filesystem, Notes, Calendar, and Reminders to build real context, then writes back structured results.
|
|
299
|
-
|
|
300
|
-
```
|
|
301
|
-
┌─────────────────────────────────────────────────────────────────┐
|
|
302
|
-
│ dev-session │
|
|
303
|
-
│ Finder (scan) → Notes (specs) → Safari (docs) → Notes (log) │
|
|
304
|
-
└─────────────────────────────────────────────────────────────────┘
|
|
305
|
-
|
|
306
|
-
┌─────────────────────────────────────────────────────────────────┐
|
|
307
|
-
│ debug-loop │
|
|
308
|
-
│ Safari (JS errors) → Clipboard → Finder (locate) → │
|
|
309
|
-
│ Notes (bug log) → Reminders (fix task) │
|
|
310
|
-
└─────────────────────────────────────────────────────────────────┘
|
|
311
|
-
|
|
312
|
-
┌─────────────────────────────────────────────────────────────────┐
|
|
313
|
-
│ idea-to-task │
|
|
314
|
-
│ Notes (capture) → AI (decompose) → Reminders (tasks) → │
|
|
315
|
-
│ Calendar (time blocks) │
|
|
316
|
-
└─────────────────────────────────────────────────────────────────┘
|
|
317
|
-
|
|
318
|
-
┌─────────────────────────────────────────────────────────────────┐
|
|
319
|
-
│ build-log │
|
|
320
|
-
│ Finder (output) → Clipboard (log) → │
|
|
321
|
-
│ ┌ fail → Notes (error log) → Reminders (fix task) │
|
|
322
|
-
│ └ pass → Notification → Music (celebrate) → Notes (success) │
|
|
323
|
-
└─────────────────────────────────────────────────────────────────┘
|
|
324
|
-
```
|
|
325
|
-
|
|
326
|
-
These prompts are designed for AI coding agents (Claude Code, Cursor, Copilot) to invoke as MCP prompts — turning your Mac into a context-aware development environment.
|
|
327
|
-
|
|
328
|
-
> Demo video coming soon.
|
|
329
|
-
|
|
330
|
-
## Configuration
|
|
331
|
-
|
|
332
|
-
| Environment Variable | Default | Description |
|
|
333
|
-
|---------------------|---------|-------------|
|
|
334
|
-
| `IMCP_INCLUDE_SHARED` | `false` | Include shared notes/folders in results |
|
|
351
|
+
- **build-log** — Analyze build output, log errors or celebrate success
|
|
335
352
|
|
|
336
353
|
## Requirements
|
|
337
354
|
|
|
338
355
|
- macOS (Apple apps require macOS)
|
|
339
356
|
- Node.js >= 18
|
|
340
|
-
- First run will prompt for Automation permission for each app — use `setup_permissions` tool to grant all at once
|
|
341
357
|
- Apple Intelligence tools require macOS 26+ with Apple Silicon
|
|
342
358
|
|
|
343
359
|
## Limitations
|
|
344
360
|
|
|
345
|
-
|
|
346
|
-
-
|
|
347
|
-
-
|
|
348
|
-
-
|
|
349
|
-
|
|
350
|
-
### Reminders / Calendar
|
|
351
|
-
- JXA recurrence rules are read-only — use `create_recurring_event`/`create_recurring_reminder` (Swift/EventKit) to create recurring items
|
|
352
|
-
- Calendar attendees are read-only
|
|
353
|
-
|
|
354
|
-
### Contacts
|
|
355
|
-
- Custom fields not accessible
|
|
356
|
-
|
|
357
|
-
### Mail
|
|
358
|
-
- Content truncated to 5000 characters by default (configurable via `maxLength` parameter)
|
|
359
|
-
|
|
360
|
-
### Messages
|
|
361
|
-
- Chat message history (individual message content) is not accessible via JXA
|
|
362
|
-
- Send requires the recipient to be a known buddy in the Messages service
|
|
363
|
-
|
|
364
|
-
### Music
|
|
365
|
-
- Smart playlists are read-only
|
|
366
|
-
- No queue manipulation
|
|
367
|
-
|
|
368
|
-
### Finder
|
|
369
|
-
- Tags use Spotlight (mdfind), performance varies with index state
|
|
370
|
-
|
|
371
|
-
### Safari
|
|
372
|
-
- Reading page content requires Allow JavaScript from Apple Events in Safari Developer menu
|
|
373
|
-
|
|
374
|
-
### Photos
|
|
375
|
-
- JXA: albums can be created and photos added, but no import/delete
|
|
376
|
-
- Swift bridge (macOS 26+): full import and delete via PhotoKit
|
|
377
|
-
|
|
378
|
-
### Apple Intelligence
|
|
379
|
-
- Requires macOS 26 (Tahoe) + Apple Silicon
|
|
380
|
-
- Run `npm run swift-build` to compile the bridge binary
|
|
361
|
+
- **Notes**: Move copies and deletes (new ID, reset dates, lost attachments). Update replaces entire body.
|
|
362
|
+
- **Calendar/Reminders**: JXA recurrence is read-only — use Swift bridge for recurring items.
|
|
363
|
+
- **Messages**: Chat message history not accessible via JXA. Send requires known buddy.
|
|
364
|
+
- **Safari**: Reading page content requires "Allow JavaScript from Apple Events" in Safari Developer menu.
|
|
365
|
+
- **Photos**: Full import/delete requires Swift bridge (macOS 26+).
|
|
381
366
|
|
|
382
367
|
## License
|
|
383
368
|
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `npx @heznpc/imcp doctor` — Diagnose iMcp installation.
|
|
3
|
+
*
|
|
4
|
+
* Checks: Node version, config files, Claude Desktop config,
|
|
5
|
+
* module status, and optionally probes macOS permissions.
|
|
6
|
+
*/
|
|
7
|
+
import { readFileSync, existsSync } from "node:fs";
|
|
8
|
+
import { join } from "node:path";
|
|
9
|
+
import { execSync } from "node:child_process";
|
|
10
|
+
import { MODULE_NAMES, STARTER_MODULES } from "../shared/config.js";
|
|
11
|
+
const HOME = process.env.HOME ?? process.env.USERPROFILE ?? "";
|
|
12
|
+
const CLAUDE_CONFIG_PATH = join(HOME, "Library", "Application Support", "Claude", "claude_desktop_config.json");
|
|
13
|
+
const IMCP_CONFIG_PATH = join(HOME, ".config", "imcp", "config.json");
|
|
14
|
+
const OK = "\x1b[32m✓\x1b[0m";
|
|
15
|
+
const WARN = "\x1b[33m⚠\x1b[0m";
|
|
16
|
+
const FAIL = "\x1b[31m✗\x1b[0m";
|
|
17
|
+
function check(label, status, detail) {
|
|
18
|
+
console.log(` ${status} ${label.padEnd(22)} ${detail}`);
|
|
19
|
+
}
|
|
20
|
+
export async function runDoctor() {
|
|
21
|
+
console.log("");
|
|
22
|
+
console.log("\x1b[1m\x1b[36m iMcp Doctor\x1b[0m");
|
|
23
|
+
console.log("");
|
|
24
|
+
// 1. Node version
|
|
25
|
+
const nodeVer = process.version;
|
|
26
|
+
const major = parseInt(nodeVer.slice(1), 10);
|
|
27
|
+
check("Node.js", major >= 18 ? OK : FAIL, `${nodeVer} ${major >= 18 ? "(>= 18 required)" : "— upgrade required (>= 18)"}`);
|
|
28
|
+
// 2. macOS check
|
|
29
|
+
const platform = process.platform;
|
|
30
|
+
check("Platform", platform === "darwin" ? OK : FAIL, platform === "darwin" ? "macOS" : `${platform} — iMcp requires macOS`);
|
|
31
|
+
// 3. Config file
|
|
32
|
+
let fileConfig = null;
|
|
33
|
+
if (existsSync(IMCP_CONFIG_PATH)) {
|
|
34
|
+
try {
|
|
35
|
+
fileConfig = JSON.parse(readFileSync(IMCP_CONFIG_PATH, "utf-8"));
|
|
36
|
+
check("Config file", OK, IMCP_CONFIG_PATH);
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
check("Config file", WARN, `${IMCP_CONFIG_PATH} (parse error)`);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
check("Config file", WARN, "Not found — using starter preset (5 modules)");
|
|
44
|
+
}
|
|
45
|
+
// 4. Claude Desktop config
|
|
46
|
+
if (existsSync(CLAUDE_CONFIG_PATH)) {
|
|
47
|
+
try {
|
|
48
|
+
const raw = JSON.parse(readFileSync(CLAUDE_CONFIG_PATH, "utf-8"));
|
|
49
|
+
const servers = raw?.mcpServers ?? {};
|
|
50
|
+
if (servers.imcp) {
|
|
51
|
+
check("Claude Desktop", OK, "imcp entry found");
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
check("Claude Desktop", WARN, "Config exists but no 'imcp' entry — run: npx @heznpc/imcp init");
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
check("Claude Desktop", WARN, `Config parse error: ${CLAUDE_CONFIG_PATH}`);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
check("Claude Desktop", WARN, "Config not found — run: npx @heznpc/imcp init");
|
|
63
|
+
}
|
|
64
|
+
// 5. Enabled modules
|
|
65
|
+
const disabledSet = new Set(fileConfig?.disabledModules ?? []);
|
|
66
|
+
const enabledMods = [];
|
|
67
|
+
const disabledMods = [];
|
|
68
|
+
for (const mod of MODULE_NAMES) {
|
|
69
|
+
if (fileConfig) {
|
|
70
|
+
// Explicit config
|
|
71
|
+
if (disabledSet.has(mod)) {
|
|
72
|
+
disabledMods.push(mod);
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
enabledMods.push(mod);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
// Starter preset
|
|
80
|
+
if (STARTER_MODULES.has(mod)) {
|
|
81
|
+
enabledMods.push(mod);
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
disabledMods.push(mod);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
console.log("");
|
|
89
|
+
console.log(` \x1b[1mModules\x1b[0m (${enabledMods.length} enabled, ${disabledMods.length} disabled)`);
|
|
90
|
+
for (const mod of MODULE_NAMES) {
|
|
91
|
+
const on = enabledMods.includes(mod);
|
|
92
|
+
console.log(` ${on ? OK : "\x1b[2m-\x1b[0m"} ${mod}${on ? "" : " \x1b[2m(disabled)\x1b[0m"}`);
|
|
93
|
+
}
|
|
94
|
+
// 6. Permission probe (macOS only, skip if not darwin)
|
|
95
|
+
if (platform === "darwin") {
|
|
96
|
+
console.log("");
|
|
97
|
+
console.log(" \x1b[1mPermissions\x1b[0m");
|
|
98
|
+
const APP_MAP = {
|
|
99
|
+
notes: "Notes",
|
|
100
|
+
reminders: "Reminders",
|
|
101
|
+
calendar: "Calendar",
|
|
102
|
+
contacts: "Contacts",
|
|
103
|
+
mail: "Mail",
|
|
104
|
+
messages: "Messages",
|
|
105
|
+
music: "Music",
|
|
106
|
+
finder: "Finder",
|
|
107
|
+
safari: "Safari",
|
|
108
|
+
system: "System Events",
|
|
109
|
+
photos: "Photos",
|
|
110
|
+
tv: "TV",
|
|
111
|
+
};
|
|
112
|
+
for (const mod of enabledMods) {
|
|
113
|
+
const appName = APP_MAP[mod];
|
|
114
|
+
if (!appName)
|
|
115
|
+
continue;
|
|
116
|
+
try {
|
|
117
|
+
execSync(`osascript -l JavaScript -e "Application('${appName}'); JSON.stringify({ok:true})"`, { timeout: 5000, stdio: "pipe" });
|
|
118
|
+
check(` ${appName}`, OK, "Accessible");
|
|
119
|
+
}
|
|
120
|
+
catch {
|
|
121
|
+
check(` ${appName}`, WARN, "Not accessible — grant permission in System Settings > Privacy");
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
// 7. Swift bridge
|
|
126
|
+
const swiftBridgePath = join(process.cwd(), "swift", ".build", "release", "imcp-bridge");
|
|
127
|
+
if (existsSync(swiftBridgePath)) {
|
|
128
|
+
check("Swift bridge", OK, "Built");
|
|
129
|
+
}
|
|
130
|
+
else {
|
|
131
|
+
check("Swift bridge", WARN, "Not built — run: npm run swift-build (optional, for EventKit/PhotoKit/Intelligence)");
|
|
132
|
+
}
|
|
133
|
+
console.log("");
|
|
134
|
+
}
|
|
135
|
+
//# sourceMappingURL=doctor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../src/cli/doctor.ts"],"names":[],"mappings":"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"}
|