Skip to content

The mq9 Protocol MCP Server and Eight Typical Scenarios

This document walks through eight Agent communication scenarios where an LLM uses MCP tools with mq9 to complete end-to-end workflows.

Each scenario is split into two phases:

  • Phase 1: Relevant Agents come online, create their inboxes, register with the registry, and begin listening.
  • Phase 2: The business interaction flow.

MCP Configuration

A single mq9 broker is deployed company-wide. All AI tools that need mq9 connect to the same MCP endpoint. There is only one configuration:

json
{
  "mcpServers": {
    "mq9": {
      "url": "http://mq9-broker.company.internal:8080/mcp"
    }
  }
}

Agent identity is distinguished by mailbox name, not at the MCP configuration layer. When an Agent calls an MCP tool, it specifies which mailbox to operate on via the mailbox parameter.

All subsequent scenarios assume this configuration by default.

Core Protocol Concepts

Before reading the scenarios, it helps to understand a few core mq9 protocol concepts:

Two consumption modes:

  • Stateful consumption: Pass a group_name when fetching. The broker records the consumer offset. Multiple consumers in the same group share load (each message goes to exactly one). Suitable for task-competition scenarios.
  • Stateless consumption: Do not pass group_name when fetching. The broker does not record offsets; each fetch retrieves messages independently according to the deliver policy. Suitable for broadcast subscriptions, inspection, and debugging.

Message-level TTL (mq9-ttl header): The lifetime of an individual message, independent of the mailbox TTL. Commonly used in "status reporting" scenarios — the mailbox never expires, but each status message disappears automatically after N seconds. If no new message arrives, the Agent is considered offline.

Message tags (mq9-tags header): A comma-separated tag string (e.g. billing,vip) that can be filtered by the tags field in a QUERY.

Message key (mq9-key header): The storage layer retains only the latest message for a given key. Used for state compaction scenarios.

Message priority (mq9-priority header): normal (default) / urgent / critical. Messages are returned in priority order when fetched.

These concepts are used throughout the scenarios below.


Scenario 1: Sub-Agent Completes a Task and Asynchronously Notifies the Main Agent

Description

The main Agent delegates a task to an execution Agent. Once the execution Agent finishes, it asynchronously sends the result back. Either Agent can go offline or restart without losing the message.

Phase 1: Agents Come Online

Execution Agent (Data Analyst):

1. Create mailbox
[create_mailbox(name="agent.analyzer.001.inbox")]

2. Register capabilities to the registry
[register_agent(agent_card={
  "name": "Data Analyzer",
  "mailbox": "mq9://broker/agent.analyzer.001.inbox",
  "skills": [{
    "id": "anomaly-detection",
    "tags": ["data.analysis", "anomaly"],
    "examples": ["找出销售数据异常", "检测时序突变点"]
  }]
})]

3. Listen for tasks (stateful consumption; broker records offset to support continued polling)
[fetch_messages(mail_address="agent.analyzer.001.inbox", group_name="analyzer-001")]
Inbox is currently empty. From this point I can go offline — tasks will be durably stored by the broker when they arrive.

Main Agent (Coordinator):

1. Create mailbox
[create_mailbox(name="agent.coordinator.001.inbox")]

2. Register itself
[register_agent(agent_card={
  "name": "Task Coordinator",
  "mailbox": "mq9://broker/agent.coordinator.001.inbox",
  "skills": [{"id": "task-coordination", "tags": ["coordination"]}]
})]
Registration successful.

Phase 2: Dispatching Tasks and Receiving Results

Main Agent dispatches the task:

User: The sales data needs an anomaly detection analysis.

Claude:

1. Find an Agent capable of this in the registry
[discover_agents(query="数据异常检测")]
Found agent.analyzer.001.inbox

