scpl-updated-mcp-server 1.0.3 → 1.0.5

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.
Files changed (2) hide show
  1. package/index.js +190 -340
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -10,7 +10,7 @@ import {
10
10
  } from "@modelcontextprotocol/sdk/types.js";
11
11
  import pkg from "scpl-macos-updated";
12
12
  const { convert } = pkg;
13
- import { writeFileSync, readFileSync, existsSync, mkdirSync } from "fs";
13
+ import { writeFileSync, readFileSync, existsSync, mkdirSync, appendFileSync } from "fs";
14
14
  import { join, dirname } from "path";
15
15
  import { homedir } from "os";
16
16
  import { fileURLToPath } from "url";
@@ -29,160 +29,41 @@ USAGE:
29
29
  npx scpl-updated-mcp-server [OPTIONS]
30
30
 
31
31
  OPTIONS:
32
- --setup Auto-install for Claude Code (recommended)
33
- --setup-codex Auto-install for OpenAI Codex CLI
34
- --help, -h Show this help message
32
+ --setup Auto-install for Claude Code
33
+ --setup-codex Auto-install for OpenAI Codex CLI (~/.codex)
34
+ --setup-codex=<dir> Auto-install for Codex forks with custom directory
35
+ --help, -h Show this help message
35
36
 
36
- EXAMPLES:
37
- npx scpl-updated-mcp-server --setup # Install for Claude Code
38
- npx scpl-updated-mcp-server --setup-codex # Install for Codex
37
+ You can combine multiple flags to set up multiple tools at once:
38
+ npx scpl-updated-mcp-server --setup --setup-codex --setup-codex=~/.code
39
39
 
