Skip to main content
Glama

Keynote MCP

License: MIT Python 3.10+ PyPI macOS

An MCP server that gives AI full control over Apple Keynote through AppleScript automation. Create, edit, and export presentations — all via natural language.

Ships with a Claude Skill that encodes layout rules, font workarounds, and design patterns so presentations come out right on the first try.

Quick Start

Prerequisites

  • macOS 10.14+

  • Keynote application installed

  • Python 3.10+

Option A: Install from PyPI

pip install keynote-mcp

Or run directly with uvx (no install needed):

uvx keynote-mcp

Option B: Install from source

git clone https://github.com/ByAxe/keynote-mcp.git
cd keynote-mcp
python -m venv .venv
source .venv/bin/activate
pip install -e .

Register the MCP server

Claude Code (PyPI install / uvx):

claude mcp add keynote-mcp keynote-mcp

Claude Code (from source):

claude mcp add keynote-mcp "bash -c cd $(pwd) && .venv/bin/python -m keynote_mcp"

Claude Desktop — add to claude_desktop_config.json:

{
  "mcpServers": {
    "keynote-mcp": {
      "command": "keynote-mcp",
      "env": {
        "UNSPLASH_KEY": "your_key_here"
      }
    }
  }
}

Or if using uvx:

{
  "mcpServers": {
    "keynote-mcp": {
      "command": "uvx",
      "args": ["keynote-mcp"],
      "env": {
        "UNSPLASH_KEY": "your_key_here"
      }
    }
  }
}

Other MCP clients:

  • Command: keynote-mcp (if installed via pip) or uvx keynote-mcp

  • Transport: stdio

The keynote-presentation skill teaches Claude how to use the MCP tools correctly — handling font clipping bugs, theme pitfalls, coordinate math, and design patterns.

Claude Code — copy the skill folder to your skills directory:

cp -r skills/keynote-presentation ~/.claude/skills/keynote-presentation

Claude.ai:

  1. Zip the skills/keynote-presentation folder

  2. Go to Settings > Capabilities > Skills

  3. Click "Upload skill" and select the zip

4. macOS permissions

  • System Settings > Privacy & Security > Accessibility — add Terminal/your IDE

  • System Settings > Privacy & Security > Automation — allow Python to control Keynote

Security note: Accessibility permissions are granted per-binary, not per-project. When you grant Accessibility access to python, all Python processes share that permission. Most keynote-mcp tools use plain AppleScript (no Accessibility needed) — only build animations require it. For stricter isolation, you can build a standalone binary (see Standalone Binary below) so keynote-mcp gets its own permission entry.

5. Use it

"Create a presentation about our Q1 results with 6 slides"
"Add a slide with a code example showing the API"
"Export the presentation as PDF"

Related MCP server: fcp-mcp

Available Tools (30+)

Category

Tools

Presentation

create, open, save, close, list, themes, resolution, slide size

Slides

add, delete, duplicate, move, select, layouts, slide info

Content

text boxes (with font/color control), titles, subtitles, bullet lists, numbered lists, code blocks (with color), quotes, images, shapes (with opacity), edit, delete, move, resize elements, set element opacity, clear slide, speaker notes, build-in animations (add/remove via UI scripting)

Export

screenshot slides, export PDF

Unsplash

search images, add to slides, random images (requires UNSPLASH_KEY)

Unsplash Integration (optional)

cp env.example .env
# Add your key from https://unsplash.com/developers
# UNSPLASH_KEY=your_access_key

About the Skill

The keynote-presentation skill (skills/keynote-presentation/) solves real problems discovered through production use:

  • Font clipping bug: Large font sizes (>48pt) create tiny text boxes that clip text to 1-2 characters. The skill teaches Claude the resize-then-edit workaround.

  • Theme pitfalls: Many themes (Gradient, Minimalist Dark) don't show backgrounds on Blank slides. The skill includes a tested compatibility table.

  • Coordinate math: No text-align property exists. The skill provides per-character width estimates for manual centering.

  • Shape fill limitation: Shape fill color is NOT writable via AppleScript. The skill documents the opacity workaround for dark-theme containers.

  • Dark theme color reference: Tested RGB values for white text, gray subtitles, green code comments, and blue section headers.

  • Two-column layouts: Proven coordinates for code-left/bullets-right slides using add_shape containers.

  • Design patterns: Landing-page-style slide templates (hero, statement, bullets, code demo, closing) with tested positions.

