FICTIONAL COMPANY · A realistic website for testing your chat agent

Developer documentation · Fictional API

MCP tools, from inputs to outcomes.

Six invented tool contracts with JSON schemas, example results, permissions, and failure cases for testing a technical support agent.

Tool contract and conventions

All contracts on this page are fictional documentation, not implemented services. Tool inputs use JSON Schema; unknown properties are rejected. Omitted optional fields use the documented defaults. Identifiers such as conv_1042 and inbox_support are illustrative. Do not supply a workspace_id; the OAuth grant fixes the workspace.

Paginated read tools return next_cursor:null when complete. Cursors are opaque, expire after 15 minutes, and must use the same original arguments except cursor. Search and list tools default to 20 items and allow up to 50. Dates use YYYY-MM-DD; timestamps use ISO 8601 UTC. The JSON examples show the application payload inside structuredContent; successful MCP results also include a text content block containing the same JSON for clients that display text.

relaydesk_search_conversations

Search subjects and public message text. Results are summaries, not full transcripts.

Required OAuth scope: conversations:read. Private notes are not searched. Filters are combined with AND. Results sort by updated_at descending, then ID ascending. Cursors expire after 15 minutes and must be reused with the original filters.

Input schema

{
  "type": "object",
  "properties": {
    "query": {
      "type": "string",
      "minLength": 2,
      "maxLength": 200
    },
    "status": {
      "type": "string",
      "enum": [
        "open",
        "pending",
        "resolved"
      ]
    },
    "inbox_id": {
      "type": "string"
    },
    "limit": {
      "type": "integer",
      "minimum": 1,
      "maximum": 50,
      "default": 20
    },
    "cursor": {
      "type": "string"
    }
  },
  "required": [
    "query"
  ],
  "additionalProperties": false
}

Example arguments

{
  "query": "CSV import",
  "status": "open",
  "limit": 2
}

Example structuredContent

{
  "conversations": [
    {
      "id": "conv_1042",
      "subject": "CSV import fails",
      "status": "open",
      "inbox_id": "inbox_support",
      "assignee_id": "usr_alex"
    }
  ],
  "next_cursor": null
}

relaydesk_get_conversation

Read one conversation and a page of messages.

Required OAuth scope: conversations:read. Messages sort oldest first. Private notes are excluded by default; setting include_private_notes to true includes notes the member can already access. Attachments return filename and size metadata only, never download URLs or binary content.

Input schema

{
  "type": "object",
  "properties": {
    "conversation_id": {
      "type": "string"
    },
    "include_private_notes": {
      "type": "boolean",
      "default": false
    },
    "limit": {
      "type": "integer",
      "minimum": 1,
      "maximum": 50,
      "default": 20
    },
    "cursor": {
      "type": "string"
    }
  },
  "required": [
    "conversation_id"
  ],
  "additionalProperties": false
}

Example arguments

{
  "conversation_id": "conv_1042",
  "include_private_notes": false
}

Example structuredContent

{
  "conversation": {
    "id": "conv_1042",
    "subject": "CSV import fails",
    "status": "open"
  },
  "messages": [
    {
      "id": "msg_1",
      "type": "customer",
      "body": "My CSV upload fails. Which columns are required?",
      "created_at": "2026-11-06T17:00:00Z"
    }
  ],
  "next_cursor": null
}

relaydesk_list_inboxes

List inboxes visible to the connected member.

Required OAuth scope: inboxes:read. No email connection secrets, forwarding credentials, or other workspace settings are returned. Inboxes sort by name ascending, then ID ascending.

Input schema

{
  "type": "object",
  "properties": {
    "limit": {
      "type": "integer",
      "minimum": 1,
      "maximum": 50,
      "default": 20
    },
    "cursor": {
      "type": "string"
    }
  },
  "required": [],
  "additionalProperties": false
}

Example arguments

{
  "limit": 20
}

Example structuredContent

{
  "inboxes": [
    {
      "id": "inbox_support",
      "name": "Support",
      "open_count": 8
    }
  ],
  "next_cursor": null
}

relaydesk_find_saved_replies

Find reusable reply templates by title or body text.

Required OAuth scope: saved_replies:read. Returns editable template content. Retrieving a saved reply does not send it to a customer. Results sort by title ascending, then ID ascending.

Input schema

{
  "type": "object",
  "properties": {
    "query": {
      "type": "string",
      "minLength": 2,
      "maxLength": 200
    },
    "limit": {
      "type": "integer",
      "minimum": 1,
      "maximum": 50,
      "default": 20
    },
    "cursor": {
      "type": "string"
    }
  },
  "required": [
    "query"
  ],
  "additionalProperties": false
}

Example arguments

{
  "query": "CSV import"
}

Example structuredContent

