Skip to main content
Glama
rosaliev24

lovense-mcp

by rosaliev24

lovense-mcp

English · 中文

By Rosalie

Overview

Control Lovense toys from the Claude app on your phone, in plain language. Deploy once; your computer can stay off.

This is an MCP server that runs on Cloudflare Workers and forwards commands through Lovense's official cloud interface (Standard API). Tested on a Lovense Vulse.

Three things it does differently:

  • Phone-only after setup. The Worker is stateless and always on; the free tier is plenty.

  • MCP spec 2026-07-28. Stateless Streamable HTTP, with fallback for older clients (2025-11-25 / 2025-06-18 / 2025-03-26), so both new and old Claude clients connect.

  • Access key, fail-closed. The key lives in the URL path, no OAuth to configure. With no key configured, the Worker refuses every request.

Other Lovense toys use the same API and should work, but only the Vulse has been tested.

Adults only. Use only on devices you own.

Related MCP server: mcp-buttplug

How it works

A command leaves Claude, passes through the Worker and Lovense's cloud, and reaches the toy over Bluetooth from the Lovense Remote app on your phone.

Claude app (phone / web)
   │  MCP · Streamable HTTP · key in the URL
   ▼
Cloudflare Worker (this project)
   │  HTTPS · Lovense Standard API
   ▼
Lovense cloud
   │  pushed to the paired phone
   ▼
Lovense Remote app (phone)
   │  Bluetooth
   ▼
Toy

On each call the Worker does three things: checks the key in the URL, translates tool arguments into Lovense API calls, and forwards them. Pairing state lives on Lovense's servers; the Worker stores nothing.

Lovense commands carry their own duration, so one call runs for the requested time without the client re-sending. Few calls per session means the context cost is negligible.

Tools

Once the connector is attached, Claude sees 6 tools. You speak normally; Claude picks the tool.

Tool

What it does

Main arguments

lovense_pair_qr

Generate a pairing QR code to scan with Lovense Remote

none

lovense_vibrate

Set vibration intensity

intensity 0–20, duration in seconds

lovense_thrust

Set thrusting speed (thrusting toys)

intensity 0–20, duration in seconds

lovense_pattern

Play a built-in pattern preset

preset name, duration

lovense_custom_pattern

Play a custom intensity sequence

intensity list, interval

lovense_stop

Stop everything immediately

none

Patterns run on the Vibrate channel by default; thrusting toys can pass function: "thrusting". Preset names and exact argument schemas are defined in src/tools.js.

Tested device: Lovense Vulse

The Vulse responds to lovense_vibrate only. lovense_thrust does nothing.

Lovense markets the Vulse as a thrusting egg (up to 120 strokes/min, 10 mm travel), so the thrust command looks like the obvious choice. In practice:

  • Lovense Remote shows a single Vibration slider for it.

  • The Lovense API exposes only the Vibrate channel. Thrust and vibration share one motor and cannot be driven separately.

  • A Thrusting command returns success from the API, and the toy stays still.

So ask for "vibration" when driving a Vulse, and build patterns on the Vibrate channel too.

Thrusting toys such as the Solace should respond to lovense_thrust, but that is untested here. The Lovense API also has a Depth command (0–3); this project does not implement it.

Prerequisites

Everything is free. The computer is needed once, for deployment.

You need

Notes

Lovense developer account

Sign up at developer.lovense.com to get a Developer Token

Cloudflare account

Free tier is enough; the Worker runs here

A computer (one time)

Windows / Mac / Linux with Node.js 20+; not needed after deployment

Claude account

A plan that allows custom connectors

Lovense Remote on your phone

The toy connects to it over Bluetooth; keep it running while you play

A Lovense toy

Tested on the Vulse

Deploy

If you have Claude Code, you can hand it the repo URL: "Deploy this repo to my Cloudflare and install whatever is missing." Apart from authorizing Cloudflare in the browser and pasting your token, it can run every command below.

  1. Clone and install:

    git clone https://github.com/rosaliev24/lovense-mcp.git
    cd lovense-mcp
    npm install
  2. Log in to Cloudflare (opens a browser to authorize):

    npx wrangler login
  3. Generate an access key and keep it somewhere safe:

    node -e "console.log(require('crypto').randomBytes(32).toString('base64url'))"
  4. Store your Lovense token and the access key. Paste at each prompt and press Enter; nothing shows while you paste, which is normal:

    npx wrangler secret put LOVENSE_TOKEN
    npx wrangler secret put MCP_ACCESS_KEY

    Do not pipe the value in with echo "xxx" | wrangler secret put; always paste interactively (see Troubleshooting).

  5. Deploy:

    npx wrangler deploy

    The output shows your Worker address, like https://lovense-mcp.<subdomain>.workers.dev.

  6. Verify (protocol checks only; sends nothing to the toy):

    node scripts/check.mjs https://lovense-mcp.<subdomain>.workers.dev <key>
  7. Set the Lovense callback URL (required): at lovense.com/user/developer/info, set the Callback URL to

    https://lovense-mcp.<subdomain>.workers.dev/lovense/callback

    Without it, Lovense rejects the QR code request even with a correct token.

Connecting Claude

Add a custom connector

The connector URL is the Worker address + /mcp/ + your key:

