AppFactory
Server Configuration
Describes the environment variables required to run the server.
| Name | Required | Description | Default |
|---|---|---|---|
No arguments | |||
Instructions
Guidance the server publishes about itself, which clients place ahead of the tool catalog so the model reads it before choosing anything.
This server publishes no instructions, or was last inspected before Glama recorded them.
Capabilities
Features and capabilities supported by this server
Protocol revision2025-11-25
| Capability | Details |
|---|---|
| tools | {
"listChanged": true
} |
| logging | {} |
| prompts | {
"listChanged": false
} |
| resources | {
"subscribe": false,
"listChanged": false
} |
| extensions | {
"io.modelcontextprotocol/ui": {}
} |
| experimental | {} |
Tools
Functions exposed to the LLM to take actions
| Name | Description |
|---|---|
| setup_statusA | Setup state per service: enabled, keys set/missing (never values), missing tools with install commands,
approvals mode, and |
| setup_servicesB | Turn services on or off (research is always on). Ask the user which ones they want first. Returns setup_status. |
| setup_setA | Set ONE non-secret config key (e.g. asc_key_id, team_id, support_email). Secrets are refused: use setup_credentials so they never pass through the chat. An empty value clears the key. |
| setup_approvalsA | Set human approvals for live writes: 'required' (recommended). 'off' is refused here; only the human can switch it off, on the setup_credentials page. |
| setup_credentialsA | Open a local browser page (127.0.0.1, random port, one-time token) where the USER types the credentials of the given (default: all enabled) services. Secrets never reach you. Returns at once with the url; tell the user to fill the form and Save, then call setup_status(). |
| config_doctorA | Report config status: which keys are present/missing (secrets are masked). |
| config_setA | Write NON-secret settings to ~/.appfactory/config.toml (0600). Fields left empty are unchanged. Secrets (passwords, sessions, tokens, API keys, phone) are refused here so they never pass through the model: the human enters them on the page opened by setup_credentials(). |
| asc_token_checkA | Check App Store Connect auth through the asc CLI: binary present, which credentials it uses (config.toml asc_* keys as env, else the asc keychain profile) and one live read-only call. A successful |
| asc_list_appsA | List the apps in App Store Connect (LIVE; requires issuer_id). |
| asc_get_appC | Find the App Store Connect app by bundle id (LIVE). |
| asc_create_bundle_idA | Register a bundle id in App Store Connect (LIVE write), then its capabilities. The App ID capabilities (IN_APP_PURCHASE, APPLE_ID_AUTH/PRIMARY_APP_CONSENT, HEALTHKIT if spec.health.enabled) must exist BEFORE any key, profile or signing step. With app_dir the spec's capabilities are checked right away; apply_capabilities=true also applies them. Human approval. |
| asc_create_appA | Create an app SHELL in App Store Connect (fastlane produce — requires Apple ID). AUTOMATIC. The one ASC write that does not go through the asc CLI: Apple's public API cannot create apps and
App names are globally unique. Pass |
| asc_create_subscription_groupC | Create a subscription group for the app (LIVE write). |
| asc_finalize_subscriptionA | FINALIZE one subscription (ORDER: localization → availability (all but CHN) → price → intro offer).
The intro offer follows the SPEC: pass the spec product's |
| asc_finalize_submission_requirementsA | Fill submit-blocking app-level fields in one call: Content Rights + Copyright + Age Rating (4+) + Free Price + App Review Contact + App Review Notes (7-item test flow). App Privacy EXCLUDED (not in Apple's API → set via ASC web UI; appDataUsages endpoints all 404). Called before submit, per app. RULE: if copyright is omitted, it's read from config ("copyright" key — set your own via config_set); if contact_email is omitted, support_email is used (NOT apple_id, which is only the developer-account login). If review_notes is omitted, a generic 7-item template is filled with app_name/ai_services (Apple 2.1). |
| asc_append_subscription_disclosureA | APPEND subscription disclosure + Terms/EULA + Privacy link to the description (per language) (Apple 3.1.2). Idempotent (skips if the marker is present). If terms_url is omitted, Apple's standard EULA is used. Truncated to ≤4000. |
| asc_ensure_subscription_pricesA | Walk ALL of the app's subscriptions; set a price on those that have NONE (clears MISSING_METADATA). Idempotent (those with a price are skipped). Price comes from usd_price_by_product[productId] or default_usd. |
| asc_add_subscription_group_localizationD | Subscription group display name (required for MISSING_METADATA). |
| asc_localize_subscriptionB | Localize the subscription in MULTIPLE LANGUAGES. items={locale:{name,description}}. IAP-unsupported languages are skipped. |
| asc_localize_groupC | Localize the subscription group name in multiple languages. |
| asc_create_subscriptionC | Create a subscription product. period: ONE_WEEK/ONE_MONTH/.../ONE_YEAR (LIVE write). |
| asc_submit_for_reviewA | SUBMIT the app to App Store review. Always needs out-of-band human approval ( |
| env_doctorB | Check the local toolchain: xcode, swift, node, asc (App Store Connect CLI), fastlane (app creation only), uv, git, maestro + Java 17+ + maestro-live (end-to-end flows, Viewer). |
| build_xcode_versionA | Return the Xcode version (the first validation tool of the build_* group). |
| build_list_simulatorsA | List the available iOS simulators (iPhones are surfaced first). |
| build_boot_simC | Boot the simulator and open Simulator.app. |
| build_screenshotC | Capture a screenshot from the booted simulator → out_path (PNG). |
| build_for_simC | Build the project for the simulator (verification). project = .xcodeproj/.xcworkspace path. |
| build_testC | xcodebuild test (on the simulator). |
| maestro_testA | Run the app's Maestro flows (.maestro/) on the booted simulator through tools/maestro-live:
it starts |
| build_archiveC | xcodebuild archive (generic iOS) → .xcarchive. |
| build_export_ipaC | xcodebuild -exportArchive → .ipa. |
| supabase_list_projectsB | List Supabase projects (LIVE). |
| supabase_list_orgsA | List Supabase organizations (org_id for project creation). |
| supabase_get_keysB | Get the project's url + anon key (anon→app). The service_role key is never returned to the agent; it is saved to ~/.appfactory/supabase/.json (0600) for server-side use. |
| supabase_run_sqlB | Run SQL on the project (schema/migration) — LIVE write, human approval. Destructive statements (DROP, TRUNCATE, ALTER … DROP, GRANT/REVOKE on auth, DELETE/UPDATE without WHERE) always need approval. |
| supabase_set_secretB | Write an edge function secret (FAL_KEY etc.) — server-side, never enters the app. Human approval. |
| supabase_create_projectA | Create a new Supabase project (LIVE — provisions resources). Human approval. |
| app_scaffoldA | Scaffold a new SwiftUI app from app.spec.json (+xcodegen) and init the pipeline manifest. spec: optional full spec dict, a dict of overrides on the defaults, or a path to an app.spec.json; otherwise the defaults for name/bundle_id. The spec is written to the app dir and drives products, StoreKit file, placements, locales, onboarding length, monetization mode (subscription strips the credit economy) and the Supabase backend mode. |
| github_create_repoB | Open a PRIVATE GitHub repo under the configured GitHub account ( dry_run=True (default) returns the exact command without running it; a live run needs human approval. |
| github_pushB | Commit + push changes (regular tracking). Human approval. |
| firebase_setupB | Set up Firebase Analytics (MANDATORY for every app): GCP project + iOS app + GoogleService-Info.plist → Resources/. Fully automatic (gcloud authed + firebase-tools). Live event tracking (from the phone). |
| app_inject_configB | Fill in the scaffolded app's AppConfig + StoreKit tokens. paywall_strategy: "hard_only" (hard paywall only) | "hard_and_offer" (default, hard paywall + a discounted offer paywall on dismiss). Credit fields fall back to defaults if omitted (15/10/10/30/60) — credit pack amounts must be kept in sync with the server-side ai-proxy PACK_MAP. |
| onboarding_planA | Return guidance for onboarding step-count selection (does not generate code). Usage: call this tool to ask the user how many onboarding steps they want, show the returned guidance, let them choose. Then during scaffold, the OnboardingStep array in Views.swift is written by hand with the chosen count and app-specific content (following the per-screen Claude Design boards) — this tool just clarifies the decision point and doesn't modify files. STANDARD: onboarding is a quiz-style Q&A with ~5 personalization questions (OnboardingStep.kind=.question), so new apps match that count (~5), not "at least one". |
| animation_fetch_recolorA | Fetch a CUTE app-specific Lottie animation + recolor it to the palette → Resources/Animations/.json. Source: the free LottieFiles library (Simple License = commercial OK, no attribution). The most-viewed
match is picked and its colors are mapped to the app palette (dominant→primary, others→accent, black/white kept).
Build-time recolor — NO runtime color code in Swift; lottie-spm renders it with |
| metadata_checkB | Validate apple-metadata.md (fields + character limits). No writes. |
| metadata_exportB | apple-metadata.md → fastlane/metadata//*.txt (validated). If app_dir is given the ASO gate applies: export is refused until ASO is complete. primary/secondary_category = appCategories id (e.g. PHOTO_AND_VIDEO, PRODUCTIVITY) → written to the root *.txt files; deliver_metadata pushes them to ASC. Photo/portrait app default: PHOTO_AND_VIDEO+PRODUCTIVITY. |
| aso_check_nameA | Is the App Store name (globally unique) available — iTunes Search exact-name collision. Call BEFORE asc_create_app. |
| aso_find_available_nameC | Pick the first AVAILABLE App Store name from the candidates (a taken name gets the submit rejected). |
| aso_fetch_competitorsC | Fetch competitor apps via iTunes Search (LIVE, read-only). |
| aso_top_grossingA | Top-grossing apps (revenue proxy) — proven-idea hunting. genre: any App Store category name from aso.GENRES (books, business, developer_tools, education, entertainment, finance, food_drink, games, graphics_design, health, lifestyle, medical, music, navigation, news, photo_video, productivity, reference, shopping, social, sports, travel, utilities, weather) or its genre id; None = overall chart. An ignored genre filter returns ok:False, never the overall chart. |
| aso_search_hintsA | App Store autocomplete = REAL search demand (free, no auth). IDEA-STAGE HARD GATE. Returns suggestions in Apple's own popularity order. 0 suggestions for a real term = no demand → REJECT the idea. expand=True appends a–z to the seed and collects the keyword universe (ASO keyword research). An endpoint error returns ok:False (NOT an empty list) — a broken endpoint must not be read as 'no competitors'. |
| aso_niche_scoreA | Idea go/no-go score: demand + competitor weakness + saturation penalty + monetization (0-100). HARD GATE: 0 autocomplete suggestions = REJECT. Competitor metrics from iTunes Search top 50 (country PINNED — userRatingCount is per storefront). Saturation penalty: the score drops if the median competitor is strong. genre: any App Store category (aso.GENRES) — the category's AI density is INFORMATIONAL only (AI is an optional edge, never required nor penalized; not part of the score). verdict: GO(≥60) | MAYBE(≥40) | WEAK | REJECT(median>50k or no demand). |
| idea_harvestA | Phase 0 idea harvest across EVERY App Store category and storefront (not only AI/photo apps). Sweeps top-grossing + top-free (legacy RSS) per genre × storefront (default us, gb, de, br, tr, jp, fr; genres None = all 24 charted categories), dedupes, enriches via iTunes lookup (release date, ratings, price) and returns chart_proven (top-grossing), rising_newcomers (released ≤ newcomer_months, sorted by ratings/day) and per-genre clusters (open_niche: open|some|closed|unmeasured). Read-only, free, paced (~0.3 s/request; a full default sweep takes ~1.5 min). A failed feed is listed in failed_feeds (ok:False) — never read as "no apps". exclude_terms drops the founder's own apps (name/seller match). |
| idea_evaluateC | Evidence bundle to rank one idea (any category): autocomplete count, niche score/verdict, two-window newcomer traction (12 + 6 months), leaders with price ladders, ai_needed (yes|optional|no heuristic + claude_assessment for Claude to set), build_complexity (low|medium|high vs the template), review_risk by genre/term, and the first available name from name_candidates. genre None = inferred from the competitors. |
| aso_competitor_iapA | Competitor's subscription/IAP price ladder (from the App Store product page). Input to the pricing decision. iTunes lookup does not expose IAPs; the product page embeds them. app_id = iTunes trackId (returned by aso_fetch_competitors). FRAGILE (undocumented): on failure ok:False + prices:None — ABSENCE means 'unknown', NOT 'free'. |
| aso_unit_economicsB | Unit economics: credit count × AI cost vs subscription revenue → margin, break-even, warnings. Grounds the price + credit decision in data at the idea/scaffold stage (the yearly_credits/weekly_credits passed to app_scaffold are validated here). apple_cut: Small Business 15% (default), otherwise 0.30. |
| aso_scaffold_outputsC | Create the outputs// skeleton (including apple-metadata.md, 32 languages). |
| aso_validate_metadataC | Validate outputs//02-metadata/apple-metadata.md. |
| aso_runC | Start the ASO stage (mandatory step): outputs skeleton + skill instructions. |
| aso_completeA | Validate the ASO output + mark the 'aso' stage done (opens the metadata/deliver gate). |
| icon_installB | Install the Claude Design app icon: the 1024×1024 master exported from B01-AppIcon.dc.html (design_export_png → design/icon.png), already uploaded + recorded (design_record_upload) → AppIcon.appiconset (alpha flattened) + .appfactory/verify/icon.json (the icon gate requires it). |
| icon_generateA | OPT-IN ONLY (spend → approval): fal raster DRAFT → design/icon_drafts/ as reference for the Claude Design icon board. Never installs an icon — the shipped icon comes from Claude Design (icon_install). |
| localize_applyB | Merge translations into the in-app String Catalog for the spec's locales.app (translations = {english_key: {locale: value}}; other locales are ignored). |
| pipeline_statusC | App pipeline status: which stages are done/pending, and what comes next. |
| pipeline_nextA | Return the next mandatory step + its instructions (driver). Refuses until the run options are confirmed (run_options → run_options_save) unless skip_options_check=true. Returns setup_required first when AppFactory is not set up yet. |
| pipeline_markC | Mark a stage (done/in_progress/pending). |
| pipeline_validateA | Run a stage's enforced gate WITHOUT modifying the manifest. For orchestrator/subagent self-checks: does the gate pass before marking it 'done'? |
| orchestrator_preflightB | Pre-flight for an autonomous run: run options confirmed + config keys + fastlane session freshness + caffeinate command. Ready if blockers is empty. Returns setup_required first when AppFactory is not set up yet. |
| orchestrator_next_actionA | Next action for the driver loop: stage + subagent role + retry budget + instructions. done=True means the pipeline is finished (submit needs human approval). Refuses until the run options are confirmed unless skip_options_check=true; setup_required comes first. |
| run_optionsA | Every optional part of a run (services, monetization, trial, paywalls, onboarding quiz, mascot, languages, store locales, screenshots, preview video, CPPs, analytics, ratings, HealthKit, Sign in with Apple, GitHub issues, e2e smoke tests…) with its question, kind, choices, default and current value. Ask the user each question one at a time (or as a compact checklist if the agent supports multi-select), then call run_options_save. Call this BEFORE any other work when the user says run. |
| run_options_saveA | Save the user's answers ({option id: value}, every id from run_options). Validates types, choices and dependencies; services go to config.toml, the rest to app.spec.json (app_dir) or to a pending file app_scaffold applies. Records options_confirmed. |
| orchestrator_record_attemptB | Count a failed attempt of a stage (after a gate failure). Returns: {stage, attempts, should_retry}. |
| orchestrator_needs_humanB | Self-correction exhausted: write NEEDS_HUMAN.md and return its path. |
| screenshot_captureB | Raw capture from the booted simulator → marketing/raw//.png. |
| screenshot_brandA | Branded App Store screenshots via the node compositor, rendering the Claude Design store layout (run screenshot_apply_layout first; screenshot_build_all does both). |
| screenshot_apply_layoutC | Merge the Claude Design store layout (design/project/store_layout.json, the ST0N boards) into marketing/screenshots/config.json so the compositor renders the approved layout for every locale. |
| screenshot_syncD | branded → fastlane/screenshots//. |
| screenshot_build_allB | MANDATORY turnkey screenshot step (UI-test style, all apps): generate a sample image → build+install → localized captions from the catalog → capture 32 languages × 6 rich screens (onboarding/create/ result/gallery/paywall/settings) → brand → sync to fastlane/screenshots. sample_prompt: a sample prompt for what the app produces (fills Result/Gallery with real output). |
| screenshot_generate_sampleC | Generate a sample image with fal.ai → Resources/sample_headshot.jpg (enriches Result/Gallery). |
| screenshot_onboarding_heroesA | LEGACY, OPT-IN ONLY: fal hero images per onboarding step (onb_step0..N). Onboarding visuals are designed in Claude Design (design/screens.json boards); use this only for a legacy hero-image onboarding. |
| growth_build_slideshowsA | Render viral TikTok/Reels slideshows (SlideSmith pattern, free, no scheduling). CLAUDE writes the hooks/slide text; images are generated with the app's AI (fal). slideshows=[{name, slides:[{text, image_prompt? or image?, cta?}]}]. Output 1080x1920, marketing/growth//NN.png — ready to share. A step for AFTER the app is submitted. |
| preview_briefC | Write marketing/preview/BRIEF.md — the HyperFrames brief (destination: app-store-preview) for this
app's App Preview, from app.spec.json (size, fps, duration, poster, locales and shares), and create
marketing/preview/recordings//. Then record the real app (Scripts/sim_store_prep.sh, then
|
| preview_checkC | Offline readiness of the App Preview set: BRIEF, real recordings per source locale, one preview per spec.preview locale (or a documented share), every file 886x1920 / <=30 fps / H.264 / 15–30 s / <=500 MB / stereo AAC or silent (ffprobe), plus the self-review status and deterministic rendering. |
| preview_review_sheetsA | Self-review material for every final preview (ffmpeg): a contact sheet (fps=2, 270 px, 6x5), a phone-size sheet (fps=1, 360 px, 5x3) and a 12-frame strip around the fastest transition, in marketing/preview/review//. Open them and score with preview_review_log. |
| preview_review_logA | Log one self-review round of a final preview (file relative to the app): scores 1–10 for hook, readability, motion, variety, brand, music; while any is under 8, the 3 worst problems with timestamps [{t, issue}]. Fix, re-render, re-review until every score is 8+ on the exact final file (MD5-matched) — preview_upload and the gate refuse otherwise. |
| preview_uploadA | Upload fastlane/app_previews// to the editable version's IPHONE_67 preview sets through the asc CLI (shares from spec.preview.shared resolved, poster time code from the spec, MD5-idempotent). dry_run=True (default) sends nothing; a live upload needs human approval; refuses while preview_check has problems. |
| cpp_build_allB | Create one CPP per Search Ads theme (create→version→localization) + return the deep-link URLs. themes=[{name, locale?}] from the theme/keyword clusters in the ASO output. The URLs feed Ad Ops. LIVE writes: human approval. |
| deliver_metadataC | Upload metadata to the ASC draft — DIRECT API (bypasses the fastlane 'No data' bug). ASO-gated. |
| deliver_screenshotsA | Upload screenshots to the ASC draft — checksum-based INCREMENTAL sync (NOT fastlane). Skips when local MD5 == ASC sourceFileChecksum; uploads only missing/changed ones → fast + reliable (fastlane was randomly dropping images). Gated on screenshots: run screenshot_build_all first. |
| deliver_screenshots_auditA | Read-only screenshot readiness audit: per locale and display type (iPhone 6.9" = APP_IPHONE_67, Watch = APP_WATCH_ULTRA) the ASC set holds exactly the local fastlane/screenshots files, in order, all COMPLETE, each with the local file's MD5; lists the preview sets. Run after deliver_screenshots and before submission. No writes. |
| deliver_subscription_review_screenshotsA | Upload the App Review screenshot of every subscription from store/review-screenshots/.png (hard paywall with real sandbox prices for the default offering, the offer paywall for offer products). Without it a subscription stays MISSING_METADATA. Idempotent by MD5. Human approval. |
| testflight_shipA | End-to-end TestFlight: distribution signing → archive → App Store profiles (the app and every
extension in project.yml, exact bundle-id match, created right before export so Xcode's profile
sweep cannot delete them) → manual-signing export → |
| signing_setup_distributionC | Create a distribution cert + install it into a temporary keychain (WWDR included). {cert_id, identity, keychain}. |
| signing_create_profileC | Create an IOS_APP_STORE provisioning profile + write it to the standard locations. |
| ai_configureC | AI provider/model selection (for now fal.ai/Flux schnell — the cheapest). |
| ai_deploy_proxyC | Deploy the AI backend. With app.spec.json in subscription mode this is backend_deploy (the full function set + migrations + secrets + auth); credits mode keeps the legacy ai-proxy deploy. AI keys go only to server-side secrets. LIVE side effects: human approval. |
| revenuecat_setupA | Idempotently set up the RC v2 project: entitlement(premium)+4 sub attach+SDK key+secret. A human creates the RC project + links ASC + provides the v2 key; the rest is automatic. Preflight returns NEEDS_HUMAN if there is no project. env_suffix for apps sharing one Supabase (e.g. _MYAPP). LIVE RevenueCat writes: human approval. |
| backend_renderA | Make the scaffolded backend follow app.spec.json (offline, idempotent): prune supabase/ to the monetization mode, render functions/_shared/app.gen.ts + config.toml (Apple client id) + the CONTRACT.md quota block, resolve/fill the legal sources, and sync listing.json locales/legal URLs. |
| backend_deployA | Deploy the spec's Supabase backend (LIVE unless dry_run): migrations (tracked), secrets (AI_MODEL, AI_FALLBACK_MODEL, caps, REQUIRE_CONSENT, RC_PROJECT_ID from app outputs, RC_SECRET_KEY
|
| legal_renderB | Fill the legal sources (store/privacy/*.md, backend/PRIVACY.md) from the spec + config (APP_NAME, CONTROLLER, SUPPORT_EMAIL, dates, trial/plan sentences) and keep/drop the |
| legal_checkC | What still blocks publishing the legal pages (placeholders, unrendered blocks, missing languages). |
| legal_verifyB | LIVE read-only: every privacy/terms page per app language answers 200 in that language with the support email and no placeholder. |
| store_setupA | Idempotent App Store Connect + RevenueCat setup from app.spec.json + listing.json. mode: plan (offline) | check (live reads, simulated writes; reports CONFLICT) | apply (live writes; human
approval via |
| metadata_listing_checkC | Validate store/metadata/listing.json: name/subtitle ≤30, keywords 95–100, promo ≤170, no word overlap across fields or cross-indexed storefronts, description ends with the subscription disclosure + Terms + Privacy links (Supabase legal, ?lang=), IAP display copy. |
| metadata_render_listingC | Sync listing.json to the spec (store locales, IAP copy slots) and fill the legal URLs. |
| pricing_unit_economicsB | Unit economics from the MEASURED AI cost per call (latest backend/eval/results for spec.ai.model, or explicit cost_photo/cost_text) × usage profiles up to the daily caps, per product; writes the generated blocks of store/pricing.md (decisions, unit economics, ASC/RC layout, local prices, anchor). |
| asc_sbp_checkB | Small Business Program proof: latest SUBSCRIPTION/SUMMARY sales report (gzip TSV) → US proceeds/price ratio (≈0.85 SBP, ≈0.70 standard). Needs a Finance-role key: asc_finance_key_id + asc_finance_key_filepath (+ asc_vendor_number); 403 → clear error. |
| storekit_generateA | Write Resources/Configuration.storekit from the app's app.spec.json (group, levels, free-trial intro offers, trial-less offer product, en_US). Deterministic; run after any product change. |
| storekit_parityA | Compare a Configuration.storekit with app.spec.json; returns every mismatch (price, period, level, intro offer, missing/extra product, group, locale). ok=true means in parity. |
| app_sync_specB | Re-generate AppSpec.swift, PaywallSource.swift and Configuration.storekit (and prune the String Catalogs to locales.app) after editing app.spec.json. |
| design_screens_skeletonA | STRUCTURAL skeleton for design/screens.json: with a design brief, the onboarding follows the brief's onboarding.flow (stubs for kinds the default funnel lacks) and carries brief_sha256; without one, the default honest funnel. Rules stay: no fake stats/reviews, spin wheel, rating or notification prompt. ADAPT EVERY SCREEN to the app and the brief — the look is authored in Claude Design, not here. write=True saves it to /design/screens.json (refuses to replace an existing file unless overwrite). |
| design_research_collectB | Design research: the category leaders across storefronts (iTunes Search for |
| design_research_brief_templateC | The design/research/brief.json shape (pre-filled with the reference ids): purpose, analysis, and a direction per section (palette tokens, typography, components, density, illustration, onboarding flow, paywall, screenshots analysis + concept + boards), each citing references and what it does differently. |
| design_research_checkB | The design_research gate: ≥6 reference apps with icon + screenshots on disk, and a valid brief (every section cited, screenshot concept citing ≥4 competitor sets, palette/type not the template defaults or another factory app's). |
| design_generateA | Prepare the app's Claude Design project (the factory's ONLY design source) from the design brief, app.spec.json and design/screens.json. Writes STRUCTURAL scaffolds to design/scaffold/ (every screen incl. paywall/offer, the B01-AppIcon slot, one ST board per brief screenshot board) and into design/project/ the mascot motion boards, canvas.json, store_layout.json and upload_plan.json (plan.authored = boards Claude must author in Claude Design from the brief). Refuses without valid research/brief or when screens/tokens are not derived from the brief. Returns the claude-design MCP calls; this tool never uploads. |
| design_record_uploadA | Record a finished Claude Design upload: SHA-256 of every file in upload_plan.json → design/project/claude_design.json. open_url = the claude.ai/design link from render_preview (never the serve_url). The design, icon and screenshots gates fail until this receipt exists and matches the files. |
| design_upload_statusC | Is the local Claude Design project uploaded and unchanged since (the check every design gate runs)? |
| design_export_pngA | Rasterize a Claude Design board with local headless Chrome (not Claude in Chrome). serve_url comes from mcp__claude-design__render_preview and is used once, never stored. Icon: B01-AppIcon, 1024×1024 → design/icon.png. Store layout check: an ST0N board at 440×956, scale=3 → 1320×2868. |
| mascot_blinkA | Closed-eye copies of the APPROVED pose PNGs (-blink.png next to each): iris blobs in the upper 55 %,
inpainted with the surrounding color, closed-lid arcs. Default input: /design/mascot/.png.
Needs the optional extra: |
| mascot_assetsB | Import approved poses + blink variants into Resources/Assets.xcassets/Mascot/{,-blink}.imageset (namespaced → Image("Mascot/idle")); states without a pose borrow a fallback pose. |
| team_briefC | Render docs/TEAM.md, docs/team/{ios,backend,store}.md, docs/onboarding-plan.md (from design/screens.json), store/aso-research.md and docs/CHECKLIST.md from the spec. sessions: {lead, ios, backend, store} names. |
| github_issues_bootstrapA | Create/refresh the label set (ios, backend, store, lead, founder, next, later, other-project) on /, gh runs as the configured GitHub account. dry_run returns the commands; live: human approval. n/a (nothing runs) when the user turned off the github_issues run option (pass app_dir to read it from the spec). |
| github_issue_createA | Open an issue for postponed work: imperative title, a role label (+ next|later), body with what/why/done-when. Runs gh as the configured GitHub account. dry_run returns the exact command; live: human approval. n/a (nothing runs) when the user turned off the github_issues run option (pass app_dir). |
| playbookA | Return the AppFactory run playbook (markdown). Read it before driving the pipeline. |
Prompts
Interactive templates invoked by user choice
| Name | Description |
|---|---|
| setup | Set up or change AppFactory: choose services and enter keys. |
| run | Run the AppFactory pipeline end to end (idea → TestFlight) following the playbook. |
Resources
Contextual data attached and managed by the client
| Name | Description |
|---|---|
| playbook_resource | The AppFactory run playbook (markdown). |
TDQS
Scored across 125 tools
The server covers many pipeline stages with explicit markers (MANDATORY, OPT-IN, LEGACY, LIVE) and cross-references between descriptions, which helps distinguish most tools. However, several clusters overlap: pipeline_next vs orchestrator_next_action, pipeline_status vs orchestrator_preflight, setup_set vs config_set, metadata_check vs metadata_listing_check vs aso_validate_metadata, and deliver_* vs *_sync variants, creating genuine ambiguity for an agent.
Almost all tool names are snake_case with a domain prefix plus action (asc_*, aso_*, build_*, supabase_*, screenshot_*, design_*, etc.), which is highly consistent within groups. Minor deviations exist: some top-level tools lack a clear domain prefix (deliver_metadata, run_options, playbook) and a few are noun phrases (pricing_unit_economics, team_brief), but there is no camelCase or chaotic mixing.
125 tools is an extreme mismatch for a single server. Even a complex app-factory pipeline likely could consolidate many single-step tools (especially the numerous ESC/design/screenshot/preview stages) into fewer, more purposeful operations.
The surface is extensive, covering idea/ASO research, scaffolding, design, backend, signing, TestFlight, metadata, screenshots, previews, legal, GitHub, and App Store submission. Some gaps remain (no update/delete for several managed resources, limited post-submission monitoring, minimal GitHub PR support), but for the stated pre-submission factory pipeline it is largely complete.