40
- After setup, restart your AI coding tool and ask:
41
- "Create a shortcut that starts a timer and plays a sound"
42
- `);
43
- process.exit(0);
44
- }
40
+ EXAMPLES:
41
+ # Claude Code only
42
+ npx scpl-updated-mcp-server --setup
45
43
 
46
- // ============================================================================
47
- // CODEX SETUP: Run with --setup-codex for OpenAI Codex CLI
48
- // ============================================================================
49
- if (process.argv.includes("--setup-codex")) {
50
- console.log("šŸš€ Setting up ScPL Shortcuts for Codex...\n");
44
+ # Codex only
45
+ npx scpl-updated-mcp-server --setup-codex
51
46
 
52
- const codexConfigPath = join(homedir(), ".codex", "config.toml");
53
- const skillDir = join(homedir(), ".codex", "skills", "scpl-shortcuts");
47
+ # Custom Codex directory (just-every/code, etc.)
48
+ npx scpl-updated-mcp-server --setup-codex=$CODE_HOME
54
49
 
55
- // Step 1: Add MCP server to ~/.codex/config.toml
56
- console.log("šŸ“ Step 1: Adding MCP server to ~/.codex/config.toml...");
57
- try {
58
- let config = "";
59
- if (existsSync(codexConfigPath)) {
60
- config = readFileSync(codexConfigPath, "utf-8");
61
- }
50
+ # All at once: Claude + Codex + custom fork
51
+ npx scpl-updated-mcp-server --setup --setup-codex --setup-codex=~/.code
62
52
 
63
- // Check if already configured
64
- if (config.includes('[mcp_servers."scpl-shortcuts"]') || config.includes('[mcp_servers.scpl-shortcuts]')) {
65
- console.log(" ā­ļø Already configured, skipping...\n");
66
- } else {
67
- const tomlBlock = `
68
- [mcp_servers.scpl-shortcuts]
69
- command = "npx"
70
- args = ["-y", "scpl-updated-mcp-server"]
71
- startup_timeout_sec = 60.0
72
- `;
73
- writeFileSync(codexConfigPath, config + tomlBlock);
74
- console.log(" āœ… MCP server added!\n");
75
- }
76
- } catch (error) {
77
- console.error(" āŒ Failed to update config:", error.message);
78
- console.log(" Add this to ~/.codex/config.toml manually:");
79
- console.log(`
80
- [mcp_servers.scpl-shortcuts]
81
- command = "npx"
82
- args = ["-y", "scpl-updated-mcp-server"]
83
- startup_timeout_sec = 60.0
53
+ After setup, restart your AI coding tool and ask:
54
+ "Create a shortcut that starts a timer and plays a sound"
84
55
  `);
85
- }
86
-
87
- // Step 2: Install skill to ~/.codex/skills/scpl-shortcuts/
88
- console.log("šŸ“ Step 2: Installing skill to ~/.codex/skills/scpl-shortcuts/...");
89
- try {
90
- mkdirSync(skillDir, { recursive: true });
91
-
92
- const skillContent = `---
93
- name: scpl-shortcuts
94
- description: Create macOS Shortcuts using natural language. Use when users want to create, generate, or build Apple Shortcuts. Converts requests to ScPL code and generates .shortcut files.
95
- metadata:
96
- short-description: Create macOS Shortcuts with AI
97
- ---
98
-
99
- # ScPL Shortcuts Skill
100
-
101
- Create macOS Shortcuts using natural language with 493 available actions.
102
-
103
- ## MCP Tools Available
104
-
105
- You have access to the \`scpl-shortcuts\` MCP server with these tools:
106
-
107
- | Tool | Description |
108
- |------|-------------|
109
- | \`create_shortcut\` | Generate a .shortcut file from ScPL code |
110
- | \`validate_scpl\` | Check if ScPL code is valid before creating |
111
- | \`list_actions\` | Search available actions by category or keyword |
112
-
113
- ## ScPL Syntax
114
-
115
- ScPL is line-based. Each line is an action. Parameters use \`key=value\` or \`key="value"\`.
116
-
117
- \`\`\`scpl
118
- # Comments start with #
119
- Text "Hello World"
120
- ShowResult
121
-
122
- # Variables
123
- Text "some value"
124
- SetVariable v:myVar
125
- ShowResult v:myVar
126
-
127
- # AI actions
128
- AskLLM model="Apple Intelligence" prompt="Summarize this"
129
- AskChatGPT prompt="Explain this"
130
- \`\`\`
131
-
132
- ## Popular Actions by Category
133
-
134
- **AI**: AskLLM, AskChatGPT, AskClaude
135
- **Clock**: StartStopwatch, StopStopwatch, CreateAlarm
136
- **Voice Memos**: CreateRecording, PlayRecording
137
- **System**: SetDarkMode, TakeScreenshot, LockScreen
138
- **Files**: GetFile, SaveFile, RenameFile, RevealInFinder
139
- **Scripting**: RunShellScript, RunAppleScript, RunJavaScriptForAutomation
140
- **Clipboard**: GetClipboard, SetClipboard
141
-
142
- ## Workflow
143
-
144
- 1. User describes what shortcut they want
145
- 2. Use \`list_actions\` if you need to find specific actions
146
- 3. Write ScPL code for the shortcut
147
- 4. Use \`validate_scpl\` to check syntax
148
- 5. Use \`create_shortcut\` to generate the .shortcut file
149
- 6. Tell user to install via Shortcut Source Helper from RoutineHub
150
-
151
- ## Example: Timer with Notification
152
-
153
- \`\`\`scpl
154
- # Start a 25-minute Pomodoro timer
155
- StartTimer minutes=25
156
- ShowAlert title="Timer Started" message="Focus for 25 minutes!"
157
- \`\`\`
158
-
159
- ## Example: Clipboard AI Enhancement
160
-
161
- \`\`\`scpl
162
- GetClipboard
163
- SetVariable v:text
164
- AskChatGPT prompt="Improve this text: \\(v:text)"
165
- SetClipboard
166
- ShowAlert title="Done" message="Improved text copied!"
167
- \`\`\`
168
- `;
169
- writeFileSync(join(skillDir, "SKILL.md"), skillContent);
170
- console.log(" āœ… Skill installed!\n");
171
- } catch (error) {
172
- console.error(" āŒ Failed to install skill:", error.message, "\n");
173
- }
174
-
175
- console.log("šŸŽ‰ Setup complete! Restart Codex to use the shortcuts tools.\n");
176
- console.log("Usage: Just ask Codex to create a shortcut!");
177
- console.log(' Example: "Create a shortcut that starts a timer and plays a sound"\n');
178
56
  process.exit(0);
