Skip to content

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 URIDescription
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}/threadLast N messages (sanitized), timestamps, who said what
freight://lanes/{originZip}-{destZip}/market_snapshotCached 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:

json
{
  "type": "object",
  "properties": {
    "quoteId": { "type": "string" }
  },
  "required": ["quoteId"]
}

Example output:

json
{
  "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:

json
{
  "type": "object",
  "properties": {
    "quoteId": { "type": "string" },
    "channel": { "type": "string", "enum": ["email", "sms"] },
    "tone": { "type": "string", "enum": ["neutral", "friendly", "direct"] }
  },
  "required": ["quoteId", "channel"]
}

Example output:

json
{
  "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:

json
{
  "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:

json
{
  "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:

json
{
  "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

json
{
  "jsonrpc": "2.0",
  "id": 12,
  "method": "tools/call",
  "params": {
    "name": "quote_get_status",
    "arguments": {
      "quoteId": "Q-104883"
    }
  }
}

Response: tool result

json
{
  "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:

  1. Pull queue of pending quotes (resource or tool)
  2. 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
  3. Generate draft:
    • quote_generate_followup_draft
  4. Optional: require approval (best practice early on)
    • Host shows draft to a human
  5. Send + log:
    • quote_send_followup
    • crm_log_activity
  6. Schedule next follow-up if needed

TIP

This gives you predictable actions, an audit trail, and the ability to tighten safety over time.

Mentium TMS API Documentation