Back to work

FrameHero

From App Store screenshot tool to AI-powered API — building a product that agents can use

iOSSwiftAPI DesignMCPAI Agents

At a Glance

Role
Design & Engineering
Timeline
3 months
Tech Stack
SwiftSwiftUICore ImageNWListenerMCP Protocol

The Problem

Publishing an iOS app to the App Store requires screenshots for every supported device size, in every locale you want to support. A single app targeting 5 device sizes across 10 languages needs 500 individual screenshots. Most indie developers either skip localization entirely or spend days in Figma doing it manually.

The existing tools (AppScreens, Screenshots Pro) work but they're web-based, expensive, and none of them can automate the hardest part: capturing locale-specific screenshots from the iOS Simulator.

What We Built

FrameHero is a macOS app that automates App Store screenshot creation. The core differentiator: it controls the iOS Simulator directly, switching locales and capturing screenshots programmatically. No other tool does this.

The App

The desktop app handles the full workflow:

  • Automated locale capture — connects to iOS Simulator via simctl, switches languages, relaunches the app, and captures screenshots across all 40 App Store locales automatically
  • Visual editor — layer-based compositor (Core Image, GPU-accelerated) for adding device frames, text overlays, backgrounds, and custom layouts
  • Template system — 12 pre-built templates covering minimal and bold styles, with full customization
  • Video previews — App Store preview video generation with captions, transitions, and device frame overlays using AVFoundation
  • AI metadata — Claude-powered generation of optimized titles, subtitles, keywords, and descriptions
  • Translation — context-aware App Store copy translation across all supported locales
  • Direct upload — App Store Connect API integration for pushing screenshots directly

The Architecture

Everything runs locally. No cloud dependency for core features.

ComponentTechnologyWhy
UISwiftUIModern, declarative, fast iteration
PersistenceSwiftDataFirst-party, simple, sufficient
Image compositingCore ImageGPU-accelerated, non-destructive pipeline
Video renderingAVFoundation + custom AVVideoCompositingAlpha-channel support for overlays
Text renderingTextKit 2Render to image, then composite
Simulator controlsimctl CLIThe differentiator
AIClaude API via proxyMetadata generation + translation
PaymentsPolar (Lemon Squeezy)License key validation
UpdatesSparkleDirect download distribution

The compositor follows a strict Model → Compositor → View pattern. Source images are never modified. The view shows a rendered CGImage from the compositor. Interaction (drag, resize, select) happens in a transparent SwiftUI overlay layer. This keeps rendering deterministic and makes the preview-to-export path trivial.

Then We Built the API

The app works great for humans. But we kept thinking about the target audience: indie developers who build with AI coding tools. If someone is using Claude Code or Cursor to build their app, why should they switch to a GUI to make screenshots?

So we built an HTTP API and MCP server directly into FrameHero.

Local HTTP API

When FrameHero is running, it serves a REST API on localhost:9820:

GET  /health
GET  /v1/templates
GET  /v1/templates/{id}
GET  /v1/devices
POST /v1/screenshots/generate
POST /v1/screenshots/batch
POST /v1/metadata/generate
POST /v1/metadata/translate
POST /v1/export

An agent can send raw simulator screenshots plus a template ID and text overlays, and get back finished App Store screenshots. The batch export endpoint generates every device size × locale combination in one call, organized in the exact directory structure App Store Connect expects.

MCP Server

The real unlock: FrameHero as an MCP tool. Launch with --mcp and it becomes a tool server that Claude Code or Cursor can call natively:

  • framehero_list_templates — browse available designs
  • framehero_generate_screenshot — create a single screenshot
  • framehero_generate_metadata — AI-optimized App Store copy
  • framehero_translate_metadata — localize to any of 40 locales
  • framehero_batch_export — full export run

The workflow becomes: developer says "make App Store screenshots for this app," the coding agent calls FrameHero's MCP tools, and the entire listing is generated without a human touching the GUI.

Technical Details

The Compositor Pipeline

Every screenshot generation request follows the same path, whether it comes from the GUI, the HTTP API, or an MCP tool call:

  1. Parse input into Layer models (background, device frame, screenshot, text overlays)
  2. Compositor renders layers bottom-to-top using Core Image (CISourceOverCompositing)
  3. Text rendered via TextKit 2 to NSImage, then converted to CIImage for compositing
  4. Device frame loaded from asset bundle, screenshot placed in screen rect
  5. Output at full resolution (e.g., 1320×2868 for iPhone 6.9")

Preview renders at 1x for speed. Export renders at full device resolution. Same pipeline, different scale factor.

The API Server

Built with Foundation's Network framework (NWListener + NWConnection). No third-party HTTP dependencies. The server runs as a Swift actor, keeping it thread-safe and non-blocking. Routes are simple pattern matches dispatched to handler functions that share logic with the app's core services.

MCP Implementation

The MCP server implements the JSON-RPC stdio transport. It handles the initialize/initialized handshake, responds to tools/list with the six tool definitions, and dispatches tools/call to the same handlers used by the HTTP routes. One codebase, two interfaces.

Results

  • 12 files, 2,289 lines of API code added to the existing app
  • Zero new dependencies — built entirely on Foundation frameworks
  • Same compositor serves GUI, HTTP, and MCP — no code duplication
  • Full App Store coverage — all 40 locales, all required device sizes
  • Sub-second screenshot generation on Apple Silicon

What We Learned

Design for the API first. If we'd built the API from the start, the compositor architecture would have been cleaner. The Layer model was already well-structured (because SwiftData needs it), which made the API translation straightforward. But some GUI-specific assumptions had to be worked around.

MCP is underrated. The stdio transport is trivially simple to implement. The hardest part was deciding which parameters to expose. If your app has clear input/output boundaries, adding MCP support is a few hundred lines of code for a significant distribution advantage.

Local-first matters. Running the API server inside the app means zero deployment, zero auth complexity, zero latency. The developer installs FrameHero, and their agent can use it immediately. No API keys, no cloud accounts, no pricing tiers.


This project was built by Parallel Studio. We design and build AI-native products — from concept through production. Tell us about your project.