https://lovense-mcp.<subdomain>.workers.dev/mcp/<key>
  1. Open claude.ai in a browser → Settings → Connectors → Add custom connector.

  2. Any name (e.g. Lovense), paste the URL above as the remote MCP server URL, leave both OAuth fields empty, click Add.

  3. The connector's detail page should list 6 tools. Permissions default to "ask first"; switch to auto-allow once you trust it.

The iOS Claude app currently has no "add custom connector" entry. Add it on the web; the phone app picks it up after a restart.

Pair the toy (one time)

  1. Open Lovense Remote on your phone and connect the toy over Bluetooth.

  2. Start a new Claude conversation and ask for a pairing QR code. Approve the permission prompt on first use.

  3. Scan the code from inside Lovense Remote. Codes expire within minutes; ask for a fresh one if it fails.

Pairing is stored on Lovense's servers. You will not need to scan again.

Daily use

Two steps each time: open Lovense Remote with the toy connected, then talk to Claude.

Examples:

  • "Vibrate at 8 for 30 seconds"

  • "Play one of the presets"

  • "Ramp up from 3 to 15, five seconds per step"

  • "Stop"

Claude picks the tool and fills in the arguments. Start low (around 3) for a few seconds the first time.

Keep in mind:

  • Lovense Remote must stay running and the toy must stay connected over Bluetooth. If the app is killed, commands report success but nothing moves.

  • Say "vibrate", not "thrust", for a Vulse (see Tested device).

  • Each call costs roughly 100–200 tokens, plus a one-time ~1–2k for the tool definitions. An hour of play is a rounding error in context.

Security

The full connector URL is the credential. Anyone who has it can drive your toy. Do not screenshot it or paste it into chats.

  • Fail-closed. With no MCP_ACCESS_KEY configured, the Worker returns 401 to everything; there is never an unprotected window. A wrong key also gets 401.

  • Whitespace-tolerant key comparison, so a stray newline from copy-paste cannot lock you out.

  • No secrets in code. The Lovense token and access key live in Cloudflare secrets, never in source or git. The locally generated .access-key.txt is in .gitignore.

  • The Worker stores nothing. No command logs, no pairing data.

Rotating the key

If you suspect a leak, or the URL ever appeared in a chat log, rotate it:

node -e "console.log(require('crypto').randomBytes(32).toString('base64url'))"
npx wrangler secret put MCP_ACCESS_KEY    # paste the new key

Then update the URL in the claude.ai connector settings. The old URL stops working immediately; no redeploy and no re-pairing needed.

Troubleshooting

Every row below actually happened, listed in deployment order.

Symptom

Cause

Fix

Developer application says "account does not exist or password incorrect"

The application form is also a login form; it wants an existing Lovense account's password

Register and log in at lovense.com first, then apply

Two tokens appear in the developer dashboard

"Add new token" was clicked by mistake

Use the first one; delete the extra

Deploy succeeds but the URL does not resolve

No workers.dev subdomain registered yet

Cloudflare dashboard → Workers & Pages → register one

401 forever after setting the secret

Used echo "xxx" | wrangler secret put; PowerShell appended a newline

Use interactive wrangler secret put and paste at the prompt

Still 401 right after setting the secret

Secret propagation delay

Wait 10–20 seconds and retry

QR code request returns "Please set your Callback URL in your developer dashboard"

Lovense requires a callback URL; a correct token is not enough

Set Callback URL to the full /lovense/callback address

Callback URL shows "please enter a URL" and will not save

On a phone in portrait, the form collapses and another section's validation blocks the whole submit

Rotate the phone to landscape and Save, or use a desktop browser

Callback endpoint returns 405 on GET

Cloudflare edge cached an old response

Current version returns 200 for GET/HEAD/POST; retry with a random query parameter

No "add custom connector" in the iOS Claude app

The app has no such entry

Add it at claude.ai on the web; the app syncs

Scanning the QR fails

Codes expire within minutes

Generate a new one and scan immediately

Command succeeds, toy does not move

Lovense Remote was killed or Bluetooth dropped; or the command uses a channel the toy lacks

Keep Remote running; use vibrate for the Vulse

Known limitations

  • Tested only on the Lovense Vulse. Other models are unverified.

  • Depth is not implemented.

  • Cloud only; Lovense's local LAN mode is not implemented.

  • No OAuth. Auth is the key in the URL: fine for one person, not for sharing.

Development

npm test                    # unit tests, fully mocked, never touch a real device
npx wrangler dev            # local server, reads .dev.vars (see .dev.vars.example)
node scripts/check.mjs      # protocol checks against the local instance
npx wrangler tail           # live logs

Credits

License

MIT © Rosalie. See LICENSE.

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables remote control of Lovense toys through Claude using natural language commands. Supports vibration patterns, presets, and intensity control from any device via Cloudflare Workers.
    6
    Apache 2.0
  • F
    license
    Not graded
    quality
    D
    maintenance
    An MCP server that connects Claude and other MCP clients to buttplug.io, allowing AI models to directly control and orchestrate intimate hardware in real-time. It provides a suite of tools for device discovery and haptic commands like vibration, rotation, and patterned pulses.
    -
  • F
    license
    Not graded
    quality
    D
    maintenance
    Deploys a remote MCP server on Cloudflare Workers without authentication, allowing custom tool definitions and connections to AI Playground and Claude Desktop.
    -