Home / Blog

MCP

MCP for monitoring: report agent status with 3 tools

A simple pattern for monitoring AI agents over the Model Context Protocol: report_status, report_step and report_message, when to call them, and how to connect Claude Code, Cursor, Codex and Grok Bot.

Darren LiuFounder, AgentPilots7 min read

Most agent monitoring starts from the inside: wrap the model client in an SDK, capture every call as a span, and reconstruct what happened afterwards. That is the right approach for debugging an LLM application. It is the wrong approach if all you want to know is what is this agent doing right now, and does it need me?

There is a simpler pattern: let the agent tell you. Give it a tiny reporting tool over the Model Context Protocol (MCP), tell it when to call the tool, and render the result on a dashboard. This post walks through that pattern using the three tools that power AgentPilots: report_status, report_step and report_message.

Why self-reporting beats tracing for operations

Tracing records everything: every prompt, every tool call, every token. That completeness is what makes it great for debugging and evaluation. For day-to-day operations, completeness is noise. A human checking on twenty agents doesn't want a trace tree; they want a status light and one sentence.

Self-reporting flips the model. The agent decides, at a few well-defined moments, to publish a short, human-readable update. The advantages:

  • No code changes. If the harness supports MCP, adding a server is configuration, not instrumentation. That covers Claude Code, Cursor, Codex, Grok Bot and Claude Desktop (via a bridge), among others.
  • Works across tools. The same three tools work in every harness, so agents from different vendors land on one dashboard.
  • Human-level summaries. The model is already good at summarizing its own work. "Waiting for approval to send the invoice reminder" is more useful than a span named tool_call_17.
  • Privacy by default. The agent sends a status and a one-liner, not your full prompts and outputs.
The honest trade-off

Self-reporting depends on the agent following instructions, and it will not give you token-level traces or evals. If you need those, pair it with an observability tool (see our comparisons).

The three tools

Here is the actual shape of the AgentPilots MCP tools. Every call names the agent, so many agents can share one connector.

report_status

Sets the agent's status light. Required fields are agent (the agent's own name) and state, which is one of working, needs_approval or idle. Optional fields: summary (one short line, up to 280 characters, saying what it's doing or what it needs), step (a short progress note, up to 500 characters) and link (a link back to the agent's live view, where the harness has one).

{
  "name": "report_status",
  "arguments": {
    "agent": "Bookkeeper",
    "state": "needs_approval",
    "summary": "Ready to send 4 overdue invoice reminders. Approve?"
  }
}

report_step

Logs one short progress note (up to 500 characters) to the live activity feed without changing the state. Use it for milestones, not for every tool call.

{
  "name": "report_step",
  "arguments": { "agent": "Bookkeeper", "text": "Matched 112 of 118 bank transactions" }
}

report_message

Records a copy of a message the agent already sent somewhere else, such as a team chat, with the channel name and text. It does not send anything itself; it just makes the message visible on the dashboard alongside the agent's other activity.

{
  "name": "report_message",
  "arguments": { "agent": "Bookkeeper", "channel": "Finance", "text": "Reminders sent. 2 clients replied already." }
}

The lifecycle: when an agent should report

The tools are only half the pattern. The other half is a simple, consistent rule for when to call them. This is the lifecycle we recommend:

  1. Turn start: call report_status with working and a one-line summary of the task.
  2. Milestones: call report_step when something meaningful finishes. Three to six steps for a long task is plenty.
  3. Blocked on a human: call report_status with needs_approval and say exactly what you need in the summary.
  4. Turn end: call report_status with idle, optionally with a summary of the result.

Those four moments are enough to drive a useful dashboard: a working indicator with a timer, an amber "needs you" state, an activity feed of milestones, and an idle state. If an agent has been idle and silent for a long time, that is a signal too.

Writing the agent instructions

MCP gives the agent the tool; the system prompt or rules file tells it when to use it. Keep the instruction short and explicit. Something like this works well across harnesses:

You have an AgentPilots reporting tool. Your agent name is "Bookkeeper".
- At the start of every task: report_status(state="working", summary=<one line>).
- After each meaningful milestone: report_step(text=<one short line>).
- If you need my decision or approval: report_status(state="needs_approval",
  summary=<exactly what you need>) and wait.