179
57
  }
180
58
 
181
59
  // ============================================================================
182
- // CLAUDE CODE SETUP: Run with --setup to install everything automatically
60
+ // SETUP FUNCTIONS
183
61
  // ============================================================================
184
- if (process.argv.includes("--setup")) {
185
- console.log("šŸš€ Setting up ScPL Shortcuts for Claude Code...\n");
62
+
63
+ function setupClaudeCode() {
64
+ console.log("═══════════════════════════════════════════════════════════════");
65
+ console.log("šŸš€ Setting up ScPL Shortcuts for Claude Code...");
66
+ console.log("═══════════════════════════════════════════════════════════════\n");
186
67
 
187
68
  const claudeJsonPath = join(homedir(), ".claude.json");
188
69
  const pluginsDir = join(homedir(), ".claude", "plugins", "local", "scpl-shortcuts");
@@ -200,18 +81,19 @@ if (process.argv.includes("--setup")) {
200
81
  claudeConfig.mcpServers = {};
201
82
  }
202
83
 
203
- claudeConfig.mcpServers["scpl-shortcuts"] = {
204
- type: "stdio",
205
- command: "npx",
206
- args: ["-y", "scpl-updated-mcp-server"]
207
- };
208
-
209
- writeFileSync(claudeJsonPath, JSON.stringify(claudeConfig, null, 2));
210
- console.log(" āœ… MCP server added!\n");
84
+ if (claudeConfig.mcpServers["scpl-shortcuts"]) {
85
+ console.log(" ā­ļø Already configured, skipping...\n");
86
+ } else {
87
+ claudeConfig.mcpServers["scpl-shortcuts"] = {
88
+ type: "stdio",
89
+ command: "npx",
90
+ args: ["-y", "scpl-updated-mcp-server"]
91
+ };
92
+ writeFileSync(claudeJsonPath, JSON.stringify(claudeConfig, null, 2));
93
+ console.log(" āœ… MCP server added!\n");
94
+ }
211
95
  } catch (error) {
212
- console.error(" āŒ Failed to update ~/.claude.json:", error.message);
213
- console.log(" You can manually add this to ~/.claude.json under mcpServers:");
214
- console.log(` "scpl-shortcuts": { "type": "stdio", "command": "npx", "args": ["-y", "scpl-updated-mcp-server"] }\n`);
96
+ console.error(" āŒ Failed:", error.message, "\n");
215
97
  }
216
98
 
217
99
  // Step 2: Create plugin directory and files
@@ -219,7 +101,6 @@ if (process.argv.includes("--setup")) {
219
101
  try {
220
102
  mkdirSync(join(pluginsDir, "skills"), { recursive: true });
221
103
 
222
- // Write plugin.json
223
104
  const pluginJson = {
224
105
  name: "scpl-shortcuts",
225
106
  version: "1.0.0",
@@ -227,75 +108,41 @@ if (process.argv.includes("--setup")) {
227
108
  skills: [
228
109
  {
229
110
  name: "create-shortcut",
230
- description: "Create a macOS Shortcut using natural language. Guides you through the process and generates a .shortcut file.",
111
+ description: "Create a macOS Shortcut using natural language.",
231
112
  path: "skills/create-shortcut.md"
232
113
  }
233
114
  ]
234
115
  };
235
116
  writeFileSync(join(pluginsDir, "plugin.json"), JSON.stringify(pluginJson, null, 2));
236
117
 
237
- // Write skill file
238
118
  const skillContent = `---
239
- description: Create macOS Shortcuts using natural language. Converts your request into ScPL code and generates a .shortcut file.
119
+ description: Create macOS Shortcuts using natural language.
240
120
  tags: [shortcuts, automation, macos, scpl]
241
121
  ---
242
122
 
243
123
  # Create Shortcut Skill
244
124
 
245
- You have access to the ScPL MCP server with 493 actions for creating macOS Shortcuts.
125
+ You have access to the ScPL MCP server with 493 actions.
246
126
 
247
- ## Available Tools
248
-
249
- 1. **create_shortcut** - Generate a .shortcut file from ScPL code
250
- 2. **validate_scpl** - Check if ScPL code is valid before creating
251
- 3. **list_actions** - Search available actions by category or keyword
252
-
253
- ## Popular Action Categories
254
-
255
- - **AI**: AskLLM (Apple Intelligence), AskChatGPT, AskClaude
256
- - **Clock**: StartStopwatch, CreateAlarm, GetCurrentTime
257
- - **Voice Memos**: CreateRecording, PlayRecording
258
- - **System**: SetDarkMode, TakeScreenshot, LockScreen
259
- - **Files**: GetFile, SaveFile, RenameFile, RevealInFinder
260
- - **Scripting**: RunShellScript, RunAppleScript
261
-
262
- ## ScPL Syntax Examples
127
+ ## Tools: create_shortcut, validate_scpl, list_actions
263
128
 
129
+ ## ScPL Syntax
264
130
  \`\`\`scpl
265
- # Simple notification
266
- ShowResult "Hello World!"
267
-
268
- # Use Apple Intelligence
269
- Text "Summarize this for me"
270
- AskLLM model="Apple Intelligence" prompt="Make it shorter"
271
- ShowResult
272
-
273
- # Shell script
274
- RunShellScript shell="/bin/zsh" script="echo Hello"
275
- ShowResult
276
-
277
- # Variables
278
131
  Text "Hello"
279
- SetVariable v:greeting
280
- ShowResult v:greeting
132
+ AskLLM model="Apple Intelligence" prompt="Make it fun"
133
+ ShowResult
281
134
  \`\`\`
282
135
 
283
- ## Workflow
284
-
285
- 1. User describes what they want
286
- 2. Use \`list_actions\` if you need to find specific actions
287
- 3. Write ScPL code for the shortcut
288
- 4. Use \`validate_scpl\` to check syntax
289
- 5. Use \`create_shortcut\` to generate the .shortcut file
290
- 6. Tell user to drag the file onto Shortcut Source Helper to install
136
+ ## Categories
137
+ AI, Clock, Voice Memos, System, Files, Scripting, Clipboard
291
138
  `;
292
139
  writeFileSync(join(pluginsDir, "skills", "create-shortcut.md"), skillContent);
293
140
  console.log(" āœ… Plugin files created!\n");
294
141
  } catch (error) {
295
- console.error(" āŒ Failed to create plugin files:", error.message, "\n");
142
+ console.error(" āŒ Failed:", error.message, "\n");
296
143
  }
297
144
 
298
- // Step 3: Register plugin in installed_plugins.json
145
+ // Step 3: Register plugin
299
146
  console.log("šŸ“‹ Step 3: Registering plugin...");
300
147
  try {
301
148
  let installedPlugins = { version: 2, plugins: {} };
@@ -303,31 +150,142 @@ ShowResult v:greeting
303
150
  installedPlugins = JSON.parse(readFileSync(installedPluginsPath, "utf-8"));
304
151
  }
305
152
 
306
- installedPlugins.plugins["scpl-shortcuts@local"] = [
307
- {
308
- scope: "user",
309
- installPath: pluginsDir,
310
- version: "1.0.0",
311
- installedAt: new Date().toISOString(),
312
- lastUpdated: new Date().toISOString(),
313
- isLocal: true
314
- }
315
- ];
153
+ if (installedPlugins.plugins["scpl-shortcuts@local"]) {
154
+ console.log(" ā­ļø Already registered, skipping...\n");
155
+ } else {
156
+ installedPlugins.plugins["scpl-shortcuts@local"] = [
157
+ {
158
+ scope: "user",
159
+ installPath: pluginsDir,
160
+ version: "1.0.0",
161
+ installedAt: new Date().toISOString(),
162
+ lastUpdated: new Date().toISOString(),
163
+ isLocal: true
164
+ }
165
+ ];
166
+ writeFileSync(installedPluginsPath, JSON.stringify(installedPlugins, null, 2));
167
+ console.log(" āœ… Plugin registered!\n");
168
+ }
169
+ } catch (error) {
170
+ console.error(" āŒ Failed:", error.message, "\n");
171
+ }
172
+
173
+ console.log("āœ… Claude Code setup complete!\n");
174
+ }
175
+
176
+ function setupCodex(codexDir) {
177
+ console.log("═══════════════════════════════════════════════════════════════");
178
+ console.log(`šŸš€ Setting up ScPL Shortcuts for Codex at ${codexDir}...`);
179
+ console.log("═══════════════════════════════════════════════════════════════\n");
180
+
181
+ const codexConfigPath = join(codexDir, "config.toml");
182
+ const skillDir = join(codexDir, "skills", "scpl-shortcuts");
183
+
184
+ // Step 1: Add MCP server to config.toml
185
+ console.log(`šŸ“ Step 1: Adding MCP server to ${codexConfigPath}...`);
186
+ try {
187
+ let config = "";
188
+ if (existsSync(codexConfigPath)) {
189
+ config = readFileSync(codexConfigPath, "utf-8");
190
+ }
191
+
192
+ if (config.includes('[mcp_servers."scpl-shortcuts"]') || config.includes('[mcp_servers.scpl-shortcuts]')) {
193
+ console.log(" ā­ļø Already configured, skipping...\n");
194
+ } else {
195
+ const tomlBlock = `
196
+ [mcp_servers.scpl-shortcuts]
197
+ command = "npx"
198
+ args = ["-y", "scpl-updated-mcp-server"]
199
+ startup_timeout_sec = 60.0
200
+ `;
201
+ writeFileSync(codexConfigPath, config + tomlBlock);
202
+ console.log(" āœ… MCP server added!\n");
203
+ }
204
+ } catch (error) {
205
+ console.error(" āŒ Failed:", error.message, "\n");
206
+ }
207
+
208
+ // Step 2: Install skill
209
+ console.log(`šŸ“ Step 2: Installing skill to ${skillDir}...`);
210
+ try {
211
+ mkdirSync(skillDir, { recursive: true });
212
+
213
+ const skillContent = `---
214
+ name: scpl-shortcuts
215
+ description: Create macOS Shortcuts using natural language.
216
+ metadata:
217
+ short-description: Create macOS Shortcuts with AI
218
+ ---
219
+
220
+ # ScPL Shortcuts Skill
221
+
222
+ 493 actions available. Tools: create_shortcut, validate_scpl, list_actions
316
223
 
317
- writeFileSync(installedPluginsPath, JSON.stringify(installedPlugins, null, 2));
318
- console.log(" āœ… Plugin registered!\n");
224
+ ## ScPL Syntax
225
+ \`\`\`scpl
226
+ Text "Hello"
227
+ AskLLM model="Apple Intelligence" prompt="Make it fun"
228
+ ShowResult
229
+ \`\`\`
230
+
231
+ ## Categories
232
+ AI, Clock, Voice Memos, System, Files, Scripting, Clipboard
233
+
234
+ ## Workflow
235
+ 1. Write ScPL code
236
+ 2. validate_scpl to check
237
+ 3. create_shortcut to generate .shortcut file
238
+ `;
239
+ writeFileSync(join(skillDir, "SKILL.md"), skillContent);
240
+ console.log(" āœ… Skill installed!\n");
319
241
  } catch (error) {
320
- console.error(" āŒ Failed to register plugin:", error.message, "\n");
242
+ console.error(" āŒ Failed:", error.message, "\n");
243
+ }
244
+
245
+ console.log(`āœ… Codex setup complete for ${codexDir}!\n`);
246
+ }
247
+
248
+ // ============================================================================
249
+ // PROCESS SETUP FLAGS
250
+ // ============================================================================
251
+
252
+ let didSetup = false;
253
+
254
+ // Claude Code setup
255
+ if (process.argv.includes("--setup")) {
256
+ setupClaudeCode();
257
+ didSetup = true;
258
+ }
259
+
260
+ // Codex setups (can have multiple --setup-codex and --setup-codex=<dir>)
261
+ const codexArgs = process.argv.filter(arg => arg.startsWith("--setup-codex"));
262
+ for (const codexArg of codexArgs) {
263
+ let codexDir = join(homedir(), ".codex"); // default
264
+
265
+ if (codexArg.includes("=")) {
266
+ let customDir = codexArg.split("=")[1];
267
+ if (customDir.startsWith("~")) {
268
+ customDir = customDir.replace("~", homedir());
269
+ }
270
+ codexDir = customDir;
321
271
  }
322
272
 
323
- console.log("šŸŽ‰ Setup complete! Restart Claude Code to use the shortcuts tools.\n");
324
- console.log("Usage: Just ask Claude to create a shortcut!");
325
- console.log(' Example: "Create a shortcut that starts a timer and plays a sound"\n');
273
+ setupCodex(codexDir);
274
+ didSetup = true;
275
+ }
276
+
277
+ // Exit after setup(s)
278
+ if (didSetup) {
279
+ console.log("═══════════════════════════════════════════════════════════════");
280
+ console.log("šŸŽ‰ All setups complete! Restart your AI tool(s) to use shortcuts.");
281
+ console.log("═══════════════════════════════════════════════════════════════");
282
+ console.log('\nUsage: Just ask to create a shortcut!');
283
+ console.log(' Example: "Create a shortcut that starts a timer"\n');
326
284
  process.exit(0);
327
285
  }
328
286
 
329
287
  // ============================================================================
330
- // MCP SERVER
288
+ // MCP SERVER (runs if no setup flags)
331
289
  // ============================================================================
332
290
 
333
291
  const server = new Server(
@@ -411,24 +369,21 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
411
369
  if (name === "create_shortcut") {
412
370
  const { scpl_code, output_name, output_dir } = args;
413
371
 
414
- // Convert ScPL to shortcut
415
372
  const shortcutBuffer = convert(scpl_code, {
416
373
  makePlist: true,
417
374
  makeShortcut: true,
418
375
  });
419
376
 
420
- // Determine output path (default to ~/Documents)
421
377
  const dir = output_dir || join(homedir(), "Documents");
422
378
  const outputPath = join(dir, `${output_name}.shortcut`);
423
379
 
424
- // Write the file
425
380
  writeFileSync(outputPath, shortcutBuffer);
426
381
 
427
382
  return {
428
383
  content: [
429
384
  {
430
385
  type: "text",
431
- text: `āœ… Shortcut created successfully!\n\nPath: ${outputPath}\n\nšŸ“ To install:\n1. Download "Shortcut Source Helper" from RoutineHub\n2. Drag ${output_name}.shortcut onto it\n3. Follow the prompts to sign and import\n\nThe shortcut will be added to your Shortcuts app!`,
386
+ text: `āœ… Shortcut created!\n\nPath: ${outputPath}\n\nTo install: Drag onto Shortcut Source Helper from RoutineHub`,
432
387
  },
433
388
  ],
434
389
  };
@@ -438,69 +393,36 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
438
393
  const { scpl_code } = args;
439
394
 
440
395
  try {
441
- convert(scpl_code, {
442
- makePlist: false,
443
- makeShortcut: false,
444
- });
445
-
446
- return {
447
- content: [
448
- {
449
- type: "text",
450
- text: "āœ… ScPL code is valid!",
451
- },
452
- ],
453
- };
396
+ convert(scpl_code, { makePlist: false, makeShortcut: false });
397
+ return { content: [{ type: "text", text: "āœ… ScPL code is valid!" }] };
454
398
  } catch (error) {
455
- return {
456
- content: [
457
- {
458
- type: "text",
459
- text: `āŒ ScPL validation failed:\n\n${error.message}`,
460
- },
461
- ],
462
- isError: true,
463
- };
399
+ return { content: [{ type: "text", text: `āŒ Invalid: ${error.message}` }], isError: true };
464
400
  }
465
401
  }
466
402
 
467
403
  if (name === "list_actions") {
468
404
  const { category, search } = args || {};
469
405
 
470
- // Embedded action list (top actions for quick reference)
471
406
  const topActions = {
472
- // AI
473
407
  "is.workflow.actions.askllm": { Name: "Ask LLM", Category: "AI" },
474
408
  "is.workflow.actions.askchatgpt": { Name: "Ask ChatGPT", Category: "AI" },
475
409
  "com.anthropic.claudeforipad.AskClaudeIntentExtension": { Name: "Ask Claude", Category: "AI" },
476
- // Clock
477
410
  "com.apple.clock.StartStopwatchIntent": { Name: "Start Stopwatch", Category: "Clock" },
478
411
  "com.apple.clock.StopStopwatchIntent": { Name: "Stop Stopwatch", Category: "Clock" },
479
412
  "com.apple.clock.CreateAlarmIntent": { Name: "Create Alarm", Category: "Clock" },
480
- // Voice Memos
481
413
  "com.apple.VoiceMemos.CreateRecordingIntent": { Name: "Create Recording", Category: "Voice Memos" },
482
414
  "com.apple.VoiceMemos.PlayRecordingIntent": { Name: "Play Recording", Category: "Voice Memos" },
483
- // System
484
415
  "is.workflow.actions.appearance": { Name: "Set Dark/Light Mode", Category: "System" },
485
416
  "is.workflow.actions.takescreenshot": { Name: "Take Screenshot", Category: "System" },
486
417
  "is.workflow.actions.lockscreen": { Name: "Lock Screen", Category: "System" },
487
- // Scripting
488
418
  "is.workflow.actions.runshellscript": { Name: "Run Shell Script", Category: "Scripting" },
489
419
  "is.workflow.actions.runapplescript": { Name: "Run AppleScript", Category: "Scripting" },
490
420
  "is.workflow.actions.runjavascriptforautomation": { Name: "Run JavaScript", Category: "Scripting" },
491
- // Files
492
421
  "is.workflow.actions.file.getfile": { Name: "Get File", Category: "Files" },
493
422
  "is.workflow.actions.file.savefile": { Name: "Save File", Category: "Files" },
494
- "is.workflow.actions.file.renamefile": { Name: "Rename File", Category: "Files" },
495
- "is.workflow.actions.file.revealfile": { Name: "Reveal in Finder", Category: "Files" },
496
- // Text
497
- "is.workflow.actions.gettext": { Name: "Get Text", Category: "Text" },
498
423
  "is.workflow.actions.showresult": { Name: "Show Result", Category: "Text" },
499
424
  "is.workflow.actions.alert": { Name: "Show Alert", Category: "Text" },
500
- // Variables
501
425
  "is.workflow.actions.setvariable": { Name: "Set Variable", Category: "Variables" },
502
- "is.workflow.actions.getvariable": { Name: "Get Variable", Category: "Variables" },
503
- // Clipboard
504
426
  "is.workflow.actions.getclipboard": { Name: "Get Clipboard", Category: "Clipboard" },
505
427
  "is.workflow.actions.setclipboard": { Name: "Set Clipboard", Category: "Clipboard" },
506
428
  };
@@ -508,108 +430,36 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
508
430
  let filtered = Object.entries(topActions);
509
431
 
510
432
  if (category) {
511
- filtered = filtered.filter(
512
- ([_, action]) => action.Category?.toLowerCase() === category.toLowerCase()
513
- );
433
+ filtered = filtered.filter(([_, a]) => a.Category?.toLowerCase() === category.toLowerCase());
514
434
  }
515
-
516
435
  if (search) {
517
- const searchLower = search.toLowerCase();
518
- filtered = filtered.filter(
519
- ([id, action]) =>
520
- id.toLowerCase().includes(searchLower) ||
521
- action.Name?.toLowerCase().includes(searchLower) ||
522
- action.Category?.toLowerCase().includes(searchLower)
436
+ const s = search.toLowerCase();
437
+ filtered = filtered.filter(([id, a]) =>
438
+ id.toLowerCase().includes(s) || a.Name?.toLowerCase().includes(s)
523
439
  );
524
440
  }
525
441
 
526
- const results = filtered
527
- .map(([id, action]) => `• **${action.Name}** - \`${id}\` (${action.Category})`)
528
- .join("\n");
529
-
530
- return {
531
- content: [
532
- {
533
- type: "text",
534
- text: `Found ${filtered.length} actions:\n\n${results}\n\nšŸ’” This is a subset of 493 total actions. For the full list, see: https://github.com/cavingraves/scpl-macos-updated`,
535
- },
536
- ],
537
- };
442
+ const results = filtered.map(([id, a]) => `• **${a.Name}** - \`${id}\``).join("\n");
443
+ return { content: [{ type: "text", text: `${filtered.length} actions:\n\n${results}\n\n(493 total available)` }] };
538
444
  }
539
445
 
540
446
  throw new Error(`Unknown tool: ${name}`);
541
447
  } catch (error) {
542
- return {
543
- content: [
544
- {
545
- type: "text",
546
- text: `Error: ${error.message}`,
547
- },
548
- ],
549
- isError: true,
550
- };
448
+ return { content: [{ type: "text", text: `Error: ${error.message}` }], isError: true };
551
449
  }
552
450
  });
