MCP server
One hosted, stateless Streamable HTTP endpoint for every host, with OAuth 2.1, plus a small npx wrapper for hosts that only run local servers.
Endpoint: https://mcp.50heads.com/mcp
Hosted: add the endpoint and sign in with OAuth in the browser. Nothing to install, and you set the connection's daily spend cap when you sign in. Local: npx -y @50heads/mcp runs the same tools over stdio for hosts that launch a command. It needs Node 20 or later and an API key from Developers in the portal, or a one-time npx -y @50heads/mcp login.
Claude (claude.ai and Claude Desktop)
Hosted, sign in with OAuth. Settings, Connectors, Add custom connector. Paste the URL and sign in when asked. On Team and Enterprise plans an owner adds it for the organization first.
https://mcp.50heads.com/mcpOr with an API key, in claude_desktop_config.json (macOS: ~/Library/Application Support/Claude/, Windows: %APPDATA%\Claude\).
{
"mcpServers": {
"50heads": {
"command": "npx",
"args": [
"-y",
"@50heads/mcp"
],
"env": {
"FIFTYHEADS_API_KEY": "fh_live_…"
}
}
}
}Claude Code
Hosted, sign in with OAuth. Run in a terminal, then /mcp in Claude Code to sign in.
claude mcp add --transport http 50heads https://mcp.50heads.com/mcpOr with an API key (CI and scripts):
claude mcp add --transport http 50heads https://mcp.50heads.com/mcp --header "Authorization: Bearer fh_live_…"Cursor
Hosted, sign in with OAuth. ~/.cursor/mcp.json (or .cursor/mcp.json in a project). Cursor opens the sign-in page.
{
"mcpServers": {
"50heads": {
"url": "https://mcp.50heads.com/mcp"
}
}
}Or with an API key:
{
"mcpServers": {
"50heads": {
"url": "https://mcp.50heads.com/mcp",
"headers": {
"Authorization": "Bearer fh_live_…"
}
}
}
}ChatGPT
Hosted, sign in with OAuth. Settings, Apps and Connectors, Advanced settings, turn on Developer mode, then Create. Paste the URL and choose OAuth. On Business and Enterprise plans an admin turns on Developer mode first.
https://mcp.50heads.com/mcpVS Code
Hosted, sign in with OAuth. .vscode/mcp.json in the workspace, or MCP: Add Server from the command palette.
{
"servers": {
"50heads": {
"type": "http",
"url": "https://mcp.50heads.com/mcp"
}
}
}Or from a terminal:
code --add-mcp '{"name":"50heads","type":"http","url":"https://mcp.50heads.com/mcp"}'Windsurf
Local, with an API key. ~/.codeium/windsurf/mcp_config.json, or Windsurf Settings, Cascade, MCP servers, View raw config.
{
"mcpServers": {
"50heads": {
"command": "npx",
"args": [
"-y",
"@50heads/mcp"
],
"env": {
"FIFTYHEADS_API_KEY": "fh_live_…"
}
}
}
}Or the hosted server with an API key:
{
"mcpServers": {
"50heads": {
"serverUrl": "https://mcp.50heads.com/mcp",
"headers": {
"Authorization": "Bearer fh_live_…"
}
}
}
}Any other host
Local, with an API key. Hosts that launch a local command. Needs Node 20 or later and an API key from the dashboard.
FIFTYHEADS_API_KEY=fh_live_… npx -y @50heads/mcpHosts that speak Streamable HTTP: https://mcp.50heads.com/mcp with the header "Authorization: Bearer fh_live_…", or OAuth.
{
"mcpServers": {
"50heads": {
"url": "https://mcp.50heads.com/mcp",
"headers": {
"Authorization": "Bearer fh_live_…"
}
}
}
}npx -y @50heads/mcp config [host] prints any of these. To check it works, ask your host to use 50heads to estimate a question: an estimate is free and never spends credits.
Where to find 50heads
| Where | What | Available |
|---|---|---|
| Hosted server | https://mcp.50heads.com/mcp, with OAuth or an API key | Now |
| npm | @50heads/mcp, for hosts that launch a local command | Now |
| Official MCP Registry | com.50heads/mcp, with the hosted server and the npm package | Now |
| Directories | The Claude, ChatGPT and Cursor directories, Smithery, Glama, PulseMCP and mcp.so | Coming soon |
Until a directory listing is live, add the hosted server yourself with the instructions above. Releases use calendar versions (2026.924.1 is the first release on 24 September 2026); the hosted server, the npm package and the registry entry carry the same one.
We don't use your questions, the answers you buy or the reasons heads write to train AI models, and we don't sell them. More in AI and your data and the privacy policy.
OAuth
The server is an OAuth 2.1 resource server. Hosts discover everything from https://mcp.50heads.com/.well-known/oauth-protected-resource, which points at the authorization server https://auth.50heads.com. PKCE (S256) and the resource parameter are required; dynamic client registration and client ID metadata documents are both supported. Access tokens last an hour; refresh tokens rotate and last 30 days.
At consent the person picks scopes and a daily spend cap for the connection (5,000 credits unless they change it). They can change or revoke it any time under Developers in the portal; a revoked connection stops within a second.
Scopes
questions:read, questions:write, templates:read, account:read, webhooks:read, webhooks:write, apps:read, apps:write, organization:read, organization:write, members:read, members:write, audit:read, events:read. A call that needs a scope the token lacks returns insufficient_scope so the host can ask for it.
What an agent can do
The server lists its tools to the host when it connects (tools/list), with a description and a schema for each, so a host never needs this page to know them. The package README names every tool and its parameters, and is the place to look: github.com/50heads/mcp, also shown on npm. Tool names can change between releases, so read them from the server or the README rather than from here.
| Capability | Scope |
|---|---|
| Price, time and validation for a question (never spends), and asking one, or a set of them behind one link | questions:write |
| Adding heads, cancelling, flagging an answer, filing questions in projects and labels, uploading images | questions:write |
| Reading results and individual answers, listing questions, projects and labels, exporting results | questions:read |
| Who the connection acts as, its scopes, caps and rate limits, and whether 50heads is working or asking is paused | account:read |
| Credits, what is reserved, and what is left under the connection's cap | account:read |
| Templates, targeting options, interest audiences, help search, a pre-filled ask link, sending feedback | none |
| Managing webhook endpoints (create, change, rotate the secret, test, replay, delete) | webhooks:write |
| Reading webhook endpoints, deliveries and events | webhooks:read |
| Listing the Slack workspaces, Microsoft Teams tenants, Jira sites, Linear workspaces and Zapier connections | apps:read |
| Reading the organization, its domains, SCIM status and service accounts (admins; read-only) | organization:read |
| Reading the organization's audit events (admins; read-only) | audit:read |
| Warehouse export status: each bucket, its state and its last runs (admins; read-only) | organization:read |
| Reading where one member is signed in (admins; read-only) | members:read |
Nothing here changes an organization, a key or single sign-on: those stay with a person (see Authentication). Asking tools need an idempotency_key, so a retry never asks or charges twice.
Pre-filled ask links
https://50heads.com/app/ask?… opens the composer with a question filled in, for a person to check the price and time and ask. The server can write these for an agent; you can write them by hand too. Nothing is asked until the person presses Ask. The composer fills itself only when the link has text or at least one optionLabel.
| Parameter | Meaning |
|---|---|
type | single_choice, multi_choice, ab_image, pairwise, scale_1_5, ranking, yes_no, yes_mostly_no, free_text, click_test, reaction or rate_each. yes_no is Yes or No. yes_mostly_no adds Mostly. |
mostly=on | On a yes/no ask, adds Mostly. Leave it off for Yes and No only. |
text | The question. |
context | One line of background. |
language | Such as en or pt-BR. Default en. |
optionLabel | An option; repeat for each, in order. |
optionImage | An https image for the option in the same position; repeat, empty for none. |
optionImages | Up to four https images for the option in the same position, space-separated, in swipe order; repeat, empty for none. |
scaleLow, scaleHigh | What 1 and 5 mean, on scale_1_5 and rate_each. Both or neither. |
stimulusImage, stimulusText | Shown above the question. |
neither=on | Adds a Neither option. |
n | Heads, 10 to 5,000. |
tier | 1, 2 or 3. |
rush=on | Show to heads first. Closes 4 hours after it goes live. |
country | ISO code; repeat for each. |
tag | A tag id; repeat. Kept at Tier 2 and 3 only. |
template | Opens a template instead (other fields are ignored). |
followUp | Opens a follow-up to that question id; type and text apply. |
reask | Re-asks the unanswered part of that question id. |
mode=bulk | Opens the bulk composer. |
Errors
JSON-RPC errors carry error.data.code: validation and not_found as −32602; insufficient_credits, spend_cap_exceeded (the API's spend_cap_reached), idempotency_conflict and content_refused as −32001; rate_limited and unavailable as −32000. Every message is one sentence a model can act on.
Limits
1 MB request bodies. Images by URL or upload only, never large inline base64. 60 requests a minute per connection and 10 asks a minute.