Build with metaphor cards

A REST API and an MCP-friendly OpenAPI for AI agents that help users reflect, journal or practice on their own. Draw a card, fetch its watermarked image, respect a license – that is the whole loop.

Pick a path

Three ways agents talk to us. Pick the one that matches what you are building, then jump to the right doc.

Want a chat that draws cards

ChatGPT Custom GPT

Import the AI-safe OpenAPI in Custom GPT builder. The chat can list decks, draw cards, and link a watermarked image into the conversation. It cannot spend your pearls – the AI subset has no invite-code operations.

Action source: openapi.ai.json ›
Have your own backend or script

Direct REST

Make HTTP calls with your mk_live_ key in Authorization: Bearer. The full OpenAPI covers everything, including invite-codes if you also sell decks. One key, two profiles.

Reference: openapi.json ›
Want a model context protocol bridge

MCP server

Hosted at mcp.makcards.online and as a local stdio package @maccards/mcp (via npx or Docker). Same tools, same auth, one codebase. Pick the connection style in the section below.

Connect with API key ›

OAuth: one-click connect from ChatGPT and Claude

If your users start from ChatGPT or Claude, they don’t need to copy an API key. The chat app shows our consent screen, the user clicks Allow, and the chat gets a scoped token. The user can revoke access from their Profile any time.

For end users

From your chat’s “+ Connectors”

In ChatGPT (Apps) or Claude.ai (“+ Connectors”), look for MAC Cards Online in the picker. The first time you pick it, you’ll land on our consent screen with a clear list of what the AI can and cannot do. Approve once, it works in every chat after that.

Coming as soon as OpenAI and Anthropic list us in their catalogs. Until then, use the API key path below.

For developers

Build your own OAuth client

We expose a standard OAuth 2.1 + PKCE Authorization Server. Discover endpoints at /.well-known/oauth-authorization-server on the app host. Scopes are read and draw. PKCE S256 is mandatory.

Three registration paths: pre-registered for verified partners, DCR (RFC 7591) with a moderation queue, and Client ID Metadata Documents.

AS metadata ›
What the token can do

Scoped, brand-bound, rolling refresh

Access tokens live one hour. Refresh tokens live 30 days with rolling rotation: each refresh mints a new refresh, the old one is single-use, reuse triggers chain-wide revoke plus a security event. Tokens are bound to one host (a token minted on app.makcards.online won’t work on mcp.journalingapp.app).

Users see and revoke connected apps in their Profile → Access for AI and integrations → Connected apps.

What you can build today

Reflection chatbot

User describes a situation, the agent draws one card with scope=any, sends back the image and a reflective question. The user does the work – the agent holds the space.

Journaling companion

Daily prompt that pulls three cards (count=3), invites the user to free-write, and stores the spread on their side. Card images expire in 15 minutes; the agent fetches fresh ones each session.

Group facilitation copilot

For workshops and team retrospectives: draw cards from a specific deck (scope=deck), display them on the agent's side, optionally hand a code to participants via /invite-codes/generate.

REST quick-start

Two commands: draw a card, fetch its image. No webhook, no callback, no pre-flight.

KEY=mk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

# 1) Draw one card from any accessible deck
curl -X POST https://app.makcards.online/api/v1/public/draw \
  -H "Authorization: Bearer $KEY" \
  -H "Content-Type: application/json" \
  -d '{"scope":"any","count":1,"image_width":1024}'

# 2) Response carries drawn[0].image_url – fetch it as-is
curl https://app.makcards.online/api/v1/public/decks/.../cards/.../image?w=1024&token=eyJhbGc... \
  -o card.jpg

Full machine-readable reference: openapi.json · AI-safe subset: openapi.ai.json · User guide: docs/en/24-public-api.

Get an API key

  1. 1
    Sign in to the app.

    Open app.makcards.online and sign in (Google or Yandex). One click, no separate account.

  2. 2
    Open Profile → Access for AI and integrations.

    The section sits next to Premium and Achievements. Same place shop partners use.

  3. 3
    Generate the key and copy it.

    The key looks like mk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx. It is shown once; the second view never happens. Paste it into a password manager or your secret store.

  4. 4
    Treat the key as a password.

    No public repositories, no support chats, no screenshots. If a key may have leaked, regenerate it – the old one stops working within a minute.