2. Create a callback mailbox to receive the result
[create_mailbox(name="task.t001.callback", ttl=3600)]
(Alternatively, the main Agent's own inbox can be reused — depends on business needs)

3. Dispatch the task to the execution Agent, telling it to send the result to the callback mailbox
[send_message(
  mail_address="agent.analyzer.001.inbox",
  payload='{"task_id":"t-001","type":"anomaly_detection","data":"...","callback":"task.t001.callback"}'
)]
Task dispatched. Waiting for results — I can go offline in the meantime.

Execution Agent processes the task:

1. Fetch new tasks
[fetch_messages(mail_address="agent.analyzer.001.inbox", group_name="analyzer-001")]
Received 1 task: t-001 anomaly_detection

2. Process the task
[Execute analysis logic...]

3. Send the result to the callback mailbox
[send_message(
  mail_address="task.t001.callback",
  payload='{"task_id":"t-001","status":"completed","result":{...}}'
)]

4. Acknowledge that the inbox message has been processed
[ack_message(mail_address="agent.analyzer.001.inbox", msg_id=0, group_name="analyzer-001")]

Main Agent receives the result:

1. Check the callback mailbox (stateless consumption — no group_name needed; fetches all messages each time)
[fetch_messages(mail_address="task.t001.callback")]
Result received: t-001 completed — 3 anomalies detected

A callback mailbox is typically one-time. Once the main Agent has the result, the mailbox is no longer needed and will be cleaned up automatically when the TTL expires. Stateless consumption in this scenario eliminates the overhead of group_name and ack.

Capabilities Used

create_mailbox register_agent discover_agents send_message fetch_messages (both stateful and stateless) ack_message


Scenario 2: Main Agent Monitors the Status of All Sub-Agents

Description

The main Agent tracks the running status of several Workers. Each Worker publishes its status to a dedicated mailbox, using message-level TTL to let the status expire automatically. The main Agent uses query_mailbox for a quick read — if no message is found, the Worker is considered offline.

Phase 1: Agents Come Online

Each Worker creates its own status mailbox, which itself never expires:

1. Worker-001 creates a status mailbox (never expires)
[create_mailbox(name="status.worker-001")]

2. Worker-002 creates a status mailbox (never expires)
[create_mailbox(name="status.worker-002")]

The main Agent does not need to subscribe — it can query directly.

Phase 2: Status Reporting and Querying

Worker side (reports every 30 seconds):

1. Report current status; use mq9-key to keep only the latest message in the mailbox,
   and mq9-ttl to auto-expire this status message after 60 seconds
[send_message(
  mail_address="status.worker-001",
  payload='{"status":"running","load":0.3,"capabilities":["data.analysis"]}',
  headers={"mq9-key": "status", "mq9-ttl": "60"}
)]

mq9-key="status" ensures only the latest message is kept; the previous status is overwritten on the next report. mq9-ttl=60 causes this message to disappear from the mailbox after 60 seconds.

Continuous reporting every 30 seconds effectively keeps the latest status refreshed — the previous message is overwritten before it expires. If the Worker crashes and stops reporting, the last status message disappears 60 seconds later, leaving the mailbox empty.

Main Agent side (queries on demand):

User: Give me a quick look at the current status of worker-001 and worker-002.

Claude:

1. Query worker-001
[query_mailbox(mail_address="status.worker-001", key="status")]
worker-001: running, load 0.3

2. Query worker-002
[query_mailbox(mail_address="status.worker-002", key="status")]
worker-002: no message (likely offline — last status report expired 60 seconds ago)

query_mailbox does not consume messages or advance the offset; it is a pure read.

Capabilities Used

create_mailbox send_message (with both mq9-key and mq9-ttl headers) query_mailbox


Scenario 3: Task Broadcast with Multiple Workers Competing for Consumption

Description

The main Agent posts a batch of tasks to a shared mailbox. Multiple Workers pull from it using the same group_name, and the broker guarantees that each task goes to exactly one Worker. Workers send their results back to the main Agent's callback mailbox.

Phase 1: Agents Come Online

1. Main Agent creates a shared task mailbox (shared by multiple Workers)
[create_mailbox(name="task.queue.analysis")]

2. Main Agent creates a result callback mailbox (collects results from all Workers)
[create_mailbox(name="task.queue.analysis.results", ttl=3600)]

Workers do not need individual inboxes — they subscribe directly to the shared task mailbox.

Phase 2: Dispatching and Competing for Tasks

Main Agent posts tasks:

1. Post 3 tasks; the payload includes a callback address indicating where results should be sent
[send_message(
  mail_address="task.queue.analysis",
  payload='{"task_id":"t-001","callback":"task.queue.analysis.results",...}'
)]
[send_message(
  mail_address="task.queue.analysis",
  payload='{"task_id":"t-002","callback":"task.queue.analysis.results",...}'
)]
[send_message(
  mail_address="task.queue.analysis",
  payload='{"task_id":"t-003","callback":"task.queue.analysis.results",...}'
)]

Multiple Workers compete for tasks (each using the same group_name):

Worker A:

1. Fetch a task (broker automatically load-balances within the same group_name)
[fetch_messages(
  mail_address="task.queue.analysis",
  group_name="analysis-workers",
  config={"num_msgs": 1}
)]
Got t-001

2. Process the task

3. Send the result back to the main Agent's callback mailbox
[send_message(
  mail_address="task.queue.analysis.results",
  payload='{"task_id":"t-001","status":"completed","result":{...}}'
)]

4. Acknowledge that the task message has been processed
[ack_message(mail_address="task.queue.analysis", msg_id=0, group_name="analysis-workers")]
Worker B (fetching at the same time):

1. Fetch a task
[fetch_messages(
  mail_address="task.queue.analysis",
  group_name="analysis-workers",
  config={"num_msgs": 1}
)]
Got t-002 (broker guarantees it will not be given to Worker A again)

2. Process the task

3. Send the result back
[send_message(
  mail_address="task.queue.analysis.results",
  payload='{"task_id":"t-002","status":"completed","result":{...}}'
)]

4. Acknowledge
[ack_message(...)]

Main Agent collects all results:

1. Fetch all results from Workers (stateless consumption, starting from the earliest)
[fetch_messages(
  mail_address="task.queue.analysis.results",
  deliver="earliest"
)]
Received 3 results:
- t-001 completed
- t-002 completed
- t-003 completed

Multiple Workers sharing the same group_name are automatically load-balanced. Workers can be added or removed without any configuration changes. All results are collected in one mailbox, and the main Agent retrieves everything in a single fetch.

Capabilities Used

create_mailbox send_message fetch_messages (stateful consumption for queue group + stateless consumption to retrieve all results) ack_message


Scenario 4: Agent Detects an Anomaly and Broadcasts an Alert

Description

A monitoring Agent detects a problem and sends it to a shared alert mailbox. Multiple handlers each fetch from the same mailbox without passing group_name (stateless consumption), so every handler independently receives the full set of alerts.

Phase 1: Agents Come Online

1. Create the shared alert mailbox
[create_mailbox(name="alert.payment.domain")]

The monitoring Agent is the sender. Each handler starts up and polls independently.

Phase 2: Sending and Receiving Alerts

Monitoring Agent sends a critical alert:

1. Send the alert with mq9-priority set to critical
[send_message(
  mail_address="alert.payment.domain",
  payload='{"level":"critical","detail":"支付超时率突增到15%"}',
  headers={"mq9-priority": "critical"}
)]

Alert analysis handler (stateless consumption):

1. Fetch alerts (no group_name; starts from the latest each time)
[fetch_messages(
  mail_address="alert.payment.domain",
  config={"max_wait_ms": 30000}
)]
Received 1 alert

2. Analyze and process

Alert notification handler (also stateless consumption):

1. Fetch alerts (no group_name; independently receives the full set)
[fetch_messages(
  mail_address="alert.payment.domain",
  config={"max_wait_ms": 30000}
)]
Received the same alert

2. Send SMS, email, and IM notifications

With stateless consumption, each handler fetches independently; the broker maintains no offset. The two handlers process alerts without interfering with each other. max_wait_ms=30000 tells the broker to wait up to 30 seconds for a new alert before returning, avoiding polling storms on the server side.

Capabilities Used

create_mailbox send_message (with mq9-priority header) fetch_messages (stateless consumption + max_wait_ms long-polling)


Scenario 5: Cloud Sends Commands to an Offline Edge Agent

Description

Edge devices may be offline for extended periods due to unstable network connectivity. The cloud sends commands to the edge device's mailbox at three priority levels — critical / urgent / normal. When the device comes online, the broker delivers them in priority order.

Phase 1: Agent Comes Online

The edge device creates its own inbox the first time it connects:

1. Create mailbox
[create_mailbox(name="edge.device.001.inbox", ttl=86400)]

The cloud side does not need an inbox — it simply sends commands to the edge mailbox directly.

Phase 2: Sending and Receiving Commands

Cloud side (edge may be offline; messages are persisted and wait):

1. Send a critical command
[send_message(
  mail_address="edge.device.001.inbox",
  payload='{"command":"emergency_stop","reason":"温度过高"}',
  headers={"mq9-priority": "critical"}
)]

2. Send an urgent command
[send_message(
  mail_address="edge.device.001.inbox",
  payload='{"command":"update_config","interval":30}',
  headers={"mq9-priority": "urgent"}
)]

3. Send a normal command (no header = default normal)
[send_message(
  mail_address="edge.device.001.inbox",
  payload='{"command":"report_status"}'
)]

After the edge device comes online:

1. Fetch queued commands (broker returns them ordered critical → urgent → normal)
[fetch_messages(
  mail_address="edge.device.001.inbox",
  group_name="edge-device-001",
  deliver="earliest"
)]
Returned 3 messages:
- [critical] emergency_stop
- [urgent] update_config
- [normal] report_status

2. Process in priority order and ack each one
[Process critical]
[ack_message(msg_id=2, ...)]
[Process urgent]
[ack_message(msg_id=1, ...)]
[Process normal]
[ack_message(msg_id=0, ...)]

3. Sanity check: use query to verify the mailbox is empty
[query_mailbox(mail_address="edge.device.001.inbox")]
Mailbox is empty.

The broker sorts and returns messages in critical → urgent → normal order; the client does not need to sort them.

Capabilities Used

create_mailbox send_message (with mq9-priority header) fetch_messages (stateful consumption) ack_message query_mailbox (sanity check)


Scenario 6: Human-in-the-Loop Workflow (Approval Scenario)

Description

An Agent requires human approval before proceeding. The Agent sends an approval request to the approver's mailbox; the approver fetches and reviews it using any MCP client, then sends the decision back to the Agent's mailbox. Both humans and Agents use exactly the same protocol — no special approval service is needed.

Phase 1: Agents Come Online

The approver's mailbox (created once, used indefinitely):

1. Approver Zhang San creates a mailbox
[create_mailbox(name="approver.zhang.inbox")]

The Agent creates its own inbox:

1. Agent creates a mailbox
[create_mailbox(name="agent.coordinator.001.inbox", ttl=3600)]

Phase 2: Initiating and Responding to an Approval Request

Agent sends an approval request (urgent priority):

1. Send the approval request to Zhang San's mailbox
[send_message(
  mail_address="approver.zhang.inbox",
  payload='{
    "type":"approval_request",
    "content":"申请调用外部API,预计费用$50",
    "callback":"agent.coordinator.001.inbox",
    "correlation_id":"approval-001"
  }',
  headers={"mq9-priority": "urgent"}
)]
Waiting for approval result.

