# Postals Mcp

> The agent skill that turns any AI into a direct mail machine. One MCP tool call mails a physical handwritten postcard — real pen-and-ink on real paper, USPS delivery in 3-5 business days, $4.99 per card. Works with Claude Desktop, Cursor, Claude Code, OpenClaw, n8n, LangChain, and any MCP-compatible client.

- **Type:** MCP server
- **Install:** `agentstack add mcp-coopergwrenn-postals-mcp`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [coopergwrenn](https://agentstack.voostack.com/s/coopergwrenn)
- **Installs:** 0
- **Category:** [AI & ML](https://agentstack.voostack.com/c/ai-and-ml)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [coopergwrenn](https://github.com/coopergwrenn)
- **Source:** https://github.com/coopergwrenn/postals-mcp

## Install

```sh
agentstack add mcp-coopergwrenn-postals-mcp
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# Postals

> **The agent skill that turns any AI into a direct mail machine.**
> One tool call. Real handwritten postcards. Delivered by USPS.

[](https://www.npmjs.com/package/postals-mcp)
[](https://modelcontextprotocol.io)
[](#license)

Send physical handwritten postcards from any MCP-compatible AI agent — **Claude Desktop, Cursor, Claude Code, OpenClaw, n8n, LangChain, CrewAI, or your own code**. Postals handles image upload, card creation, robotic handwriting (real pen and ink), and USPS mailing.

Website: [postals.ai](https://postals.ai)

- 💌 **$4.99 per card** — no subscriptions, no monthly minimums
- ✍️ **Real handwriting** — robotic pens hold real ink (not font simulation)
- 📬 **3–5 business days** — printed and mailed via USPS
- 🤖 **Built for agents** — one tool call, spend controls, idempotency, test mode
- 🌎 **US + international** — worldwide delivery, pricing varies by destination

---

## Table of Contents

- [Why this exists](#why-this-exists)
- [Quick start (under 5 minutes)](#quick-start)
- [Client configuration](#client-configuration)
- [Tools reference](#tools-reference)
- [The pool builder workflow](#the-pool-builder-workflow)
- [Message generation](#message-generation)
- [Image handling](#image-handling)
- [Test mode](#test-mode)
- [Spend control](#spend-control)
- [Error handling](#error-handling)
- [Configuration reference](#configuration-reference)
- [Handwriting styles](#handwriting-styles)
- [Troubleshooting](#troubleshooting)
- [FAQ](#faq)
- [What's next (roadmap)](#whats-next)
- [Contributing](#contributing)
- [License](#license)

---

## Why this exists

A new pattern is emerging in the AI agent ecosystem: autonomous bots that scan the world (satellite imagery, social media, public records), identify opportunities, and **reach out with real physical mail**. Pool builders, landscapers, roofers, solar installers, real estate agents — they're closing five- and six-figure deals from postcards mailed by bots.

Before Postals, every builder hand-rolled their own mailing stack: image upload, card templating, print API, address validation, USPS handoff, tracking. It took weeks and was fragile.

We ship this as **one tool**. Your agent calls `send_postcard` with a recipient and a message. We do the rest.

---

## Quick start

### 1. Sign up and get an API key

> **Coming soon — the developer portal at [postals.ai/developers](https://postals.ai/developers) is launching shortly.** Once live, the flow is:
>
> 1. Go to [postals.ai/developers](https://postals.ai/developers)
> 2. Create an account with your email (one-click magic link — no password)
> 3. Fund your wallet ($25 / $50 / $100 / $250 via Stripe or crypto)
> 4. Copy your `postals_live_` API key
> 5. Paste it into your MCP config (see step 2 below)
>
> That's it. No external accounts needed. Just Postals.

### 2. Add the server to your MCP client

#### Option A — ask your coding agent to install it (fastest path)

If you're in **Claude Code**, **Cursor**, **Continue**, **Aider**, or any other MCP client with filesystem access, just tell your agent:

> Install the postals-mcp MCP server for this client. My Postals API key is: `PASTE_YOUR_KEY_HERE`. Start in test mode so I can verify the setup before sending real cards.

Your agent will locate your MCP config file, merge the `postals` entry into your existing `mcpServers` (preserving any other servers you have), wire up the env vars, and tell you to restart the client. You never touch JSON.

Optional — add return-address details to the same prompt so `send_postcard` works without per-call overrides:

> ...and use Jane Smith, 123 Main St, Austin TX 78701 as my return address.

Then **fully quit and relaunch the client** (Cmd+Q on macOS — just closing the window isn't enough).

#### Option B — edit your MCP config file directly

For **Claude Desktop** (no built-in filesystem access by default), or any client where you'd rather set it up manually, edit `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) or `%APPDATA%\Claude\claude_desktop_config.json` (Windows):

```json
{
  "mcpServers": {
    "postals": {
      "command": "npx",
      "args": ["-y", "postals-mcp"],
      "env": {
        "POSTALS_API_KEY": "your_api_key",
        "POSTALS_SENDER_NAME": "Jane Smith",
        "POSTALS_SENDER_ADDRESS": "123 Main St",
        "POSTALS_SENDER_CITY": "Austin",
        "POSTALS_SENDER_STATE": "TX",
        "POSTALS_SENDER_ZIP": "78701",
        "POSTALS_TEST_MODE": "true"
      }
    }
  }
}
```

Configs for other clients (Cursor, Claude Code, OpenClaw) are in the [Client configuration](#client-configuration) section below.

Fully restart the client after editing. (Not just close the window — quit from the menu.)

### 3. Verify it's working

Open a new chat and ask:

> "List the MCP tools you have available."

You should see `send_postcard` and `generate_message`.

### 4. Send a test card

Still in test mode (`POSTALS_TEST_MODE=true`), ask:

> "Send a postcard to Jane Smith at 123 Oak St, Austin TX 78701 saying 'Thanks for the great meeting yesterday — looking forward to next steps.'"

The agent will call `send_postcard`. You'll get back a mock `order_id` and confirmation that test mode is on. No card mailed, no money spent.

### 5. Go live

Remove `POSTALS_TEST_MODE` from your config (or set to `false`), restart, and your next send will mail a real card.

---

## Client configuration

Copy-paste-ready configs for every major MCP client. If you're in Claude Code, Cursor, Continue, or Aider, you can skip this section entirely — just tell your agent to install Postals (see [Option A in Quick Start](#option-a--ask-your-coding-agent-to-install-it-fastest-path)) and it'll handle the config for you.

### Claude Desktop

`~/Library/Application Support/Claude/claude_desktop_config.json` (macOS)
`%APPDATA%\Claude\claude_desktop_config.json` (Windows)

```json
{
  "mcpServers": {
    "postals": {
      "command": "npx",
      "args": ["-y", "postals-mcp"],
      "env": {
        "POSTALS_API_KEY": "your_key"
      }
    }
  }
}
```

### Cursor

Global: `~/.cursor/mcp.json`
Per-project: `.cursor/mcp.json` in repo root

```json
{
  "mcpServers": {
    "postals": {
      "command": "npx",
      "args": ["-y", "postals-mcp"],
      "env": {
        "POSTALS_API_KEY": "your_key"
      }
    }
  }
}
```

### Claude Code

```bash
claude mcp add postals npx -y postals-mcp
```

Then set env vars in `~/.claude/settings.json` under `mcpServers.postals.env`.

### OpenClaw / InstaClaw

See the bundled [SKILL.md](./SKILL.md) for the full agent-facing skill definition. For standalone OpenClaw usage:

```yaml
mcp_servers:
  postals:
    command: npx
    args: ["-y", "postals-mcp"]
    env:
      POSTALS_API_KEY: ${POSTALS_API_KEY}
```

### n8n (via Composio — v1.1+)

Install the Postals toolkit from the Composio marketplace. One-click add to any workflow. See [Composio docs](https://composio.dev) when available.

### Custom agents (programmatic)

Any MCP client library works. Example with the official TypeScript SDK:

```ts
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";

const transport = new StdioClientTransport({
  command: "npx",
  args: ["-y", "postals-mcp"],
  env: { POSTALS_API_KEY: "your_key", POSTALS_TEST_MODE: "true" },
});
const client = new Client({ name: "my-agent", version: "1.0" }, { capabilities: {} });
await client.connect(transport);

const result = await client.callTool({
  name: "send_postcard",
  arguments: {
    to_name: "John Smith",
    to_address: "123 Oak St",
    to_city: "Austin",
    to_state: "TX",
    to_zip: "78701",
    message: "Hey John — thought you'd love this.",
    front_image_url: "https://example.com/render.png",
    idempotency_key: "john-smith-123-oak-001",
  },
});
```

---

## Tools reference

### `send_postcard`

Mails one physical handwritten postcard to a US address.

**Input**

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `to_name` | string | ✓ | Recipient's full name |
| `to_address` | string | ✓ | Street address line 1 |
| `to_address_2` | string | | Apt/suite/unit |
| `to_city` | string | ✓ | City |
| `to_state` | string | ✓ | 2-letter US state code |
| `to_zip` | string | ✓ | 5-digit ZIP (or 5+4) |
| `message` | string | ✓ | Handwritten message (max 400 chars) |
| `front_image_url` | string | | HTTPS URL to card front image (PNG/JPEG). Falls back to `POSTALS_DEFAULT_CARD_IMAGE`. |
| `handwriting_style` | string | | Font name. Default: `Joyful Jennifer` |
| `return_address` | object | | Per-call sender override. Falls back to `POSTALS_SENDER_*` env vars. |
| `idempotency_key` | string | | Unique dedup key. Same key = same result, no duplicate send. 24h TTL. |

**Output (success)**

```json
{
  "success": true,
  "order_id": 196937,
  "card_id": 305570,
  "recipient": "John Smith",
  "estimated_delivery": "3-5 business days via USPS",
  "balance_remaining": -1,
  "cards_available": -1,
  "cards_sent_today": 7,
  "daily_limit": 25
}
```

`balance_remaining` and `cards_available` return real values when using a `postals_live_` API key from postals.ai/developers.

**Output (test mode)** adds `test_mode: true` and `mock_order_id`. No card is mailed.

**Output (error)** returns `isError: true` with an actionable message. See [Error handling](#error-handling).

### `generate_message`

AI-drafts a personalized postcard message. Uses Cloudflare AI if configured; otherwise returns a structured prompt your agent can use to self-generate (which is often just as good, since the agent is already an LLM).

**Input**

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `recipient_context` | string | ✓ | Who the recipient is and why you're writing |
| `tone` | enum | | `warm` (default), `professional`, `casual`, `excited` |
| `max_chars` | number | | Max message length. Default 350, max 400. |
| `sender_context` | string | | Who the sender is |

**Output (AI configured)**

```json
{
  "message": "Hey John — drove by your place on Oak St and couldn't help but picture how a pool would transform that backyard. Happy to share a quick render if you're curious. — Kevin, Blue Wave Pools",
  "char_count": 212,
  "tone": "warm",
  "ai_generated": true
}
```

**Output (AI not configured)** — returns the system + user prompts your agent can feed into its own LLM:

```json
{
  "message": null,
  "ai_generated": false,
  "prompt": {
    "system": "You write short, personal messages for physical handwritten postcards...",
    "user": "Recipient: John Smith, homeowner at 123 Oak St...\nSender: Blue Wave Pools\n\nWrite the postcard message now."
  },
  "instructions": "Cloudflare AI not configured. Use the system/user prompts above to generate the message...",
  "tone": "warm",
  "max_chars": 350
}
```

### `compose_postcard_message` (MCP prompt)

An MCP prompt primitive (not a tool). Returns a formatted prompt template for your agent to use with its own LLM. Zero external API dependencies. Useful when you want deterministic, dependency-free message composition.

**Arguments:** `recipient`, `sender` (optional), `tone` (optional).

---

## The pool builder workflow

This is the viral use case that put autonomous postcard sending on the map. Pool builders run agents that:

1. **Scan** satellite imagery of a neighborhood (Google Maps, Nearmap, etc.)
2. **Classify** — find homes without pools
3. **Render** — generate a personalized before/after showing a pool in that exact backyard
4. **Compose** — write a warm, specific message about that home
5. **Send** — mail the handwritten postcard
6. **Close** — five-figure deals landing weekly

Postals owns steps 4–5 with two tool calls. You own 1–3 (any image pipeline works).

### Full example

```js
// Your pipeline produced:
//   - homeowner: { name, street, city, state, zip }
//   - renderUrl: "https://cdn.mybucket.com/renders/123-oak-st-pool.jpg"

const msg = await generate_message({
  recipient_context: `${homeowner.name}, homeowner at ${homeowner.street}. Corner lot with large flat backyard, no pool.`,
  sender_context: "Blue Wave Pools — Austin, TX. Specializing in fiberglass pools installed in 14 days.",
  tone: "warm",
});

const result = await send_postcard({
  to_name: homeowner.name,
  to_address: homeowner.street,
  to_city: homeowner.city,
  to_state: homeowner.state,
  to_zip: homeowner.zip,
  message: msg.message,
  front_image_url: renderUrl,
  idempotency_key: `prospect-${homeowner.id}`,  // crucial for retries
});

console.log(`Mailed card ${result.order_id}. ${result.cards_sent_today}/${result.daily_limit} today.`);
```

### Why this works

- **Real handwriting** beats printed mail 5–10× on open rate
- **Hyper-personalized image** (their actual house!) makes it unignorable
- **Warm, specific message** feels human, not mass-mailed
- **USPS delivery** triggers the "this is important" instinct

### Variations

| Industry | Scan for | Render | Tone |
|----------|----------|--------|------|
| **Pool builders** | No pool in backyard | Pool in their yard | Warm, aspirational |
| **Landscapers** | Overgrown / dead yards | Manicured landscape | Warm, visual |
| **Roofers** | Damaged or aged roofs | New roof render | Professional, urgent |
| **Solar installers** | Large south-facing roofs | Solar panel render | Professional, savings-focused |
| **Real estate agents** | FSBO or expired listings | Staged interior render | Professional, helpful |
| **Home remodelers** | Outdated exteriors | Modern renovation render | Excited, transformative |

All use the same two tool calls. Only the scanning, rendering, tone, and message change.

---

## Message generation

You have three ways to compose the handwritten message. Pick based on your setup:

### Option A — `generate_message` tool with Cloudflare AI

Set `CLOUDFLARE_ACCOUNT_ID` + `CLOUDFLARE_API_TOKEN`. The server calls Llama 3.1 8B Instruct via Cloudflare Workers AI with Postals' proven tone profiles. Returns a ready-to-use message.

```json
"env": {
  "POSTALS_API_KEY": "...",
  "CLOUDFLARE_ACCOUNT_ID": "...",
  "CLOUDFLARE_API_TOKEN": "..."
}
```

### Option B — `generate_message` tool without AI (recommended for most agents)

Don't set the CF vars. The tool returns a **structured prompt** (system + user) that your agent uses with its own LLM. Since the calling agent is already an LLM (Claude, GPT, etc.), it generates a message at least as good as Llama 3.1 — often better.

### Option C — `compose_postcard_message` MCP prompt

An MCP prompt primitive (not a tool). Claude Desktop surfaces this in the slash-command menu. The agent injects Postals' guidelines directly into its context and composes.

### Option D — Your agent writes the message itself

Skip `generate_message` entirely. Your agent already knows how to write. Just pass a message directly to `send_postcard`.

---

## Image handling

The `front_image_url` must be a **public HTTPS URL** to a PNG or JPEG. The server fetches the image, uploads it to our print partner and creates a custom card.

### Recommended specs

- **Format:** PNG or JPEG
- **Orientation:** Landscape (wider than tall)
- **Size:** 2100 × 1500 px (7×5 inches at 300 DPI) — print quality
- **Minimum:** 1050 × 750 px
- **Max file size:** 10 MB
- **Accessibility:** Public URL, no auth headers, no signed URLs with short TTLs

### Common sources

| Source | Example |
|--------|---------|
| Your own CDN / S3 / Cloudflare R2 | `https://cdn.yoursite.com/renders/xyz.png` |
| AI image generation output | Most services return a public URL |
| Static templates | Pre-designed company cards hosted on your site |
| Recraft V3 (coming in a future release) | `generate_card_image` tool will return a URL |

### No image?

Set `POSTALS_DEFAULT_CARD_IMAGE` to your branded fallback. Every call without `front_image_url` uses the default. This is ideal for business use cases where every ca

…

## Source & license

This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [coopergwrenn](https://github.com/coopergwrenn)
- **Source:** [coopergwrenn/postals-mcp](https://github.com/coopergwrenn/postals-mcp)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** yes
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** yes
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/mcp-coopergwrenn-postals-mcp
- Seller: https://agentstack.voostack.com/s/coopergwrenn
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