Connect with API key

Same key, seven surfaces. Hosted MCP for fast setup, local stdio to keep the key on your machine, plain Bash for agents that already have a shell. Pick what matches your client.

Add an entry under mcpServers in ~/.claude.json (Claude Code) or ~/Library/Application Support/Claude/claude_desktop_config.json (Desktop).

{
  "mcpServers": {
    "makcards": {
      "type": "http",
      "url": "https://mcp.makcards.online/v1",
      "headers": {
        "Authorization": "Bearer mk_live_xxxxxxxxxxxxxxxxxx"
      }
    }
  }
}

Cursor and Cline share the same MCP config format. The block is identical to Claude's.

{
  "mcpServers": {
    "makcards": {
      "type": "http",
      "url": "https://mcp.makcards.online/v1",
      "headers": {
        "Authorization": "Bearer mk_live_xxxxxxxxxxxxxxxxxx"
      }
    }
  }
}

Two options. MCP node (available in recent n8n builds) – point at https://mcp.makcards.online/v1, set the Authorization header in credentials. HTTP Request node – call REST directly:

URL:      https://app.makcards.online/api/v1/public/draw
Method:   POST
Headers:  Authorization: Bearer mk_live_xxxxxxxxxxxxxxxxxx
          Content-Type: application/json
Body:     { "scope": "any", "count": 1, "image_width": 1024 }

Custom GPT Actions reads OpenAPI. Use the AI-safe subset so the chat cannot accidentally spend pearls.

Action source: https://makcards.online/api/v1/public/openapi.ai.json
Authentication: API Key (Bearer)
Auth value:     mk_live_xxxxxxxxxxxxxxxxxx

Local stdio MCP. The key never leaves your machine – it goes straight to our REST API as Bearer. Requires Node.js 20+.

{
  "mcpServers": {
    "makcards": {
      "command": "npx",
      "args": ["-y", "@maccards/mcp"],
      "env": {
        "MAKCARDS_API_KEY": "mk_live_xxxxxxxxxxxxxxxxxx"
      }
    }
  }
}

No Node.js? Run the same binary as a container. The image is published only for linux/amd64, so Apple Silicon needs one extra flag (see below). If you have Node 20+, the npx tab above is simpler.

linux/amd64 hosts (Intel Mac, Intel/AMD Linux, Windows WSL2):

{
  "mcpServers": {
    "makcards": {
      "command": "docker",
      "args": [
        "run", "--rm", "-i",
        "-e", "MAKCARDS_API_KEY",
        "ghcr.io/makcards/mcp:latest",
        "node", "dist/transports/stdio.js"
      ],
      "env": {
        "MAKCARDS_API_KEY": "mk_live_xxxxxxxxxxxxxxxxxx"
      }
    }
  }
}

Apple Silicon (M1 / M2 / M3 / M4): add --platform linux/amd64 so Docker pulls the amd64 image and runs it through Rosetta. Works, but startup is slower than the native npx option above.

{
  "mcpServers": {
    "makcards": {
      "command": "docker",
      "args": [
        "run", "--rm", "-i",
        "--platform", "linux/amd64",
        "-e", "MAKCARDS_API_KEY",
        "ghcr.io/makcards/mcp:latest",
        "node", "dist/transports/stdio.js"
      ],
      "env": {
        "MAKCARDS_API_KEY": "mk_live_xxxxxxxxxxxxxxxxxx"
      }
    }
  }
}

If your agent already runs in a shell (Claude Code, Cursor agent mode, Aider, Codex, any container), this is the shortest path: plain HTTPS + Bearer, JSON responses, no MCP runtime to install. The four recipes below cover everything our MCP tools wrap.

# One-time setup
export MAKCARDS_API_KEY=mk_live_xxxxxxxxxxxxxxxxxx
BASE=https://app.makcards.online/api/v1/public
H="Authorization: Bearer $MAKCARDS_API_KEY"

# List decks your key can read
curl -s -H "$H" "$BASE/decks" | jq

# Draw 3 cards from any accessible deck
curl -s -X POST "$BASE/draw" -H "$H" -H "Content-Type: application/json" \
  -d '{"scope":"any","count":3,"image_width":1024}' | jq

