Wink Developers
Home Wink MCP Layer 3 · Agents
Wink MCP · Layer 3

Wink MCP

Make your AI agent recognise people, charge cards, and prove identity over the Model Context Protocol. One bearer token, one URL — agents in Claude Code, Claude Desktop, Cursor, and any MCP-aware host can call Wink's biometric and wallet primitives without a custom integration.

Endpoint https://mcp.wink.bio/api/mcp Transport Streamable HTTP Auth Bearer token Tools 25

What is Wink MCP

Wink MCP is a hosted MCP server that wraps the Wink Core API as a set of agent-callable tools. You connect once with a bearer token; your agent then has access to face / voice recognition, wallet operations, biometric authentication, age verification, and checkout — all as ordinary tool calls in whatever MCP host you use.

Two things distinguish it from calling the Core API directly:

  • Server-side credentials. Your Wink merchant clientId / clientSecret never leave Wink's infrastructure. The MCP server holds them and signs every call to Wink on your behalf, so the agent (and the model running it) can't see your secrets even if a prompt injection tries.
  • Agent-shaped tool surface. Tools encapsulate the multi-call flows the Core API needs — for example, recognize_face handles session-mint-then-multipart-recognise as a single call, returns just the fields an agent cares about, and masks PII by default so a chat transcript doesn't accidentally store full names.
i

Layer 3 in the Wink stack. Layer 1 (Core API + SDKs) is for direct integration. Layer 2 (WinkKey) is biometric sign-in for end users. Layer 3 (Wink MCP) is what you reach for when the consumer of Wink's primitives is an AI agent rather than a human-driven app.

Get an API key

Wink MCP keys are provisioned per-merchant. Reach out to your Wink contact (or use the Get keys link in the top-right of this site) and you'll receive a 64-character hex token tied to your merchant account.

Treat the token like a password:

  • Don't paste it into a Git repo or share it in a chat.
  • Each developer on your team gets their own token — revoke individually when someone leaves.
  • If a token leaks, ask Wink to rotate it and your agents will need the new one.

Connect a client

Three of the most common MCP hosts cover most cases. The pattern is identical: point the host at https://mcp.wink.bio/api/mcp with an Authorization: Bearer <token> header.

Claude Code

One CLI invocation:

Bash terminal
claude mcp add --transport http wink \
  https://mcp.wink.bio/api/mcp \
  --header "Authorization: Bearer <your-token>"

Then in any Claude Code session, ask the agent to call a Wink tool — it'll appear in /mcp alongside your other servers.

Claude Desktop

Edit claude_desktop_config.json (Settings → Developer → Edit Config):

JSON claude_desktop_config.json
{
  "mcpServers": {
    "wink": {
      "url": "https://mcp.wink.bio/api/mcp",
      "headers": {
        "Authorization": "Bearer <your-token>"
      }
    }
  }
}

Restart Claude Desktop. The Wink tools appear in the tool picker.

Cursor

Settings → Cursor Settings → MCP → Add new MCP server:

JSON ~/.cursor/mcp.json
{
  "mcpServers": {
    "wink": {
      "url": "https://mcp.wink.bio/api/mcp",
      "headers": {
        "Authorization": "Bearer <your-token>"
      }
    }
  }
}

Sanity check

Before you wire it into an agent, confirm the server answers a raw tools/list:

Bash terminal
curl -i -X POST https://mcp.wink.bio/api/mcp \
  -H "Authorization: Bearer <your-token>" \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'

You should see all 25 tools enumerated. A 401 means the token is wrong; a 502 means Wink is upstream-failing (rare on stage).

Tool reference

Tools are grouped by purpose. Each one is a single MCP tools/call on the server side; on the agent side it just looks like a tool the model can invoke. Argument and return shapes are advertised via JSON schema in the tools/list response — your MCP host pulls them automatically.

Recognition
recognize_face

Identify a person from a face image. Returns winkTag, confidence, masked name on match; null on no-match.

recognize_voice

Identify a person from a short voice clip. Same return shape as recognize_face.

recognize_face_cards

Recognise face and return the user's saved cards in one call. For payment-shaped flows.

recognize_face_wallet

Recognise face and return the full wallet block (cards + addresses + profile).

Profile
get_user_profile

Fetch first/last name, email, contact no, dateOfBirth (where available) for an authenticated user.

update_user_profile

Update profile fields. Only the fields you provide are touched.

validate_contact_no

Check whether a phone number is already registered with Wink. Useful for "have we met before?" branches.

check_age_verified

Boolean: has this user passed age verification on this merchant? No DoB ever returned.

Wallet
show_wallet

Return cards + addresses + profile in one shot. The agent's go-to "tell me about this user" call.

get_user_cards

List saved cards (last-4, brand, expiry, token). Set merchantSpecific to scope to your merchant or pull cross-merchant.

