Appcircle MCP Server
MCP server for Appcircle: exposes Build, Signing Identities, Testing Distribution, Enterprise App Store, Publish to Stores, and Reporting tools to any MCP-capable client (Claude Desktop, Cursor, VS Code, etc.). The Appcircle MCP Server acts as the bridge between AI tools and Appcircle; thus, AI agents, assistants and chatbots to safely access and interact with Appcircle resources through structured, governed, and task-level tools.
Use Cases
- CI/CD and Workflow Intelligence: Monitor pipeline runs, track release status, and get insights into your mobile CI/CD workflows.
- Configuration and Environment Insights: Query build configurations and signing setup to understand how a project is configured and where issues may originate.
- Reporting and Operational Insights: Generate summaries of CI stability, recurring issues, pipeline performance, and overall CI/CD health.
Running Modes
You can use the MCP server in four ways:
Detailed client configuration (Cursor, Claude, etc.) lives in the dedicated installation guides; this section is a high-level summary only.
Installation
Client-specific setup guides:
- Claude Applications - Installation guide for Claude Desktop and Claude Code CLI.
- Cursor IDE - Installation guide for Cursor IDE.
- Codex - Installation guide for Codex app and Codex CLI.
- Antigravity IDE - Installation guide for Antigravity IDE.
- VS Code (GitHub Copilot) - Installation guide for VS Code with GitHub Copilot.
- Windsurf IDE - Installation guide for Windsurf IDE.
- Gemini CLI - Installation guide for Gemini CLI.
- GitHub Copilot CLI - Installation guide for GitHub Copilot CLI.
Configuration (Environment Variables)
Set these in your shell or in your MCP client’s configuration.
Toolsets
Available Toolsets
The following sets of tools are available:
You can exclude one or more toolsets so their tools are not registered. Exclusions can be set via CLI arguments or the APPCIRCLE_EXCLUDED_TOOLSETS environment variable; both are merged (union).
- CLI:
--exclude toolset1 toolset2or--exclude-toolsets toolset1,toolset2 - Env:
APPCIRCLE_EXCLUDED_TOOLSETS=build_module,report
Example MCP config (Cursor / Claude Desktop) with exclusions:
{
"mcpServers": {
"appcircle": {
"command": "appcircle-mcp",
"args": ["--exclude", "report"]
}
}
}
Tools
Tools are exposed via MCP tools/list. Reference below lists all tools by toolset; for response shape and examples see docs/tool_contract.md.
-
get_build_profiles - Get build profiles for the current organization (paginated). Optionally filter by profile name, platform, last build status, and repository source. Optionally sort.
- Access level: read
page: Page number (1-based). Default: 1. (number, optional)size: Page size (1-100). Default: 25. Values above 100 are capped at 100. (number, optional)search: Optional search term to filter profiles (case-insensitive partial match on profile name; the API's search may also match other profile fields). (string, optional)platform: Optional list of platform codes to filter by. Allowed values: 1=iOS, 2=Android. (list of numbers, optional)last_build_status: Optional list of last build status codes to filter by. Allowed values: 0=Success, 1=Failed, 2=Canceled, 3=Timeout, 90=Waiting, 91=Running. (list of numbers, optional)repository_source: Optional list of repository source codes to filter by. Allowed values: 1=GitHub, 2=Bitbucket, 3=GitLab, 4=Azure DevOps, 6=Public Repository, 7=Private Repository, 8=SSH. (list of numbers, optional)sort: Optional sort field code. Allowed values: 1=Profile Name, 2=Create Date, 3=Last Build Date. (number, optional)sort_direction: Optional sort direction code. Allowed values: 1=ASC, 2=DESC. (number, optional)
-
get_build_profile_details - Get a single build profile by ID, optionally including its build configurations.
- Access level: read
profile_id: The build profile ID (e.g. UUID). (string, required)configurations: If true, also fetch the profile's build configurations. Default: false. (boolean, optional)
-
get_build_configuration_details - Get a single build configuration by profile ID and configuration ID.
- Access level: read
profile_id: The build profile ID (e.g. UUID). (string, required)configuration_id: The build configuration ID (e.g. UUID). (string, required)
-
get_build_profile_workflows - Get workflows for a build profile by profile ID.
- Access level: read
profile_id: The build profile ID (e.g. UUID). (string, required)
-
get_workflow_detail - Get a single workflow by build profile ID and workflow ID.
-
get_bundle_identifiers - Get all bundle identifiers for the organization (iOS/macOS app bundle IDs).
- Access level: read
- No parameters.
-
get_certificates - Get all signing certificates for the organization. Sensitive fields (p12Password, p12Binary, metaData, thumbprint) are omitted.
- Access level: read
- No parameters.
-
get_keystores - Get all keystores for the organization (e.g. Android signing keystores). Sensitive fields (password, aliasPassword, binary, checkSum, sha256FingerPrint) are omitted.
- Access level: read
- No parameters.
-
get_provisioning_profiles - Get provisioning profiles for the organization (e.g. iOS/macOS). Sensitive/large fields (binary, metaData, certificateThumbPrints, provisionedDevices, connectApiKeyId) are omitted. Optionally filter by app (bundle) ID.
- Access level: read
app_id: Optional app (bundle) ID to filter provisioning profiles (e.g. com.example.app). (string, optional)
-
get_distribution_profiles - Get testing distribution profiles for the current organization (paginated). Optionally filter by profile name, platform, and authentication type. Optionally sort.
- Access level: read
page: Page number (1-based). Default: 1. (number, optional)size: Page size (1-100). Default: 25, max 100. (number, optional)search: Optional search term to filter profiles (case-insensitive partial match on profile name; the API's search may also match other profile fields). (string, optional)platform: Optional list of platform codes to filter by. Allowed values: 1=iOS, 2=Android. (list of numbers, optional)authentication_type: Optional list of authentication type codes to filter by. Allowed values: 1=None, 3=Static Login, 4=LDAP, 5=SSO. (list of numbers, optional)sort: Optional sort field code. Allowed values: 1=Profile Name, 2=Create Date, 3=Last Upload Date. (number, optional)sort_direction: Optional sort direction code. Allowed values: 1=ASC, 2=DESC. (number, optional)
-
get_distribution_profile_details - Get a single testing distribution profile by ID (with optional app versions pagination).
- Access level: read
profile_id: The distribution profile ID (e.g. UUID). (string, required)page: Page number for app versions (1-based). Default: 1. (number, optional)size: Page size for app versions (1-100). Default: 25, max 100. (number, optional)
-
get_testing_groups - Get all testing distribution groups for the organization, including each group's member tester emails and group type.
- Access level: read
- Takes no parameters.
-
update_app_version_release_notes - SIDE EFFECT: overwrites the release notes ("message") shown to testers for a distribution app version. Returns the updated app version object (excludes certThumbPrints). Registered by default; set
AC_MCP_ENABLE_WRITE_TOOLS=falseto opt out.- Access level: write
profile_id: The distribution profile ID (e.g. UUID). (string, required)app_version_id: The app version ID (e.g. UUID). (string, required)message: The new release notes text. (string, required)
-
get_publish_profiles - Get publish profiles for the current organization for a given platform type (paginated). Optionally filter by flow status, target marketplace, release-candidate binary presence, and store status. Optionally sort.
- Access level: read
platform_type: Platform type of publish profiles ("ios" or "android"). (string, required)page: Page number (1-based). Default: 1. (number, optional)size: Page size (1-100). Default: 25, max 100. (number, optional)flow_status: Optional flow status code to filter by (e.g. 0=Success, 1=Failed, 91=Running). (number, optional)market_place_type: Optional list of target marketplace codes to filter by. Allowed values depend on platform_type -- ios: 0=Not Available, 1=App Store Connect, 4=Intune; android: 0=Not Available, 2=Google Play, 3=AppGallery, 4=Intune. (list of numbers, optional)has_rc_binary: Optional filter for whether the profile has a release-candidate binary. (boolean, optional)store_status: Optional list of store status codes to filter by. Allowed values depend on platform_type (many more codes for ios than android, e.g. ios: "IN_REVIEW", "READY_FOR_SALE", "REJECTED"; android: "NOT_AVAILABLE", "DRAFT", "IN_PROGRESS", "HALTED", "COMPLETED"). (list of strings, optional)sort: Optional sort field code. Allowed values: 1=Profile Name, 2=Create Date. (number, optional)sort_direction: Optional sort direction code. Allowed values: 1=ASC, 2=DESC. (number, optional)
-
get_publish_profile_details - Get a single publish profile by platform type and ID (with optional app versions pagination).
- Access level: read
platform_type: Platform type ("ios" or "android"). (string, required)profile_id: The publish profile ID (e.g. UUID). (string, required)page: Page number for app versions (1-based). Default: 1. (number, optional)size: Page size for app versions (1-100). Default: 25, max 100. (number, optional)
-
get_app_version_metadata - Get store listing metadata for a single app version (app review information, localizations, release information, app version information). appReviewInformation.demoPassword is excluded.
- Access level: read
platform_type: Platform type ("ios" or "android"). (string, required)
-
get_store_profiles - Get enterprise app store profiles for the current organization (paginated). Does not support search, but can filter by platform, publish type, and visibility. Optionally sort.
- Access level: read
page: Page number (1-based). Default: 1. (number, optional)size: Page size (1-100). Default: 25, max 100. (number, optional)platform_type: Optional list of platform codes to filter by. Allowed values: 1=iOS, 2=Android. (list of numbers, optional)publish_type: Optional list of publish type codes to filter by. Allowed values: 1=Published to Beta, 2=Published to Live. (list of numbers, optional)visibility: Optional filter for whether the profile is publicly listed (true=Listed, false=Unlisted). (boolean, optional)sort: Optional sort field code. Allowed values: 1=App Name, 2=Create Date, 3=Download Count, 4=Binary Receive Date. (number, optional)sort_direction: Optional sort direction code. Allowed values: 1=ASC, 2=DESC. (number, optional)
-
get_store_profile_details - Get a single enterprise app store profile by ID (with optional app versions pagination).
- Access level: read
profile_id: The enterprise app store profile ID (e.g. UUID). (string, required)page: Page number for app versions (1-based). Default: 1. (number, optional)size: Page size for app versions (1-100). Default: 25, max 100. (number, optional)- Each app version's
publishTypefield is an int: 0=None, 1=Beta, 2=Live.
-
get_build_history_report - Get build history report, optionally filtered by date range, build profile, and organization. Paginated.
- Access level: read
start_date: Optional start date (YYYY-MM-DD). (string, optional)end_date: Optional end date (YYYY-MM-DD). (string, optional)page: Page number (default: 1). (number, optional)size: Items per page (1-100, default: 50). (number, optional)build_profile_name: Filter by build profile name. (string, optional)organization_id: Filter by organization UUID. (string, optional)
-
get_build_queue_waiting_report - Get the build queue waiting report, optionally filtered by date range. Paginated. Note: on this endpoint,
buildDurationmeans queue wait time in minutes, not execution time (unlike get_build_history_report).- Access level: read
start_date: Optional start date (YYYY-MM-DD). Must be <= end_date if both are given. (string, optional)end_date: Optional end date (YYYY-MM-DD). (string, optional)page: Page number (default: 1). (number, optional)size: Items per page (1-100, default: 50). (number, optional)
-
get_build_activity_log - Get the build activity log (workflow/profile changes, CodePush releases, etc.), optionally filtered by date range and other parameters. Paginated.
- Access level: read
start_date: Optional start date (YYYY-MM-DD). Must be <= end_date if both are given. (string, optional)end_date: Optional end date (YYYY-MM-DD). (string, optional)page: Page number (default: 1). (number, optional)size: Items per page (1-100, default: 50). (number, optional)organization_id: Filter by organization UUID. (string, optional)platform: Filter by platform type (integer code, e.g. 0=Android, 1=iOS). (number, optional)email: Filter by acting user's email. (string, optional)profile_name: Filter by build profile name. (string, optional)action: Filter by activity action code (integer; seeBUILD_ACTIVITY_ACTIONSin the tool source for the full mapping). (number, optional)
Running the server
From the repo root:
python -m src.server
Or after pip install -e .:
appcircle-mcp
The server runs over stdio (or SSE/HTTP depending on how your client starts it).
Response format
Every tool returns a standard envelope:
- Success:
{ "success": true, "data": <payload>, "meta": { ... } }
datais the tool result;metais optional (e.g.count,page,filters). - Error:
{ "success": false, "error": { "tool", "type", "message", "details" } }
Same shape for all tools so clients can parse errors consistently.
Full specification: docs/tool_contract.md.
Testing
Install with dev dependencies:
pip install -e ".[dev]"
Unit tests (default)
Use a mocked API; no APPCIRCLE_ACCESS_TOKEN needed. Default pytest only runs these (see testpaths in pyproject.toml):
pytest test/unit/ -v
- Single file:
pytest test/unit/tools/build_module/test_get_build_profiles.py -v - With coverage:
pytest test/unit/ --cov=src --cov-report=term-missing
Integration tests
Call the real Appcircle API. Set APPCIRCLE_ACCESS_TOKEN in the environment, then run:
pytest test/integration/ -v
- All integration tests:
pytest test/integration/ -v - By tool:
pytest test/integration/build_module/ -v,pytest test/integration/report/ -v, etc. - By marker:
pytest -m integration -v(when running from repo root; includes only integration tests if both unit and integration are collected)
If APPCIRCLE_ACCESS_TOKEN is not set, integration tests are skipped (no failure).
Optional env vars for integration tests (when discovery fails or tests need real IDs; omit to skip those tests):
Write/action integration tests (trigger_build, cancel_build, etc.) are marked integration_write and are opt-in on top of APPCIRCLE_ACCESS_TOKEN — they mutate real data (trigger real builds, etc.), so they never run just from pytest test/integration/ -v. Set APPCIRCLE_RUN_WRITE_INTEGRATION_TESTS=true (pointing APPCIRCLE_ACCESS_TOKEN at a dedicated test org, not production) to enable them.
Security
This project depends on third-party open-source packages listed in
pyproject.toml. While we pin dependency version ranges and
ship a lockfile (uv.lock) with cryptographic hashes, these packages are
maintained independently and provided "as-is." Appcircle makes no guarantees
regarding the security or reliability of third-party dependencies.
We recommend auditing installed packages before use:
uv run pip-audit