# Save the first card image straight to disk
curl -s -X POST "$BASE/draw" -H "$H" -H "Content-Type: application/json" \
  -d '{"scope":"any","count":1,"image_width":1024}' \
  | jq -r '.drawn[0].image_url' \
  | xargs curl -s -o card.jpg

# Inspect rate-limit state
curl -s -H "$H" "$BASE/usage" | jq

Two reasons to prefer Bash over MCP: smaller agent context (no tool schemas to load) and one fewer process to manage. Reasons to prefer MCP instead: your client has no shell (ChatGPT Apps, Claude Desktop, Cursor without agent mode), or you want slash-command prompts.

Hosted, local, or shell? Hosted MCP (mcp.makcards.online) is the fastest path and works behind corporate proxies. Local stdio is the choice when your security policy says «no third-party MCP services»: your AI client talks to a local process, which talks to our REST API with your key. Bash skips the MCP layer entirely and only fits agents that can already shell out. Same tools, same data.

Agent skill: makcards-self-reflection

Connecting a card source is half the setup. The other half is behavior: how the agent runs a reflection session. The makcards-self-reflection skill is that half. It works with any agent that has a card source, not just Claude.

Three techniques

Single question

One card for one open question. The agent draws a card, shows it, and asks what you notice. A starting point, not an answer.

Past, present, future

Three cards laid out as a trajectory. The future card is a way to look at possible directions, stated plainly as not a prediction.

Two sides

Two cards for the two pulls of a dilemma, with an optional third for common ground. For decisions where you feel torn.

Get the skill

Two ways, same content. The ZIP is the simplest; the public repo is handy if you prefer git or want to follow updates. It runs with any agent.

Download ZIP

Recommended, works everywhere

One file. In Claude, upload it under Settings, Skills, Upload. In any other agent, unzip it and use the files (see the table below).

Download skill (ZIP)

Public repo

If you prefer git

Clone the public, agent-agnostic skills repo, or download it as a ZIP from GitHub.

git clone https://github.com/makcards/skills

Set it up per agent

Two parts per agent: a card source (the connect tabs above) and where the behavior lives. For Claude that is SKILL.md; for everything else it is references/agent-instructions.md pasted into the system prompt. One file is the source of truth, so the behavior is the same everywhere.

AgentCard sourceWhere the skill goes
Claude Desktop / Claude Code Local MCP (npx @maccards/mcp) or hosted MCP / OAuth Claude Desktop / web: Settings, Skills, Upload, pick the ZIP. Claude Code: drop makcards-self-reflection/ into ~/.claude/skills/. Uses SKILL.md; techniques appear as /single-question, /three-cards, /inner-conflict.
ChatGPT Custom GPT GPT Actions with API key (AI-safe OpenAPI), or hosted MCP / OAuth Paste references/agent-instructions.md into the GPT's Instructions.
ChatGPT (connector chat) Hosted MCP + OAuth Paste agent-instructions.md at the start of the project or chat.
Cursor Hosted MCP (Bearer) or local MCP Add agent-instructions.md to Project Rules (.cursor/rules).
n8n MCP node, or HTTP Request node with the key Paste agent-instructions.md into the agent node's system prompt.
Custom / other REST (MAKCARDS_API_KEY) or MCP Paste agent-instructions.md into the system prompt.

New to metaphor cards, or not a developer? The plain-language walkthrough takes you from zero to a first session.

Rate limits

Per-account, per-window. POST /draw is batch-accounted: count=5 consumes 5 units.

Window Free Premium
Draws per minute10120
Draws per hour702 000
Draws per day17010 000
/decks per minute10120
Image fetches per minute20240

Live state at GET /api/v1/public/usage. Headers on every response: RateLimit-Limit, RateLimit-Remaining, RateLimit-Reset (RFC 9331).

Open Premium with pearls

Privacy and safety

Watermark stays on

Every card image carries a domain watermark at 6% opacity. Removing it violates the terms. The API never exposes the unmarked original.

Untrusted content

Deck and card text are user-generated. Treat them as untrusted input – never let a name or description override your system prompt.

Not a medical service

