Field Notes

Let Claude Code ask you a question in a Mac notification

Claude Code stops to ask a question and waits in a terminal you are not watching. One Watchflows flow, exposed over MCP, asks you in a Mac notification instead.

Ask Me called through the MCP server the way Claude Code calls it. The run waits on the question until Yes is chosen in Notification Center, and "button: Yes" goes back to the caller.

You give Claude Code a long job: rename a module across 80 files, then run the migrations. You go and make lunch. Halfway through it reaches a step it should not take alone, a migration that drops a table, and it stops to ask. The question sits in a terminal tab behind three windows for 40 minutes.

The agent can post a banner with a shell command, but a banner cannot carry a button press back. What it needs is one narrow tool: ask the person at this Mac, wait, return the answer.

Watchflows can hand it that tool. With AI Agents on, the app runs a small MCP server on your Mac, and any flow you expose becomes a tool an assistant can call. The flow here shows your question as a notification with Yes, No and a typed reply, then returns what you chose.

Connect Claude Code to Watchflows over MCP

Open Settings ▸ AI Agents and turn on Enable AI Agents. Until you do, nothing listens. Connect your AI assistant lists a snippet per client. The Claude Code one is a single command:

claude mcp add --transport stdio watchflows -- /Applications/Watchflows.app/Contents/MacOS/watchflows-mcp

Copy it from the pane rather than from here, since the pane builds the path from wherever your copy of the app actually lives. There is no token in it. watchflows-mcp is a small program inside the app that reads the token from a file only your user account can read (mcp-token in ~/Library/Application Support/Watchflows/). If the app is not running, the shim launches it hidden and waits about ten seconds for the server. Keep running in the background makes that rarer by registering a login item.

Fig. 1Settings ▸ AI Agents: the switch that starts the server, the loopback port it listens on, and one-click setup for each assistant.

What Claude Code can call

Five core tools read and run, and none of them can create, edit or enable a flow:

ToolWhat it does
list_workflowsEvery flow, with agentRunnable marking the ones it may run
describe_workflowNodes in order, and the exact inputs a run takes
run_workflowRuns one by id, waits up to 60 seconds
get_runThe full record of one run
list_runsA flow's run history

Each exposed flow also becomes its own tool, named after the flow in snake case. This one is called Ask Me, so Claude Code sees mcp__watchflows__ask_me, with one string argument, text.

Importing the flow does not expose it. Open it, select nothing, and turn on Expose to AI agents in the flow's inspector (or in the pane's Exposed watchflows list). The switch is not stored in the .watchflow file, on purpose.

Build the Ask Me flow

Fig. 2Input, Notification Prompt, and a Template on each of its two outlets.

Question is an Input trigger with Input Type Text. Because it is an Input trigger, the tool gets a typed text argument instead of a loose payload object. The saved text is a sample question, used when you press Run yourself or when a caller leaves text out.

Fig. 3The Input inspector. The Text field is the default question.

Ask me is a Notification Prompt. Title is Claude Code is asking, Message is {{text}}, and Buttons has Yes and No on two lines, with No listed under Destructive Buttons so it draws in red. Allow a typed reply is on, with the Reply Button renamed Answer, for the times the right answer is "no, do this instead". Give up after (seconds) is 1800.

Fig. 4The question in Notification Center, with its Options menu open: the two buttons and the typed reply.
Fig. 5The prompt inspector: two buttons, a typed reply, and a 30 minute wait.

Answer is a Template on the Action outlet, with Output Key result and this text:

button: {{action}}
reply: {{text}}

Dismissed is a second Template on the Dismissed outlet that sets result to dismissed: closed without an answer.

The key has to be result. Unless you mark a node Return this to the agent, a finished run hands back output from the one node that ended the path, and only its result key. A flow that ends in a plain Notification returns output_source: none:side-effect and no answer at all. Only one outlet fires, so only one Template runs and there is exactly one end node.

Paste into the Flow Builder

Take a question as text from an Input trigger, ask me in a notification with Yes and No buttons and a typed reply, wait up to 30 minutes, and put my answer in a key called result. If I dismiss the notification, set result to "dismissed".

When you are slow, typing, or away

Claude Code will not guess any of this, so tell it in your project's CLAUDE.md:

Before any destructive or irreversible step, call the watchflows ask_me tool
with the question as text. If it returns status running, poll get_run with the
run_id every 30 seconds. Treat "dismissed" or a failed run as "no" and stop.

Who else can call it

The server listens only on 127.0.0.1, port 52916. It refuses a request unless the Host header names loopback, there is no Origin header (which rules out web pages in your browser), and the bearer token matches. The token survives relaunches and updates. Rotate, under Advanced in the pane, replaces it, and every client then has to reconnect.

A run also needs the flow to be enabled and exposed. The read tools still list every flow by name, so an assistant knows what exists, but an unexposed flow has no tool of its own and run_workflow refuses it. See AI Agents (MCP) for the full contract.

Variations

What's in this flow

One trigger. Nodes are listed in the order a run reaches them; the canvas above shows where it branches.

Download this flow
  1. InputQuestion
  2. Notification PromptAsk me
  3. TemplateAnswer
  4. TemplateDismissed

Run this one yourself

Download the flow, double-click it, and Watchflows opens it on the canvas. Everything in this note is on the 14-day free trial.