Expo Application Services

com.foreverworks由 foreverworks.com 發布v0.1.2更新於 Nov 7, 2026

查明 Expo 建立、工作流執行或應用程式商店提交失敗的原因,併發布更新。

AI 翻譯由 AI 模型根據下方的原文描述翻譯,可能有誤。

原文描述

Find out why an Expo build, workflow run or store submission failed, and roll out updates.

已驗證STDIO僅桌面

概覽

Expo Application Services 的本機 MCP 服務,由 foreverworks.com 發布;無需登入;STDIO;23 個工具。

暫無 AI 概覽:以下資訊來自註冊中心條目和服務本身。

發布者
foreverworks.com

安裝

在 SourceWeft 中

  1. 開啟 儀表板中的 Expo Application Services,將其新增到工作區。
  2. 為需要使用其工具的對話啟用該服務。

Desktop only,透過 STDIO。 STDIO 服務會啟動本機處理程序,因此需要 SourceWeft 桌面主機。

其他 MCP 客戶端

參照 儲存庫 中的啟動說明。

README

[Expo Application Services icon] Expo Application Services MCP server

Find out from your AI assistant why an Expo app's build, workflow run or store submission failed, through Expo Application Services (EAS): job logs by step, Apple's or Google's error text, a credentials audit, fingerprints and update channels. It can also cancel builds and runs, submit an existing build, republish or roll out an update, set the App Store Connect key a bundle id submits with, and dispatch a workflow. dispatch_workflow is the one money tool: your client asks you before each call.

You need an Expo account with an EAS project, and an access token in a file, ideally a robot user's with the Developer role. A dispatch runs a workflow file from the project's GitHub repository, and its build jobs spend build credits on your Expo plan.

What you can ask

  • "Why did the last iOS workflow run of @acme/my-app fail?"
  • "Does every iOS bundle have a key set for TestFlight submissions, and does any certificate expire in the next 30 days?"
  • "Run ios-beta.yml on main and tell me when it finishes."
  • "Which fingerprints have updates but no build yet?"
  • "Promote the latest update on the staging branch to production."
  • "Raise the rollout of the latest production update to 50%."

Install

[Install in VS Code] [Install in Cursor] [Download for Claude Desktop]

With Claude Code:

bash
claude mcp add eas -e EXPO_TOKEN_FILE="<path to Expo token file>" -- npx -y @foreverworks/mcp-eas

Claude Desktop (Settings, Developer, Edit Config) and most other clients read the same command as JSON:

json
{  "mcpServers": {    "eas": {      "command": "npx",      "args": ["-y", "@foreverworks/mcp-eas"],      "env": {        "EXPO_TOKEN_FILE": "<path to Expo token file>"      }    }  }}

Each runs the published package on Node 22.19 or newer. VS Code and the Claude Desktop bundle ask for each setting as they add the server; leave an optional one empty. Cursor reads each from your environment instead (${env:EXPO_TOKEN_FILE} and so on), so set them before you start Cursor. The commands above set only what is required; Configuration has the rest.

From a clone

bash
git clone https://github.com/foreverworks/mcps.git && cd mcpsnpm ci && npm run buildclaude mcp add eas -e EXPO_TOKEN_FILE="<path to Expo token file>" -- node "$PWD/servers/eas/dist/index.js"

In a JSON configuration, the command is node and its one argument the full path of servers/eas/dist/index.js. To share one running copy between several clients over HTTP, see docs/deploying.md.

Configuration

