# Send SMS from the Vercel AI SDK

Source: https://jointextkit.com/integrations/vercel-ai-sdk
Index: https://jointextkit.com/llms.txt

Give an AI SDK agent TextKit's tools so it can send texts, check delivery and
manage contacts, with two packages and one transport block.

## 1. Get a test key

Create a test key on the [API keys](/console) page of the console. It starts
`ssms_sk_test_`, runs everything in the [sandbox](/docs/sandbox), and texts no
real phone except your own verified one. Put it in your environment as
`TEXTKIT_API_KEY`:

```bash
export TEXTKIT_API_KEY=ssms_sk_test_...
```

## 2. Connect the MCP server

The AI SDK's MCP client lives in `@ai-sdk/mcp`. Point its HTTP transport at
`https://mcp.jointextkit.com` and send your key as a header:

```bash
npm install ai @ai-sdk/mcp
```

```typescript
import { createMCPClient } from '@ai-sdk/mcp';
import { generateText, isStepCount } from 'ai';

const textkit = await createMCPClient({
  transport: {
    type: 'http',
    url: 'https://mcp.jointextkit.com',
    headers: { Authorization: `Bearer ${process.env.TEXTKIT_API_KEY}` },
  },
});

try {
  // tools() returns every TextKit tool, keyed by name. Keep the ones you need.
  const { send_message, get_message } = await textkit.tools();

  const { text } = await generateText({
    model: 'anthropic/claude-haiku-5.5',
    tools: { send_message, get_message },
    stopWhen: isStepCount(5),
    prompt: 'Text +15005550006 "Your order shipped."',
  });
  console.log(text);
} finally {
  await textkit.close();
}
```

Use any model the AI SDK supports. Passing all tools works too
(`tools: await textkit.tools()`), but a short list keeps each request small
and the agent focused. The server exposes 142 tools: messages, verification, numbers, contacts,
segments, broadcasts, automations and account reads. Each one is a single API
call with your key, so the key's scopes, rate limits and send checks apply
unchanged. The full list is on the [MCP server](/docs/mcp) page.

## 3. Check the sandbox run

`+15005550006` is a sandbox number that always ends `delivered`, so the
agent's tool call returns a message with an id starting `msg_` and nothing
reaches a phone. The message also shows in the console's message log, tagged
`Test`. Ask for a text to your own number instead and, once that number is
verified under Settings, it really arrives (up to 10 a day, ending
"- via TextKit sandbox").

## Without MCP: one tool on the SDK

If your app should not depend on a second connection, wrap the TextKit SDK
in an AI SDK `tool`. It does the same send, with the SDK's retries and
idempotency keys:

```bash
npm install ai zod jointextkit
```

```typescript
import { tool } from 'ai';
import { z } from 'zod';
import { TextKit } from 'jointextkit';

const sms = new TextKit(); // reads TEXTKIT_API_KEY

export const sendText = tool({
  description: 'Send one SMS to a US or Canadian phone number.',
  inputSchema: z.object({
    to: z.string().describe('E.164, for example +14155550132'),
    body: z.string().describe('The text to send'),
  }),
  execute: async ({ to, body }) => {
    const message = await sms.messages.send({ to, body });
    return { id: message.id, status: message.status };
  },
});
```

Pass it as `tools: { sendText }`. In a route that end users reach, set `to`
on the server from your own records (the signed-in user's verified phone)
rather than letting the model choose it.

## Go live

Swap the test key for a live one (`ssms_sk_live_`). A live text needs a
number on your account: [buy one](/docs/numbers) and
[register your use case](/docs/compliance) with the carriers. When the
account has one number, `from` is optional and the text goes out from it.
To limit what an agent can do with a live key, give it one with only the
[scopes](/docs/authentication) it needs.

## Sources

- [AI SDK: Model Context Protocol (MCP) tools](https://ai-sdk.dev/docs/ai-sdk-core/mcp-tools)
- [AI SDK: Tool calling](https://ai-sdk.dev/docs/ai-sdk-core/tools-and-tool-calling)
- [AI SDK: Tools](https://ai-sdk.dev/docs/foundations/tools)