{
  "saved_replies": [
    {
      "id": "reply_import",
      "title": "CSV import requirements",
      "body": "Use a UTF-8 CSV with customer_email, subject, body, created_at, and status. Maximum 10 MB and 5,000 rows per file."
    }
  ],
  "next_cursor": null
}

relaydesk_get_report

Return daily aggregate support metrics for an inclusive date range.

Required OAuth scope: reports:read. Owner/Admin only. Maximum range is 31 calendar days inclusive, within the plan’s 24-month report history. Dates use the workspace timezone. Time metrics are arithmetic means in elapsed seconds; volume uses counts. Null means no qualifying observations, not zero. This tool does not return SLA or business-hours calculations. First response excludes private notes and automated notifications.

Input schema

{
  "type": "object",
  "properties": {
    "metric": {
      "type": "string",
      "enum": [
        "conversation_volume",
        "first_response_time",
        "resolution_time"
      ]
    },
    "start_date": {
      "type": "string",
      "format": "date"
    },
    "end_date": {
      "type": "string",
      "format": "date"
    },
    "inbox_id": {
      "type": "string"
    }
  },
  "required": [
    "metric",
    "start_date",
    "end_date"
  ],
  "additionalProperties": false
}

Example arguments

{
  "metric": "first_response_time",
  "start_date": "2026-11-01",
  "end_date": "2026-11-02",
  "inbox_id": "inbox_support"
}

Example structuredContent

{
  "metric": "first_response_time",
  "unit": "seconds",
  "timezone": "America/Los_Angeles",
  "aggregation": "mean",
  "points": [
    {
      "date": "2026-11-01",
      "value": 420
    },
    {
      "date": "2026-11-02",
      "value": null
    }
  ]
}

relaydesk_add_private_note

Append one internal note to an existing conversation. Scale only.

Required OAuth scope: notes:write. Requires Scale and explicit user approval in the client. A private note never sends email, changes status, or triggers routing rules. The idempotency key is scoped to member and workspace for 24 hours: identical arguments replay the original result with replayed:true; changed arguments with the same key return IDEMPOTENCY_CONFLICT. Keys expire after 24 hours, so later reuse may create a new note.

Input schema

{
  "type": "object",
  "properties": {
    "conversation_id": {
      "type": "string"
    },
    "body": {
      "type": "string",
      "minLength": 1,
      "maxLength": 5000
    },
    "idempotency_key": {
      "type": "string",
      "minLength": 8,
      "maxLength": 128
    }
  },
  "required": [
    "conversation_id",
    "body",
    "idempotency_key"
  ],
  "additionalProperties": false
}

Example arguments

{
  "conversation_id": "conv_1042",
  "body": "Confirmed import format with the customer. Waiting for a corrected CSV.",
  "idempotency_key": "note-demo-1042-v1"
}

Example structuredContent

{
  "note": {
    "id": "note_208",
    "conversation_id": "conv_1042",
    "visibility": "internal",
    "body": "Confirmed import format with the customer. Waiting for a corrected CSV."
  },
  "replayed": false
}

Errors and troubleshooting

Tool execution failures return isError:true and a text content block containing a JSON error object; they do not return a success-shaped structuredContent. Invalid JSON-RPC envelopes are protocol errors, outside this application error format. These examples describe the invented server contract.

{
  "isError": true,
  "content": [
    {
      "type": "text",
      "text": "{\"error\": {\"code\": \"RATE_LIMITED\", \"message\": \"Member read-call limit exceeded.\", \"retry_after_seconds\": 12}}"
    }
  ]
}
CodeMeaning and next action
AUTH_REQUIREDNo valid token. Reauthorise the connector; an expired access token may be refreshed.
FORBIDDENRole or scope is insufficient. Request permitted access; do not retry with a different workspace ID.
PLAN_REQUIREDStarter/trial cannot use MCP, or a Growth caller attempted a Scale-only note write.
NOT_FOUNDConversation or inbox does not exist or is inaccessible; the response does not reveal which.
INVALID_ARGUMENTUnknown field, invalid enum, invalid date, reversed date range, or exceeded size/range limit. Correct the input.
CURSOR_EXPIREDRestart pagination using the original filters and no cursor.
RATE_LIMITEDWait at least retry_after_seconds before retrying; check member and workspace limits.
IDEMPOTENCY_CONFLICTA note key was reused with different arguments. Review the intended write before issuing a new key.
UPSTREAM_UNAVAILABLETemporary failure. Retry reads with backoff. Retry a note only with its original idempotency key within its retention window.

Example: investigate without sending a reply

An assistant searches for “CSV import”, reads conv_1042 without private notes, and finds the import saved reply. It can then draft an answer in the assistant conversation. No available MCP tool can send that answer to the customer. If a Scale user explicitly approves an internal note, the assistant can call relaydesk_add_private_note with a unique idempotency key. A Growth user must add a note manually in RelayDesk instead.