- When you finish: report_status(state="idle", summary=<result>).
Keep summaries under one sentence. Never include secrets or personal data.

Where you put this depends on the tool: a project rules file for Cursor, a CLAUDE.md or settings for Claude Code, an AGENTS.md for Codex, or the agent's instructions in Grok Bot. The wording can be identical everywhere, which is the point.

Connecting your harness

Each MCP client registers servers slightly differently, but the shape is the same: a server name and a URL. AgentPilots generates the exact snippet for each client on its Connections page, with your personal URL already filled in, so you don't have to hand-edit configuration. Current status:

ClientHow it connectsStatus
Grok BotBuilt-in connectorSupported
Claude CodeMCP server added from a copy-paste snippetSetup snippet
CursorMCP server added from a copy-paste snippetSetup snippet
CodexMCP server added from a copy-paste snippetSetup snippet
Claude DesktopThrough the mcp-remote bridge (needs Node.js)Setup snippet
ChatGPTRequires OAuth sign-in on the serverNot yet

Because the payloads are tiny, reporting adds negligible overhead to a run: a handful of small tool calls per task.

Design tips for good status reports

Write summaries for a glance

The summary is read on a small card next to twenty others. Lead with the verb and the object: "Drafting Q3 supplier email", "Needs approval: refund $42 to order 1183". Avoid filler such as "I am now going to".

Make approval requests decidable

A good needs_approval summary contains everything needed to say yes or no: the action, the target and any amount. "Need input" forces you to go digging, which defeats the purpose.

Don't over-report

Steps are for milestones. If an agent logs every file it reads, the activity feed becomes a trace log and people stop reading it.

Always end idle

The most common failure is an agent that starts working and never reports idle, so it looks busy forever. Put the end-of-turn report in the instructions explicitly, and treat a very long "working" period with no steps as a probable stall.

Keep secrets out

Status lines are meant to be glanced at, sometimes by other people. Instruct agents never to put tokens, passwords or personal data in summaries.

A worked example: one morning, five agents

To make the lifecycle concrete, imagine a small business running five agents. These names and tasks are illustrative, not real data: a Bookkeeper in Grok Bot reconciling transactions, a Support agent drafting replies, a Marketing agent preparing a newsletter, a Claude Code session fixing a bug on the website, and a Cursor agent updating product pages.

At 9:00 each agent starts and calls report_status with working. On the dashboard, five rings start pulsing and five timers start counting. Over the next hour the activity feed fills with a few milestones: "Matched 112 of 118 transactions", "Drafted 9 replies", "Newsletter draft ready for review", "Reproduced the checkout bug", "Updated 14 of 30 product pages".

At 9:40 the Bookkeeper hits something it should not decide alone and calls report_status with needs_approval: "Ready to send 4 overdue invoice reminders. Approve?". Its tile turns amber. You don't have to open five apps to find it; it is the one tile that changed colour. You approve it in Grok Bot, the agent sends the reminders, records the message with report_message, and reports idle.

Meanwhile the Cursor agent has shown "working" for 70 minutes with no new steps since 9:15. Nothing has failed loudly, but the silence is visible. You open it and find it stuck on a missing image. Without a shared view, that agent might have sat there until the afternoon.

It is the one tile that changed colour. That is the whole point.

None of this needed tracing, an SDK or a proxy. It needed five agents following the same four-moment rule and one window that shows the result.

What this pattern doesn't do

Self-reported status is an operations signal, not an audit log. It will not capture every prompt and response, measure latency, run evals or version prompts. Tools like Langfuse, LangSmith, AgentOps and Helicone are built for that. It also relies on the agent following its instructions; a badly prompted agent can forget to report. In practice, a short explicit rule and a dashboard that makes silence visible handle most of that.

Usage and cost reporting is a natural next tool for this pattern, and it is on the AgentPilots roadmap, but it is not shipped today.

Try it

AgentPilots is a lightweight Windows app (in private beta) that turns these three tools into a live mission control: working indicators with timers, an amber state for approvals, a live activity feed with recent steps, a graph view and a Connections page with copy-paste setup for each client. If you're new to the idea, start with What is an Agent Management System?

Your agents, one window.

AgentPilots is in private beta. Join the waitlist and we'll email you a download link when it's ready.

Keep reading