VariableRequiredMeaning
EXPO_TOKEN_FILEyes, or EXPO_TOKENFile holding the Expo access token. It is read again after a 401, so a replaced token works without a restart.
EXPO_TOKENnoThe token itself (eas-cli's own name), for a local stdio run.
EAS_PROJECTnoThe project a call means when it names none and the token sees several: @account/slug, a slug or an id.
EAS_PRODUCTION_CHANNELSnoComma-separated channel names whose updates reach real users; default production. A republish or a rollout names the ones it reaches.
EXPO_API_URLnoThe GraphQL endpoint; default https://api.expo.dev/graphql.

validate_workflow reads a file given by path from MCP_FILE_ROOTS. That and the other variables every server shares (transport, limits, what tools may do) are in docs/configuration.md.

Getting a robot user's token

Make a robot user for the server: it belongs to the account rather than to a person, its role bounds what the server can do, and you can revoke it on its own. At expo.dev, in the account's settings:

  1. Open Robots and Create robot, with a name that says where it runs. Give it the Developer role, which is enough for every tool here (build, submit, credentials; no billing, no members). Viewer limits the server to the reads: every write then answers forbidden.
  2. On the robot, Create access token. Expo shows it once: save it in a file readable only by you (chmod 600).
  3. Point EXPO_TOKEN_FILE at that file.

Expo access tokens do not expire; to rotate one, replace the file.

First run

  1. Ask your assistant to run the EAS health check. It says whether the token works, as which actor (ideally a robot user), and the accounts and projects it sees.
  2. If it sees several projects, set EAS_PROJECT, or name the project in each request (list_projects gives the names).
  3. Ask for a credentials audit (audit_credentials) to see what is missing or about to expire.

Tools

read changes nothing; write changes something at EAS or in a store without spending build credits; money spends EAS build credits, and your client asks you before each call.

ToolAccessWhat it does
healthreadThe token is accepted; its actor (ideally a robot user), accounts and visible projects.
list_projectsreadThe projects the token sees, per account: what project takes everywhere.
list_buildsreadBuilds, newest first, by platform, status, profile, bundle id or package, commit, fingerprint.
get_buildreadOne build: artifacts, fingerprint, runtime, timings, error; for an ERRORED build the failed step and its line, from the log.
list_workflowsreadThe project's .eas/workflows files.
validate_workflowreadChecks a workflow file before it runs, at a ref or as a file: valid or not, each problem EAS's validator names, the jobs, and the builds a dispatch would spend credits on.
list_workflow_runsreadRuns, newest first, by file, status or ref; each FAILURE run carries reason, read from its failed jobs' logs.
get_workflow_runreadA run's jobs (type, status, outputs, artifacts) and, when it failed, why per job, with the failed step's tail.
wait_for_runreadWaits for a run or a build to end (up to 14 minutes a call), reporting progress, then answers like get_workflow_run or get_build.
get_job_logsreadA job's log by step: every step's result, and one step's last lines (the failed one by default).
list_submissionsreadSubmissions with Apple's or Google's error text (for a workflow's submission it lives on the job, which this reads).
get_submissionreadOne submission, and for an ERRORED one the failed step of its log.
audit_credentialsreadPer bundle id and package: certificate and profile with expiry, the App Store Connect key for submissions, push key, keystore fingerprints, Play service account; what is missing, expired or expiring in 30 days.
list_fingerprintsreadFingerprints, newest first or by hash, with the builds and updates that carry each.
list_updatesreadChannels and the branches they serve (production marked), and per branch the latest update for each platform and runtime.
cancel_buildwriteCancels a queued or running build.
cancel_workflow_runwriteCancels a run that has not ended.
set_submit_keywriteSets or clears the App Store Connect API key EAS submits one bundle id with, by its Apple key id or EAS id; answers with the bundle's audit after.
submit_buildwriteSubmits an existing FINISHED build: iOS to App Store Connect, Android to a Play track; refuses one that differs from expect_version or expect_build_number.
republish_updatewritePuts an existing update group on a branch again (a rollback or a promotion), uploading nothing; refuses a group of another project, a signed one, one in a rollout, or one not from expect_commit.
set_rolloutwriteRaises an update group's rollout to a percentage of its branch's devices; 100 rolls it out to all. The same percentage again changes nothing.
revert_rolloutwriteEnds a rollout by sending its devices back to the update before it; deletes nothing.
dispatch_workflowmoneyRuns a workflow file at a git ref the repository already has; its build jobs spend EAS build credits.

Money

The only way this server starts a build is a workflow run, so dispatch_workflow is the one money tool. It is marked so in tools/list, and your client asks you to approve each call (Claude Code does, in every permission mode). Before the call, the server reads the workflow file at that ref from EAS (which runs nothing), and the run starts that revision of the file, so it runs those jobs even if the branch moves in between. With MCP_CONFIRM=elicit the server asks you itself instead, in one line naming each build job's platform and profile:

eas: Run EAS workflow ios-beta.yml of @acme/my-app at main: builds ios preview (if its condition holds); may spend EAS build credits.

The line names no commit: EAS keys a revision by its content and reports the commit where it first saw that content, not where the ref points now. A file without build jobs says it spends no build credits.

The other changes spend nothing, so they are write, though a republish or a rollout reaches a branch's devices at their next launch, production included (each answer names the production channels it reached), and another republish undoes it.

submit_build and republish_update take an id the model copies, and a miscopied one would ship something else unnoticed. So each answer says what shipped (a build's platform, profile, app version, build number and commit; a group's project, source branch, commit and message), and each checks what you expect before sending: expect_version and expect_build_number for a build, expect_commit (a prefix of 7 or more characters) for a group. A group from another project is always refused.

Troubleshooting

config: "neither EXPO_TOKEN_FILE nor EXPO_TOKEN is set". Give the server a token (Getting a robot user's token).

auth. EAS refused the token: the robot or its token was deleted or revoked. Check them at expo.dev (account settings, Robots) and replace the token file; it is read again on the next call.

forbidden. The robot lacks the permission: writes need the Developer role on the project's account. Change its role at expo.dev (account settings, Members).

not_found. Check the id or name: list_projects, list_builds, list_workflow_runs and list_submissions give them. A project of another account answers not_found too.

input. The arguments failed a check here or at EAS: a build or group other than the one you expected, a rollout percentage lower than now, a ref that is not a git ref. For a workflow file, issues lists every problem EAS's validator named, field by field (jobs.build.params.platform: Required). Nothing changed.

refused. EAS declined as the message says (a build that already ended, a workflow file that is not on that ref). Nothing changed.

outcome_unknown after a dispatch, a submission or another change. The connection dropped after the request left, so nobody knows whether EAS acted. Look first (get_workflow_run, get_build, list_submissions): repeating a dispatch or a submission does it twice.

A submit job fails at "Prepare credentials" with a message that names nothing. The bundle id usually has no App Store Connect key set for submissions, often a development twin of one that has it. audit_credentials shows it, and set_submit_key sets a key the account already holds.

wait_for_run answers done: false. The run is waiting for an approval, or still going after the minutes you gave. Call it again; the run is not affected.

rate_limited. EAS is throttling the token; wait a minute. api with status 0 means EAS was unreachable; another status, that it failed: retry later, and check status.expo.dev if it persists. drift means EAS's API changed (a query no longer validates): please report it with the message.

How it works

One GraphQL endpoint, https://api.expo.dev/graphql. A query repeats after a 5xx or a dropped connection; a mutation is never repeated blind and fails as outcome_unknown. The projects the token sees are kept for 5 minutes, shared by every client of an HTTP process. EAS answers errors with HTTP 200 and an errors list, which src/infra/graphqlErrors.ts maps: *_NOT_FOUND is not_found, VALIDATION_ERROR is input, another USER error is refused, GRAPHQL_VALIDATION_FAILED is drift.

Queries written from the schema, holding no secret. The queries in src/infra/easApi/queries.ts come from EAS's introspection and eas-cli 24.10's own, validated against the live schema; EAS validates each one on every request too, so a removed field fails loudly as drift. None selects a secret: no P12 or its password, no provisioning profile file, no keystore or its passwords, no .p8, no FCM key, no environment variable value. set_submit_key names a key the account already holds; nothing is uploaded.

Logs are signed Cloud Storage URLs, fetched without the token: brotli-compressed, one JSON object per line. src/domain/logs.ts groups them by step and picks the line that says why a failed step failed (the last it printed that is not the builder's "exited with non-zero code").

Rollouts

An update published with eas update --rollout-percentage reaches that share of the devices on its branch and runtime; the others keep the update before it. list_updates shows a group's rolloutPercentage. From there:

  • Further: set_rollout with a higher percentage moves every platform of the rollout together (or one, with platform). EAS only lets a rollout grow, so a lower number is refused with a pointer to the revert. At 100 every device gets the update, which ends the rollout.
  • Back: revert_rollout publishes the update before it on the branch again, naming the rollout it ends (EAS requires that to publish over a rollout in progress). Unlike eas-cli, it deletes no rollout group. A second revert, or one after a newer publish, is refused instead of publishing twice, because the rollout must still be the latest update for its platform and runtime.
  • Not covered: reverting a rollout with no update before it (the branch's first on its runtime), which means going back to the update embedded in the app and needs the project's expo-updates version (eas update:revert-update-rollout does that); and rollouts between two branches on a channel (eas channel:rollout).

Checking a workflow before it runs

validate_workflow answers "will this file run?" without a checkout or spending anything. Give it workflow and git_ref to check the copy a dispatch would run, or path for a file you are still editing (inside the server's file roots; over HTTP, copy it there, or have a script send it as content_base64 with its sha256). It parses the YAML as a dispatch does (merge keys on, as EAS reads them), so it lists the build jobs a dispatch line would name, then asks EAS's own validator, as eas workflow:validate does. That command also checks that each build job's profile exists in your eas.json; this cannot.

npx tsx scripts/smoke.ts drives the built server read-only and checks that dispatch_workflow is the one money tool (--project, --workflow, and --expect-key <Apple key id> to fail unless every iOS bundle has that submit key).

Limitations

  • No build from a local tree (eas build, or eas workflow:run without --ref). That uploads the working directory, which is slow and can hang, and nobody could see what is built; dispatch at a ref instead.
  • No eas update publish, only republishing an existing group, and no credential uploads: certificates, profiles, keystores and keys stay where eas credentials puts them.
  • submit_build uses what EAS already holds for the build's identifier; audit_credentials says what is missing first.
  • The token sees what its robot sees: a project of another account is invisible.
  • Rollouts: per-update rollouts only, and no revert to the embedded update (Rollouts).

Other servers for Expo Application Services

Searched 2026-10-15. Expo publishes one, and two community servers touch EAS:

  • Expo MCP Server, hosted by Expo: Streamable HTTP, with a person's OAuth sign-in in a browser. It starts, cancels and reads builds and their logs; creates, validates, runs, cancels and reads workflow runs and job logs; submits a finished build; reads TestFlight crashes and feedback, App Store and Google Play reviews (and replies) and Play crashes; and searches the docs. With the expo-mcp package it drives a local simulator. It is ahead of this one on writing workflows, building from a profile, crashes and store reviews.
  • shipstores on PyPI: stdio, maintained; five EAS tools that run eas-cli in a project folder, beside many App Store Connect and Play Console tools.
  • expo-mcp-server on GitHub: stdio; builds, updates and submissions; unchanged since December 2025.

This one adds what they lack: a credentials audit per bundle id and package; submissions listed with Apple's or Google's error text; each failed run's reason in the list itself; fingerprints, update channels and republishing an update group; and setting the App Store Connect key a bundle id submits with. It signs in as a robot user whose role bounds what it may do, with the token in a file, so it can run as a shared service; Expo's server signs in only interactively.

來源:servers/eas/README.md,提交 7b93f2f

工具

23

audit_credentials

Audit credentials

Per bundle id (iOS) and package (Android) of a project: the distribution certificate and provisioning profile with their expiry, the App Store Connect API key for submissions, the push key, the upload keystore's fingerprints and the Google service account for submissions, and in words what is missing, expired or expiring within 30 days. Every identifier the project has credentials for or has built is covered, so one built without credentials shows up. No secret is ever read.

輸入參數projectplatformidentifier

cancel_build

Cancel build

Cancel a build that is queued or running. EAS refuses one that has already ended, and says so; nothing else changes.

輸入參數build必填

cancel_workflow_run

Cancel workflow run

Cancel a workflow run that has not ended, with its running jobs (a build in progress stops spending).

輸入參數run必填

dispatch_workflow

Dispatch workflow

Run an EAS workflow file at a git ref the project's GitHub repository already has. EAS reads the file and the code from GitHub; nothing local is uploaded. A build job spends EAS build credits; the summary line names the project, the file, the ref and each build job's platform and profile. Answers with the new run; follow it with get_workflow_run. Moves money or makes a legal document: the client asks the user to approve each call.

輸入參數inputsgit_ref必填projectworkflow必填

get_build

Get build

One build: its artifacts (the .ipa/.aab URL), fingerprint, runtime version, channel, timings and error. A build that ERRORED also carries failedStep, the step that failed and the line that says why, read from its log; steps lists them all.

輸入參數build必填linessteps

get_job_logs

Get job logs

A workflow job's log, by step: every step with its result and size, and the last lines of one step (the failed one by default). What eas workflow:logs --all-steps prints, without the noise.

輸入參數job必填steplines

get_submission

Get submission

One submission with Apple's or Google's error text; one that ERRORED also carries failedStep from its log (its own, or the workflow job's that made it); steps lists every step.

輸入參數linesstepssubmission必填

get_workflow_run

Get workflow run

One workflow run with its jobs: each job's type, status and outputs (build_id, fingerprint hashes, app_build_version...) and artifacts. When it failed: reason in one line, and failures per job (the job's own error, which for an App Store upload is Apple's text, else its failed step and the line that says why); lines adds each failed step's tail.

輸入參數run必填lines

health

Health

Check that the Expo access token is present and accepted: which actor it is (a robot user, ideally), its accounts and the projects it sees. Reads only. Run this before concluding the server is broken.

無需輸入參數。

list_builds

List builds

A project's builds, newest first, filtered by platform, status, profile, bundle id or package, commit or fingerprint. Each says its status, profile, identifier, version and build number, commit, fingerprint, runtime, who started it and its error.

輸入參數limitcommitoffsetstatusprofileprojectplatformfingerprintapp_identifier

list_fingerprints

List fingerprints

A project's fingerprints (the hash of its native side), newest first, or one by hash: how many builds and updates carry each, and the latest of them. Answers whether a build exists for a native state, the question a fingerprint-gated workflow asks.

輸入參數hashlimitproject

list_projects

List projects

The EAS projects this token can see, per account, with their full names (@account/slug) and ids: what every other tool's project argument takes. A tool may leave project out when the token sees only one.

無需輸入參數。

list_submissions

List submissions

A project's App Store Connect and Google Play submissions, newest first: status, the build (identifier, version, build number), the ASC app or Play track, the workflow job that made it, and error: Apple's or Google's own text (for a workflow's submission it lives on the job, which this reads).

輸入參數limitoffsetstatusprojectplatform

list_updates

List updates

A project's EAS Update channels with the branches they serve (production ones marked), and per branch the latest update for each platform and runtime version: what a device on that runtime downloads next.

輸入參數project

list_workflow_runs

List workflow runs

A project's workflow runs, newest first, optionally of one workflow file, status or ref: status, ref, commit, trigger (a GitHub push, a schedule, a dispatch) and who. A FAILURE run carries reason: the failed job, its failed step and the line that says why, read from the job's log (e.g. "submit_ios > Prepare credentials: eas-cli failed to resolve submission config ...").

輸入參數limitcursorstatusgit_refprojectreasonsworkflow

list_workflows

List workflows

A project's EAS workflow files (.eas/workflows/*.yml), by file name: what list_workflow_runs and dispatch_workflow take.

輸入參數project

republish_update

Republish update

Put an existing update group on a branch again, as eas update:republish does: roll a branch back to an earlier group, or promote a group from one branch to another. Nothing is uploaded. Refuses a group of another project, a code-signed group or one in a rollout, and with expect_commit a group published from another commit. Answers with where the group came from (its branch, commit and message) and the new group.

輸入參數group必填branch必填messageprojectplatformexpect_commit

revert_rollout

Revert rollout

End an update group's rollout by sending every device on its branch and runtime back to the update before it, as eas update:revert-update-rollout does: that update's group is published on the branch again, ending the rollout; nothing is deleted or uploaded. Refuses a rollout something newer already ended, and one with no update before it (the app's embedded update; revert that with eas-cli in the project). Answers with the groups republished and the production channels.

輸入參數group必填projectplatform

set_rollout

Set rollout

Raise an update group's rollout to a percentage of the devices on its branch and runtime, as eas update:edit does; 100 rolls it out to every device and ends the rollout. A rollout only grows (revert_rollout takes it back); setting what it already is changes nothing. Answers with the percentage before and after, and the production channels that serve the branch.

輸入參數group必填projectplatformpercentage必填

set_submit_key

Set submit key

Set (or clear) the App Store Connect API key EAS uses to submit one iOS bundle id, as eas credentials does. Without one, eas submit and a workflow's submit job fail at Prepare credentials. Answers with the key before and the bundle's audit after.

輸入參數keyclearprojectbundle_id必填

submit_build

Submit build

Submit an existing FINISHED build: iOS to App Store Connect (TestFlight), Android to a Google Play track. It uses what EAS holds for the build's own bundle id or package (the ASC key or Google service account set for submissions, as audit_credentials shows it), so it fails before scheduling anything when that is missing. Spends no build credits. Give expect_version or expect_build_number when you know what should ship: a build that differs is refused. Answers with the build as submitted (platform, profile, app version, build number, commit) and the submission; follow it with get_submission.

輸入參數build必填trackgroupsrolloutasc_app_idwhat_to_testexpect_versionrelease_statusexpect_build_number

validate_workflow

Validate workflow

Check an EAS workflow file before it runs, the way eas workflow:validate does, without a checkout: the file as the project's repository has it at a ref (workflow and git_ref; EAS reads it from GitHub, as a dispatch would), or a file (path). Answers valid, the issues (YAML that does not parse, a needs: naming no job, and every problem EAS's own validator names, field by field), the jobs, and the build jobs a dispatch would spend credits on. Runs nothing, spends nothing. Never type or paste a file's base64 yourself: a retyped file can arrive changed. Give the path of a file in your workspace folders (the roots this client shares; without them /workspace/mcp-validate), or have a script that read the file send content_base64 with its sha256.

輸入參數pathsha256git_refprojectworkflowcontent_base64

wait_for_run

Wait for a run or a build

Wait until a workflow run or a build ends (give run or build), looking every 15 s, and answer as get_workflow_run or get_build would then: the outcome and, when it failed, the reason. While it waits, a client that asks for progress hears where it stands (jobs done, the job running). A run that waits for someone's approval, or one still going after minutes, answers done: false with its state; cancelling the call only stops the waiting, never the run.

輸入參數runbuildlinesminutes

版本歷史

1
  1. v0.1.2最新Nov 3, 2026

評分

已滿足適用檢查項的 90%

該評分衡量此收錄條目的完整程度,依據註冊中心條目、端點與公開來源計算得出。它不是對伺服器本身的評價,也不表示伺服器安全或目前可用:可連通性是帶日期的檢查結果,評分也不包含安裝量或使用者評價。

  • 近 30 天內可連通25 分
  • 已宣告認證方式10 分

    請在註冊中心條目中宣告憑證請求標頭,或保持端點能夠回應探測,以便判定其認證方式。

  • 已列出工具必需15 分
  • 描述必需15 分
  • 圖示10 分
  • 文件15 分
  • 授權條款10 分