Appshots MCP
MCP server for generating ASO-optimized App Store screenshots
Ask AI about Appshots MCP
Powered by Claude Β· Grounded in docs
I know everything about Appshots MCP. Ask me about installation, configuration, usage, or troubleshooting.
0/500
Reviews
Documentation
appshots-mcp
MCP server for generating ASO-optimized App Store screenshots. Generates up to 780 final images per app (39 locales x 5-10 screenshots x 1-2 devices).
AI logic lives in Claude Code; the server provides tools, rendering, and validation.
Why appshots-mcp?
| Current solution | Problem |
|---|---|
| Manual Figma | Days of work, repeat on every update |
| AppScreens / Screenshots.pro | Paid, vendor lock-in |
| fastlane frameit + ImageMagick | Flat PNG frames, ~10% layout accuracy, RTL/emoji breaks |
Core problem: screenshot captions are disconnected from ASO keywords. Captions must reinforce keyword coverage, not be random marketing text. appshots-mcp solves this by integrating ASO keyword analysis directly into the screenshot generation pipeline.
Features
- 24 MCP tools for the complete screenshot pipeline
- 3 MCP prompts guiding app preparation, template design, and batch generation
- Simulator state management β pre-warm, seed UserDefaults, scroll/tap before capture
- Clean capture + Typst compositing β framebuffer screenshots with device frames added in templates
- Typst rendering β native RTL/CJK support, exact layout, sub-second renders
- OKLCH color space exclusively β perceptually uniform, no hex/RGB
- 39 ASO locales with fallback chains
- Granular regeneration β fix one screenshot without re-rendering all 780
- Keyword-aware captions β AI incorporates ASO keywords into every locale's captions
- Parallel rendering with configurable concurrency (4 concurrent by default)
- Auto font discovery from
appshots/fonts/directory - Compilation timeout (30s) prevents infinite-loop templates
- Atomic file writes with advisory locking
- Path containment prevents symlink escape attacks
Quick Start
Installation
Homebrew (macOS/Linux):
brew install Murzav/tap/appshots-mcp
Cargo:
cargo install appshots-mcp
cargo-binstall (prebuilt binary):
cargo binstall appshots-mcp
Configuration
Claude Code:
claude mcp add appshots-mcp -- appshots-mcp --project-dir /path/to/your/app
Generic MCP client (stdio):
{
"mcpServers": {
"appshots-mcp": {
"command": "appshots-mcp",
"args": ["--project-dir", "/path/to/your/app"]
}
}
}
CLI Options
| Flag | Default | Description |
|---|---|---|
--project-dir | . | Path to the app project root |
--glossary-path | glossary.json | Path to shared glossary file |
--config-path | appshots.json | Path to screenshot config |
Usage
Typical Workflow
- Prepare your app β use the
prepare-appprompt to createScreenshotModeenum in Swift - Design templates β use the
design-templateprompt to create Typst templates withpreview_design - Generate all screenshots β use the
generate-screenshotsprompt for the full pipeline:
scan_project β analyze_keywords β plan_screens β save_captions (en-US)
β translate captions (38 locales) β validate_layout
β warm_simulator β seed_defaults β capture_screenshots
β compose_screenshots β run_deliver
Tools
Capture & Setup
| Tool | Description |
|---|---|
list_simulators | List available iOS simulators (UDID, runtime, state) |
warm_simulator | Pre-boot simulator, grant permissions, set Apple canonical status bar (9:41) |
seed_defaults | Seed UserDefaults via plist import (run after install, before launch) |
interact_simulator | Scroll or tap in iOS Simulator via CGEvent mouse drag simulation |
capture_screenshots | Capture clean screenshots from simulator framebuffer (no device bezels) |
Discovery & Analysis
| Tool | Description |
|---|---|
scan_project | Parse fastlane/metadata/ across all 39 locales |
analyze_keywords | Find keyword coverage gaps for a locale |
get_project_status | Check config, templates, captions, captures readiness |
Strategy
| Tool | Description |
|---|---|
plan_screens | Save mode -> keyword -> messaging mapping |
get_plans | Retrieve current screen plans |
save_captions | Save captions for a locale (upsert by mode) |
get_captions | Get captions with locale/mode filters |
get_locale_keywords | Read keywords.txt for a locale |
get_caption_coverage | Coverage matrix: locale x mode |
review_captions | Keyword coverage analysis per caption |
Design & Rendering
| Tool | Description |
|---|---|
save_template | Save Typst template source |
get_template | Read template with resolution chain |
preview_design | Render a single design preview |
validate_layout | Check all templates for errors/warnings |
suggest_font | Suggest system font for a locale's script |
compose_screenshots | Render final PNGs via Typst |
Pipeline & Glossary
| Tool | Description |
|---|---|
run_deliver | Run fastlane deliver to upload screenshots |
get_glossary | Get glossary entries (shared with xcstrings-mcp) |
update_glossary | Update glossary entries |
Prompts
| Prompt | Description |
|---|---|
prepare-app | Guide: create ScreenshotMode enum + ScreenshotDataProvider in Swift; documents defaults import for seeding mock data |
design-template | Guide: design Typst template with OKLCH colors, auto-scaling text, RTL support; includes device frame compositing approaches |
generate-screenshots | Guide: full 10-step pipeline from scan to deliver; covers warm/seed/interact prep steps and compose internals |
Granular Regeneration
All rendering tools accept optional modes and locales filters. Omitting = process all.
"Fix screenshot 3" β compose_screenshots(modes: [3])
"Fix German text on #5" β compose_screenshots(modes: [5], locales: ["de-DE"])
"Re-capture stats screen" β capture_screenshots(modes: [4])
Key Rules
- OKLCH Only: All colors use
oklch(L%, C, Hdeg). No hex, RGB, or HSL. - Template Resolution:
templates/template-{mode}.typ->templates/template.typ->template.typ - Locale Fallback: es-MX->es-ES, fr-CA->fr-FR, en-AU/CA/GB->en-US, pt-PT->pt-BR, zh-Hant->zh-Hans
- Required Sizes: iPhone 6.9" (1320x2868), iPad 13" (2064x2752). Max 10 per locale.
How Screenshot Modes Work
Each app screen is assigned a numeric mode (1-10). The app's ScreenshotMode Swift enum maps modes to specific UI states:
- The app is launched with
xcrun simctl launch --screenshot-N <udid> <bundle_id>where N is the mode number ScreenshotDataProviderin the app checksProcessInfo.processInfo.argumentsfor--screenshot-Nand configures mock data accordingly- For complex state (e.g., streak counts, pro status), use
seed_defaultsto write UserDefaults before launching the app capture_screenshotscaptures a clean framebuffer image per mode β no device bezelscompose_screenshotsrenders the final PNG via Typst, overlaying captions and optionally adding device frames
Project Directory Structure
project-root/
βββ fastlane/
β βββ metadata/{locale}/ β keywords.txt, name.txt, subtitle.txt
β βββ screenshots/{locale}/ β final output
βββ appshots.json β project config (plan, captions, template)
βββ appshots/
β βββ template.typ β single template
β βββ templates/ β per-screen templates
β βββ fonts/ β custom fonts (.ttf, .otf, .woff2)
β βββ captures/ β simulator captures (clean framebuffer)
β βββ previews/ β design iteration previews
β βββ .seed-defaults.plist β temporary plist for defaults import
βββ examples/ β reference Typst templates
βββ glossary.json β shared with xcstrings-mcp
Device Frame Compositing
capture_screenshots produces clean framebuffer images without device bezels. Device frames are added during compose_screenshots via Typst templates. Three approaches:
- Raw screenshot β no frame, just the capture with captions overlay
- Rounded card β Typst
rect(radius: ...)withclip: trueto simulate device corners - PNG overlay β place a transparent device frame PNG on top of the screenshot (pixel-perfect Apple bezels)
See examples/template-with-frame.typ for a reference template demonstrating approach #2 with RTL support, auto-scaling text, and OKLCH colors.
Architecture
main.rs β CLI (clap), tokio current_thread, stdio transport
server.rs β #[tool_router] (24 tools) + #[prompt_router] (3 prompts)
tools/ β capture, scan, analyze, plan, captions, design, render,
deliver, validate, glossary β all I/O via FileStore trait
service/ β metadata_parser, locale, keyword_matcher, font_resolver,
template_resolver, typst_renderer, typst_world, validator,
config_parser β pure functions, NO I/O
model/ β ProjectConfig, Caption, OklchColor, AsoLocale, Device,
TemplateConfig β data types with serde + JsonSchema
io/ β FileStore trait + FsFileStore (atomic writes, flock)
error.rs β AppShotsError enum (thiserror)
prompts.rs β prompt content generators
Layer rule: server -> tools -> service -> model. Services have NO I/O.
Performance
| Operation | Target |
|---|---|
scan_project (39 locales) | < 50ms |
compose_screenshots (1) | < 100ms |
compose_screenshots (all, parallel) | < 20s |
capture_screenshots (1x1) | ~3s |
Related
- MCP Protocol β Model Context Protocol specification
- xcstrings-mcp β Sister project for .xcstrings localization
- Typst β The typesetting system used for rendering
- fastlane β App Store automation
License
Licensed under either of:
- Apache License, Version 2.0 (LICENSE-APACHE)
- MIT License (LICENSE-MIT)
at your option.
Contributing
Contributions are welcome! Please open an issue or submit a PR.
