name: bitrise-ci-onboarding description: > Take a Bitrise prospect from "I have an account" to "my first build is green" by registering a project, connecting a repo, uploading signing credentials, and triggering the first build via the Bitrise MCP server. Use this when the user asks to "set up my project on Bitrise", "connect my repo to Bitrise", "run my first Bitrise build", "onboard my app to Bitrise CI", or "get my iOS/Android app building on Bitrise". The user must already have a Bitrise PAT wired into the MCP — if they don't, run bitrise-signup first. Use this skill regardless of whether it's iOS or Android; the skill branches internally.
Bitrise CI Onboarding
Drive a prospect through the full first-build flow: app registration → repository connection → signing credentials → trigger build → watch it go green. This is the second of three skills in the prospect onboarding journey.
Why these instructions exist
The CI onboarding flow has more moving parts than signup, and the parts have an order: you can't trigger a build before the app is finished, you can't sign without the credential uploaded, and you can't push to a private repo without the SSH key registered. This skill is the recipe.
It also branches by platform (iOS vs. Android) at two points: project config selection and credential upload. Read the platform-specific section for the user's platform; ignore the other.
Preconditions
- The user must have a working Bitrise PAT in the MCP. Sanity-check by
calling
mefirst — if it errors, route the user tobitrise-signup. - The user must be on the
agentic-onboardingbranch's MCP for the signing-upload tools (upload_build_certificate,upload_provisioning_profile,upload_android_keystore_file) to be available. The hostedmcp.bitrise.iodoes not have these yet. If the signing tools error with "tool not found", fall back to the manual web upload — see "Fallback: web-based credential upload" below.
The flow
1. Confirm context: workspace, platform, repo
Before calling any tools, gather four things by asking the user:
- Workspace. Call
list_workspaces. If there's exactly one, use it. If there are several, present the list and ask the user to pick. Capture theworkspace_slug. - Platform. iOS or Android? This decides the project config and the signing flow.
- Repository URL. Confirm the full URL (e.g.,
https://github.com/acme/cool-app.git). Confirm whether it's public or private — private repos need SSH key registration. - Git provider. GitHub, GitLab, Bitbucket, or self-hosted variants?
Defaults to
githubif unsure but ask.
If the user hasn't connected the provider's account to Bitrise yet, call
get_provider_connect_url with the chosen provider. Open the returned URL
in their browser, ask them to complete the OAuth flow, then poll
list_connected_accounts until the provider shows as connected. Don't move
on until it is.
2. Register the app
Call register_app with:
repo_url: as confirmed aboveis_public: boolean from the user's answerorganization_slug: the workspace slugprovider: e.g.,githubdefault_branch_name: ask the user; default tomain. (The MCP defaults tomaster, which is wrong for most modern repos.)
Capture the returned app_slug. The MCP description says not to prompt for
finishing the app — chain straight into the next step.
3. Register the SSH key (private repos only)
For a private repo, build won't be able to clone without an SSH key. The prospect probably doesn't have one ready. Two options:
- Have the MCP generate one for them. Generate an ed25519 keypair on
the user's machine via shell:
ssh-keygen -t ed25519 -f bitrise_deploy_key -N "" -C "bitrise-<app-slug>". Read both files. Then callregister_ssh_keywithapp_slug,auth_ssh_private_key,auth_ssh_public_key, andis_register_key_into_provider_service: trueso Bitrise auto-registers the public key as a deploy key on GitHub/GitLab/Bitbucket. Delete the local keypair files after — they're only needed for the upload. - Have the user paste an existing key. If they already have a deploy
key, ask for both halves. Same
register_ssh_keycall, but setis_register_key_into_provider_service: false.
For a public repo, skip this step.
4. Pick a stack and finish setup
Call list_available_stacks (pass workspace_slug to include workspace
custom stacks). Pick a sensible default for the platform — for iOS, the
latest macOS stack; for Android, the latest linux-docker-android-22.04 or
similar. Tell the user which stack you picked and why; let them override.
Then call finish_bitrise_app with:
app_slug: from step 2project_type:iosorandroid(orflutter,react-native, etc. if the user said so)stack_id: from aboveconfig: a starter config that matches the project type. Common values:default-ios-config,default-android-config-kts,default-flutter-config-android,default-react-native-config, etc.
Per the MCP tool description, don't prompt the user before this call — just run it.
5. Register a webhook
Call register_webhook with app_slug. This makes git pushes auto-trigger
builds, which is what the user expects from CI. Skip if the user
explicitly asked for manual-only triggering.
6. Set up signing credentials
This is where the flow forks by platform. For the very first build, consider whether signing is even needed yet. The default starter configs build & test on every push but don't always require distribution signing. If the user just wants to see a green build, you can skip this step on the first run and circle back when they want to ship to TestFlight / Play Console / Release Management.
If signing IS needed:
iOS
Two files must be uploaded: a .p12 build certificate and a
.mobileprovision provisioning profile. Ask the user where on disk both
files live. The MCP reads them from the local filesystem (the file_path
arg is read with os.ReadFile), so the files must be reachable to whatever
process the MCP runs as — practically, the user's machine.
upload_build_certificatewithapp_slug,file_path(absolute path to.p12), andcertificate_passwordif the cert is password-protected. Returns the API response; capturedata.slugif you want to chain updates.upload_provisioning_profilewithapp_slug,file_path(absolute path to.mobileprovision).
If the user doesn't have a build certificate or provisioning profile yet, walk them through generating them in Xcode → Apple Developer portal, or suggest the workspace-level "Apple API key" automatic provisioning flow (set up in the Bitrise web UI at workspace settings; the MCP doesn't expose it). Don't fabricate certs.
Android
A keystore (.jks or .keystore) plus its alias and two passwords:
upload_android_keystore_filewithapp_slug,file_path(absolute path to keystore),alias,keystore_password,private_key_password. All five are required.
If the user doesn't have a keystore yet and just wants a green build, the default Android config will use the auto-generated debug keystore, which ships with the Android SDK. Skip the upload and only set up a release keystore when the user is ready to publish.
Fallback: web-based credential upload
If the MCP signing tools aren't available (e.g., user's on the hosted
mcp.bitrise.io), point them at the Code Signing tab of the Workflow
Editor:
https://app.bitrise.io/app/<app_slug>/workflow_editor#code-signing. The
upload UI there is the same flow, just in a browser. Don't pretend the
tools work and then fail.
7. Trigger the first build
Call trigger_bitrise_build:
app_slug: from step 2branch: the default branch the user confirmed (main, usually)workflow_id: leave empty to use the config's default workflow (typicallyprimaryordeploy), or pass one explicitly if the user has a preference
Capture the returned build_slug and build_url. Share build_url with
the user immediately so they can watch in the browser if they want.
8. Wait for the build
Poll get_build with build_slug until the status field changes from 0
(not finished) to 1 (success), 2 (failed), or 3 (aborted). Status code 4
means in-progress. Reasonable polling cadence: every 10–15 seconds for the
first minute, then every 30 seconds. Tell the user roughly how long mobile
builds take (5–15 minutes is typical) so they don't think it's hung.
If the build succeeds: report the build URL, the duration, and offer to
move on to Release Management (bitrise-release-management) if they want
a public install page.
If the build fails: call get_build_log with build_slug and read the
log. Look for the failing step. Common first-build failures and how to
respond:
- Clone failure on a private repo: SSH key not registered or not
authorized at the provider. Re-run step 3 and confirm the deploy key
shows up at github.com/
/settings/keys. - Code signing error on iOS: Provisioning profile mismatch or wrong bundle ID. Surface the error message to the user and suggest the automatic provisioning flow.
- Stack mismatch: Build expects an Xcode/Java version not on the
chosen stack. Re-run
finish_bitrise_appwith a differentstack_id, or edit the bitrise.yml directly viaget_bitrise_yml→update_bitrise_yml.
Don't paper over a failed first build — the user wants to know what's wrong, not be told everything's fine.
Hand-off to Release Management
When the build is green and the user wants a public install page, call
bitrise-release-management and pass:
workspace_slugapp_slugplatformbuild_slug(latest successful build)- The bundle ID (iOS) or package name (Android) — the user will know this or you can extract it from the build artifact
Things to watch out for
- The MCP's
register_appdefaultsdefault_branch_nametomaster. Almost always wrong now — ask the user. finish_bitrise_appis mandatory. Aregister_app'd app withoutfinish_bitrise_appis in a half-configured state and won't build. The MCP description tells the agent to chain immediately.- Tool description for
register_appsays "always prompt the user to choose which workspace if they have multiple". Honor this — don't silently pick the first one. - Build status codes: 0=not finished (queued), 1=success, 2=failed, 3=aborted, 4=in-progress. Don't conflate "not finished" with "failed".
- Don't put PATs, keystores, or
.p12contents into the chat. All of these are secrets. Reference them by file path or by Bitrise slug. - The signing-upload tools read files from local disk. They only work in stdio mode (or against an MCP server with access to the same filesystem as the file). HTTP-hosted MCPs can't read the user's local disk; in that case use the web fallback.