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.

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://verifyhuman.riwi.com/mcp"
    }
  }
}
JSON

Claude Code

Run from a terminal in any directory. Adds to your local Claude Code config.

claude mcp add verifyhuman https://verifyhuman.riwi.com/mcp
bash

Cursor / Continue / others

Any MCP-compatible client supporting Streamable HTTP + OAuth 2.1.

{
  "mcpServers": {
    "verifyhuman": {
      "url": "https://verifyhuman.riwi.com/mcp"
    }
  }
}
JSON

Staging URL: https://vhuman.riwi.com/mcp

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 (write operations via dashboard or the new server-to-server /projects/provision endpoint)
  • 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

OAuth discovery

For MCP clients that don't have a built-in "add server" UI: discovery metadata is served at https://verifyhuman.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 23 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/vh for the verification.completed event, then test it."

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 metadata
  • projects:write — change widget mode, project settings
  • verifications:read — read verification logs and per-question events
  • analytics:read — pass rates, quota, time-series
  • keys:write — mint / revoke API keys, rotate signing keys
  • webhooks: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_organization tool.

Issues + roadmap: docs/plans/mcp_hosted_server.md.