scpl-updated-mcp-server 1.0.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 +324 -0
- package/index.js +342 -0
- package/package.json +26 -0
package/README.md
ADDED
|
@@ -0,0 +1,324 @@
|
|
|
1
|
+
# ScPL MCP Server
|
|
2
|
+
|
|
3
|
+
Model Context Protocol server for creating macOS Shortcuts using ScPL (Shortcuts Programming Language).
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Create Shortcuts**: Convert ScPL code to .shortcut files
|
|
8
|
+
- **Validate Syntax**: Check ScPL code without creating files
|
|
9
|
+
- **Discover Actions**: Browse 294 available actions with descriptions
|
|
10
|
+
- **Documentation**: Access action reference and examples
|
|
11
|
+
|
|
12
|
+
## ⚠️ Shortcut Signing & Installation
|
|
13
|
+
|
|
14
|
+
Generated .shortcut files need to be signed before macOS will allow you to run them. You have two options:
|
|
15
|
+
|
|
16
|
+
### Option 1: Shortcut Source Helper (Free - Recommended)
|
|
17
|
+
|
|
18
|
+
**Setup (one-time):**
|
|
19
|
+
1. Install required shortcuts from RoutineHub:
|
|
20
|
+
- [Shortcut Source Helper](https://routinehub.co/shortcut/10060/)
|
|
21
|
+
- [Shortcut Source Tool](https://routinehub.co/shortcut/5256/)
|
|
22
|
+
- [Tinycut Builder](https://routinehub.co/shortcut/5217/)
|
|
23
|
+
2. Add **Shortcut Source Helper** to your Dock for easy access
|
|
24
|
+
|
|
25
|
+
**To install a generated shortcut:**
|
|
26
|
+
1. Drag and drop the `.shortcut` file onto Shortcut Source Helper in your Dock
|
|
27
|
+
2. Follow the prompts to sign and import
|
|
28
|
+
3. The shortcut will be added to your Shortcuts app and ready to use!
|
|
29
|
+
|
|
30
|
+
### Option 2: Apple Developer Account
|
|
31
|
+
|
|
32
|
+
If you have an Apple Developer account ($99/year), you can sign shortcuts with your developer certificate for distribution.
|
|
33
|
+
|
|
34
|
+
**Disclaimer**: We are not associated with Shortcut Source Tool/Helper or their creators. Use third-party tools at your own risk. Always review shortcuts before running them.
|
|
35
|
+
|
|
36
|
+
## Installation
|
|
37
|
+
|
|
38
|
+
### Step 1: Install the Package
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
npm install -g scpl-updated-mcp-server
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### Step 2: Register with Your AI Assistant
|
|
45
|
+
|
|
46
|
+
Choose your platform below:
|
|
47
|
+
|
|
48
|
+
#### Claude Code
|
|
49
|
+
|
|
50
|
+
**Option 1: CLI command** (may not always work):
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
claude mcp add scpl-shortcuts npx scpl-updated-mcp-server
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
**Option 2: Manual config** (recommended):
|
|
57
|
+
|
|
58
|
+
Add this to the `mcpServers` section in `~/.claude.json`:
|
|
59
|
+
|
|
60
|
+
```json
|
|
61
|
+
"scpl-shortcuts": {
|
|
62
|
+
"type": "stdio",
|
|
63
|
+
"command": "npx",
|
|
64
|
+
"args": [
|
|
65
|
+
"-y",
|
|
66
|
+
"scpl-updated-mcp-server"
|
|
67
|
+
]
|
|
68
|
+
}
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Or for project-specific config, add to `.claude/mcp.json` in your project directory.
|
|
72
|
+
|
|
73
|
+
#### Claude Desktop
|
|
74
|
+
|
|
75
|
+
Add to `~/Library/Application Support/Claude/claude_desktop_config.json`:
|
|
76
|
+
|
|
77
|
+
```json
|
|
78
|
+
{
|
|
79
|
+
"mcpServers": {
|
|
80
|
+
"scpl-shortcuts": {
|
|
81
|
+
"command": "npx",
|
|
82
|
+
"args": ["scpl-updated-mcp-server"]
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
#### Codex / Code (and forks)
|
|
89
|
+
|
|
90
|
+
Add to `~/.code/config.toml` (or `~/.codex/config.toml`):
|
|
91
|
+
|
|
92
|
+
```toml
|
|
93
|
+
[mcp_servers.scpl-shortcuts]
|
|
94
|
+
command = "npx"
|
|
95
|
+
args = ["scpl-updated-mcp-server"]
|
|
96
|
+
startup_timeout_sec = 60.0
|
|
97
|
+
tool_timeout_sec = 120
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
**For local development:**
|
|
101
|
+
|
|
102
|
+
```toml
|
|
103
|
+
[mcp_servers.scpl-shortcuts]
|
|
104
|
+
command = "node"
|
|
105
|
+
args = ["/path/to/scpl-updated/mcp-server/index.js"]
|
|
106
|
+
cwd = "/path/to/scpl-updated/mcp-server"
|
|
107
|
+
startup_timeout_sec = 60.0
|
|
108
|
+
tool_timeout_sec = 120
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
## Tools
|
|
112
|
+
|
|
113
|
+
### `create_shortcut`
|
|
114
|
+
|
|
115
|
+
Create a macOS Shortcut from ScPL code.
|
|
116
|
+
|
|
117
|
+
**Parameters:**
|
|
118
|
+
- `scpl_code` (required): The ScPL code to convert
|
|
119
|
+
- `output_name` (required): Name for the .shortcut file
|
|
120
|
+
- `output_dir` (optional): Output directory (defaults to ~/Documents)
|
|
121
|
+
|
|
122
|
+
**Example:**
|
|
123
|
+
```json
|
|
124
|
+
{
|
|
125
|
+
"scpl_code": "Text \"Hello World\"\nShowResult",
|
|
126
|
+
"output_name": "HelloWorld",
|
|
127
|
+
"output_dir": "~/Desktop"
|
|
128
|
+
}
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
### `validate_scpl`
|
|
132
|
+
|
|
133
|
+
Validate ScPL code syntax without creating a file.
|
|
134
|
+
|
|
135
|
+
**Parameters:**
|
|
136
|
+
- `scpl_code` (required): The ScPL code to validate
|
|
137
|
+
|
|
138
|
+
**Example:**
|
|
139
|
+
```json
|
|
140
|
+
{
|
|
141
|
+
"scpl_code": "GetClipboard\nShowResult"
|
|
142
|
+
}
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
### `list_actions`
|
|
146
|
+
|
|
147
|
+
List available ScPL actions with descriptions.
|
|
148
|
+
|
|
149
|
+
**Parameters:**
|
|
150
|
+
- `category` (optional): Filter by category (e.g., "Scripting", "Files")
|
|
151
|
+
- `search` (optional): Search term to filter actions
|
|
152
|
+
|
|
153
|
+
**Example:**
|
|
154
|
+
```json
|
|
155
|
+
{
|
|
156
|
+
"category": "Scripting",
|
|
157
|
+
"search": "shell"
|
|
158
|
+
}
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
## Resources
|
|
162
|
+
|
|
163
|
+
### `scpl://actions/tahoe`
|
|
164
|
+
|
|
165
|
+
Documentation for 22 new macOS Tahoe actions.
|
|
166
|
+
|
|
167
|
+
### `scpl://examples`
|
|
168
|
+
|
|
169
|
+
Example shortcuts demonstrating various ScPL features.
|
|
170
|
+
|
|
171
|
+
## Usage with Claude Code
|
|
172
|
+
|
|
173
|
+
Once registered, Claude can create shortcuts for you:
|
|
174
|
+
|
|
175
|
+
```
|
|
176
|
+
Claude, create a shortcut that:
|
|
177
|
+
1. Gets text from clipboard
|
|
178
|
+
2. Asks ChatGPT to improve it
|
|
179
|
+
3. Copies the result back to clipboard
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
Claude will:
|
|
183
|
+
1. Write the ScPL code
|
|
184
|
+
2. Validate the syntax
|
|
185
|
+
3. Create the .shortcut file
|
|
186
|
+
4. Provide installation instructions
|
|
187
|
+
|
|
188
|
+
## Usage with Claude Skill
|
|
189
|
+
|
|
190
|
+
The included `/create-shortcut` skill provides a guided experience:
|
|
191
|
+
|
|
192
|
+
```
|
|
193
|
+
/create-shortcut
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
Then describe what you want your shortcut to do.
|
|
197
|
+
|
|
198
|
+
## ScPL Syntax Quick Reference
|
|
199
|
+
|
|
200
|
+
```scpl
|
|
201
|
+
# Comments
|
|
202
|
+
# Single-line comments start with #
|
|
203
|
+
|
|
204
|
+
# Text and Output
|
|
205
|
+
Text "Hello World"
|
|
206
|
+
ShowResult "My Result"
|
|
207
|
+
ShowAlert title="Title" message="Message"
|
|
208
|
+
|
|
209
|
+
# Variables
|
|
210
|
+
SetVariable v:myVar
|
|
211
|
+
GetVariable v:myVar
|
|
212
|
+
|
|
213
|
+
# Clipboard
|
|
214
|
+
GetClipboard
|
|
215
|
+
SetClipboard
|
|
216
|
+
|
|
217
|
+
# Apple Intelligence (Apple Silicon only)
|
|
218
|
+
AskLLM model="Apple Intelligence" prompt="Your prompt here"
|
|
219
|
+
|
|
220
|
+
# ChatGPT (requires app installed)
|
|
221
|
+
Text "Your question"
|
|
222
|
+
AskChatGPT
|
|
223
|
+
|
|
224
|
+
# Shell Scripts (Intel & Apple Silicon)
|
|
225
|
+
RunShellScript shell="/bin/zsh" script="echo 'Hello'"
|
|
226
|
+
|
|
227
|
+
# Files (Intel & Apple Silicon)
|
|
228
|
+
GetFile path="~/Desktop"
|
|
229
|
+
SaveFile path="~/Documents/file.txt"
|
|
230
|
+
|
|
231
|
+
# Conditionals
|
|
232
|
+
If condition="Equals" value="test"
|
|
233
|
+
ShowResult "Match!"
|
|
234
|
+
Otherwise
|
|
235
|
+
ShowResult "No match"
|
|
236
|
+
End If
|
|
237
|
+
|
|
238
|
+
# Menus
|
|
239
|
+
ChooseFromMenu items=["Option 1", "Option 2"]
|
|
240
|
+
Case "Option 1"
|
|
241
|
+
Text "You chose 1"
|
|
242
|
+
Case "Option 2"
|
|
243
|
+
Text "You chose 2"
|
|
244
|
+
End Menu
|
|
245
|
+
|
|
246
|
+
# Loops
|
|
247
|
+
RepeatWithEachItem
|
|
248
|
+
ShowResult
|
|
249
|
+
End Repeat
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
## Examples
|
|
253
|
+
|
|
254
|
+
### Simple Notification
|
|
255
|
+
|
|
256
|
+
```scpl
|
|
257
|
+
Text "Hello from ScPL!"
|
|
258
|
+
ShowResult
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
### AI Text Improver
|
|
262
|
+
|
|
263
|
+
```scpl
|
|
264
|
+
GetClipboard
|
|
265
|
+
SetVariable v:originalText
|
|
266
|
+
|
|
267
|
+
AskLLM model="Apple Intelligence" prompt="Improve this text for clarity: \\(v:originalText)"
|
|
268
|
+
SetClipboard
|
|
269
|
+
ShowAlert title="Done" message="Improved text copied to clipboard"
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
### Shell Script Runner
|
|
273
|
+
|
|
274
|
+
```scpl
|
|
275
|
+
RunShellScript shell="/bin/zsh" script="sw_vers"
|
|
276
|
+
ShowResult "macOS Version"
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
### File Counter
|
|
280
|
+
|
|
281
|
+
```scpl
|
|
282
|
+
GetFile path="~/Desktop"
|
|
283
|
+
Count
|
|
284
|
+
ShowResult "Files on Desktop"
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
## Troubleshooting
|
|
288
|
+
|
|
289
|
+
### "Command not found: scpl-updated-mcp-server"
|
|
290
|
+
|
|
291
|
+
Make sure you installed globally:
|
|
292
|
+
```bash
|
|
293
|
+
npm install -g scpl-updated-mcp-server
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
### "Error: Cannot find module 'scpl-macos-updated'"
|
|
297
|
+
|
|
298
|
+
The MCP server depends on scpl-macos-updated. Ensure it's installed:
|
|
299
|
+
```bash
|
|
300
|
+
npm list -g scpl-macos-updated
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
### "Permission denied"
|
|
304
|
+
|
|
305
|
+
Make the script executable:
|
|
306
|
+
```bash
|
|
307
|
+
chmod +x index.js
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
### ScPL Validation Errors
|
|
311
|
+
|
|
312
|
+
Check the error message for line numbers and syntax issues. Common mistakes:
|
|
313
|
+
- Forgetting to close `If` with `End If`
|
|
314
|
+
- Forgetting to close `Menu` with `End Menu`
|
|
315
|
+
- Using wrong parameter names (use `list_actions` to check)
|
|
316
|
+
- Missing quotes around text values
|
|
317
|
+
|
|
318
|
+
## Contributing
|
|
319
|
+
|
|
320
|
+
Found a bug or want to add features? See [CONTRIBUTING.md](../CONTRIBUTING.md)
|
|
321
|
+
|
|
322
|
+
## License
|
|
323
|
+
|
|
324
|
+
MIT - Same as scpl-macos-updated
|
package/index.js
ADDED
|
@@ -0,0 +1,342 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
4
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
5
|
+
import {
|
|
6
|
+
CallToolRequestSchema,
|
|
7
|
+
ListToolsRequestSchema,
|
|
8
|
+
ListResourcesRequestSchema,
|
|
9
|
+
ReadResourceRequestSchema,
|
|
10
|
+
} from "@modelcontextprotocol/sdk/types.js";
|
|
11
|
+
import { convert } from "scpl-macos-updated";
|
|
12
|
+
import { writeFileSync, readFileSync } from "fs";
|
|
13
|
+
import { join } from "path";
|
|
14
|
+
import { homedir } from "os";
|
|
15
|
+
|
|
16
|
+
const server = new Server(
|
|
17
|
+
{
|
|
18
|
+
name: "scpl-updated-mcp-server",
|
|
19
|
+
version: "1.0.0",
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
capabilities: {
|
|
23
|
+
tools: {},
|
|
24
|
+
resources: {},
|
|
25
|
+
},
|
|
26
|
+
}
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
// Tool handlers
|
|
30
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
31
|
+
return {
|
|
32
|
+
tools: [
|
|
33
|
+
{
|
|
34
|
+
name: "create_shortcut",
|
|
35
|
+
description: "Create a macOS Shortcut from ScPL code. Returns the path to the generated .shortcut file.",
|
|
36
|
+
inputSchema: {
|
|
37
|
+
type: "object",
|
|
38
|
+
properties: {
|
|
39
|
+
scpl_code: {
|
|
40
|
+
type: "string",
|
|
41
|
+
description: "The ScPL code to convert to a shortcut",
|
|
42
|
+
},
|
|
43
|
+
output_name: {
|
|
44
|
+
type: "string",
|
|
45
|
+
description: "Name for the output .shortcut file (without extension)",
|
|
46
|
+
},
|
|
47
|
+
output_dir: {
|
|
48
|
+
type: "string",
|
|
49
|
+
description: "Optional output directory (defaults to ~/Downloads)",
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
required: ["scpl_code", "output_name"],
|
|
53
|
+
},
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
name: "validate_scpl",
|
|
57
|
+
description: "Validate ScPL code syntax without creating a file",
|
|
58
|
+
inputSchema: {
|
|
59
|
+
type: "object",
|
|
60
|
+
properties: {
|
|
61
|
+
scpl_code: {
|
|
62
|
+
type: "string",
|
|
63
|
+
description: "The ScPL code to validate",
|
|
64
|
+
},
|
|
65
|
+
},
|
|
66
|
+
required: ["scpl_code"],
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
name: "list_actions",
|
|
71
|
+
description: "List available ScPL actions with descriptions. Filter by category or search term.",
|
|
72
|
+
inputSchema: {
|
|
73
|
+
type: "object",
|
|
74
|
+
properties: {
|
|
75
|
+
category: {
|
|
76
|
+
type: "string",
|
|
77
|
+
description: "Optional category filter (e.g., 'Scripting', 'Files', 'AI')",
|
|
78
|
+
},
|
|
79
|
+
search: {
|
|
80
|
+
type: "string",
|
|
81
|
+
description: "Optional search term to filter actions",
|
|
82
|
+
},
|
|
83
|
+
},
|
|
84
|
+
},
|
|
85
|
+
},
|
|
86
|
+
],
|
|
87
|
+
};
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
91
|
+
const { name, arguments: args } = request.params;
|
|
92
|
+
|
|
93
|
+
try {
|
|
94
|
+
if (name === "create_shortcut") {
|
|
95
|
+
const { scpl_code, output_name, output_dir } = args;
|
|
96
|
+
|
|
97
|
+
// Convert ScPL to shortcut
|
|
98
|
+
// Note: parse() returns a Buffer directly when makeShortcut: true
|
|
99
|
+
const shortcutBuffer = convert(scpl_code, {
|
|
100
|
+
makePlist: true,
|
|
101
|
+
makeShortcut: true,
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
// Determine output path (default to ~/Documents)
|
|
105
|
+
const dir = output_dir || join(homedir(), "Documents");
|
|
106
|
+
const outputPath = join(dir, `${output_name}.shortcut`);
|
|
107
|
+
|
|
108
|
+
// Write the file
|
|
109
|
+
writeFileSync(outputPath, shortcutBuffer);
|
|
110
|
+
|
|
111
|
+
return {
|
|
112
|
+
content: [
|
|
113
|
+
{
|
|
114
|
+
type: "text",
|
|
115
|
+
text: `✅ Shortcut created successfully!\n\nPath: ${outputPath}\n\n📝 To install and sign it:\n\n1. Install Shortcut Source Helper from RoutineHub (if you haven't already)\n - Also install: Shortcut Source Tool, Tinycut Builder\n2. Add Shortcut Source Helper to your Dock\n3. Drag and drop ${output_name}.shortcut onto it\n4. Follow the prompts to sign and import\n\nThe shortcut will be added to your Shortcuts app and ready to use!`,
|
|
116
|
+
},
|
|
117
|
+
],
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
if (name === "validate_scpl") {
|
|
122
|
+
const { scpl_code } = args;
|
|
123
|
+
|
|
124
|
+
try {
|
|
125
|
+
// Just parse to validate, don't generate output
|
|
126
|
+
convert(scpl_code, {
|
|
127
|
+
makePlist: false,
|
|
128
|
+
makeShortcut: false,
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
return {
|
|
132
|
+
content: [
|
|
133
|
+
{
|
|
134
|
+
type: "text",
|
|
135
|
+
text: "✅ ScPL code is valid!",
|
|
136
|
+
},
|
|
137
|
+
],
|
|
138
|
+
};
|
|
139
|
+
} catch (error) {
|
|
140
|
+
return {
|
|
141
|
+
content: [
|
|
142
|
+
{
|
|
143
|
+
type: "text",
|
|
144
|
+
text: `❌ ScPL validation failed:\n\n${error.message}`,
|
|
145
|
+
},
|
|
146
|
+
],
|
|
147
|
+
isError: true,
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
if (name === "list_actions") {
|
|
153
|
+
const { category, search } = args || {};
|
|
154
|
+
|
|
155
|
+
// Read the actions data
|
|
156
|
+
const actionsPath = join(
|
|
157
|
+
process.cwd(),
|
|
158
|
+
"..",
|
|
159
|
+
"src",
|
|
160
|
+
"Data",
|
|
161
|
+
"OutActions.json"
|
|
162
|
+
);
|
|
163
|
+
const actions = JSON.parse(readFileSync(actionsPath, "utf-8"));
|
|
164
|
+
|
|
165
|
+
let filtered = Object.entries(actions);
|
|
166
|
+
|
|
167
|
+
// Filter by category
|
|
168
|
+
if (category) {
|
|
169
|
+
filtered = filtered.filter(
|
|
170
|
+
([_, action]) =>
|
|
171
|
+
action.Category?.toLowerCase() === category.toLowerCase()
|
|
172
|
+
);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// Filter by search term
|
|
176
|
+
if (search) {
|
|
177
|
+
const searchLower = search.toLowerCase();
|
|
178
|
+
filtered = filtered.filter(
|
|
179
|
+
([id, action]) =>
|
|
180
|
+
id.toLowerCase().includes(searchLower) ||
|
|
181
|
+
action.Name?.toLowerCase().includes(searchLower) ||
|
|
182
|
+
action.Description?.DescriptionSummary?.toLowerCase().includes(
|
|
183
|
+
searchLower
|
|
184
|
+
)
|
|
185
|
+
);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// Format the results
|
|
189
|
+
const results = filtered
|
|
190
|
+
.slice(0, 50) // Limit to 50 results
|
|
191
|
+
.map(([id, action]) => {
|
|
192
|
+
return `• **${action.Name || id}**\n ID: \`${id}\`\n ${
|
|
193
|
+
action.Description?.DescriptionSummary || "No description"
|
|
194
|
+
}\n Category: ${action.Category || "Unknown"}`;
|
|
195
|
+
})
|
|
196
|
+
.join("\n\n");
|
|
197
|
+
|
|
198
|
+
const total = filtered.length;
|
|
199
|
+
const showing = Math.min(50, total);
|
|
200
|
+
|
|
201
|
+
return {
|
|
202
|
+
content: [
|
|
203
|
+
{
|
|
204
|
+
type: "text",
|
|
205
|
+
text: `Found ${total} action${
|
|
206
|
+
total !== 1 ? "s" : ""
|
|
207
|
+
} (showing ${showing}):\n\n${results}`,
|
|
208
|
+
},
|
|
209
|
+
],
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
throw new Error(`Unknown tool: ${name}`);
|
|
214
|
+
} catch (error) {
|
|
215
|
+
return {
|
|
216
|
+
content: [
|
|
217
|
+
{
|
|
218
|
+
type: "text",
|
|
219
|
+
text: `Error: ${error.message}`,
|
|
220
|
+
},
|
|
221
|
+
],
|
|
222
|
+
isError: true,
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
// Resource handlers (for documentation)
|
|
228
|
+
server.setRequestHandler(ListResourcesRequestSchema, async () => {
|
|
229
|
+
return {
|
|
230
|
+
resources: [
|
|
231
|
+
{
|
|
232
|
+
uri: "scpl://actions/all",
|
|
233
|
+
name: "All Available Actions",
|
|
234
|
+
description: "Complete list of all 294 ScPL actions",
|
|
235
|
+
mimeType: "text/markdown",
|
|
236
|
+
},
|
|
237
|
+
{
|
|
238
|
+
uri: "scpl://actions/tahoe",
|
|
239
|
+
name: "macOS Tahoe New Actions",
|
|
240
|
+
description: "22 new actions added for macOS Tahoe",
|
|
241
|
+
mimeType: "text/markdown",
|
|
242
|
+
},
|
|
243
|
+
{
|
|
244
|
+
uri: "scpl://examples",
|
|
245
|
+
name: "ScPL Examples",
|
|
246
|
+
description: "Example shortcuts written in ScPL",
|
|
247
|
+
mimeType: "text/markdown",
|
|
248
|
+
},
|
|
249
|
+
],
|
|
250
|
+
};
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
|
|
254
|
+
const { uri } = request.params;
|
|
255
|
+
|
|
256
|
+
if (uri === "scpl://actions/tahoe") {
|
|
257
|
+
const content = readFileSync(
|
|
258
|
+
join(process.cwd(), "..", "MACOS_TAHOE_UPDATES.md"),
|
|
259
|
+
"utf-8"
|
|
260
|
+
);
|
|
261
|
+
return {
|
|
262
|
+
contents: [
|
|
263
|
+
{
|
|
264
|
+
uri,
|
|
265
|
+
mimeType: "text/markdown",
|
|
266
|
+
text: content,
|
|
267
|
+
},
|
|
268
|
+
],
|
|
269
|
+
};
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
if (uri === "scpl://examples") {
|
|
273
|
+
const examples = `# ScPL Examples
|
|
274
|
+
|
|
275
|
+
## Apple Intelligence Example
|
|
276
|
+
\`\`\`scpl
|
|
277
|
+
# Ask Apple Intelligence to summarize text
|
|
278
|
+
Text "The quick brown fox jumps over the lazy dog. This is a sample text."
|
|
279
|
+
AskLLM model="Apple Intelligence" prompt="Summarize this in 5 words"
|
|
280
|
+
ShowResult
|
|
281
|
+
\`\`\`
|
|
282
|
+
|
|
283
|
+
## Shell Script Example
|
|
284
|
+
\`\`\`scpl
|
|
285
|
+
# Run a shell script and show the result
|
|
286
|
+
RunShellScript shell="/bin/zsh" script="sw_vers"
|
|
287
|
+
ShowResult "macOS Version"
|
|
288
|
+
\`\`\`
|
|
289
|
+
|
|
290
|
+
## File Operations Example
|
|
291
|
+
\`\`\`scpl
|
|
292
|
+
# Get files from Desktop and show count
|
|
293
|
+
GetFile path="~/Desktop" errorIfNotFound=false
|
|
294
|
+
Count
|
|
295
|
+
ShowResult "Files on Desktop"
|
|
296
|
+
\`\`\`
|
|
297
|
+
|
|
298
|
+
## ChatGPT Integration Example
|
|
299
|
+
\`\`\`scpl
|
|
300
|
+
# Ask ChatGPT a question
|
|
301
|
+
Text "What is the meaning of life?"
|
|
302
|
+
AskChatGPT
|
|
303
|
+
ShowResult
|
|
304
|
+
\`\`\`
|
|
305
|
+
|
|
306
|
+
## Combined Workflow Example
|
|
307
|
+
\`\`\`scpl
|
|
308
|
+
# Get clipboard, ask AI to improve it, copy back
|
|
309
|
+
GetClipboard
|
|
310
|
+
SetVariable v:originalText
|
|
311
|
+
|
|
312
|
+
AskLLM model="Apple Intelligence" prompt="Improve this text for clarity and grammar: \\(v:originalText)"
|
|
313
|
+
SetClipboard
|
|
314
|
+
ShowAlert title="Text Improved" message="The improved text has been copied to your clipboard"
|
|
315
|
+
\`\`\`
|
|
316
|
+
`;
|
|
317
|
+
|
|
318
|
+
return {
|
|
319
|
+
contents: [
|
|
320
|
+
{
|
|
321
|
+
uri,
|
|
322
|
+
mimeType: "text/markdown",
|
|
323
|
+
text: examples,
|
|
324
|
+
},
|
|
325
|
+
],
|
|
326
|
+
};
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
throw new Error(`Unknown resource: ${uri}`);
|
|
330
|
+
});
|
|
331
|
+
|
|
332
|
+
// Start the server
|
|
333
|
+
async function main() {
|
|
334
|
+
const transport = new StdioServerTransport();
|
|
335
|
+
await server.connect(transport);
|
|
336
|
+
console.error("ScPL Updated MCP server running on stdio");
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
main().catch((error) => {
|
|
340
|
+
console.error("Server error:", error);
|
|
341
|
+
process.exit(1);
|
|
342
|
+
});
|
package/package.json
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "scpl-updated-mcp-server",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "MCP server for creating macOS Shortcuts using ScPL (macOS Tahoe updated fork)",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "index.js",
|
|
7
|
+
"bin": {
|
|
8
|
+
"scpl-updated-mcp-server": "./index.js"
|
|
9
|
+
},
|
|
10
|
+
"scripts": {
|
|
11
|
+
"start": "node index.js"
|
|
12
|
+
},
|
|
13
|
+
"keywords": [
|
|
14
|
+
"mcp",
|
|
15
|
+
"shortcuts",
|
|
16
|
+
"scpl",
|
|
17
|
+
"macos",
|
|
18
|
+
"automation"
|
|
19
|
+
],
|
|
20
|
+
"author": "Cavin Graves",
|
|
21
|
+
"license": "MIT",
|
|
22
|
+
"dependencies": {
|
|
23
|
+
"@modelcontextprotocol/sdk": "^0.5.0",
|
|
24
|
+
"scpl-macos-updated": "^2.0.0"
|
|
25
|
+
}
|
|
26
|
+
}
|