Skill structure

skills/keynote-presentation/
    SKILL.md                              # Main skill file with YAML frontmatter
    references/
        theme-reference.md                # Theme compatibility table
        coordinate-reference.md           # Layout math and centering formulas

Project Structure

src/
  keynote_mcp/
    __init__.py            # Package version
    __main__.py            # python -m keynote_mcp entry point
    server.py              # MCP server — routes tool calls via stdio
    tools/
      presentation.py      # Presentation lifecycle tools
      slide.py             # Slide management tools
      content.py           # Content creation and editing tools
      export.py            # Screenshot and PDF export tools
      unsplash.py          # Unsplash image integration
    utils/
      applescript_runner.py # Executes AppleScript via osascript
      error_handler.py     # Exception hierarchy and validation
    applescript/           # AppleScript source files
skills/                    # Claude Skills for this MCP
tests/                     # Test scaffolding

Standalone Binary

For security-conscious users who don't want to grant Accessibility permissions to the shared python binary, you can build keynote-mcp as a standalone executable with its own permission entry:

# Install pyinstaller
pip install pyinstaller

# Build standalone binary (~31MB)
pyinstaller --onefile --name keynote-mcp src/keynote_mcp/__main__.py

# Code-sign so macOS tracks it as its own app
codesign -s - -f dist/keynote-mcp

Then use the binary in your MCP config:

{
  "mcpServers": {
    "keynote-mcp": {
      "command": "/absolute/path/to/dist/keynote-mcp"
    }
  }
}

When you grant Accessibility permission, it will appear as "keynote-mcp" instead of "Python".

Contributing

See CONTRIBUTING.md for details.

License

MIT — see LICENSE.

Acknowledgments

Available Tools

42 tools
add_build_inA

Add a Build In animation to an element so it appears step-by-step (e.g. bullets one by one on click). Uses UI scripting — requires Accessibility permissions.

Inputs: slide_number (required), element_type (required), element_index (required), effect, +1 more.

add_builds_to_slideA

Add Build In animations to multiple elements on a slide in one call. Applies builds in order so elements appear sequentially on click. Auto-skips bullet dots (text items containing only '•'). Uses UI scripting.

Inputs: slide_number (required), element_indices (required), element_type, effect.

add_bullet_listC

Add a bullet list to a slide

Inputs: slide_number (required), items (required), x, y, +2 more.

add_code_blockC

Add a code block to a slide

Inputs: slide_number (required), code (required), x, y, +3 more.

add_imageC

Add an image to a slide

Inputs: slide_number (required), image_path (required), x, y.

add_numbered_listC

Add a numbered list to a slide

Inputs: slide_number (required), items (required), x, y, +2 more.

add_quoteC

Add a quote to a slide

Inputs: slide_number (required), quote (required), x, y, +2 more.

add_shapeC

Create a rectangle shape with optional position, size, and opacity

Inputs: slide_number (required), x, y, width, +3 more.

add_slideC

Add a new slide to the presentation

Inputs: doc_name, position, layout.

add_subtitleC

Add a subtitle to a slide

Inputs: slide_number (required), subtitle (required), x, y, +2 more.

add_text_boxC

Add a text box to a slide

Inputs: slide_number (required), text (required), x, y, +3 more.

add_titleC

Add a title to a slide

Inputs: slide_number (required), title (required), x, y, +2 more.

clear_slideA

Clear all user-created content from a slide, preserving background images and theme placeholders

Inputs: slide_number (required), doc_name.

close_presentationB

Close a presentation

Inputs: doc_name, should_save.

create_presentationC

Create a new Keynote presentation

Inputs: title (required), theme, template.

delete_elementC

Delete an element by type and index from a slide