get_user_addresses

List saved billing + shipping addresses.

add_user_address

Save a new billing or shipping address. Returns the new address id.

delete_user_address

Remove a saved address by id.

Biometric authentication
request_biometric_auth

Initiate a biometric auth challenge (face / voice / palm). Returns a rid and a URL the agent can hand to the user.

check_biometric_auth

Single-shot status poll for a rid. Returns pending / consumed / expired.

wait_for_biometric_auth

Block-and-poll variant — convenient when the agent has time to wait. Times out after the auth-request's TTL.

cancel_biometric_auth

Cancel a pending auth-request before the user completes it.

send_biometric_auth_email

Email the auth-request URL to a user — handy when the agent doesn't have the user in front of it.

Enrollment
request_enrollment

Start an enrolment flow for a new user. Returns a URL the user opens to capture face / voice / palm.

send_enrollment_email

Email the enrolment URL to the user.

Checkout
prepare_checkout

Mint a Wink checkout session. Agent attaches it to the human-facing UI / link.

prepare_email_checkout

Variant that emails the checkout URL directly to the user.

prepare_inline_checkout

Variant for embedding checkout inline (in-app webview, bot reply, etc.).

wait_for_checkout

Block-and-poll until the checkout completes, fails, or times out. Returns the authorization result.

PIN
generate_winkpin

Generate a one-time numeric PIN for the user (sent via their preferred channel) — usable as a 2FA factor.

Example flows

"Identify the person in this photo"

The simplest possible flow — agent gets a JPEG, returns who it is.

  1. Agent receives an image (e.g. user uploads a photo to Claude Desktop).
  2. Agent calls recognize_face with the base64-encoded image.
  3. Server returns { match: true, winktag: ";stage-…", first_name: "A****x", confidence: 0.99 }.
  4. Agent narrates the masked result back to the user.

Names are masked by default. Full PII is reserved for a future scoped token; the pii_mode: "full" argument is accepted for forward-compat but currently falls back to masked.

"Charge this person for $20"

Recognition + wallet + checkout, three tools, one user-visible step (biometric auth on their device).

  1. recognize_face_wallet on a captured photo to identify the user and load their cards.
  2. request_biometric_auth for confirmation — the user gets a URL on their phone.
  3. wait_for_biometric_auth blocks until they consent.
  4. prepare_checkout with the chosen card token + amount.
  5. wait_for_checkout blocks until the authorization clears.

"Is this user old enough to buy alcohol?"

For age-gated commerce — no DoB ever leaves Wink.

  1. recognize_face identifies the user.
  2. check_age_verified with their winktag returns { verified: true } or false.
  3. If false, agent points the user at request_enrollment to add ID-document verification, then loops back.

Self-host

If your data-residency or compliance posture rules out a hosted MCP server, the implementation is open. Clone wink-mcp-server, configure your own Wink merchant credentials and Turso DB, and deploy to your own Vercel project (or any Node 22 host that supports streaming HTTP).

Bash terminal
git clone https://github.com/wink/wink-mcp-server.git
cd wink-mcp-server
pnpm install
cp .env.example .env.local
# fill in WINK_*, MCP_API_KEYS, TURSO_*
pnpm db:push
pnpm dev   # http://localhost:3030/api/mcp

The server is intentionally framework-light — Next.js 15 App Router + @vercel/mcp-adapter + Drizzle + libsql. Roughly 4k LoC; review-friendly.

Notes & gotchas

Bearer tokens, not OAuth (yet)

The current scheme is a shared bearer per developer. We'll add OAuth 2.1 client credentials when the use case appears — for instance, when an agent platform wants to mint per-end-user tokens. Until then: keep your bearer where you keep API keys.

PII is masked by default

Names come back as A****x K****m (first + last char visible). This is so a chat transcript can't reconstruct identifying detail by accident. Tools that read profile fields (get_user_profile, show_wallet) honour the same default. To opt into full PII, you'd ask Wink for a scoped token — that mechanism doesn't exist yet but the wire format already accepts pii_mode: "full".

No biometric data ever leaves Wink

The MCP server only ever proxies recognition results. Face images, voice clips, and the embeddings Wink computes from them stay on Wink's infrastructure. The audit log on the MCP side captures tool name, latency, and Wink's response status code — never the inputs.

Single-use sessions are handled for you

Wink Core sessions are single-use; the MCP server mints fresh sessions per call and self-heals on stale-session 401s. You don't need to think about session lifecycle when using MCP — it's the same model as calling REST through the playground console.

Function timeout is 60 s on Vercel Pro

Most tools complete in under a second. The exceptions are the blocking polls — wait_for_biometric_auth and wait_for_checkout — which honour their own TTL but cap at the function deadline. If you need longer waits, use request_* + check_* (non-blocking) and poll from your agent's loop instead.