Magic Envelope

Create and send invitations and letters in a sealed envelope, with one personal link per guest. Free, no auth.

Servidor MCP hospedado

npx add-mcp 'https://magic-envelope.com/api/mcp'

Instala no Claude Code, Codex, Cursor e outros

Documentação

For agents & developers

Everything a person can do in Magic Envelope, an agent can do: compose a letter from typed blocks, pick a style, add guests and publish. Every guest gets their own addressed link. Free and keyless — the editKey returned on creation is the only credential, and only for editing.

https://magic-envelope.com/api/mcp

Just ask your agent

Once Magic Envelope is connected (below), plain language is enough. The agent reads the catalog, builds the letter and hands back one link per guest.

Using Magic Envelope, make a Spanish invitation for Ana's 8th birthday:
Saturday 14 November at 17:00, Parque del Retiro (Madrid), RSVP by WhatsApp to +34 600 123 123.
Playful style. Give me one link for each guest: Lucía, Tom, Marco.

Claude

Claude Code: one command. Claude apps (web, desktop, mobile): Settings → Connectors → Add custom connector, and paste the URL.

claude mcp add --transport http magic-envelope https://magic-envelope.com/api/mcp
https://magic-envelope.com/api/mcp

ChatGPT

Add it as an app with developer mode on (Settings → Apps), using the MCP URL and no authentication. For a custom GPT, add an Action and import the OpenAPI schema from its URL.

https://magic-envelope.com/api/mcp

GPT Action → Import from URL

https://magic-envelope.com/api/v1/openapi.json

Cursor, VS Code, Windsurf

Add the server to the editor's MCP config file.

{
  "mcpServers": {
    "magic-envelope": {
      "url": "https://magic-envelope.com/api/mcp"
    }
  }
}
{
  "servers": {
    "magic-envelope": {
      "type": "http",
      "url": "https://magic-envelope.com/api/mcp"
    }
  }
}
{
  "mcpServers": {
    "magic-envelope": {
      "serverUrl": "https://magic-envelope.com/api/mcp"
    }
  }
}

Clients that only speak stdio

Bridge the remote server with mcp-remote.

{
  "mcpServers": {
    "magic-envelope": {
      "command": "npx",
      "args": [
        "-y",
        "mcp-remote",
        "https://magic-envelope.com/api/mcp"
      ]
    }
  }
}

curl

Create and publish a letter. The response has the letter's link, one link and one image per guest, and the editKey (keep it to make changes or delete it).

curl -X POST https://magic-envelope.com/api/v1/letters \
  -H "content-type: application/json" \
  -d '{
  "lang": "en",
  "style": "romance",
  "preset": "wedding",
  "seal": "duo:L|T",
  "blocks": [
    { "type": "heading", "text": "{name}, we're getting married!" },
    { "type": "date", "start": "2026-11-14T18:00" },
    { "type": "place", "name": "The Orangery", "address": "Kew Gardens, London" },
    { "type": "rsvp", "channel": "email", "contacts": { "email": "us@example.com", "whatsapp": "", "sms": "" } },
    { "type": "signature", "text": "Lucía & Tom" }
  ],
  "guests": [{ "name": "Emma" }, { "name": "Noah" }]
}'

Change it later (only what you send changes; same links)

curl -X PATCH https://magic-envelope.com/api/v1/letters/LETTER_ID \
  -H "authorization: Bearer EDIT_KEY" \
  -H "content-type: application/json" \
  -d '{ "style": "midnight", "addGuests": [{ "name": "Olivia" }] }'
curl https://magic-envelope.com/api/v1/letters/LETTER_ID -H "authorization: Bearer EDIT_KEY" | jq .rsvps

Every guest's letter as an image (ZIP named after the letter)

curl -L -O -J "https://magic-envelope.com/api/v1/letters/LETTER_ID/images.zip" \
  -H "authorization: Bearer EDIT_KEY"

Copy a photo (Drive, Dropbox or any public image) and use it on the letter

curl -X POST https://magic-envelope.com/api/v1/media \
  -H "content-type: application/json" \
  -d '{ "url": "https://drive.google.com/file/d/FILE_ID/view" }'
curl -X DELETE https://magic-envelope.com/api/v1/letters/LETTER_ID -H "authorization: Bearer EDIT_KEY"

JavaScript / TypeScript

Works in Node 18+, Deno, Bun, browsers and edge functions (CORS is open).

const res = await fetch("https://magic-envelope.com/api/v1/letters", {
  method: "POST",
  headers: { "content-type": "application/json" },
  body: JSON.stringify({
    "lang": "en",
    "style": "romance",
    "preset": "wedding",
    "seal": "duo:L|T",
    "blocks": [
      { "type": "heading", "text": "{name}, we're getting married!" },
      { "type": "date", "start": "2026-11-14T18:00" },
      { "type": "place", "name": "The Orangery", "address": "Kew Gardens, London" },
      { "type": "rsvp", "channel": "email", "contacts": { "email": "us@example.com", "whatsapp": "", "sms": "" } },
      { "type": "signature", "text": "Lucía & Tom" }
    ],
    "guests": [{ "name": "Emma" }, { "name": "Noah" }]
  }),
});
if (!res.ok) throw new Error(JSON.stringify(await res.json()));
const letter = await res.json();
for (const guest of letter.guests) console.log(guest.name, guest.url);