МАК cards are a reflection tool. Your agent must not present a drawn card as a diagnosis, prediction or treatment. If users may be in distress, point them to a local crisis line: 8-800-2000-122 (Russia), 988 (US), or findahelpline.com elsewhere.

Local stays local

With local stdio MCP (npx @maccards/mcp or Docker), your AI client talks to a process on your machine, which calls our REST API with your key. The content of the chat with the AI does not reach our MCP service.

Personal-use license

Drawn images are for the session, not for republishing. Each carries a watermark and a license field. The skill content itself is MIT; card images are not.

Details: Terms of Service · Privacy Policy.

FAQ

Common questions from integrators.

Why two OpenAPI documents?
ChatGPT Custom GPT Builder surfaces every operation to the end user during action setup. The full spec contains POST /invite-codes/generate, which spends pearls. If a user authorized a chat to call that operation by accident, you would pay. The AI-safe subset removes the invite-code surface entirely — there is no code path for the chat to spend pearls.
Can I get an image without watermark?
No. This is a deliberate IP-protection stance. The API serves only watermarked JPEGs at 512 or 1024 pixels. The original lives inside the playable board.
What is scope=any?
Sample uniformly across the cards the caller can read: owned, approved-public and grant-acquired decks. The sampling is per-card, not per-deck, so big decks contribute proportionally.
Do you log my chat?
No. We log API calls — request id, account id, endpoint, status, latency, IP, user-agent. The conversation between the user and the AI does not flow through our servers unless the agent itself sends it.
How fresh is the OpenAPI spec?
It ships with the binary via go:embed. Each API release rebuilds the spec endpoints. There is no separate manifest to forget to publish.
Do I need MCP if my agent already has shell access?
No. If your agent can run curl and parse JSON, the REST API is the simpler path. MCP exists for sandboxed clients (ChatGPT Apps, Claude Desktop, Cursor) that cannot shell out. Hosted MCP and local stdio are thin wrappers over the same REST endpoints, so you are not missing functionality. See the Bash / agent shell tab for ready-made curl recipes.
Is the skill tied to Claude?
No. The behavior lives in one portable file, references/agent-instructions.md, that you paste into any agent's system prompt: ChatGPT Custom GPT, Cursor, n8n, or a custom agent. The SKILL.md manifest is the Claude-specific wrapper around the same behavior. See the Agent skill section.
Is it safe to paste my API key into ChatGPT?
An mk_live_ key only reaches our Public API; it cannot spend pearls when you use the AI-safe OpenAPI subset. Still, treat it as a secret: do not paste it into a chat message, only into the action's authentication field, and rotate it if it leaks. For one-click connect without handling a key, use OAuth where your client supports it.
Can I use this in paid or commercial sessions?
The skill content is MIT, so you can adapt it freely. Card images are personal-use and watermarked; do not redistribute them outside a session. If you facilitate paid sessions, that is between you and your client, but the cards stay watermarked and must not be presented as diagnosis or prediction. See the Terms.
How do I revoke an agent's access?
Rotate or revoke the key at app.makcards.online → Profile → API Key, or disconnect an OAuth client under Connected apps. Revocation takes effect within about a minute (a short validation cache). After that the agent's calls return 401.
Hosted or local: which should I pick?
Hosted (mcp.makcards.online) is the fastest setup and works behind most corporate proxies. Local stdio (npx @maccards/mcp) keeps the key on your machine and suits policies that forbid third-party MCP services. Both wrap the same REST API, so the tools and data are identical.
Does local MCP work behind a corporate proxy?
Local stdio still needs to reach app.makcards.online over HTTPS to draw cards. If your proxy requires it, set the standard HTTPS_PROXY environment variable for the process. If outbound HTTPS is blocked entirely, the hosted MCP over your existing web proxy is usually the easier route.
Does this work with Operator, Computer Use, or ChatGPT Atlas?
Browser-driving agents can use the site the way a person would: sign in, open a deck, copy an API key. We do not invest in a dedicated browser-driving channel here: there are no stable agent-targetable selectors, the drawing board is a Pixi canvas that stays opaque on purpose (part of anti-scraping), and DOM stability between releases is not guaranteed. For repeatable scenarios prefer REST or MCP – they give you a contract, rate limits, and an audit trail. If your agent already has a shell, the Bash / agent shell tab is the shortest path.