MCP server
Programmatic admin for VerifyHuman from any MCP-compatible client — Claude Desktop, Claude Code, Cursor, Continue, or your own. Hosted and OAuth-secured. Connect once, then ask your LLM to manage projects, rotate signing keys, mint demo keys, or inspect analytics — same surface as the dashboard.
Install (Claude Code)
From a terminal where the Claude Code CLI is installed:
claude mcp add verifyhuman https://vhuman.riwi.com/mcpFirst call triggers an OAuth 2.1 + PKCE consent in your browser. After that, Claude Code has the full 34-tool surface available — see first project below for a 60-second walkthrough.
Other clients (Claude Desktop, Cursor, Continue): use the builder below for a connector spec, or paste the URL into your client's MCP-server config panel.
Quick connect
Pick your MCP client. First tool call opens a browser for OAuth login — same Auth0 session as the VerifyHuman dashboard.
Claude Desktop
Paste into claude_desktop_config.json (Settings → Developer → Edit Config).
{
"mcpServers": {
"verifyhuman": {
"url": "https://vhuman.riwi.com/mcp"
}
}
}JSONClaude Code
Run from a terminal in any directory. Adds to your local Claude Code config.
claude mcp add verifyhuman https://vhuman.riwi.com/mcpbashCursor / Continue / others
Any MCP-compatible client supporting Streamable HTTP + OAuth 2.1.
{
"mcpServers": {
"verifyhuman": {
"url": "https://vhuman.riwi.com/mcp"
}
}
}JSONStaging URL: https://vhuman.riwi.com/mcp
Your first project — paste this prompt into Claude
Once the MCP is connected, the fastest way to bootstrap a new integration is one paste into Claude:
Create a new VerifyHuman project named "My survey site" and mint
me a project-scoped API key for it. Then tell me:
- the project ID
- the API key (vf_live_*)
- what env-var names you recommend I useClaude will call provision_project_with_key (the one-round-trip combo of project create + key mint — the recommended path for first integrations), show you the UUID + secret, and walk you through the NEXT_PUBLIC_VH_SITE_KEY / VH_API_KEY split.
Save the API key on first display — it's shown ONCE. You can always re-discover what project a key is configured for via GET /api/v1/api-keys/current later.
What is it?
VerifyHuman exposes its admin API as a remote Model Context Protocol server. Any MCP-compatible LLM client can connect to it via OAuth 2.1 + PKCE — no local install, no Python, no env vars. Once connected, the LLM has tools for the full customer surface:
- Projects — list, get,
create_project, andprovision_project_with_key(the latter creates a project AND mints an API key for it in one round-trip; ideal for survey platforms that auto-provision one VH project per study). - API keys — list, create, revoke
- Verifications — list, look up, query analytics
- Widget config — get, set mode
- Webhooks — full CRUD, test delivery
- Signing keys — inspect, rotate
- Demo keys — mint short-lived test keys (billing-isolated)
- Phase 3 — read per-question scoring events
- Server-Side (fraud_gate) — the full VH-Lite journey: fetch the integration contract (
lite_integration_guide), create a fraud_gate project (lite_create_project), fire a live test score (lite_score_test_call), read the effective scoring config (lite_get_config), pull usage stats (lite_stats), simulate a threshold change (lite_simulate_threshold), read fitted ground-truth and recommendations (lite_ground_truth,lite_threshold_recommendations), and apply the calibration bands (lite_set_thresholds). See the Server-Side scoring API.
OAuth discovery
For MCP clients that don't have a built-in "add server" UI: discovery metadata is served at https://vhuman.riwi.com/api/v1/.well-known/oauth-authorization-server. Well-behaved clients fetch that automatically. (The non-standard /api/v1/ prefix is historical — for clients that look at the root path, /.well-known/oauth-authorization-server is being added as a mirror in a follow-up.) Demo verifications minted via the MCP demo-key tool run with is_demo=true and stay isolated from billed usage — safe to play with.
What the LLM can do
Once connected, your LLM has 34 tools spanning the admin surface. A few representative prompts:
- "List my VerifyHuman projects and tell me which ones haven't been verified against in the last week."
- "Create a 30-minute demo key for project X and send me the URL."
- "Rotate the signing key for project Y. Confirm the rotation timestamp moved."
- "Show me yesterday's analytics for project Z — pass rate, failure breakdown, average liveness score."
- "Add a webhook on project A pointing at
https://my-receiver.example/vhfor theverification.completedevent, then test it." - "For my Server-Side project, fire a test score for a datacenter IP and show me the recommendation, then simulate moving the block threshold to 80."
Server-to-server provisioning (CoolTool-style integrations)
Higher-level products that embed VerifyHuman often want to auto-create one VH project per study, panel, or campaign. The MCP provision_project_with_key tool is the intended entry point.
Heads up — MCP does NOT use an API key. The credential type for server-to-server MCP calls is OAuth 2.1 client credentials (a client_id and client_secret pair), not a vf_live_* API key. Your backend exchanges the credentials for a short-lived bearer token and passes that to the MCP server. If you find yourself wanting to set a single VERIFYHUMAN_PLATFORM_API_KEY env var for MCP, you're on the wrong path — either switch to the REST flow at /docs/api → /projects/provision or contact onboarding to register a service-account OAuth client.
Pseudocode (your backend, called from your "new study" handler):
# Pseudocode — your backend, called from your "new study" handler
response = await mcp_client.call_tool(
"provision_project_with_key",
{
"name": f"Study {study.id}",
"external_id": study.id, # cross-reference back to you
"api_key_name": f"study-{study.id}-key",
"is_test_key": False, # live key for production traffic
},
)
# Persist BOTH in your study's config:
study.verifyhuman_site_key = response["site_key"] # → SDK siteKey
study.verifyhuman_api_key = response["api_key"] # → /token/verify
# (api_key is the full plaintext — only shown ONCE)The composite handles both halves atomically. If api-key minting fails after the project was created, the response has api_key: null + an api_key_error string — you can retry with create_api_key(project_id) using the returnedproject_id.
Scopes required: projects:write AND keys:write on the bearer token. First-party MCP clients (Claude Desktop, Claude Code) get the full scope set at consent time; service-account integrations request both explicitly.
When to use MCP vs. the dashboard vs. the SDK
- SDK — you're embedding the verify widget in your product. See the SDK guide.
- Dashboard — you want a visual UI to inspect projects, edit widget config, browse analytics, manage team.
- MCP — you want to script those admin actions or have an LLM do them for you. Same operations as the dashboard, just via tool calls.
Security model
- OAuth 2.1 with PKCE — the standard public-client flow. Each LLM client gets browser-driven consent and short-lived access tokens (1 hour) plus rotating refresh tokens (30 days).
- Tokens are scoped to your org. Every tool call resolves the bearer to a specific user + organization; the LLM cannot reach projects in another org even if it knows their IDs.
- PII never leaves the server in tool responses. Verification logs strip IP addresses and user-agent strings before returning to the LLM.
- Plaintext secrets surface once. API keys, webhook signing secrets, and project signing keys are returned in plaintext only at creation/rotation; subsequent reads show metadata only.
- Refresh-token theft detection. Re-using a rotated refresh token revokes the entire chain — both old and new bearers — forcing a fresh login.
Tool scopes
Different tools require different scopes on the bearer token. First-party clients (Claude Desktop, Claude Code) get the full scope set by default at consent time. Third-party clients can request a subset:
projects:read— list / read project metadataprojects:write— change widget mode, project settings, create fraud_gate projects, and set Server-Side (VH-Lite) calibration thresholdsverifications:read— read verification logs and per-question eventsanalytics:read— pass rates, quota, time-serieskeys:write— mint / revoke API keys, rotate signing keyswebhooks:write— CRUD webhooks and test delivery
Not in scope
Some operations stay dashboard-only on purpose — they're admin-sensitive or human-in-the-loop:
- Billing tier changes
- Organization member invitations / removal
- DSR / appeals / legal endpoints
Self-hosted / local stdio MCP
For air-gapped environments or contributors hacking on the tool surface, an older stdio-transport package is available at packages/mcp/ in the repository. It uses Auth0 Device Code flow and runs as a Python subprocess of the LLM client. Most customers should prefer the hosted server — it's zero-install, gets fixes immediately, and doesn't require local Python or env-var configuration.
Troubleshooting
- Connection fails / 401 errors — your tokens may have expired. Most clients re-do the OAuth flow automatically; if not, remove the MCP server from your client config and re-add it. The browser opens for a fresh login.
- "org not found" on a tool call — your bearer is scoped to a specific org. If you belong to multiple, the first one is selected by default; disconnecting and reconnecting lets you pick a different org during consent.
- Rate-limit errors on demo-key minting — the demo-key endpoint is IP rate-limited (10/minute soft, then a short hard block). Slow down and retry.
- Tool says "not_found" for a project I own — that response also covers cross-org access (an existence leak would be a security hole). Confirm you're connected as the right org via the
get_organizationtool.
Issues + roadmap: docs/plans/mcp_hosted_server.md.