A side-by-side look at the Codemagic MCP and Valet MCP servers: transport, auth, tools, quality signals, and the config to install either one in Claude, Cursor, Windsurf or VS Code.
Verdict: choose Codemagic MCP for developer tools work as a local process; choose Valet for developer tools over a hosted endpoint. You can also run both side by side in one mcpServers block.
CODEMAGIC_API_TOKEN, ASC_KEY_ID, ASC_ISSUER_ID, ASC_PRIVATE_KEY_B64, ASC_BYPASS_KEYCHAIN, GOOGLE_PLAY_SERVICE_ACCOUNT_CREDENTIALS.ping, list_applications, list_teams.attach_channel, attach_connector, attach_resource.Rows where the two servers differ are marked.
| Spec | ||
|---|---|---|
| Category | Developer Tools | Developer Tools |
| Quality signal | 57/100 · Good | 60/100 · Good |
| Install command | Confirmed | Confirmed |
| Transport | Local subprocess (stdio) | Remote HTTP/SSE |
| Auth | API key required | OAuth 2.0 |
| Pricing | Free | Freemium |
| Required env vars | CODEMAGIC_API_TOKENASC_KEY_IDASC_ISSUER_IDASC_PRIVATE_KEY_B64ASC_BYPASS_KEYCHAINGOOGLE_PLAY_SERVICE_ACCOUNT_CREDENTIALS | None listed |
| Verified owner | Community listing | Community listing |
| GitHub stars | 1 | 1 |
| Directory activity | 3 views 0 installs 0 upvotes | 2 views 0 installs 1 upvotes |
| Tools | 63 | 56 |
| Full listing | View Codemagic MCP | View Valet |
pingCheck that the server is alive and return its versionlist_applicationsList all applications in your Codemagic account. Call this first to get the app IDs needed by all other Codemagic tools.list_teamsList teams the authenticated Codemagic account belongs to. Use the team IDs returned here with list_applications, list_builds, and other tools that accept an optional team_id.list_workflowsList workflows for an application. Returns workflow names and IDs — use the ID in trigger_build to run a specific workflow. Note: yaml-defined workflows only appear after their first build has run.list_buildsList builds for a team with optional filters. Returns build IDs and status. Use get_build with a build ID to retrieve full details and artifact download URLs.get_buildGet full details for a single build including artifact download URLs. The build ID comes from trigger_build or list_builds. Artifact URLs require x-auth-token — use them with upload_to_testflight, upload_to_google_play, or create_public_artifact_url.trigger_buildTrigger a new build on Codemagic. For release builds: determine BUILD_NUMBER first using list_asc_builds (iOS) or list_google_play_tracks (Android), then pass it in the variables parameter. Use yaml_content to supply an inline codemagic.yaml — get a starter template from get_yaml_template and validate it with validate_codemagic_yaml before triggering. Call wait_for_build with the returned build ID to wait for completion and retrieve artifact URLs.wait_for_buildCheck the current status of a Codemagic build. Returns immediately — no polling loop. If the build has not finished, call this tool again with the same build_id. A Codemagic build takes 10–40 minutes; calling this 20+ times is normal and expected. Returns full build details and artifact download URLs once a terminal state is reached.cancel_buildCancel a running or queued Codemagic build. Use when a triggered build is no longer needed — for example if the wrong branch was used or an error was found after triggering. Has no effect on builds that have already finished.add_applicationAdd a new application to Codemagic by connecting a Git repository. For HTTPS URLs: if you have connected your GitHub, GitLab, or Bitbucket account via Codemagic Settings → Integrations, private repositories are accessible with just the URL — no credentials needed. For SSH URLs (git@... or ssh://git@...): a fresh Ed25519 deploy key is generated automatically. The private key is stored directly in Codemagic and the public key is added to GitHub automatically if the gh CLI is installed and authenticated, or shown for manual setup otherwise. Note: after adding, the app shows 'Set up build' in the Codemagic UI — this is expected.list_variable_groupsList variable groups for a team or app in Codemagic. Use group names to reference them in trigger_build. Secret values are never returned — manage secrets directly in the Codemagic UI.list_variablesList variables in a Codemagic variable group. Returns variable IDs, names, and values. Secret variable values are returned as null — only non-secret values are visible. Use the variable IDs with update_variable and delete_variable.attach_channelAttach an existing organization channel to an agent, so the channel's events wake it. Find the channel with list_channels. A webhook channel lets callers outside Valet reach the agent. Attaching a channel that is already attached reports it and changes nothing. Slack needs a Slack app and a browser, so for Slack this gives the step to take and attaches nothing. Requires connecting a Valet account.attach_connectorAttach an organization connector to a website or agent so it can call the connector's tools with the credential Valet holds.
Attaching is a grant, and it is wider than it looks: for a website, every person who can open the page can call every tool the connector exposes. On a private website that is every member of the organization; on a password-protected or shared one it is everyone holding the password or the link. For an agent, the agent can. Valet does not narrow the connector's reach, so attach only what the thing needs, and check a website's access mode before you do.
A website can hold only an organization connector that is an HTTP MCP server, on the sse or streamable-http transport; list_connectors with name marks which ones. A page calls the connector by its own name, which list_connector_tools reports. An app cannot hold a connector yet and the call says so. A connector that belongs to a single agent cannot be attached to anything else. Attaching a connector that is already attached changes nothing and is safe to repeat. Requires connecting a Valet account.attach_resourceAttach a resource to an app: a named set of environment variables, such as a database's connection string, that the app reads as secrets. Name the resource. When the organization has none by that name, pass a provider from list_catalog_resources and the first call creates it, returning at once with state provisioning. Call again with the same arguments, env_prefix included, until the state is attached: the call that finds the resource ready attaches it and sets its variables, then asks for a restart if the app is running. The state is attaching while Valet still owes the restart or the variables, and conflicted when a name the resource sets is already set on the app; the answer gives the reason. An existing resource attaches by name alone, including one another app holds. The call is safe to repeat: one name is one resource however many times it is called, and an app can hold several under different names. Pass env_prefix when two resources would set the same variables. Read the names an attachment sets from list_catalog_resources before writing the app's code. A new database is empty, so the app creates its own tables, and its URL carries the TLS settings it needs. The app must exist, so publish it first. The running process does not see the variables until the restart completes; get_service shows the attachment's status and when the new process is running. Provisioning takes about a minute; call again every ten seconds. Values are never returned here. Requires connecting a Valet account.attach_skillAttach a skill to an agent so the agent can use it. Give skill as catalog:<name> for a skill from Valet's curated catalog, org:<name> or a bare name for a skill the organization published, and add @v<N> to pin a version; without a pin the agent follows the latest. An org skill must already exist (publish_skill creates one). The agent is rebuilt so the change takes effect. A skill that is already attached answers that nothing changed, without a rebuild; one whose name another attached skill holds is refused with nothing changed. Skills attach to agents only. Requires connecting a Valet account.call_connectorRun one tool on a connector attached to a website and return what the connector answered. It is the sampling step of building a page that calls live data: discover, attach, read the schemas, then call one tool for real before you write any page code.
Call it because a schema is not a shape. list_connector_tools gives you each tool's name and argument schema, which is what your call has to satisfy; this tells you what comes back, which is what the page has to parse. Results are text to read, not JSON to assume: many servers answer in markdown tables or prose, some expose a single meta-tool taking a whole command as one string, and a server that completes the handshake can still refuse half its tools when the stored credential's scope does not cover them. One real call settles all three.
This runs the tool for real, with the organization's own credential and whatever side effects the tool has. It is not a dry run and there is no preview: a tool that sends, writes, or deletes will do so. Prefer a read-only tool when you are only learning the shape, and ask the user before running anything that changes their systems.
The connector must already be attached to the site — attach_connector does that — and must be an HTTP MCP server. A tool that answers with an error is reported as an error carrying the connector's own text, which is usually the sentence that says what to fix. It calls a website's connectors only; an app's or agent's are refused. Requires connecting a Valet account.claim_siteMove a site published anonymously into one of the caller's Valet organizations, making it permanent. Takes the claim_token, the last part of the claim URL that the anonymous publish_site returned, not the site_token: the site_token republishes the site and can never claim it. The site moves into an organization the account already belongs to; this tool never creates one. Pass new_name to rename the site on the way in, otherwise it keeps its generated name, with a suffix if the organization already holds that name. Claiming spends both credentials: afterwards use the site's name. Repeating a claim that already succeeded for this account reports where the site lives. Requires connecting a Valet account.create_channelCreate a channel on an agent: a cron or heartbeat channel that wakes it on a schedule, a webhook channel that lets callers outside Valet reach it, or an mcp channel that serves it as an MCP server. The channel starts the agent's work; what the agent does when it fires is the prompt file channels/<name>.md in its source. A webhook is signed by a secret you choose, because this never returns a secret value: set it with set_env_vars on the agent first, then pass its name as secret_name. A webhook without secret_name is refused. Creating a channel that already exists with the same kind and settings reports it and changes nothing; different settings are refused, so destroy it first. Slack and Telegram need a browser, so for them this gives the step to take and creates nothing. Requires connecting a Valet account.create_connectorCreate an organization connector from a Valet catalog entry. It is the step after list_catalog_connectors found the entry for the product the user named; attach_connector then lets a website's pages call it.
It creates an entry whose credential is a secret. Pass each slot the entry asks for in secrets, as slot name to value. A slot the organization already holds as a secret needs no value here. If a required slot has neither, nothing is created and the answer names the slots still needed.
A key given here passes through this conversation. That is a real cost and it is the user's call to make: if they hand you the key, use it, and say that they could instead enter it on the dashboard's Integrations page, where it goes straight to Valet. The answer names the slots that were filled and never the values in them.
An entry that authorizes in a browser — OAuth, or a Composio toolkit — is not created here. The answer gives the entry's name and the Integrations page, which creates the connector and runs the authorization in one place. An entry the organization already has is reported as already there; no second connector is made. Requires connecting a Valet account.create_pushOpen a Git push on a website, app, or agent that exists: a branch of its repository, writable for one hour, that you push source to before you publish. Use it when you can run git with network access; it sends only what changed, so a large service publishes without carrying its files through the conversation. Otherwise publish with files. The service must exist first: create_service makes it. The result carries a Git URL with a credential, the push's id and branch, the commit it starts from, the name and email to commit as, and two recipes with every value filled in: clone the branch and edit, or push a directory as it stands. Run a recipe, then call publish_site, publish_app, or publish_agent with push: {id, commit}, where commit is the sha the recipe prints. The URL writes only this push's branch, cannot force-push, and expires with the push; do not share or log it. A service holds ten open pushes at once. Requires connecting a Valet account.create_serviceCreate an empty website, app, or agent in an organization, before publishing to it. This is the first step for anything new: publish_site, publish_app, and publish_agent change a service that exists and refuse a name that does not. Pass kind to say which you mean, and name to choose its name; omit name to have one generated. A name another website, app, or agent in the organization holds is refused, as is a create past the organization's limit for that kind. The result names the organization, kind, name, and URL; publish to the name next. Requires connecting a Valet account.destroy_channelDestroy a channel and its routes. This cannot be undone, so confirm with the user first. Without name, it destroys an organization channel found with list_channels; an organization channel that any agent still holds is refused, and the answer names each holder: free each with detach_channel, then destroy it. With name, it destroys a channel that agent owns, such as one create_channel made; a channel the agent only holds from the organization is detached with detach_channel instead. A channel found only in the other scope is refused with the call to make. Destroying a channel that is already gone changes nothing. The organization's Slack integration removes every agent's Slack app, so for it this gives the step to take and destroys nothing. Requires connecting a Valet account.destroy_connectorDestroy an organization connector and its stored credential. This cannot be undone, so confirm with the user first. A connector that any website, app, or agent still holds is refused, and the answer names each holder: free each with detach_connector, then destroy it. A connector an agent owns is not an organization connector; the answer says what removes it. Destroying a connector that is already gone changes nothing. Requires connecting a Valet account.Paste either block (or both) into your client config, e.g. claude_desktop_config.json or ~/.cursor/mcp.json. We only show a config when the install command is confirmed.
{
"mcpServers": {
"todah-zg-codemagic-mcp": {
"command": "npx",
"args": [
"-y",
"codemagic-mcp-server"
],
"env": {
"CODEMAGIC_API_TOKEN": "YOUR_CODEMAGIC_API_TOKEN_HERE",
"ASC_KEY_ID": "YOUR_ASC_KEY_ID_HERE",
"ASC_ISSUER_ID": "YOUR_ASC_ISSUER_ID_HERE",
"ASC_PRIVATE_KEY_B64": "YOUR_ASC_PRIVATE_KEY_B64_HERE",
"ASC_BYPASS_KEYCHAIN": "YOUR_ASC_BYPASS_KEYCHAIN_HERE",
"GOOGLE_PLAY_SERVICE_ACCOUNT_CREDENTIALS": "YOUR_GOOGLE_PLAY_SERVICE_ACCOUNT_CREDENTIALS_HERE"
}
}
}
}
{
"mcpServers": {
"valet": {
"url": "https://api.valet.dev/mcp"
}
}
}