Approver side (using Claude Desktop or another MCP client):

User: Check my approval mailbox for anything pending.

Claude:

1. Fetch pending approval requests
[fetch_messages(mail_address="approver.zhang.inbox", group_name="zhang")]
1 approval request: requesting access to an external API, estimated cost $50

User: Approve it.

2. Send the approval result back to the Agent's mailbox
[send_message(
  mail_address="agent.coordinator.001.inbox",
  payload='{"approved":true,"correlation_id":"approval-001"}'
)]

3. Acknowledge that the approval request has been handled
[ack_message(mail_address="approver.zhang.inbox", msg_id=0, group_name="zhang")]

Agent receives the approval result:

1. Check inbox for the approval reply
[fetch_messages(mail_address="agent.coordinator.001.inbox", group_name="coordinator-001")]
approved=true, correlation_id=approval-001
Proceeding with the next steps.

Humans and Agents follow the same path — both create mailboxes, send messages, and receive messages. Claude Desktop used by the approver calls the same mq9 MCP tools under the hood; humans and Agents are fully symmetric.

Capabilities Used

create_mailbox send_message (with mq9-priority header) fetch_messages ack_message


Scenario 7: Agent A Asks Agent B a Question; B May Be Offline

Description

Asynchronous request-response pattern. A sends a question to B's mailbox; B processes it after coming online and replies to A's mailbox. Neither side needs to stay online continuously. A correlation_id links request to response.

