Start a workflow from an MCP event¶
An MCP server can offer events as well as tools and views: "a pull request's checks
failed", "a message arrived". A workflow can run on one of them. This guide uses this
project's own CI watcher, a small MCP server that turns GitHub Actions failures into
checks.failed events, and the Fix failed checks workflow that starts an agent on each
one.
The app asks servers for events in poll mode, following the MCP events draft
(experimental-ext-triggers-events). A server that offers events only by push or webhook
is shown as not supported yet.
Before you start¶
- A project with an MCP server that offers events. The CI watcher ships with Agents Host and
the Linux host, and needs a signed-in
gh(gh auth status) on the host. SeePackages/MCPServers/README.mdin the repo. - For every setting, see Workflow triggers and actions, and for what the event carries, Events from MCP servers.
Start the server¶
Server events come from servers the project can already use: the project's
.agents/mcp.json, your own ~/.agents/mcp.json, or a plugin. The CI watcher is in this
project's .agents/mcp.json as ci, a local server the app hosts:
{ "mcpServers": { "ci": { "command": "ci-watcher", "hosted": true } } }
- In Project Settings ▸ Agent Configuration ▸ MCP servers,
ciarrived with the project, so it is waiting for your OK: choose Approve. Until you do, it is asked for nothing, and the workflow's page says it is waiting for approval. See Add an MCP server from the registry. - There is nothing to start. The app runs one copy of it on the host, the first time a
workflow or an agent asks it something, and every agent shares that copy. It holds no
token of its own: every GitHub call goes through your
gh. See Share one copy of a local MCP server.
A local server without "hosted": true works too: the app runs its own copy of it to ask
for events, with the same environment and secrets an agent gets, and each agent runs
another for its tools.
Write the workflow¶
A server's event is named the way the app's own are, noun.verbed, with no prefix. Under
the name, the keys are the event's own filters, sent to the server:
---
name: Fix failed checks
on:
- checks.failed:
repo: alexec/Agents
agent: new
cooldown: 5m
labels: [ci]
---
A pull request's checks failed. The event's data says which PR, branch and jobs.
Use the `ci` server's `failed_log` to read each failed job. If it is a test known to be
flaky under load, use `rerun_failed`. Otherwise fix it on the PR's branch in a worktree,
push, and use `comment_on_pr` to say what you changed.
- Without
server:, the trigger listens to every server here that offerschecks.failed. Addserver: cito listen to that one only, orserver: [github, gitlab]for a list. - The
ciserver'schecks.failed,pr.merged,pr.closed(closed without merging) andpr.conflicted(began to conflict with its base, #712) all takerepo,branch(only that PR branch) andpr(only that pull request, by number). Left out,repois the one the project's folder pushes to (#702). Given together, each must hold:{pr: 551}hears only PR 551's failures and merge. - Its
pr.opened(#833) is raised when a pull request opens, or when a draft is marked ready for review. It takes the same filters andanyone. Drafts never raise it. The Review pull requests workflow in.agents/workflows/starts an agent on it that reads the diff and leaves one comment. checks.failed,pr.openedand the issue events are raised only for the repo's owner, members and collaborators, never a bot (#728).anyone: trueraises them for everyone.- Its issue events,
issue.opened,issue.labelled,issue.commentedandissue.closed, takerepo(optional, as above) andlabel; all butissue.openedalso takeissue, by number. Onissue.labelled,labelis the label added:{repo: alexec/Agents, label: bug}hears each issue as it is marked a bug. - A filter the server's event doesn't take, or a value of the wrong type, shows on the workflow's page as an error, naming the filters it does take.
- This project's copy of the workflow arrives with
enabled: false. Turn it on with its Enabled switch, and approve it.
Each event starts the workflow once, after its prompt. The agent is told the event's details and, in a fenced block, the server's data, marked as coming from the server and not from you. The workflow's prompt and permission mode decide what the agent may do with it.
Check it is listening¶
Open the workflow's page, on the Mac, the iPhone or iPad, or the web page. Under Triggers, a line for each server the trigger listens to says how it is doing:
- ci · checks.failed: Checked 20 s ago · last event 25 min ago: it is listening. A new subscription starts from now, so events from before it are not run.
- Can't reach ci since 12:01 · trying again in 40 s, in orange: the server is down. The app tries again, waiting longer each time up to 5 minutes, and the line comes back by itself once the server answers.
- A line in red says why it stopped: the server no longer offers the event, refused it, or doesn't take its filters. It is asked again once the file or the server's events change.
- Events may have been missed since 09:14: the app was away longer than the server keeps events. Events it did get still run. Clear takes the line away.
Each event is also on the Events page, under the name checks.failed, with the run it
started.
Turn it off¶
Turn the workflow off with its Enabled switch, and the app stops asking the server for its events. The CI watcher itself stops once nothing uses it: no agent's session has it open and no workflow listens for its events.
See also¶
- Events
- Workflow triggers and actions
- Set up a workflow
- Pin a page to a project: the CI watcher's board,
ui://ci/board, can be pinned