cleat.

For AI agents

A phone number your agent can actually read

An agent that signs up for things hits the same wall a person does: a six-digit code sent by text. Cleat gives it a real US mobile line and an MCP server to read that line, so the code goes straight into the agent's context instead of into someone's phone.

Point your client at it

The server speaks the Model Context Protocol over HTTP. Add it to any MCP client that can send an Authorization header. Create the key in your workspace settings, where it's shown once.

mcp.json
{
  "mcpServers": {
    "cleat": {
      "type": "http",
      "url": "https://cleat.so/api/mcp",
      "headers": { "Authorization": "Bearer clt_your_api_key" }
    }
  }
}

The key decides what the agent can reach: its own workspace's lines and nothing else. Revoke it and the agent is locked out on the next call, with no effect on anyone's password or session.

The four tools

ToolWhat it does
list_linesThe workspace's numbers, newest first. Start here: every other tool takes a lineId from it.
list_messagesTexts received by one line, newest first. Up to 200.
latest_codeThe most recent verification code on a line, or found: false if none has arrived.
wait_for_codeWaits for the *next* code and returns it. Up to 55 seconds; 30 by default.
Anything the key can't reach comes back as a readable tool error, not a crash, so the model can act on it.

Waiting beats polling

wait_for_code only counts texts that arrive after the call starts, so a code left over from an earlier sign-in is never mistaken for this one. Call it immediately before the step that triggers the text, then submit the form: the tool is already listening.

Wait for the next code
curl https://cleat.so/api/mcp \
  -H "Authorization: Bearer $CLEAT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/call",
    "params": {
      "name": "wait_for_code",
      "arguments": { "lineId": "8f14e45f-ceea-4b6b-9d3c-2a1f0e7c5b10", "timeoutSeconds": 45 }
    }
  }'
The answer
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "structuredContent": {
      "found": true,
      "from": "55512",
      "body": "Your verification code is 704 118",
      "code": "704118",
      "receivedAt": "2026-09-11T10:02:41.000Z"
    }
  }
}

If nothing arrives in time it returns found: false with timedOut: true — an ordinary result the agent can retry, not an error.

What this is, and what it isn't

  • Receive only. Cleat Line receives texts. It cannot send them, and there is no tool that tries. It cannot place or answer a call either.
  • A code phoned in still lands. When a service reads a code out over an automated call, the call is transcribed and the transcript arrives as an ordinary message, code extracted, with the number that called in from. No field marks it as a call, so an agent treats it like any other text.
  • One number per subscription. Each line is $24.99 a month. Cleat isn't a pool of throwaway numbers, and there's no endpoint that rotates them.
  • A verified human owns every line. Identity is checked once, for the account, before any number is issued — an agent can't sign itself up.
  • 120 requests a minute per key. A wait_for_code that's waiting isn't spending requests.
  • A line on hold can't be read. If a subscription lapses, the number is held and its texts stay locked until it resumes.

If you'd rather not use MCP

The same data is a plain REST API with signed webhooks, which suits a long-running service better than an agent session: see Cleat for developers. Sharing codes with people instead of programs is the team inbox. On why a real mobile line receives codes that an internet number never gets, see non-VoIP numbers and Google Voice and verification codes.

Questions

Which clients work?

Any MCP client that can reach an HTTP server and set an Authorization header. The server answers JSON-RPC over POST and returns ordinary JSON — there's no SSE to configure, because every tool returns a single result.

Can the agent send a text?

No. Cleat Line is receive-only, and no tool sends.

What if the service phones the code instead of texting it?

It still arrives. The call is transcribed and the transcript is stored like a text, so latest_code and wait_for_code return the code from it, and list_messages shows it with the calling number in from. Nothing distinguishes it from a text, and the agent can't answer or return the call.

Can I give each agent its own number?

Yes — add a line per agent in the same workspace, each its own $24.99 subscription, and give each agent a key. Every key sees every line in its workspace, so use separate workspaces if agents must not see each other's texts.

What happens if two agents wait on the same line?

Both are told about the next code. The line is a shared inbox, not a queue, so give agents that must not collide their own lines.

Does an agent need to verify its identity?

The account does, once, and a person does it. Agents work under a verified account's key; they never sign up on their own.

Is there a free tier?

No. One line is $24.99 a month, cancel anytime.

Get a line your agent can read.

$24.99/month · cancel anytime