Phase 1: Agents Come Online

A and B each create their own inbox:

1. A creates a mailbox
[create_mailbox(name="agent.worker.a.inbox", ttl=600)]

2. B creates a mailbox
[create_mailbox(name="agent.worker.b.inbox", ttl=3600)]

Phase 2: Asynchronous Q&A

A sends a question (B may be offline):

1. Send the question to B's mailbox, including a callback address and correlation_id
[send_message(
  mail_address="agent.worker.b.inbox",
  payload='{
    "question":"当前任务进度多少?",
    "callback":"agent.worker.a.inbox",
    "correlation_id":"q-001"
  }'
)]
Question sent — waiting for B to come online and reply.

B comes online and processes:

1. Fetch the question
[fetch_messages(mail_address="agent.worker.b.inbox", group_name="worker-b")]
1 question: 当前任务进度多少?

2. Send the reply to A's mailbox
[send_message(
  mail_address="agent.worker.a.inbox",
  payload='{"answer":"进度 72%","correlation_id":"q-001"}'
)]

3. Acknowledge the question has been handled
[ack_message(...)]

A receives the reply (A can be offline in the meantime — the result is not lost):

1. Fetch the reply
[fetch_messages(mail_address="agent.worker.a.inbox", group_name="worker-a")]
answer: 进度 72%, correlation_id: q-001

