Example: Freight Quote Follow-Up Agent
This section walks through a concrete MCP server design for a freight quote follow-up agent. It shows how resources and tools map to real logistics operations, and how an AI Agent in Mentium would use them.
What the Agent Does
A freight quote follow-up agent typically needs to:
- Look up quote requests and statuses
- Check whether a customer responded
- Send follow-up emails or SMS
- Log activity in CRM/TMS
- Escalate to a human when:
- high value
- ambiguity
- customer asks for special handling
- the model is uncertain
MCP is a good fit because these actions map cleanly to tools, and the data maps cleanly to resources.
Resources (Read-Only Context)
These help the model write relevant follow-ups without calling side-effect tools.
| Resource URI | Description |
|---|---|
freight://customers/{customerId} | Name, company, lanes, preferences, timezone, compliance notes |
freight://quotes/{quoteId} | Equipment type, pickup/delivery windows, commodity class, accessorials, last offered rate, validity |
freight://quotes/{quoteId}/thread | Last N messages (sanitized), timestamps, who said what |
freight://lanes/{originZip}-{destZip}/market_snapshot | Cached market rate bands, capacity notes |
Tools (Actions)
Below is a realistic starting set of tools for this domain.
Tool 1: quote_get_status
Purpose: Fetch current quote status and last activity.
Input schema:
{
"type": "object",
"properties": {
"quoteId": { "type": "string" }
},
"required": ["quoteId"]
}Example output:
{
"quoteId": "Q-104883",
"status": "SENT",
"lastSentAt": "2026-03-04T14:22:00-06:00",
"opened": true,
"customerReplied": false,
"priority": "NORMAL"
}Tool 2: quote_generate_followup_draft
Purpose: Generate a follow-up message body without sending it.
This is safer than a "send" tool because you can add a human approval step.
Input schema:
{
"type": "object",
"properties": {
"quoteId": { "type": "string" },
"channel": { "type": "string", "enum": ["email", "sms"] },
"tone": { "type": "string", "enum": ["neutral", "friendly", "direct"] }
},
"required": ["quoteId", "channel"]
}Example output:
{
"subject": "Quick follow-up on your Chicago to Dallas shipment",
"body": "Hi Matt - checking in on quote Q-104883 for the 53' dry van move. Do you want us to hold the pickup window for Thursday, or should we adjust dates/rate options?"
}Tool 3: quote_send_followup
Purpose: Actually send the follow-up via your email/SMS provider.
Safety constraints:
- Require an
idempotencyKey - Validate recipients
- Enforce scope:
quotes:followup:send
Input schema:
{
"type": "object",
"properties": {
"quoteId": { "type": "string" },
"channel": { "type": "string", "enum": ["email", "sms"] },
"to": { "type": "string" },
"subject": { "type": "string" },
"body": { "type": "string" },
"idempotencyKey": { "type": "string" }
},
"required": ["quoteId", "channel", "to", "body", "idempotencyKey"]
}Example output:
{
"messageId": "msg_9f3b2",
"sentAt": "2026-03-04T15:10:00-06:00",
"provider": "sendgrid",
"status": "SENT"
}Tool 4: crm_log_activity
Purpose: Record the follow-up in CRM so humans see it.
Input schema:
{
"type": "object",
"properties": {
"customerId": { "type": "string" },
"quoteId": { "type": "string" },
"activityType": {
"type": "string",
"enum": ["EMAIL_SENT", "SMS_SENT", "CALL_REQUESTED", "NOTE"]
},
"summary": { "type": "string" }
},
"required": ["customerId", "activityType", "summary"]
}Tool 5: rep_escalate
Purpose: Hand off to a human with a structured summary (Slack, ticket, etc.).
Trigger conditions:
- Quote value over threshold
- Customer replied with negotiation
- Customer asks about hazmat / temperature / special permits
- Model confidence is low
Example MCP Message Flow
Below is what the host sends over Streamable HTTP when calling a tool.
Request: call quote_get_status
{
"jsonrpc": "2.0",
"id": 12,
"method": "tools/call",
"params": {
"name": "quote_get_status",
"arguments": {
"quoteId": "Q-104883"
}
}
}Response: tool result
{
"jsonrpc": "2.0",
"id": 12,
"result": {
"content": [
{
"type": "text",
"text": "{\"quoteId\":\"Q-104883\",\"status\":\"SENT\",\"opened\":true,\"customerReplied\":false}"
}
]
}
}Practical Workflow
A production-minded "quote follow-up" loop:
- Pull queue of pending quotes (resource or tool)
- For each quote:
quote_get_status- If customer replied -> stop, log, possibly escalate
- If opened but no reply in X hours -> follow-up
- If not opened -> shorter nudge, or try alternate channel
- Generate draft:
quote_generate_followup_draft
- Optional: require approval (best practice early on)
- Host shows draft to a human
- Send + log:
quote_send_followupcrm_log_activity
- Schedule next follow-up if needed
TIP
This gives you predictable actions, an audit trail, and the ability to tighten safety over time.