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 | Report the AppFactory setup state per service: enabled, keys set or missing (never values), missing tools with install commands, approvals mode. Use when: first call of every session, and after any setup change. Works with no config file. Returns: {ok, services: {name: {enabled, keys, missing}}, approvals, next: [steps]}. |
| setup_servicesA | Turn optional services on or off (research is always on). Use when: the user has said which services they want; ask them first. Not for: entering credentials (use setup_credentials). Returns: the setup_status result after the change. |
| setup_setA | Set ONE non-secret config key such as asc_key_id, team_id or support_email; an empty value clears it. Use when: changing a single key. Secrets are refused; use setup_credentials so they never pass through the chat. For several fields at once use config_set. Returns: {ok, key, error?}. |
| setup_approvalsA | Set human approvals for live writes to 'required' (recommended). Use when: re-enabling approvals. 'off' is refused here; only the human can switch it off on the setup_credentials page. Returns: {ok, approvals}. |
| setup_credentialsA | Open a local browser page (127.0.0.1, random port, one-time token) where the USER types credentials for the given services. Use when: setup_status shows missing keys. Secrets never reach the agent; return immediately, tell the user to fill the form and Save, then call setup_status. Returns: {ok, url, services}. |
| config_doctorA | Report which config keys in ~/.appfactory/config.toml are present or missing (secrets masked). Use when: diagnosing ASC/Finance key paths, session state or CLI availability. Not for: overall setup guidance (use setup_status) or toolchain checks (use env_doctor). Returns: {ok, config_path, present, missing, locales, asc_p8_resolved, session, asc_cli, maestro, notes}. |
| config_setA | Write several NON-secret settings (ASC key id/issuer/path, team id, copyright, support email, ...) to ~/.appfactory/config.toml. Use when: setting multiple ASC/identity fields together; fields left empty are unchanged. Not for: secrets (use setup_credentials) or one key (use setup_set). Returns: the config_doctor result after the update, or {ok: false, error} if a secret key was passed. |
| asc_token_checkA | Verify App Store Connect authentication through the asc CLI with one live read-only call. Use when: before any asc_* tool, to confirm key id, issuer and .p8 work. Not for: listing apps (use asc_list_apps). Returns: {ok, asc: {path, version}, auth_source, key_id, p8, keychain_profiles, note, error?}. |
| asc_list_appsA | List the apps in App Store Connect (live, read-only). Use when: you need app ids or want to see what exists. To find one app by bundle id use asc_get_app. Returns: {ok, count, apps: [{id, bundleId, name, sku}]}. |
| asc_get_appA | Find one App Store Connect app by bundle id (live, read-only). Use when: you need the numeric app id for a known bundle id. Not for: listing all apps (use asc_list_apps). Returns: {ok, data: {data: [app resources]}} from the ASC API. |
| asc_create_bundle_idA | Register a bundle id in App Store Connect and check or apply its App ID capabilities (live write, needs human approval). Use when: first ASC step for a new app; capabilities (IN_APP_PURCHASE, Sign in with Apple, HEALTHKIT if enabled) must exist before signing. Not for: creating the app record (use asc_create_app). Returns: {bundle_id: , capabilities: <store_setup report>} or an approval_required refusal. |
| asc_create_appA | Create an app shell in App Store Connect via fastlane produce (live write, needs human approval). Use when: after aso_check_name confirms a free name; pass candidate_names and the first available is used. Not for: bundle ids (asc_create_bundle_id) or metadata (deliver_metadata). Returns: {ok, app_id, name, ...} or an approval_required refusal. |
| asc_create_subscription_groupA | Create a subscription group for an app (live write, needs human approval). Use when: hand-building the subscription tree. Prefer store_setup, which does groups, products, prices and offers idempotently from app.spec.json. Returns: {ok, data: {data: {id, ...}}} or an approval_required refusal. |
| asc_finalize_subscriptionA | Finalize one subscription in order: localization, availability (all but CHN), price, intro offer (live write, needs human approval). Use when: fixing a single product by hand. Prefer store_setup, which does every product idempotently. Pass the spec product's intro (e.g. {"type": "free", "duration": "P3D"}); offer products get no intro. Returns: {ok, steps...} per step, or an approval_required refusal. |
| asc_finalize_submission_requirementsA | Fill the submit-blocking app-level fields in one call: content rights, copyright, age rating (4+), free price, App Review contact and notes (live write, needs human approval). Use when: once per app before asc_submit_for_review. App Privacy is not in Apple's API and must be set in the ASC web UI. Missing copyright falls back to config; missing contact_email to support_email. Returns: {ok, steps...} or an approval_required refusal. |
| asc_append_subscription_disclosureA | Append the subscription disclosure, Terms/EULA and Privacy links to the app description in every language (Apple 3.1.2; live write, needs human approval). Use when: preparing a subscription app for review. Idempotent (skips when the marker is present) and truncated to 4000 characters. Not for: uploading other metadata (use deliver_metadata). Returns: {ok, per-locale results} or an approval_required refusal. |
| asc_ensure_subscription_pricesA | Set a price on every subscription of the app that has none, clearing MISSING_METADATA (live write, needs human approval). Use when: subscriptions are stuck in MISSING_METADATA for price. Idempotent: priced subscriptions are skipped. Returns: {ok, priced: [...], skipped: [...]} or an approval_required refusal. |
| asc_add_subscription_group_localizationA | Add one display-name localization to a subscription group (required to clear MISSING_METADATA; live write, needs human approval). Use when: a single locale is needed. For many languages use asc_localize_group. Returns: {ok, data} or an approval_required refusal. |
| asc_localize_subscriptionA | Localize a subscription's name and description in many languages at once (live write, needs human approval). Use when: filling per-locale product copy. Languages the IAP API does not support are skipped. Returns: {ok, done: [locales], skipped: [locales]} or an approval_required refusal. |
| asc_localize_groupA | Localize a subscription group's display name in many languages at once (live write, needs human approval). Use when: several locales are needed; for one locale use asc_add_subscription_group_localization. Returns: {ok, done: [locales], skipped: [locales]} or an approval_required refusal. |
| asc_create_subscriptionA | Create a subscription product inside a subscription group (live write, needs human approval). Use when: hand-building a single product. Prefer store_setup for the whole spec. Returns: {ok, data: {data: {id, ...}}} or an approval_required refusal. |
| asc_submit_for_reviewA | Submit the app to App Store review (live write, ALWAYS needs out-of-band human approval, even with approvals off). Use when: everything else is ready and the human has approved. Without a valid approval_id nothing is submitted. Not for: uploading a TestFlight build (use testflight_ship). Returns: {ok, review_submission_id, detail} or {ok: false, blockers, next}, or an approval_required refusal. |
| env_doctorA | Check the local toolchain: xcode, swift, node, ruby, git, uv, asc, fastlane, maestro, Java 17+ and maestro- live. Use when: something fails to run locally. Not for: credentials/config (use config_doctor or setup_status). Returns: {ok, available: {tool: bool}, versions: {tool: str}, notes?}. |
| build_xcode_versionA | Return the installed Xcode version. Use when: a quick check that xcodebuild works before build_* tools. Returns: {ok, exit_code, stdout, stderr} (stdout holds the version lines). |
| build_list_simulatorsA | List the available iOS simulators, iPhones first. Use when: you need a udid for build_boot_sim, build_screenshot or screenshot_capture. Returns: {ok, count, simulators: [{name, udid, state, runtime}]}. |
| build_boot_simA | Boot an iOS simulator and open Simulator.app. Use when: before capturing screenshots or running maestro_test. Idempotent if already booted. Returns: {ok, exit_code, stdout, stderr}, or {ok, note: 'already booted'}. |
| build_screenshotA | Capture a PNG screenshot of the booted simulator to out_path. Use when: an ad-hoc check. For localized store screenshots use screenshot_capture / screenshot_build_all. Returns: {ok, exit_code, stdout, stderr, path}. |
| build_for_simA | Build the Xcode project for the simulator to verify it compiles. Use when: verifying code changes. Not for: signed/release builds (use build_archive or testflight_ship). Returns: {ok, exit_code, stdout, stderr} from xcodebuild. |
| build_testA | Run xcodebuild test for the scheme on a simulator. Use when: running unit/UI tests. For end-to-end Maestro flows use maestro_test. Returns: {ok, exit_code, stdout, stderr} from xcodebuild. |
| maestro_testA | Run the app's Maestro flows (.maestro/) on the booted simulator with the live Viewer, and write .appfactory/verify/maestro.json. Use when: verifying the app end to end; testflight_ship and the features gate require every smoke flow green. The app must already be installed (build_for_sim + simctl install). Opens the Viewer at http://localhost:7777; there is no headless mode. Returns: {ok, flows: [{name, passed}], report path}. |
| build_archiveA | Run xcodebuild archive (generic iOS device) to produce a .xcarchive. Use when: manual signing pipeline steps. For the whole signed TestFlight flow use testflight_ship. Returns: {ok, exit_code, stdout, stderr} from xcodebuild. |
| build_export_ipaA | Run xcodebuild -exportArchive to turn a .xcarchive into an .ipa. Use when: after build_archive with an ExportOptions.plist. For the whole flow use testflight_ship. Returns: {ok, exit_code, stdout, stderr} from xcodebuild. |
| supabase_list_projectsA | List Supabase projects (live, read-only). Use when: you need a project ref. For org ids use supabase_list_orgs. Returns: {ok, projects: [{name, ref, region, status}]}. |
| supabase_list_orgsA | List Supabase organizations (live, read-only). Use when: you need the org_id for supabase_create_project. Returns: {ok, data: [{id, name}]}. |
| supabase_get_keysA | Get a Supabase project's URL and anon key; the service_role key is saved to ~/.appfactory/supabase/.json (0600) and never returned. Use when: wiring the app (app_inject_config) or backend. Returns: {ok, project_url, anon_key, service_role_key_file}. |
| supabase_run_sqlA | Run SQL on a Supabase project (live write, needs human approval). Use when: applying schema or migrations by hand; backend_deploy applies the spec's migrations for you. Destructive statements (DROP, TRUNCATE, ALTER ... DROP, GRANT/REVOKE on auth, DELETE/UPDATE without WHERE) always need approval. Returns: {ok, data} rows/result, or an approval_required refusal. |
| supabase_set_secretA | Write one edge-function secret on a Supabase project, server-side only (live write, needs human approval). Use when: adding a single secret such as FAL_KEY. backend_deploy sets the standard set for you. Returns: {ok, name} (value never echoed), or an approval_required refusal. |
| supabase_create_projectA | Create a new Supabase project (live write that provisions billable resources, needs human approval). Use when: the app has no backend project yet. Check supabase_list_projects first to avoid duplicates. Returns: {ok, data: {id/ref, name, region, ...}} or an approval_required refusal. |
| app_scaffoldA | Scaffold a new SwiftUI app from app.spec.json (xcodegen), init the pipeline manifest and a local git repo. Use when: starting a new app after idea validation. The spec drives products, StoreKit file, locales, onboarding length, monetization mode and backend mode. Not for: editing an existing app (use app_sync_spec after changing the spec). Returns: {ok, dir, name, bundle_id, manifest}. |
| github_create_repoA | Create a PRIVATE GitHub repo under the configured account and push the app (needs human approval unless dry_run). Use when: the app should be tracked on GitHub. dry_run=true (default) only returns the command. For later commits use github_push. Returns: {ok, command/url, dry_run} or an approval_required refusal. |
| github_pushA | Commit all changes in the app repo and push (live write, needs human approval). Use when: regular tracking after milestones. For the first push of a new repo use github_create_repo. Returns: {ok, commit, push} or an approval_required refusal. |
| firebase_setupA | Set up Firebase Analytics: GCP project, iOS app and GoogleService-Info.plist into Resources/ (live write, needs human approval). Use when: once per app (mandatory for every app). Requires gcloud auth and firebase-tools. Returns: {ok, project_id, app_id, google_analytics, console, plist} or an approval_required refusal. |
| app_inject_configA | Fill in the scaffolded app's AppConfig and StoreKit tokens (Supabase, proxy, PostHog, product ids, credits, paywall strategy). Use when: after backend and RevenueCat values exist. Credit fields default to 15/10/10/30/60 and pack amounts must match the server-side PACK_MAP. Not for: spec-driven changes (edit app.spec.json, then app_sync_spec). Returns: {ok, changed: [files]}. |
| onboarding_planA | Return guidance for choosing the onboarding step count; does not change any file. Use when: deciding onboarding length with the user (quiz-style flow with about 5 personalization questions is the standard). Returns: {ok, step_count, ranges: {"8-10"|"11-13"|"14-15": description}, warning?}. |
| animation_fetch_recolorA | Fetch a cute Lottie animation from the free LottieFiles library and recolor it to the app palette into Resources/Animations/.json. Use when: once per slot (loading, success, empty, onboarding_hero) for every app; rendered by lottie-spm with .named(slot). Colors are mapped at build time (dominant to primary, others to accent). Returns: {ok, path, source, colors}. |
| metadata_checkA | Validate an apple-metadata.md file: required fields and character limits (no writes). Use when: checking a single metadata file. For the store listing.json use metadata_listing_check; for the ASO outputs folder use aso_validate_metadata. Returns: {ok, problems: [...], locales}. |
| metadata_exportA | Export apple-metadata.md to fastlane/metadata//*.txt after validation. Use when: preparing metadata for deliver_metadata. With app_dir set, refuses until the ASO stage is complete. Not for: uploading to App Store Connect (use deliver_metadata). Returns: {ok, written: [files], locales} or a gate refusal. |
| aso_check_nameA | Check whether an App Store app name is free, by exact-name collision in iTunes Search. Use when: testing one name before asc_create_app. For several names use aso_find_available_name. Returns: {ok, name, available, conflicts: [...]}. |
| aso_find_available_nameA | Pick the first available App Store name from a candidate list. Use when: you have ordered name options; a taken name gets a submission rejected. For one name use aso_check_name. Returns: {ok, name, checked: [...]} or {ok: false} if none is free. |
| aso_fetch_competitorsA | Fetch competitor apps for a search term through iTunes Search (live, read-only). Use when: sizing up a niche or getting trackIds for aso_competitor_iap. For a scored go/no-go use aso_niche_score. Returns: {ok, count, apps: [{trackId, name, ratings, price, ...}]} (untrusted_content). |
| aso_top_grossingA | List the top-grossing apps of a storefront and optional category as a revenue proxy. Use when: hunting proven ideas in one category. To sweep all categories and storefronts use idea_harvest. An unknown genre returns ok:false, never the overall chart. Returns: {ok, apps: [...]} (untrusted_content). |
| aso_search_hintsA | Query App Store autocomplete for real search demand; the idea-stage hard gate (0 suggestions for a real term = no demand, reject). Use when: validating an idea or expanding keywords (expand=true appends a-z). An endpoint error returns ok:false, never an empty list. Returns: {ok, term, suggestions: [...], count} (untrusted_content). |
| aso_niche_scoreA | Score an idea 0-100 from demand, competitor weakness, saturation and monetization, with a go/no-go verdict. Use when: ranking one idea quickly. For the full evidence bundle use idea_evaluate. verdict: GO (>=60), MAYBE (>=40), WEAK, REJECT (median competitor >50k ratings or no demand). Returns: {ok, score, verdict, demand, competitors, ...} (untrusted_content). |
| idea_harvestA | Sweep top-grossing and top-free charts across every App Store category and storefront to find proven and rising ideas. Use when: Phase 0 idea generation (about 1.5 minutes for the default sweep). Not for: evaluating one idea (use idea_evaluate) or a single chart (use aso_top_grossing). Failed feeds are listed, never read as no apps. Returns: {ok, chart_proven, rising_newcomers, clusters: [{genre, open_niche}], failed_feeds} (untrusted_content). |
| idea_evaluateA | Build the evidence bundle to rank one idea in any category. Use when: comparing shortlisted ideas after idea_harvest. Not for: a quick score only (use aso_niche_score). Includes ai_needed and build_complexity heuristics for Claude to judge. Returns: {ok, autocomplete, niche, newcomers, leaders, ai_needed, build_complexity, review_risk, available_name} (untrusted_content). |
| aso_competitor_iapA | Fetch a competitor's subscription/IAP price ladder from its App Store product page. Use when: setting our pricing. app_id is the iTunes trackId from aso_fetch_competitors. Fragile, undocumented source: on failure ok:false and prices null mean unknown, not free. Returns: {ok, prices: [{name, price}] | null} (untrusted_content). |
| aso_unit_economicsA | Compute margin, break-even and warnings from prices, credits and AI cost (pure calculation, no network). Use when: idea/scaffold stage pricing decisions. Not for: measured-cost economics for a built app (use pricing_unit_economics). apple_cut is 0.15 for Small Business, else 0.30. Returns: {ok, weekly, yearly, margins, break_even, warnings}. |
| aso_scaffold_outputsA | Create the outputs// ASO skeleton including apple-metadata.md in 32 languages. Use when: standalone ASO work. Inside the pipeline use aso_run, which also returns the skill instructions. Returns: {ok, dir, files}. |
| aso_validate_metadataA | Validate outputs//02-metadata/apple-metadata.md (fields and character limits). Use when: checking ASO output by app name and base dir. For an arbitrary file use metadata_check; to mark the stage done use aso_complete. Returns: {ok, problems: [...]}. |
| aso_runA | Start the mandatory ASO stage: create the outputs skeleton and return the skill instructions. Use when: the pipeline reaches ASO. Finish with aso_complete. Returns: {ok, outputs_dir, instructions}. |
| aso_completeA | Validate the ASO output and mark the 'aso' stage done, opening the metadata/deliver gate. Use when: ASO files are written. Not for: other stages (use pipeline_mark). Returns: {ok, problems?} or a refusal listing what is missing. |
| icon_installA | Install the Claude Design app icon (1024x1024 master) into AppIcon.appiconset and write .appfactory/verify/icon.json. Use when: after design_export_png produced design/icon.png and design_record_upload recorded the upload; the icon gate requires it. Alpha is flattened. Returns: {ok, icon, marker} or an error naming the missing/invalid master. |
| icon_generateA | Generate a fal.ai raster icon DRAFT into design/icon_drafts/ as reference for the Claude Design icon board (paid, opt-in only). Use when: the user explicitly allows an external generator. Never installs an icon; the shipped icon comes from Claude Design (icon_install). Returns: {ok, draft, prompt, next} or a refusal unless allow_external_generator is true. |
| localize_applyA | Merge translations into the in-app String Catalog for the spec's app locales. Use when: after translating UI strings; locales not in spec locales.app are ignored. Not for: store listing copy (use metadata_render_listing / deliver_metadata). Returns: {ok, locales, keys, missing}. |
| pipeline_statusA | Show which pipeline stages are done or pending and what comes next. Use when: checking progress of one app. To get the next instructions use pipeline_next; for the autonomous loop use orchestrator_next_action. Returns: {ok, stages: {stage: status}, next}. |
| pipeline_nextA | Return the next mandatory pipeline step with its instructions. Use when: driving the pipeline manually. Refuses until run options are confirmed (run_options, run_options_save) unless skip_options_check. Not for: the autonomous loop with retry budgets (use orchestrator_next_action). Returns: {ok, stage, instructions} or setup_required / options-not-confirmed errors. |
| pipeline_markA | Set a pipeline stage's status (done, in_progress, pending) in the app manifest. Use when: recording progress. Marking done runs the stage's enforced gate. To only test the gate use pipeline_validate. Returns: {ok, stage, status} or a gate refusal. |
| pipeline_validateA | Run a stage's enforced gate without modifying the manifest. Use when: self-checking before pipeline_mark(done). Read-only. Returns: {ok, stage, problems: [...]}. |
| orchestrator_preflightA | Pre-flight for an autonomous run: run options confirmed, config keys present, fastlane session fresh, caffeinate command. Use when: before starting the orchestrator_next_action loop. Ready when blockers is empty. Returns setup_required first if AppFactory is not set up. Returns: {ok, blockers: [...], caffeinate, ...}. |
| orchestrator_next_actionA | Return the next action for the autonomous driver loop: stage, subagent role, retry budget and instructions. Use when: running unattended. done=true means the pipeline is finished (submit still needs human approval). For a manual step use pipeline_next. Returns: {ok, done, stage, role, attempts_left, instructions}. |
| run_optionsA | List every optional part of a run with its question, kind, choices, default and current value. Use when: BEFORE any other work when the user says run. Ask the user each question one at a time (or as a checklist), then call run_options_save. Returns: {ok, options: [{id, question, kind, choices, default, value}], confirmed}. |
| run_options_saveA | Save the user's answers to the run options and mark options confirmed. Use when: after asking every question from run_options. Validates types, choices and dependencies; services go to config.toml, the rest to app.spec.json (or a pending file that app_scaffold applies). Returns: {ok, saved, errors?}. |
| orchestrator_record_attemptA | Count one failed attempt of a stage after a gate failure. Use when: a stage gate failed in the autonomous loop; escalate with orchestrator_needs_human when should_retry is false. Returns: {ok, stage, attempts, should_retry}. |
| orchestrator_needs_humanA | Write NEEDS_HUMAN.md when self-correction is exhausted and return its path. Use when: a stage keeps failing and only the human can unblock it (stop the loop afterwards). Returns: {ok, path}. |
| screenshot_captureA | Capture a raw screenshot from the booted simulator into marketing/raw//.png. Use when: capturing a single screen manually. For the full localized set use screenshot_build_all. Returns: {ok, path}. |
| screenshot_brandA | Render branded App Store screenshots with the node compositor using the Claude Design store layout. Use when: raw captures exist; run screenshot_apply_layout first (screenshot_build_all does both). Returns: {ok, rendered: count, dir}. |
| screenshot_apply_layoutA | Merge the Claude Design store layout (design/project/store_layout.json) into marketing/screenshots/config.json. Use when: before screenshot_brand so every locale renders the approved layout. Returns: {ok, config path, boards}. |
| screenshot_syncA | Copy branded screenshots into fastlane/screenshots//. Use when: after screenshot_brand, before deliver_screenshots. Local only; nothing is uploaded. Returns: {ok, synced: count}. |
| screenshot_build_allA | Run the whole turnkey screenshot step: sample image, build and install, captions, capture 32 languages x 6 screens, brand, sync to fastlane/screenshots. Use when: the mandatory screenshots stage. Not for: single captures (use screenshot_capture) or uploading (use deliver_screenshots). Long-running. Returns: {ok, locales, screens, dir} or the first failing step. |
| screenshot_generate_sampleA | Generate a sample image with fal.ai into Resources/sample_headshot.jpg to fill the Result/Gallery screens (paid). Use when: screenshots need real-looking app output; screenshot_build_all calls it for you. Returns: {ok, path}. |
| screenshot_onboarding_heroesA | LEGACY, opt-in: generate fal hero images per onboarding step (onb_step0..N). Use when: only for a legacy hero-image onboarding. Onboarding visuals normally come from Claude Design boards. Requires allow_external_generator=true. Returns: {ok, images: [paths]} or a refusal. |
| growth_build_slideshowsA | Render viral TikTok/Reels slideshows (1080x1920 PNGs) to marketing/growth//NN.png. Use when: post-launch content only, after the app is submitted. You write the hooks and slide text; images come from the app's AI (fal). No scheduling. Returns: {ok, sets: [{name, slides, ok, dir}]}. |
| preview_briefA | Write marketing/preview/BRIEF.md (the HyperFrames App Preview brief) from app.spec.json and create the recordings folders. Use when: starting the App Preview video. Then record the real app and author the video with the hyperframes skill (real footage only). Check with preview_check. Returns: {ok, brief path, recordings dirs}. |
| preview_checkA | Check offline readiness of the App Preview set: brief, recordings, one preview per locale, ffprobe specs, self-review status. Use when: before preview_upload. Files must be 886x1920, <=30 fps, H.264, 15-30 s, <=500 MB, stereo AAC or silent. Returns: {ok, problems: [...], plan}. |
| preview_review_sheetsA | Generate self-review material (contact sheet, phone-size sheet, transition strip) for every final preview with ffmpeg. Use when: reviewing a rendered preview; open the sheets, score them, then call preview_review_log. Returns: {ok, sheets: {locale: [paths]}}. |
| preview_review_logA | Log one self-review round (scores 1-10 and worst problems) for a final preview file. Use when: after preview_review_sheets. Every score must reach 8+ on the exact final file (MD5-matched) or preview_upload and the gate refuse. Returns: {ok, passed, scores, problems}. |
| preview_uploadA | Upload fastlane/app_previews// to the editable version's iPhone preview sets via the asc CLI (needs human approval unless dry_run). Use when: preview_check is clean and self-review passed. dry_run=true (default) sends nothing. MD5-idempotent; refuses while preview_check has problems. Returns: {ok, uploaded/planned: [...], dry_run} or an approval_required refusal. |
| cpp_build_allA | Create one Custom Product Page per Search Ads theme (page, version, localization) and return the deep-link URLs (live write, needs human approval). Use when: after ASO produced theme clusters; the URLs feed Ad Ops. Returns: {ok, pages: [{theme, ok, id, version_id, localization_id, url}]} or an approval_required refusal. |
| deliver_metadataA | Upload metadata to the App Store Connect draft version through the API (live write, needs human approval, ASO-gated). Use when: metadata files are exported (metadata_export). Not for: screenshots (deliver_screenshots) or the submit step (asc_submit_for_review). Returns: {ok, uploaded: [...]} or a gate / approval_required refusal. |
| deliver_screenshotsA | Upload screenshots to the App Store Connect draft with checksum-based incremental sync (live write, needs human approval). Use when: screenshot_build_all is done; unchanged files (MD5 match) are skipped. To verify afterwards use deliver_screenshots_audit. Returns: {ok, uploaded, skipped} or a gate / approval_required refusal. |
| deliver_screenshots_auditA | Read-only audit that App Store Connect screenshot sets exactly match the local fastlane/screenshots files (order, COMPLETE state, MD5). Use when: after deliver_screenshots and before submission. No writes. Returns: {ok, locales: {locale: {display_type: status}}, previews, problems}. |
| deliver_subscription_review_screenshotsA | Upload the App Review screenshot of every subscription from store/review-screenshots/.png (live write, needs human approval). Use when: subscriptions sit in MISSING_METADATA for the review screenshot. Idempotent by MD5. Returns: {ok, uploaded, skipped} or an approval_required refusal. |
| testflight_shipA | Build, sign and upload a TestFlight build end to end: distribution signing, archive, App Store profiles, manual-signing export, asc builds upload (needs human approval). Use when: shipping a build to TestFlight. Refuses unless the Maestro smoke flows passed (maestro_test) and App ID capabilities exist. Never submits for App Store review (use asc_submit_for_review for that). Not for: single build steps (build_archive, build_export_ipa, signing_*). Returns: {ok, build, ...} or an error / approval_required refusal. |
| signing_setup_distributionA | Create a distribution certificate and install it into a temporary keychain (WWDR included; live write, needs human approval). Use when: hand-running signing steps; testflight_ship does this for you. Returns: {ok, cert_id, identity, keychain}. |
| signing_create_profileA | Create an IOS_APP_STORE provisioning profile and write it to the standard locations (live write, needs human approval). Use when: after signing_setup_distribution; testflight_ship does this for you. Returns: {ok, profile_id, name, path}. |
| ai_configureA | Report the AI provider/model selection (currently fal.ai Flux schnell); does not change anything. Use when: checking which image model the backend will use. Keys are set with ai_deploy_proxy or backend_deploy. Returns: {ok, providers, models, note}. |
| ai_deploy_proxyA | Deploy the AI backend: the full spec-driven backend in subscription mode, or the legacy ai-proxy in credits mode (live, needs human approval). Use when: the app has an AI feature. AI keys go only to server-side secrets. For explicit dry-run planning use backend_deploy. Returns: {ok, deployed: [...]} or an approval_required refusal. |
| revenuecat_setupA | Idempotently set up the RevenueCat v2 project: premium entitlement, subscription attachments, SDK key and Supabase secret (live write, needs human approval). Use when: after a human created the RC project, linked ASC and supplied the v2 key. Returns NEEDS_HUMAN if no project exists. For ASC plus RC in one pass use store_setup. Returns: {ok, entitlement, sdk_key_set, secrets} or an approval_required refusal. |
| backend_renderA | Render the scaffolded backend from app.spec.json (offline, idempotent): prune supabase/ to the monetization mode, generate shared config, legal sources and listing locales. Use when: after editing the spec, before backend_deploy. Nothing is deployed. Returns: {ok, mode, render, legal, listing?}. |
| backend_deployA | Deploy the spec's Supabase backend: migrations, secrets, auth, legal build and edge functions (live unless dry_run; needs human approval). Use when: after backend_render. dry_run=true (default) returns the plan without any call. Not for: single SQL (supabase_run_sql) or one secret (supabase_set_secret). Returns: {ok, plan/steps, dry_run} or an approval_required refusal. |
| legal_renderA | Fill the legal sources (store/privacy/*.md, backend/PRIVACY.md) from the spec and config, keeping or dropping the HealthKit block. Use when: before legal_check. Local writes only. Returns: {ok, files, placeholders_left}. |
| legal_checkA | List what still blocks publishing the legal pages: placeholders, unrendered blocks, missing languages. Use when: after legal_render, offline. For checking the live pages use legal_verify. Returns: {ok, problems: [...]}. |
| legal_verifyA | Check that every deployed privacy/terms page answers 200 in each app language with the support email and no placeholder (live, read-only). Use when: after backend_deploy. Needs supabase_url in app outputs. For offline checks use legal_check. Returns: {ok, pages: [{locale, url, status, problems}]}. |
| store_setupA | Idempotent App Store Connect and RevenueCat setup from app.spec.json and listing.json (capabilities, subscriptions, prices, offers, age rating, legal URLs, RC entitlement/offerings). Use when: the standard way to set up the store side. mode: plan (offline), check (live reads, simulated writes, reports CONFLICT), apply (live writes, needs human approval). Prefer this over the individual asc_* write tools; asc_create_app is still separate. Returns: {ok, mode, steps: [...], conflicts} or an approval_required refusal. |
| metadata_listing_checkA | Validate store/metadata/listing.json: length limits, keyword rules, no word overlap, subscription disclosure and legal links. Use when: before deliver_metadata. For a bare apple-metadata.md use metadata_check. Returns: {ok, problems: [...]}. |
| metadata_render_listingA | Sync listing.json to the spec (store locales, IAP copy slots) and fill the legal URLs. Use when: after changing the spec's store locales or products. Local writes only; verify with metadata_listing_check. Returns: {ok, locales, changed}. |
| pricing_unit_economicsA | Compute unit economics from the measured AI cost per call and usage profiles, and write the generated blocks of store/pricing.md. Use when: pricing a built app with real eval data. For quick what-if numbers at idea stage use aso_unit_economics. Returns: {ok, products: [{margin, ...}], path}. |
| asc_sbp_checkA | Prove Small Business Program status from the latest subscription sales report (US proceeds/price ratio, about 0.85 SBP vs 0.70 standard; live, read-only). Use when: confirming the 15% commission. Needs a Finance-role key (asc_finance_key_id, asc_finance_key_filepath, asc_vendor_number); a 403 gives a clear error. Returns: {ok, ratio, program, report_date}. |
| storekit_generateA | Write Resources/Configuration.storekit from app.spec.json (group, levels, free-trial intros, trial-less offer product). Use when: after any product change. Deterministic. app_sync_spec also regenerates it together with Swift sources. Returns: {ok, path, products}. |
| storekit_parityA | Compare a Configuration.storekit with app.spec.json and list every mismatch (read-only). Use when: verifying products match before store_setup or release. ok=true means in parity. Returns: {ok, mismatches: [...]}. |
| app_sync_specA | Regenerate AppSpec.swift, PaywallSource.swift and Configuration.storekit and prune String Catalogs to locales.app. Use when: after editing app.spec.json. Local writes only. Returns: {ok, files}. |
| design_screens_skeletonA | Produce the structural skeleton for design/screens.json, following the design brief's onboarding flow when one exists. Use when: starting design. Adapt every screen to the app; the look is authored in Claude Design. write=true saves it (refuses to replace an existing file unless overwrite). Returns: {ok, screens|path, onboarding, main}. |
| design_research_collectA | Download category-leader App Store screenshots and icons into design/research/apps/ with references.json (study material only). Use when: first design step. Then write the brief (design_research_brief_template) and run design_research_check. Returns: {ok, apps: [{id, name, files}], references} (untrusted_content). |
| design_research_brief_templateA | Return the design/research/brief.json shape pre-filled with the reference ids. Use when: authoring the design brief after design_research_collect. Read-only. Returns: {ok, template, write_to: [paths]}. |
| design_research_checkA | Run the design_research gate: at least 6 reference apps on disk and a valid, cited brief. Use when: before design_generate. Read-only. Returns: {ok, problems: [...]}. |
| design_generateA | Prepare the app's Claude Design project from the brief, spec and screens.json: scaffolds, mascot boards, canvas, store layout and upload plan. Use when: after design_research_check passes. Never uploads; it returns the claude-design MCP calls to make. Then record with design_record_upload. Returns: {ok, plan, mcp_calls}. |
| design_record_uploadA | Record a finished Claude Design upload: the SHA-256 of every file in upload_plan.json into design/project/claude_design.json. Use when: after uploading through the claude-design MCP; the design, icon and screenshot gates fail until this receipt matches. Returns: {ok, receipt path, files}. |
| design_upload_statusA | Check whether the local Claude Design project is uploaded and unchanged since (read-only). Use when: diagnosing a design gate failure. Returns: {ok, uploaded, changed_files}. |
| design_export_pngA | Rasterize a Claude Design board to PNG with local headless Chrome. Use when: icon (B01-AppIcon 1024x1024 to design/icon.png) or store layout boards (440x956, scale 3). serve_url comes from claude-design render_preview and is used once. Returns: {ok, path, width, height}. |
| mascot_blinkA | Create closed-eye blink copies (-blink.png) of the approved mascot pose PNGs. Use when: before mascot_assets. Needs the optional extra |
| mascot_assetsA | Import approved mascot poses and blink variants into Resources/Assets.xcassets/Mascot/. Use when: after mascot_blink; states without a pose borrow a fallback. Returns: {ok, imagesets: [names]}. |
| team_briefA | Render the team docs (TEAM.md, per-role briefs, onboarding plan, ASO research, CHECKLIST.md) from the spec. Use when: setting up multi-session work. Existing files are kept unless overwrite=true. Returns: {ok, files}. |
| github_issues_bootstrapA | Create or refresh the GitHub label set (ios, backend, store, lead, founder, next, later, other-project) on a repo (needs human approval unless dry_run). Use when: before github_issue_create. dry_run=true (default) returns the commands. No-op (n/a) when the github_issues run option is off. Returns: {ok, commands/created, dry_run} or an approval_required refusal. |
| github_issue_createA | Open a GitHub issue for postponed work (needs human approval unless dry_run). Use when: parking work with a role label plus next or later. dry_run=true (default) returns the exact command. No-op (n/a) when the github_issues run option is off. Returns: {ok, url/command, dry_run} or an approval_required refusal. |
| playbookA | Return the AppFactory run playbook as markdown. Use when: before driving the pipeline; the same text is the |
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 tool descriptions are unusually thorough with 'Use when' and 'Not for' cross-references, which helps separate many overlapping areas. However, with 125 tools, several boundaries remain easy to confuse: setup_set vs config_set, pipeline_mark vs orchestrator_record_attempt, metadata_check vs metadata_listing_check vs aso_validate_metadata, and individual asc_* writes vs store_setup. Descriptions mitigate but do not fully eliminate ambiguity at this scale.
Tool names are overwhelmingly snake_case and grouped by domain prefix (asc_, setup_, pipeline_, screenshot_, etc.), which gives a readable and predictable surface. The main inconsistency is the internal pattern: some names use verb_noun (asc_list_apps), others noun_verb (metadata_check) or noun_noun (config_doctor), but these deviations are minor and not chaotic.
125 tools is an extreme mismatch for an MCP server, far beyond the recommended 3-15 range and well past the 50+ threshold that the rubric treats as severe. Even for a broad app-factory pipeline, the surface is too large for an agent to navigate reliably, with many legacy or narrowly scoped operations that could be consolidated.
The server covers an unusually complete app lifecycle: idea validation, ASO, design, scaffolding, backend deployment, store setup, screenshots, TestFlight shipping, metadata, legal pages, and submission. Remaining gaps are minor, such as TestFlight tester management, App Privacy settings (explicitly unavailable via API), and post-launch review/analytics management, which agents can work around or handle manually.