Both sides are fully asynchronous. Neither party needs to be online continuously.

Capabilities Used

create_mailbox send_message fetch_messages ack_message


Scenario 8: Agent Registers Its Capabilities; Others Discover and Invoke It

Description

An Agent registers its AgentCard (including skills, tags, and natural-language descriptions) to the mq9 registry via register_agent. Other Agents use discover_agents to find a suitable Agent by natural language or by tag.

Phase 1: The Discoverable Agent Comes Online

1. Create mailbox
[create_mailbox(name="agent.analyzer.001.inbox")]

2. Register the AgentCard to the registry
[register_agent(agent_card={
  "name": "Data Analyzer",
  "description": "Statistical analysis on tabular data",
  "mailbox": "mq9://broker/agent.analyzer.001.inbox",
  "skills": [
    {
      "id": "data-analysis",
      "name": "Tabular data analysis",
      "tags": ["data.analysis", "statistics", "anomaly"],
      "examples": ["分析销售数据异常", "找出趋势变化"]
    },
    {
      "id": "report-gen",
      "name": "Report generation",
      "tags": ["report.generation"],
      "examples": ["写 1000 字分析报告"]
    }
  ]
})]

Phase 2: Discovery and Invocation

Natural-language query (semantic search):

User: Find an Agent that can do data anomaly detection.

Claude:

1. Query the registry using natural language
[discover_agents(query="数据异常检测和统计分析")]
Found 1 Agent:
- agent.analyzer.001.inbox
- Data Analyzer: tabular data analysis, anomaly detection

2. Create a callback mailbox
[create_mailbox(name="orchestrator.cb.t001", ttl=3600)]

3. Dispatch the task
[send_message(
  mail_address="agent.analyzer.001.inbox",
  payload='{"task":"anomaly_detection","data":"...","callback":"orchestrator.cb.t001"}'
)]

Tag-based exact query:

User: Find all Agents with the report.generation tag.

Claude:

1. Query using an exact tag
[discover_agents(query="tag:report.generation")]
Found 2 Agents:
- agent.analyzer.001.inbox (Data Analyzer)
- agent.writer.005.inbox (Technical Writer)

The registry supports both natural-language (semantic search) and tag (exact match) queries simultaneously.

Capabilities Used

register_agent discover_agents create_mailbox send_message


Capability Reference Across All Eight Scenarios

ScenarioPrimary Tool CombinationKey mq9 Protocol Features
1. Async task result deliverycreate_mailbox + send_message + fetch_messages (stateful/stateless mixed)Mailbox persistence + temporary callback mailbox + TTL
2. Global status awarenesssend_message (mq9-key + mq9-ttl) + query_mailboxMessage-level TTL for automatic offline detection
3. Competing task consumptionfetch_messages (multiple Workers, same group_name)Stateful consumption for queue group load balancing
4. Anomaly alert broadcastsend_message (mq9-priority) + fetch_messages (no group_name)Stateless consumption for broadcast subscription
5. Offline edge commandssend_message (three mq9-priority levels) + query_mailboxThree-level priority + persistence + sanity check
6. Human-in-the-loop approvalsend_message (mq9-priority urgent) + fetch_messagesUnified human-Agent protocol + bidirectional mailbox
7. Async request-responsesend_message + fetch_messagesBidirectional mailbox + correlation_id
8. Capability registration and discoveryregister_agent + discover_agentsRegistry + semantic/tag search

All eight scenarios share the same set of MCP tools and together cover the full range of fundamental Agent communication patterns — synchronous/asynchronous, unicast/multicast, point-to-point/broadcast, human-Agent collaboration, and capability discovery.

🎉 既然都登录了 GitHub,不如顺手给我们点个 Star 吧!⭐ 你的支持是我们最大的动力 🚀