scpl-updated-mcp-server 1.0.5 → 1.0.6
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/SCPL_REFERENCE.md +504 -0
- package/index.js +125 -32
- package/package.json +6 -1
|
@@ -0,0 +1,504 @@
|
|
|
1
|
+
# ScPL Language Reference
|
|
2
|
+
|
|
3
|
+
ScPL (Shortcut Programming Language) lets you write Apple Shortcuts as text code instead of dragging blocks.
|
|
4
|
+
|
|
5
|
+
## Basic Syntax
|
|
6
|
+
|
|
7
|
+
```scpl
|
|
8
|
+
ActionName "argument1" "argument2"
|
|
9
|
+
ActionName argument=value anotherArg=value
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
## Variables
|
|
13
|
+
|
|
14
|
+
Three types with `type:name` syntax:
|
|
15
|
+
|
|
16
|
+
| Type | Syntax | Description |
|
|
17
|
+
|------|--------|-------------|
|
|
18
|
+
| Named | `v:MyVar` | Set with SetVariable |
|
|
19
|
+
| Magic | `mv:MyVar` | Auto-created with `->` arrow |
|
|
20
|
+
| Special | `s:Name` | Built-in system variables |
|
|
21
|
+
|
|
22
|
+
### Special Variables
|
|
23
|
+
- `s:ShortcutInput` - Input to the shortcut
|
|
24
|
+
- `s:Clipboard` - Current clipboard contents
|
|
25
|
+
- `s:CurrentDate` - Current date/time
|
|
26
|
+
- `s:AskWhenRun` - Prompt user at runtime
|
|
27
|
+
- `s:ActionInput` - Input to current action
|
|
28
|
+
|
|
29
|
+
### Setting Variables
|
|
30
|
+
|
|
31
|
+
```scpl
|
|
32
|
+
# Named variable (creates SetVariable action)
|
|
33
|
+
Text "Hello" -> v:MyText
|
|
34
|
+
# or
|
|
35
|
+
SetVariable v:MyText
|
|
36
|
+
|
|
37
|
+
# Magic variable (no action created, just reference)
|
|
38
|
+
Text "Hello" -> mv:MyMagic
|
|
39
|
+
|
|
40
|
+
# Pre-assignment style
|
|
41
|
+
mv:Result = Text "Hello"
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### Using Variables in Text
|
|
45
|
+
|
|
46
|
+
```scpl
|
|
47
|
+
Text "The value is \(v:MyVariable)"
|
|
48
|
+
Text "Clipboard: \(s:Clipboard)"
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Flow Control
|
|
52
|
+
|
|
53
|
+
### If/Otherwise/End If
|
|
54
|
+
|
|
55
|
+
```scpl
|
|
56
|
+
Text "test"
|
|
57
|
+
If Equals "test"
|
|
58
|
+
ShowResult "Match!"
|
|
59
|
+
Otherwise
|
|
60
|
+
ShowResult "No match"
|
|
61
|
+
End If
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### Repeat
|
|
65
|
+
|
|
66
|
+
```scpl
|
|
67
|
+
Repeat 5
|
|
68
|
+
ShowResult "Loop iteration"
|
|
69
|
+
End Repeat
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### Repeat with Each
|
|
73
|
+
|
|
74
|
+
```scpl
|
|
75
|
+
RepeatWithEach [item1, item2, item3]
|
|
76
|
+
ShowResult "Processing: \(mv:RepeatItem)"
|
|
77
|
+
End RepeatWithEach
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### Choose from Menu
|
|
81
|
+
|
|
82
|
+
```scpl
|
|
83
|
+
ChooseFromMenu "Pick one" ["Option A", "Option B"]
|
|
84
|
+
Case "Option A"
|
|
85
|
+
ShowResult "You picked A"
|
|
86
|
+
Case "Option B"
|
|
87
|
+
ShowResult "You picked B"
|
|
88
|
+
End Menu
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## Field Types
|
|
92
|
+
|
|
93
|
+
### Text Fields
|
|
94
|
+
```scpl
|
|
95
|
+
Text "Single line"
|
|
96
|
+
Text
|
|
97
|
+
| Multiline text
|
|
98
|
+
| Second line
|
|
99
|
+
| With variable: \(v:Name)
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### Numbers
|
|
103
|
+
```scpl
|
|
104
|
+
Number 42
|
|
105
|
+
Number 3.14
|
|
106
|
+
Number -100
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### Booleans
|
|
110
|
+
```scpl
|
|
111
|
+
SetWifi true
|
|
112
|
+
SetBluetooth false
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### Lists
|
|
116
|
+
```scpl
|
|
117
|
+
List ["item1", "item2", "item3"]
|
|
118
|
+
# or
|
|
119
|
+
List
|
|
120
|
+
| Item 1
|
|
121
|
+
| Item 2
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
### Dictionaries
|
|
125
|
+
```scpl
|
|
126
|
+
Dictionary {
|
|
127
|
+
key: "value"
|
|
128
|
+
number: 42
|
|
129
|
+
nested: {inner: "data"}
|
|
130
|
+
}
|
|
131
|
+
# Quotes and commas optional
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
## Variable Aggrandizements
|
|
135
|
+
|
|
136
|
+
Access properties of variables:
|
|
137
|
+
|
|
138
|
+
```scpl
|
|
139
|
+
# Get dictionary key
|
|
140
|
+
v:MyDict{as:Dictionary,key:myKey}
|
|
141
|
+
# Shorthand
|
|
142
|
+
v:MyDict:myKey
|
|
143
|
+
|
|
144
|
+
# Get property
|
|
145
|
+
v:Contact{as:Contact,get:Email}
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
## Actions Inside Actions
|
|
149
|
+
|
|
150
|
+
Inline actions in parentheses:
|
|
151
|
+
|
|
152
|
+
```scpl
|
|
153
|
+
Text "Number is \(Number 42)"
|
|
154
|
+
If Equals (Text "compare value")
|
|
155
|
+
ShowResult "Match"
|
|
156
|
+
End If
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
## Comments
|
|
160
|
+
|
|
161
|
+
```scpl
|
|
162
|
+
# This is a comment
|
|
163
|
+
// Also a comment
|
|
164
|
+
-- Also works
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
---
|
|
168
|
+
|
|
169
|
+
# Common Actions
|
|
170
|
+
|
|
171
|
+
## Text & Display
|
|
172
|
+
|
|
173
|
+
```scpl
|
|
174
|
+
Text "Your text here"
|
|
175
|
+
ShowResult "Display this"
|
|
176
|
+
ShowAlert title="Title" message="Body text"
|
|
177
|
+
ShowNotification title="Hey" body="Message"
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
## Clipboard
|
|
181
|
+
|
|
182
|
+
```scpl
|
|
183
|
+
GetClipboard
|
|
184
|
+
SetClipboard "New content"
|
|
185
|
+
# or with variable
|
|
186
|
+
Text "Copy this" -> mv:Content
|
|
187
|
+
SetClipboard mv:Content
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
## Variables
|
|
191
|
+
|
|
192
|
+
```scpl
|
|
193
|
+
SetVariable v:Name
|
|
194
|
+
GetVariable v:Name
|
|
195
|
+
AddToVariable v:List
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
## Lists & Dictionaries
|
|
199
|
+
|
|
200
|
+
```scpl
|
|
201
|
+
List ["a", "b", "c"]
|
|
202
|
+
GetItemFromList "First Item"
|
|
203
|
+
GetItemFromList "Last Item"
|
|
204
|
+
GetItemFromList "Random Item"
|
|
205
|
+
Count "Items"
|
|
206
|
+
|
|
207
|
+
Dictionary {key: "value"}
|
|
208
|
+
GetDictionaryValue key="mykey"
|
|
209
|
+
SetDictionaryValue key="mykey" value="newvalue"
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
## Math
|
|
213
|
+
|
|
214
|
+
```scpl
|
|
215
|
+
Number 10
|
|
216
|
+
Calculate "+" 5
|
|
217
|
+
Calculate "*" 2
|
|
218
|
+
Calculate "/" 4
|
|
219
|
+
RoundNumber "Normal"
|
|
220
|
+
RandomNumber min=1 max=100
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
## Dates
|
|
224
|
+
|
|
225
|
+
```scpl
|
|
226
|
+
Date "tomorrow at 9am"
|
|
227
|
+
FormatDate "short"
|
|
228
|
+
AdjustDate "1 week"
|
|
229
|
+
GetTimeBetweenDates unit="Days"
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
## Files
|
|
233
|
+
|
|
234
|
+
```scpl
|
|
235
|
+
GetFile service="iCloud Drive" filepath="/path/to/file"
|
|
236
|
+
SaveFile destinationpath="/save/here"
|
|
237
|
+
GetFolderContents
|
|
238
|
+
DeleteFiles immediately=true
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
## Web
|
|
242
|
+
|
|
243
|
+
```scpl
|
|
244
|
+
URL "https://example.com"
|
|
245
|
+
GetContentsOfURL
|
|
246
|
+
ExpandURL
|
|
247
|
+
GetComponentOfURL component="Host"
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
---
|
|
251
|
+
|
|
252
|
+
# macOS Tahoe Actions (New)
|
|
253
|
+
|
|
254
|
+
## Apple Intelligence (Apple Silicon only)
|
|
255
|
+
|
|
256
|
+
```scpl
|
|
257
|
+
# Ask AI model
|
|
258
|
+
AskLLM model="Apple Intelligence" prompt="Summarize this text"
|
|
259
|
+
AskLLM model="ChatGPT" prompt="Explain quantum computing"
|
|
260
|
+
|
|
261
|
+
# Image generation
|
|
262
|
+
GenerateImage prompt="A sunset over mountains" style="Illustration"
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
## AI Assistants
|
|
266
|
+
|
|
267
|
+
```scpl
|
|
268
|
+
# ChatGPT (requires app)
|
|
269
|
+
AskChatGPT prompt="Help me write an email"
|
|
270
|
+
OpenChatGPTVoiceMode
|
|
271
|
+
|
|
272
|
+
# Claude (requires app)
|
|
273
|
+
AskClaude message="Analyze this code"
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
## Shell Scripts
|
|
277
|
+
|
|
278
|
+
```scpl
|
|
279
|
+
# Bash script
|
|
280
|
+
RunShellScript shell="/bin/bash" script="echo Hello World"
|
|
281
|
+
|
|
282
|
+
# Zsh with input
|
|
283
|
+
GetClipboard
|
|
284
|
+
RunShellScript shell="/bin/zsh" script="cat | wc -w"
|
|
285
|
+
|
|
286
|
+
# AppleScript
|
|
287
|
+
RunAppleScript script="display dialog \"Hello!\""
|
|
288
|
+
|
|
289
|
+
# JavaScript for Automation
|
|
290
|
+
RunJavaScriptForAutomation script="Application('Finder').selection()"
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
## File Operations
|
|
294
|
+
|
|
295
|
+
```scpl
|
|
296
|
+
# Get file by path
|
|
297
|
+
File path="~/Documents/myfile.txt"
|
|
298
|
+
|
|
299
|
+
# Rename
|
|
300
|
+
RenameFile name="newname.txt"
|
|
301
|
+
|
|
302
|
+
# Move
|
|
303
|
+
MoveFile destination="~/Desktop/"
|
|
304
|
+
|
|
305
|
+
# Reveal in Finder
|
|
306
|
+
RevealInFinder
|
|
307
|
+
|
|
308
|
+
# Select file (prompt)
|
|
309
|
+
SelectFile
|
|
310
|
+
|
|
311
|
+
# Get folder contents
|
|
312
|
+
GetFolderContents path="~/Documents"
|
|
313
|
+
|
|
314
|
+
# Get Finder selection
|
|
315
|
+
GetSelectedFiles
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
## System
|
|
319
|
+
|
|
320
|
+
```scpl
|
|
321
|
+
# Dark/Light mode
|
|
322
|
+
SetAppearance "Dark"
|
|
323
|
+
SetAppearance "Light"
|
|
324
|
+
|
|
325
|
+
# Screenshots
|
|
326
|
+
TakeScreenshot
|
|
327
|
+
|
|
328
|
+
# Lock screen
|
|
329
|
+
LockScreen
|
|
330
|
+
|
|
331
|
+
# On-screen OCR
|
|
332
|
+
GetOnScreenContent
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
## Clock & Timers
|
|
336
|
+
|
|
337
|
+
```scpl
|
|
338
|
+
StartStopwatch
|
|
339
|
+
StopStopwatch
|
|
340
|
+
CreateAlarm time="7:00 AM" label="Wake up"
|
|
341
|
+
StartTimer minutes=25
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
## Voice Memos
|
|
345
|
+
|
|
346
|
+
```scpl
|
|
347
|
+
CreateRecording
|
|
348
|
+
PlayRecording
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
---
|
|
352
|
+
|
|
353
|
+
# Complete Workflow Examples
|
|
354
|
+
|
|
355
|
+
## Morning Routine
|
|
356
|
+
|
|
357
|
+
```scpl
|
|
358
|
+
# Turn off dark mode
|
|
359
|
+
SetAppearance "Light"
|
|
360
|
+
|
|
361
|
+
# Check weather
|
|
362
|
+
GetCurrentWeather -> mv:Weather
|
|
363
|
+
Text "Good morning! Today's weather: \(mv:Weather)"
|
|
364
|
+
ShowNotification title="Morning" body=mv:Text
|
|
365
|
+
|
|
366
|
+
# Open calendar
|
|
367
|
+
OpenApp "Calendar"
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
## Clipboard AI Enhancement
|
|
371
|
+
|
|
372
|
+
```scpl
|
|
373
|
+
GetClipboard -> mv:Original
|
|
374
|
+
AskLLM model="Apple Intelligence" prompt="Improve this text for clarity: \(mv:Original)"
|
|
375
|
+
SetClipboard
|
|
376
|
+
ShowAlert title="Done" message="Improved text copied!"
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
## Pomodoro Timer with Logging
|
|
380
|
+
|
|
381
|
+
```scpl
|
|
382
|
+
# Start work session
|
|
383
|
+
ShowNotification title="Pomodoro" body="25 minute focus session started"
|
|
384
|
+
StartTimer minutes=25
|
|
385
|
+
|
|
386
|
+
# Log session
|
|
387
|
+
Date -> mv:StartTime
|
|
388
|
+
Text "Work session started at \(mv:StartTime)" -> mv:Log
|
|
389
|
+
AppendToFile path="~/Documents/pomodoro-log.txt" text=mv:Log
|
|
390
|
+
```
|
|
391
|
+
|
|
392
|
+
## Screenshot with AI Description
|
|
393
|
+
|
|
394
|
+
```scpl
|
|
395
|
+
TakeScreenshot -> mv:Screenshot
|
|
396
|
+
AskLLM model="Apple Intelligence" prompt="Describe what's in this image"
|
|
397
|
+
SetVariable v:Description
|
|
398
|
+
|
|
399
|
+
# Save with description
|
|
400
|
+
Text "Screenshot: \(v:Description)"
|
|
401
|
+
ShowResult
|
|
402
|
+
```
|
|
403
|
+
|
|
404
|
+
## DevOps Status Check
|
|
405
|
+
|
|
406
|
+
```scpl
|
|
407
|
+
RunShellScript shell="/bin/zsh" script="git status --short" -> mv:GitStatus
|
|
408
|
+
RunShellScript shell="/bin/zsh" script="docker ps --format 'table {{.Names}}\t{{.Status}}'" -> mv:Docker
|
|
409
|
+
|
|
410
|
+
Text
|
|
411
|
+
| Git Status:
|
|
412
|
+
| \(mv:GitStatus)
|
|
413
|
+
|
|
|
414
|
+
| Docker Containers:
|
|
415
|
+
| \(mv:Docker)
|
|
416
|
+
|
|
417
|
+
ShowResult
|
|
418
|
+
```
|
|
419
|
+
|
|
420
|
+
## File Organizer
|
|
421
|
+
|
|
422
|
+
```scpl
|
|
423
|
+
GetSelectedFiles -> mv:Files
|
|
424
|
+
RepeatWithEach mv:Files
|
|
425
|
+
GetDetailsOfFiles detail="File Extension" -> mv:Ext
|
|
426
|
+
|
|
427
|
+
If Equals "pdf"
|
|
428
|
+
MoveFile destination="~/Documents/PDFs/"
|
|
429
|
+
Otherwise
|
|
430
|
+
If Equals "jpg"
|
|
431
|
+
MoveFile destination="~/Pictures/"
|
|
432
|
+
End If
|
|
433
|
+
End If
|
|
434
|
+
End RepeatWithEach
|
|
435
|
+
|
|
436
|
+
ShowNotification title="Done" body="Files organized!"
|
|
437
|
+
```
|
|
438
|
+
|
|
439
|
+
## Quick Note from Voice
|
|
440
|
+
|
|
441
|
+
```scpl
|
|
442
|
+
DictateText -> mv:Spoken
|
|
443
|
+
AskLLM model="Apple Intelligence" prompt="Clean up and format: \(mv:Spoken)"
|
|
444
|
+
SetVariable v:CleanedNote
|
|
445
|
+
|
|
446
|
+
CreateNote title="Voice Note" body=v:CleanedNote
|
|
447
|
+
ShowNotification title="Saved" body="Voice note created"
|
|
448
|
+
```
|
|
449
|
+
|
|
450
|
+
---
|
|
451
|
+
|
|
452
|
+
# Tips & Common Patterns
|
|
453
|
+
|
|
454
|
+
## Error Handling Pattern
|
|
455
|
+
```scpl
|
|
456
|
+
GetFile path="~/file.txt" errorIfNotFound=false -> mv:File
|
|
457
|
+
Count
|
|
458
|
+
If Equals 0
|
|
459
|
+
ShowAlert title="Error" message="File not found"
|
|
460
|
+
ExitShortcut
|
|
461
|
+
End If
|
|
462
|
+
# Continue with file...
|
|
463
|
+
```
|
|
464
|
+
|
|
465
|
+
## User Input Validation
|
|
466
|
+
```scpl
|
|
467
|
+
AskForInput prompt="Enter a number" -> mv:Input
|
|
468
|
+
If "is not" "Number"
|
|
469
|
+
ShowAlert title="Error" message="Please enter a valid number"
|
|
470
|
+
ExitShortcut
|
|
471
|
+
End If
|
|
472
|
+
```
|
|
473
|
+
|
|
474
|
+
## Chaining API Calls
|
|
475
|
+
```scpl
|
|
476
|
+
URL "https://api.example.com/data"
|
|
477
|
+
GetContentsOfURL -> mv:Response
|
|
478
|
+
GetDictionaryValue key="items"
|
|
479
|
+
RepeatWithEach
|
|
480
|
+
# Process each item
|
|
481
|
+
End RepeatWithEach
|
|
482
|
+
```
|
|
483
|
+
|
|
484
|
+
---
|
|
485
|
+
|
|
486
|
+
# Quick Reference
|
|
487
|
+
|
|
488
|
+
| Task | ScPL Code |
|
|
489
|
+
|------|-----------|
|
|
490
|
+
| Show text | `ShowResult "Hello"` |
|
|
491
|
+
| Get clipboard | `GetClipboard` |
|
|
492
|
+
| Set clipboard | `SetClipboard "text"` |
|
|
493
|
+
| User input | `AskForInput prompt="Question"` |
|
|
494
|
+
| Run shell | `RunShellScript shell="/bin/zsh" script="cmd"` |
|
|
495
|
+
| AI prompt | `AskLLM model="Apple Intelligence" prompt="..."` |
|
|
496
|
+
| Variable | `Text "x" -> v:Name` then `\(v:Name)` |
|
|
497
|
+
| Magic var | `Text "x" -> mv:Name` then `mv:Name` |
|
|
498
|
+
| Condition | `If Equals "value"` ... `End If` |
|
|
499
|
+
| Loop | `Repeat 5` ... `End Repeat` |
|
|
500
|
+
| Menu | `ChooseFromMenu "title" [options]` ... `End Menu` |
|
|
501
|
+
|
|
502
|
+
---
|
|
503
|
+
|
|
504
|
+
**493 total actions available.** Use `list_actions` tool to search by category or keyword.
|
package/index.js
CHANGED
|
@@ -29,26 +29,30 @@ USAGE:
|
|
|
29
29
|
npx scpl-updated-mcp-server [OPTIONS]
|
|
30
30
|
|
|
31
31
|
OPTIONS:
|
|
32
|
-
--setup Auto-install for Claude Code
|
|
32
|
+
--setup Auto-install for Claude Code (CLI)
|
|
33
|
+
--setup-desktop Auto-install for Claude Desktop (GUI app)
|
|
33
34
|
--setup-codex Auto-install for OpenAI Codex CLI (~/.codex)
|
|
34
35
|
--setup-codex=<dir> Auto-install for Codex forks with custom directory
|
|
35
36
|
--help, -h Show this help message
|
|
36
37
|
|
|
37
38
|
You can combine multiple flags to set up multiple tools at once:
|
|
38
|
-
npx scpl-updated-mcp-server --setup --setup-
|
|
39
|
+
npx scpl-updated-mcp-server --setup --setup-desktop --setup-codex
|
|
39
40
|
|
|
40
41
|
EXAMPLES:
|
|
41
|
-
# Claude Code only
|
|
42
|
+
# Claude Code (CLI) only
|
|
42
43
|
npx scpl-updated-mcp-server --setup
|
|
43
44
|
|
|
45
|
+
# Claude Desktop (GUI app) only
|
|
46
|
+
npx scpl-updated-mcp-server --setup-desktop
|
|
47
|
+
|
|
44
48
|
# Codex only
|
|
45
49
|
npx scpl-updated-mcp-server --setup-codex
|
|
46
50
|
|
|
47
51
|
# Custom Codex directory (just-every/code, etc.)
|
|
48
52
|
npx scpl-updated-mcp-server --setup-codex=$CODE_HOME
|
|
49
53
|
|
|
50
|
-
# All
|
|
51
|
-
npx scpl-updated-mcp-server --setup --setup-
|
|
54
|
+
# All Claude + Codex tools at once
|
|
55
|
+
npx scpl-updated-mcp-server --setup --setup-desktop --setup-codex
|
|
52
56
|
|
|
53
57
|
After setup, restart your AI coding tool and ask:
|
|
54
58
|
"Create a shortcut that starts a timer and plays a sound"
|
|
@@ -115,7 +119,30 @@ function setupClaudeCode() {
|
|
|
115
119
|
};
|
|
116
120
|
writeFileSync(join(pluginsDir, "plugin.json"), JSON.stringify(pluginJson, null, 2));
|
|
117
121
|
|
|
118
|
-
|
|
122
|
+
// Read comprehensive ScPL reference
|
|
123
|
+
const refPath = join(__dirname, "SCPL_REFERENCE.md");
|
|
124
|
+
let skillContent = "";
|
|
125
|
+
if (existsSync(refPath)) {
|
|
126
|
+
const reference = readFileSync(refPath, "utf-8");
|
|
127
|
+
skillContent = `---
|
|
128
|
+
description: Create macOS Shortcuts using natural language with ScPL.
|
|
129
|
+
tags: [shortcuts, automation, macos, scpl, apple-intelligence]
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
# ScPL Shortcuts Skill
|
|
133
|
+
|
|
134
|
+
You have access to the ScPL MCP server with **493 actions**.
|
|
135
|
+
|
|
136
|
+
## Available Tools
|
|
137
|
+
- \`create_shortcut\` - Convert ScPL code to .shortcut file
|
|
138
|
+
- \`validate_scpl\` - Check syntax without creating file
|
|
139
|
+
- \`list_actions\` - Search available actions by category/keyword
|
|
140
|
+
|
|
141
|
+
${reference}
|
|
142
|
+
`;
|
|
143
|
+
} else {
|
|
144
|
+
// Fallback minimal skill if reference not found
|
|
145
|
+
skillContent = `---
|
|
119
146
|
description: Create macOS Shortcuts using natural language.
|
|
120
147
|
tags: [shortcuts, automation, macos, scpl]
|
|
121
148
|
---
|
|
@@ -123,19 +150,13 @@ tags: [shortcuts, automation, macos, scpl]
|
|
|
123
150
|
# Create Shortcut Skill
|
|
124
151
|
|
|
125
152
|
You have access to the ScPL MCP server with 493 actions.
|
|
153
|
+
Tools: create_shortcut, validate_scpl, list_actions
|
|
126
154
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
\`\`\`scpl
|
|
131
|
-
Text "Hello"
|
|
132
|
-
AskLLM model="Apple Intelligence" prompt="Make it fun"
|
|
133
|
-
ShowResult
|
|
134
|
-
\`\`\`
|
|
135
|
-
|
|
136
|
-
## Categories
|
|
137
|
-
AI, Clock, Voice Memos, System, Files, Scripting, Clipboard
|
|
155
|
+
Basic syntax: \`ActionName "arg"\` or \`ActionName param=value\`
|
|
156
|
+
Variables: \`v:Named\`, \`mv:Magic\`, \`s:Special\`
|
|
157
|
+
Flow: \`If\`/\`End If\`, \`Repeat\`/\`End Repeat\`
|
|
138
158
|
`;
|
|
159
|
+
}
|
|
139
160
|
writeFileSync(join(pluginsDir, "skills", "create-shortcut.md"), skillContent);
|
|
140
161
|
console.log(" ✅ Plugin files created!\n");
|
|
141
162
|
} catch (error) {
|
|
@@ -173,6 +194,57 @@ AI, Clock, Voice Memos, System, Files, Scripting, Clipboard
|
|
|
173
194
|
console.log("✅ Claude Code setup complete!\n");
|
|
174
195
|
}
|
|
175
196
|
|
|
197
|
+
function setupClaudeDesktop() {
|
|
198
|
+
console.log("═══════════════════════════════════════════════════════════════");
|
|
199
|
+
console.log("🚀 Setting up ScPL Shortcuts for Claude Desktop...");
|
|
200
|
+
console.log("═══════════════════════════════════════════════════════════════\n");
|
|
201
|
+
|
|
202
|
+
// Determine config path based on OS
|
|
203
|
+
let configPath;
|
|
204
|
+
const platform = process.platform;
|
|
205
|
+
if (platform === "darwin") {
|
|
206
|
+
configPath = join(homedir(), "Library", "Application Support", "Claude", "claude_desktop_config.json");
|
|
207
|
+
} else if (platform === "win32") {
|
|
208
|
+
configPath = join(process.env.APPDATA || "", "Claude", "claude_desktop_config.json");
|
|
209
|
+
} else {
|
|
210
|
+
configPath = join(homedir(), ".config", "Claude", "claude_desktop_config.json");
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
console.log(`📝 Adding MCP server to ${configPath}...`);
|
|
214
|
+
try {
|
|
215
|
+
// Ensure directory exists
|
|
216
|
+
mkdirSync(dirname(configPath), { recursive: true });
|
|
217
|
+
|
|
218
|
+
let config = {};
|
|
219
|
+
if (existsSync(configPath)) {
|
|
220
|
+
config = JSON.parse(readFileSync(configPath, "utf-8"));
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
if (!config.mcpServers) {
|
|
224
|
+
config.mcpServers = {};
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
if (config.mcpServers["scpl-shortcuts"]) {
|
|
228
|
+
console.log(" ⏭️ Already configured, skipping...\n");
|
|
229
|
+
} else {
|
|
230
|
+
config.mcpServers["scpl-shortcuts"] = {
|
|
231
|
+
command: "npx",
|
|
232
|
+
args: ["-y", "scpl-updated-mcp-server"]
|
|
233
|
+
};
|
|
234
|
+
writeFileSync(configPath, JSON.stringify(config, null, 2));
|
|
235
|
+
console.log(" ✅ MCP server added!\n");
|
|
236
|
+
}
|
|
237
|
+
} catch (error) {
|
|
238
|
+
console.error(" ❌ Failed:", error.message, "\n");
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
console.log("✅ Claude Desktop setup complete!\n");
|
|
242
|
+
console.log("ℹ️ Note: Claude Desktop doesn't have plugins/skills.\n");
|
|
243
|
+
console.log(" The MCP tools (create_shortcut, validate_scpl, list_actions)");
|
|
244
|
+
console.log(" will be available, but Claude won't have the full ScPL reference");
|
|
245
|
+
console.log(" loaded as context. Consider using Claude Code for best results.\n");
|
|
246
|
+
}
|
|
247
|
+
|
|
176
248
|
function setupCodex(codexDir) {
|
|
177
249
|
console.log("═══════════════════════════════════════════════════════════════");
|
|
178
250
|
console.log(`🚀 Setting up ScPL Shortcuts for Codex at ${codexDir}...`);
|
|
@@ -210,32 +282,47 @@ startup_timeout_sec = 60.0
|
|
|
210
282
|
try {
|
|
211
283
|
mkdirSync(skillDir, { recursive: true });
|
|
212
284
|
|
|
213
|
-
|
|
285
|
+
// Read comprehensive ScPL reference
|
|
286
|
+
const refPath = join(__dirname, "SCPL_REFERENCE.md");
|
|
287
|
+
let skillContent = "";
|
|
288
|
+
if (existsSync(refPath)) {
|
|
289
|
+
const reference = readFileSync(refPath, "utf-8");
|
|
290
|
+
skillContent = `---
|
|
214
291
|
name: scpl-shortcuts
|
|
215
|
-
description: Create macOS Shortcuts using natural language.
|
|
292
|
+
description: Create macOS Shortcuts using natural language with ScPL.
|
|
216
293
|
metadata:
|
|
217
294
|
short-description: Create macOS Shortcuts with AI
|
|
218
295
|
---
|
|
219
296
|
|
|
220
297
|
# ScPL Shortcuts Skill
|
|
221
298
|
|
|
222
|
-
|
|
299
|
+
You have access to the ScPL MCP server with **493 actions**.
|
|
300
|
+
|
|
301
|
+
## Available Tools
|
|
302
|
+
- \`create_shortcut\` - Convert ScPL code to .shortcut file
|
|
303
|
+
- \`validate_scpl\` - Check syntax without creating file
|
|
304
|
+
- \`list_actions\` - Search available actions by category/keyword
|
|
305
|
+
|
|
306
|
+
${reference}
|
|
307
|
+
`;
|
|
308
|
+
} else {
|
|
309
|
+
// Fallback minimal skill
|
|
310
|
+
skillContent = `---
|
|
311
|
+
name: scpl-shortcuts
|
|
312
|
+
description: Create macOS Shortcuts using natural language.
|
|
313
|
+
metadata:
|
|
314
|
+
short-description: Create macOS Shortcuts with AI
|
|
315
|
+
---
|
|
223
316
|
|
|
224
|
-
|
|
225
|
-
\`\`\`scpl
|
|
226
|
-
Text "Hello"
|
|
227
|
-
AskLLM model="Apple Intelligence" prompt="Make it fun"
|
|
228
|
-
ShowResult
|
|
229
|
-
\`\`\`
|
|
317
|
+
# ScPL Shortcuts Skill
|
|
230
318
|
|
|
231
|
-
|
|
232
|
-
AI, Clock, Voice Memos, System, Files, Scripting, Clipboard
|
|
319
|
+
493 actions available. Tools: create_shortcut, validate_scpl, list_actions
|
|
233
320
|
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
3. create_shortcut to generate .shortcut file
|
|
321
|
+
Basic syntax: \`ActionName "arg"\` or \`ActionName param=value\`
|
|
322
|
+
Variables: \`v:Named\`, \`mv:Magic\`, \`s:Special\`
|
|
323
|
+
Flow: \`If\`/\`End If\`, \`Repeat\`/\`End Repeat\`
|
|
238
324
|
`;
|
|
325
|
+
}
|
|
239
326
|
writeFileSync(join(skillDir, "SKILL.md"), skillContent);
|
|
240
327
|
console.log(" ✅ Skill installed!\n");
|
|
241
328
|
} catch (error) {
|
|
@@ -257,6 +344,12 @@ if (process.argv.includes("--setup")) {
|
|
|
257
344
|
didSetup = true;
|
|
258
345
|
}
|
|
259
346
|
|
|
347
|
+
// Claude Desktop setup
|
|
348
|
+
if (process.argv.includes("--setup-desktop")) {
|
|
349
|
+
setupClaudeDesktop();
|
|
350
|
+
didSetup = true;
|
|
351
|
+
}
|
|
352
|
+
|
|
260
353
|
// Codex setups (can have multiple --setup-codex and --setup-codex=<dir>)
|
|
261
354
|
const codexArgs = process.argv.filter(arg => arg.startsWith("--setup-codex"));
|
|
262
355
|
for (const codexArg of codexArgs) {
|
package/package.json
CHANGED
|
@@ -1,12 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "scpl-updated-mcp-server",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.6",
|
|
4
4
|
"description": "AI-powered Apple Shortcuts creation with Claude Code! Generate macOS shortcuts using natural language. 493 actions available. MCP server for text-based shortcut programming. Vibe code your automation workflows.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.js",
|
|
7
7
|
"bin": {
|
|
8
8
|
"scpl-updated-mcp-server": "index.js"
|
|
9
9
|
},
|
|
10
|
+
"files": [
|
|
11
|
+
"index.js",
|
|
12
|
+
"SCPL_REFERENCE.md",
|
|
13
|
+
"README.md"
|
|
14
|
+
],
|
|
10
15
|
"scripts": {
|
|
11
16
|
"start": "node index.js"
|
|
12
17
|
},
|