Beyond-Better/bb-applescript-mcp-server
If you are the rightful owner of bb-applescript-mcp-server and would like to certify it and/or have it hosted online, please leave a comment on the right or send an email to henry@mcphub.com.
The AppleScript MCP Server allows LLM clients to interact with macOS applications using AppleScript, providing a safe and controlled environment for script execution.
AppleScript MCP Server
A Model Context Protocol (MCP) server that enables LLM clients to interact with macOS applications through AppleScript. Built using the @beyondbetter/bb-mcp-server library, this server provides safe, controlled execution of predefined scripts with optional support for arbitrary script execution.
Features
- š Safe by Default: Arbitrary script execution disabled by default
- š¦ Plugin Architecture: Modular design with task-focused plugins
- š ļø Standard Tools: Read dictionaries, check permissions, Finder operations
- š BBEdit Integration: Create notebooks and projects
- ā±ļø Timeout Protection: Configurable timeouts with hard limits
- š Structured Errors: Consistent error handling with LLM-friendly hints
- š Performance: Support for both compiled and template-based scripts
Prerequisites
- Deno: Version 2.5.0 or later
- macOS: Required for AppleScript execution
- Applications: Any macOS application that supports AppleEvents (scriptable applications)
- Examples: Finder (built-in), BBEdit, Mail, Safari, etc.
- This server includes plugins for Finder and BBEdit by default
- You can create plugins for any scriptable application
Quick Start
Option 1: Run Directly from JSR (Recommended)
No installation required! Just Deno and a config file.
1. Install Deno (if needed)
curl -fsSL https://deno.land/install.sh | sh
2. Configure in Beyond Better
Global Configuration (applies to all projects):
- Open BB Settings
- Go to "MCP Servers" tab
- Click "Configure Servers"
- Add new server with:
- Server ID:
applescript
- Display Name:
AppleScript Tools
- Transport Type:
STDIO (Local Process)
- Command:
deno
- Arguments:
run --allow-all --unstable-kv jsr:@beyondbetter/bb-applescript-mcp-server
- Server ID:
Project-Level Configuration (specific project only):
- Open your project in BB
- Go to Project Settings ā "MCP Servers"
- Enable server for
AppleScript Tools
3. Start Using
That's it! The server runs directly from JSR with no download or installation needed.
Alternative: Claude Desktop Configuration
Add to ~/Library/Application Support/Claude/claude_desktop_config.json
:
{
"mcpServers": {
"applescript": {
"command": "deno",
"args": [
"run",
"--allow-all",
"--unstable-kv",
"jsr:@beyondbetter/bb-applescript-mcp-server"
]
}
}
}
Restart Claude Desktop.
4. Optional: Configuration
By default, the server runs with safe defaults:
- Arbitrary script execution: disabled
- All standard plugins: enabled
- Default timeouts: 30s default, 5min max
To customize, add environment variables in BB's MCP server configuration:
In BB Settings ā MCP Servers ā Edit Server ā Environment Variables:
Key | Value | Description |
---|---|---|
LOG_LEVEL | info | Set to debug for detailed logs |
ENABLE_ARBITRARY_SCRIPTS | false | Set to true to enable run_script tool |
PLUGINS_ALLOWED_LIST | (empty) | Comma-separated list to load specific plugins |
PLUGINS_BLOCKED_LIST | (empty) | Comma-separated list to block plugins |
Option 2: Run from Local Repository
For development or customization:
1. Clone and Setup
# Clone the repository
git clone https://github.com/your-username/bb-mcp-applescript.git
cd bb-mcp-applescript/server
# Copy environment template
cp .env.example .env
2. Configure Environment
Edit .env
to customize:
# Basic Configuration
MCP_TRANSPORT=stdio
LOG_LEVEL=info
# Plugin Control
PLUGINS_ALLOWED_LIST= # Empty = load all plugins
PLUGINS_BLOCKED_LIST= # Block specific plugins
# Safety (IMPORTANT)
ENABLE_ARBITRARY_SCRIPTS=false # Set to true to enable run_script tool
# Timeouts
APPLESCRIPT_TIMEOUT_DEFAULT=30000 # 30 seconds
APPLESCRIPT_TIMEOUT_MAX=300000 # 5 minutes
3. Run the Server
# Development mode (with auto-reload)
deno task dev
# Production mode
deno task start
4. Configure in Beyond Better
Global Configuration:
- Open BB Settings (or Project Settings)
- Go to "MCP Servers" tab
- Add new server:
- Server ID:
applescript
- Display Name:
AppleScript Tools (Local Dev)
- Transport Type:
STDIO (Local Process)
- Command:
deno
- Arguments:
run --allow-all --unstable-kv /absolute/path/to/bb-mcp-applescript/server/main.ts
- Environment Variables (optional):
LOG_LEVEL
:debug
ENABLE_ARBITRARY_SCRIPTS
:false
- Server ID:
Alternative: Claude Desktop Configuration
Add to ~/Library/Application Support/Claude/claude_desktop_config.json
:
{
"mcpServers": {
"applescript": {
"command": "deno",
"args": [
"run",
"--allow-all",
"--unstable-kv",
"/absolute/path/to/bb-mcp-applescript/server/main.ts"
]
}
}
}
Restart Claude Desktop.
Project Structure
server/
āāā main.ts # Server entry point
āāā deno.jsonc # Deno configuration
āāā .env.example # Environment template
āāā mcp_server_instructions.md # LLM context/instructions
āāā src/
ā āāā plugins/
ā ā āāā standard.plugin/ # Standard tools plugin
ā ā ā āāā plugin.ts # Plugin implementation
ā ā ā āāā scripts/ # AppleScript files
ā ā ā āāā read_dictionary.applescript
ā ā ā āāā check_permissions.applescript
ā ā ā āāā finder/
ā ā ā āāā set_file_label.applescript
ā ā ā āāā get_file_label.applescript
ā ā ā āāā get_file_info_extended.applescript
ā ā ā āāā reveal_in_finder.applescript
ā ā ā āāā get_selection.applescript
ā ā āāā bbedit.plugin/ # BBEdit tools plugin
ā ā āāā plugin.ts
ā ā āāā scripts/
ā ā āāā create_notebook.applescript
ā ā āāā create_project.applescript
ā āāā utils/
ā āāā scriptLoader.ts # Script loading/discovery
ā āāā scriptRunner.ts # Script execution
ā āāā templateRenderer.ts # Template interpolation
ā āāā errorHandler.ts # Error standardization
āāā tests/
Available Tools
AppleScript Tools (Standard Plugin)
š§ run_script
Status: š Disabled by default
Execute arbitrary AppleScript code.
Enable: Set ENABLE_ARBITRARY_SCRIPTS=true
in .env
Parameters:
script
: AppleScript code to executetimeout
: Optional timeout in milliseconds
Example:
{
script: 'tell application "Finder" to get name of startup disk',
timeout: 5000
}
š read_dictionary
Read an application's AppleScript dictionary to understand its scriptable interface.
Parameters:
application
: Application name (e.g., "BBEdit", "Finder")filter
: Optional filter criteriainclude.types
: Array of types to includeinclude.names
: Specific names to includesearchTerms
: Terms for fuzzy matchingformat
: "full" or "summary" (default: "summary")
timeout
: Optional timeout
Example:
{
application: "BBEdit",
filter: {
include: { names: ["project", "notebook"] },
searchTerms: ["create"],
format: "summary"
}
}
ā check_applescript_permissions
Check automation permissions for applications.
Parameters:
applications
: Optional array of app names (default: ["Finder", "BBEdit", "Terminal"])timeout
: Optional timeout
Returns: Permission status for each application with instructions if needed.
Finder Tools (Standard Plugin)
š·ļø set_file_label
Set Finder label colors for files/folders.
Parameters:
paths
: Array of file/folder pathslabelIndex
: 0=None, 1=Red, 2=Orange, 3=Yellow, 4=Green, 5=Blue, 6=Purple, 7=Graytimeout
: Optional timeout
š·ļø get_file_label
Get Finder label colors for files/folders.
Parameters:
paths
: Array of file/folder pathstimeout
: Optional timeout
š get_file_info_extended
Get detailed file information including Spotlight comments, tags, labels, etc.
Parameters:
path
: File or folder pathtimeout
: Optional timeout
š reveal_in_finder
Reveal and select files/folders in Finder.
Parameters:
paths
: Array of paths to revealtimeout
: Optional timeout
š get_finder_selection
Get currently selected items in Finder.
Parameters:
timeout
: Optional timeout
BBEdit Tools (BBEdit Plugin)
š create_bbedit_notebook
Create a new BBEdit notebook.
Parameters:
name
: Notebook name (required)location
: Optional save location (default: ~/Documents/BBEdit Notebooks/)content
: Optional array of content itemstype
: "text" or "file"data
: Text content or file path
open
: Whether to open after creation (default: true)timeout
: Optional timeout
Example:
{
name: "Project Notes",
content: [
{ type: "text", data: "Meeting notes..." },
{ type: "file", data: "/path/to/notes.txt" }
],
open: true
}
š create_bbedit_project
Create a new BBEdit project.
Parameters:
name
: Project name (required)location
: Optional save location (default: ~/Documents/BBEdit Projects/)items
: Optional array of file/folder paths to addsettings
: Optional project settings (reserved for future)open
: Whether to open after creation (default: true)timeout
: Optional timeout
Example:
{
name: "Website Project",
items: [
"/Users/username/Projects/website/src",
"/Users/username/Projects/website/docs"
],
open: true
}
Plugin Management
Loading Plugins
Plugins are auto-discovered from src/plugins/
directory.
Load all plugins (default):
PLUGINS_ALLOWED_LIST=
PLUGINS_BLOCKED_LIST=
Load specific plugins only:
PLUGINS_ALLOWED_LIST=standard,bbedit
PLUGINS_BLOCKED_LIST=
Load all except specific plugins:
PLUGINS_ALLOWED_LIST=
PLUGINS_BLOCKED_LIST=experimental
Creating Custom Plugins
Plugins allow you to add tools for any scriptable macOS application. See the complete guide:
š
Quick example for a Mail.app plugin:
// src/plugins/mail.plugin/plugin.ts
import { AppPlugin, ToolRegistry, z } from 'jsr:@beyondbetter/bb-mcp-server';
import { findAndExecuteScript } from '../../utils/scriptLoader.ts';
export default {
name: 'mail',
version: '1.0.0',
description: 'Tools for Mail.app',
workflows: [],
tools: [],
async initialize(dependencies, toolRegistry, workflowRegistry) {
const pluginDir = getPluginDir();
toolRegistry.registerTool(
'send_email',
{
title: 'Send Email',
description: 'Create an email in Mail.app',
category: 'Mail',
inputSchema: {
to: z.string().email().describe('Recipient'),
subject: z.string().describe('Subject'),
body: z.string().describe('Body'),
},
},
async (args) => {
// Runs scripts/send_email.applescript with template variables
return await findAndExecuteScript(
pluginDir,
'send_email',
{ to: args.to, subject: args.subject, body: args.body }
);
},
);
},
} as AppPlugin;
The guide covers:
- Plugin structure and file naming
- AppleScript template variables
- Multiple tools per plugin
- Error handling and debugging
- Complete working examples
Script Development
Template Scripts
Use template variables in .applescript
files:
-- my_script.applescript
tell application "Finder"
set file label of (POSIX file ${filePath} as alias) to ${labelIndex}
end tell
Variables are automatically escaped and type-converted:
- Strings: Wrapped in quotes, escaped
- Arrays: Converted to AppleScript lists:
{"item1", "item2"}
- Objects: Converted to AppleScript records:
{key:"value"}
- null/undefined: Converted to
missing value
Compiled Scripts
For better performance, use compiled scripts:
# Compile an AppleScript
osacompile -o my_script.scpt my_script.applescript
Compiled scripts run directly without compilation overhead.
Error Handling
All tools return consistent error structures:
{
"success": false,
"error": {
"type": "permission|timeout|script_error|system_error|disabled",
"message": "Human-readable error",
"code": "ERR_CODE",
"hint": "LLM-friendly suggestion",
"details": "Technical details"
},
"metadata": {
"executionTime": 123,
"scriptPath": "/path/to/script",
"timeoutUsed": 30000
}
}
Common Issues
Permission Denied
Solution: Grant automation permissions
- Use
check_applescript_permissions
to identify which apps need permissions - Go to System Settings > Privacy & Security > Automation
- Enable automation for the MCP server process
Script Timeouts
Solution: Increase timeout or optimize script
- Set higher
timeout
parameter - Check
APPLESCRIPT_TIMEOUT_MAX
configuration - Break complex operations into smaller scripts
run_script Disabled
Solution: Enable in configuration
- Set
ENABLE_ARBITRARY_SCRIPTS=true
in.env
- Restart server
- Be aware of security implications
Security Considerations
- š Arbitrary Scripts: Disabled by default. Only enable if you trust the LLM client.
- š File System: Scripts run with server process permissions.
- šÆ Application Control: Can control any app with granted automation permissions.
- ā±ļø Timeout Limits: Always enforced to prevent runaway scripts.
- š Error Details: May contain system information. Review error output.
Performance Tips
- Use compiled scripts (
.scpt
) for frequently-used operations - Set appropriate timeouts based on operation complexity
- Batch operations when possible (e.g., multiple files at once)
- Cache results for read-only operations (e.g., dictionary reads)
Testing
# Run tests
deno task test
# Run specific test file
deno test tests/scriptRunner.test.ts
Contributing
This is a showcase example for the @beyondbetter/bb-mcp-server library.
Contributions welcome:
- Fork the repository
- Create a feature branch
- Add tests for new functionality
- Submit a pull request
License
MIT License - see LICENSE file for details
Related Projects
- bb-mcp-server: The MCP server library powering this project
- Model Context Protocol: The protocol specification
Support
- Issues: GitHub Issues
- Discussions: GitHub Discussions
- Library Docs: bb-mcp-server Documentation
Built with @beyondbetter/bb-mcp-server - A powerful framework for building MCP servers with plugins, workflows, and OAuth support.