Inputs: slide_number (required), element_type (required), element_index (required), doc_name.

delete_slideC

Delete a slide

Inputs: slide_number (required), doc_name.

duplicate_slideC

Duplicate a slide

Inputs: slide_number (required), doc_name, new_position.

edit_text_itemC

Edit a text item's content by index on a slide

Inputs: slide_number (required), item_index (required), new_text (required), doc_name.

export_pdfC

Export presentation as PDF

Inputs: output_path (required).

get_available_layoutsC

Get list of available slide layouts

Inputs: doc_name.

get_available_themesB

Get list of available themes

Inputs: no named parameters.

get_presentation_infoC

Get presentation info (name, slide count, theme)

Inputs: doc_name.

get_presentation_resolutionC

Get presentation resolution (width, height, aspect ratio)

Inputs: doc_name.

get_slide_contentA

Get all elements on a slide — returns counts and details for text items, images, shapes, and tables

Inputs: slide_number (required), doc_name.

get_slide_countD

Get slide count

Inputs: doc_name.

get_slide_infoB

Get slide info (number, layout, text item count)

Inputs: slide_number (required), doc_name.

get_slide_sizeB

Get slide size, aspect ratio, and layout reference info

Inputs: doc_name.

get_speaker_notesC

Get presenter notes from a slide

Inputs: slide_number (required), doc_name.

list_presentationsB

List all open presentations

Inputs: no named parameters.

move_elementC

Move an element to new coordinates on a slide

Inputs: slide_number (required), element_type (required), element_index (required), x (required), +2 more.

move_slideC

Move a slide to a different position

Inputs: from_position (required), to_position (required), doc_name.

open_presentationC

Open an existing Keynote presentation

Inputs: file_path (required).

remove_build_inC

Remove Build In animation from an element. Uses UI scripting.

Inputs: slide_number (required), element_type (required), element_index (required).

resize_elementC

Resize an element on a slide

Inputs: slide_number (required), element_type (required), element_index (required), width (required), +2 more.

save_presentationC

Save a presentation

Inputs: doc_name.

screenshot_slideC

Take a screenshot of a single slide

Inputs: slide_number (required), output_path (required), format.

select_slideC

Select a specific slide

Inputs: slide_number (required), doc_name.

set_element_opacityC

Set opacity (0-100) on any element

Inputs: slide_number (required), element_type (required), element_index (required), opacity (required), +1 more.

set_presentation_themeC

Set presentation theme

Inputs: theme_name (required), doc_name.

set_slide_layoutD

Set slide layout

Inputs: slide_number (required), layout (required), doc_name.

set_speaker_notesC

Set presenter notes on a slide

Inputs: slide_number (required), notes (required), doc_name.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    C2.9/5.0

    Scored across 42 tools

    Disambiguation4/5

    Most tools have distinct purposes targeting specific presentation elements or actions, but some overlap exists between 'add_build_in' and 'add_builds_to_slide' (both handle build animations) and between various 'add_' tools for different content types, which could cause minor confusion. Descriptions generally clarify differences, such as 'add_build_in' for single elements versus 'add_builds_to_slide' for multiple.

    Naming Consistency5/5

    Tool names follow a highly consistent verb_noun pattern throughout, such as 'add_slide', 'delete_element', 'get_presentation_info', and 'set_slide_layout'. All tools use snake_case without deviation, making the naming predictable and easy to understand across the entire set.

    Tool Count2/5

    With 42 tools, the count is excessive for a presentation management server, likely leading to complexity and potential redundancy. While the domain is broad, many tools could be consolidated (e.g., multiple 'add_' tools for different content types), making the set feel heavy and overwhelming for typical agent use.

    Completeness5/5

    The tool set provides comprehensive coverage for Keynote presentation management, including full CRUD operations for slides and elements, animation handling, export capabilities, and metadata access. No obvious gaps exist; it supports creation, editing, styling, and presentation workflows end-to-end.

    Maintenance

    ActivityInactive
    ResponsivenessOutdated data

    Related MCP Connectors

    Related MCP Servers