Python

With requests.

import requests

letter = requests.post(
    "https://magic-envelope.com/api/v1/letters",
    json={
        "lang": "en", "style": "parchment", "preset": "birthday",
        "blocks": [
            {"type": "heading", "text": "{name}, come to my party!"},
            {"type": "date", "start": "2026-11-14T17:00"},
            {"type": "place", "name": "Home", "address": "221B Baker Street, London"},
        ],
        "guests": [{"name": "Emma"}, {"name": "Noah"}],
    },
    timeout=30,
).json()

for guest in letter["guests"]:
    print(guest["name"], guest["url"])

Google Sheets

Guest names in column A (row 1 is a header). Extensions → Apps Script, paste, run: each guest's personal link lands in column B.

function sendInvitations() {
  const sheet = SpreadsheetApp.getActiveSheet();
  const rows = sheet.getRange(2, 1, sheet.getLastRow() - 1, 1).getValues();
  const guests = rows.map(([name]) => ({ name: String(name).trim() })).filter((g) => g.name);

  const res = UrlFetchApp.fetch("https://magic-envelope.com/api/v1/letters", {
    method: "post",
    contentType: "application/json",
    payload: JSON.stringify({
      lang: "en", style: "botanical", preset: "dinner",
      blocks: [
        { type: "heading", text: "{name}, dinner at ours?" },
        { type: "date", start: "2026-11-21T20:30" },
      ],
      guests,
    }),
  });
  const letter = JSON.parse(res.getContentText());
  sheet.getRange(2, 2, letter.guests.length, 1).setValues(letter.guests.map((g) => [g.url]));
}

n8n

In an AI Agent workflow, add an MCP Client Tool with the endpoint below (HTTP Streamable, no auth). Without an agent, use an HTTP Request node: POST, body JSON.

https://magic-envelope.com/api/mcp
https://magic-envelope.com/api/v1/letters
{
  "lang": "en",
  "style": "romance",
  "preset": "wedding",
  "seal": "duo:L|T",
  "blocks": [
    { "type": "heading", "text": "{name}, we're getting married!" },
    { "type": "date", "start": "2026-11-14T18:00" },
    { "type": "place", "name": "The Orangery", "address": "Kew Gardens, London" },
    { "type": "rsvp", "channel": "email", "contacts": { "email": "us@example.com", "whatsapp": "", "sms": "" } },
    { "type": "signature", "text": "Lucía & Tom" }
  ],
  "guests": [{ "name": "Emma" }, { "name": "Noah" }]
}

Zapier / Make

Webhooks by Zapier → Custom Request (or Make's HTTP → Make a request): method POST, header content-type: application/json, raw body below. Map guest names from your trigger into "guests".

https://magic-envelope.com/api/v1/letters
{
  "lang": "en",
  "style": "romance",
  "preset": "wedding",
  "seal": "duo:L|T",
  "blocks": [
    { "type": "heading", "text": "{name}, we're getting married!" },
    { "type": "date", "start": "2026-11-14T18:00" },
    { "type": "place", "name": "The Orangery", "address": "Kew Gardens, London" },
    { "type": "rsvp", "channel": "email", "contacts": { "email": "us@example.com", "whatsapp": "", "sms": "" } },
    { "type": "signature", "text": "Lucía & Tom" }
  ],
  "guests": [{ "name": "Emma" }, { "name": "Noah" }]
}

Reference

  • get_catalog, create_letter, get_letter, update_letter, delete_letter — the MCP tools
  • GET /api/v1/catalog — styles, presets, block types with examples, envelope slots, stamps, seals
  • POST /api/v1/letters — create and publish
  • GET, PATCH and DELETE /api/v1/letters/:id — with Authorization: Bearer <editKey>. PATCH takes the fields you want to change, or the same object GET returns. GET includes guests' RSVP answers
  • POST /api/v1/media — copy a public image, or a Drive, Dropbox or Wikimedia link, and get a src
  • GET /api/v1/letters/:id/image?g=<guest>&download=1 and /images.zip — one PNG per guest; the ZIP is named after the letter
  • OpenAPI 3.1
  • JSON Schemas
  • Catalog
  • MCP Server Card
  • AI Catalog
  • llms.txt

Good to know

Write {name} in a title, text, signature or envelope line to address each guest. Blocks may be partial — missing fields take the editor's defaults. A text block has no character limit; set italic: true or fontStyle: "italic" for italics, and custom.frame to none, rule or ornate. Dates are the local time at the venue: 2026-11-14T18:00, or 2026-11-14 for a whole day. Guest names are stored server-side and each guest page only ever receives its own name. Letters are in English, Spanish, French, Portuguese, Italian or German (lang).