553
451
 
554
- // Resource handlers
555
452
  server.setRequestHandler(ListResourcesRequestSchema, async () => {
556
- return {
557
- resources: [
558
- {
559
- uri: "scpl://examples",
560
- name: "ScPL Examples",
561
- description: "Example shortcuts written in ScPL",
562
- mimeType: "text/markdown",
563
- },
564
- ],
565
- };
453
+ return { resources: [{ uri: "scpl://examples", name: "ScPL Examples", mimeType: "text/markdown" }] };
566
454
  });
567
455
 
568
456
  server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
569
- const { uri } = request.params;
570
-
571
- if (uri === "scpl://examples") {
572
- const examples = `# ScPL Examples
573
-
574
- ## Apple Intelligence
575
- \`\`\`scpl
576
- Text "Summarize this document"
577
- AskLLM model="Apple Intelligence" prompt="Make it concise"
578
- ShowResult
579
- \`\`\`
580
-
581
- ## Timer with Sound
582
- \`\`\`scpl
583
- # Start a 5-minute timer
584
- StartTimer minutes=5
585
- ShowAlert title="Timer Started" message="5 minutes"
586
- \`\`\`
587
-
588
- ## Shell Script
589
- \`\`\`scpl
590
- RunShellScript shell="/bin/zsh" script="echo Hello World"
591
- ShowResult
592
- \`\`\`
593
-
594
- ## Clipboard Workflow
595
- \`\`\`scpl
596
- GetClipboard
597
- SetVariable v:text
598
- AskChatGPT prompt="Improve this: \\(v:text)"
599
- SetClipboard
600
- ShowAlert title="Done" message="Improved text copied!"
601
- \`\`\`
602
- `;
603
-
604
- return {
605
- contents: [{ uri, mimeType: "text/markdown", text: examples }],
606
- };
457
+ if (request.params.uri === "scpl://examples") {
458
+ return { contents: [{ uri: "scpl://examples", mimeType: "text/markdown", text: "# Examples\n\n```scpl\nShowResult \"Hello!\"\n```" }] };
607
459
  }
608
-
609
- throw new Error(`Unknown resource: ${uri}`);
460
+ throw new Error("Unknown resource");
610
461
  });
611
462
 
612
- // Start server
613
463
  async function main() {
614
464
  const transport = new StdioServerTransport();
615
465
  await server.connect(transport);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "scpl-updated-mcp-server",
3
- "version": "1.0.3",
3
+ "version": "1.0.5",
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",