MCP Server
Control Chorus Research from any AI assistant or coding agent via the Model Context Protocol (MCP).
Hosted Remote Server
https://mcp.chorusresearch.io/mcpStreamable HTTP · OAuth sign-in · no API key
Local stdio Package
@chorus-research/mcpRuns via npx · authenticates with an API key
The Model Context Protocol (MCP) is an open standard that lets AI assistants connect to external tools and data sources. The Chorus Research MCP server gives your AI agent direct access to survey creation, audience building, launch, and response collection — no HTTP calls or SDK wrappers needed.
The server exposes:
- 15 tools — Surveys, audiences, custom audience building, pricing, launch, and response export
- 2 resources — Audience catalog and pricing configuration
- 2 prompts — Survey design guide and pre-launch checklist
There are two ways to connect, and the launch flow differs between them:
- Hosted remote server (Claude.ai, Claude Desktop, ChatGPT, and other remote-MCP clients) — sign in with your Chorus account via OAuth. Launching returns a secure browser checkout link; you review the cost and pay on the Chorus website. No tool on the remote server ever charges money.
- Local stdio server (Claude Code, Cursor, Windsurf) — runs on your machine with an API key. Launching uses an in-tool two-step estimate/confirm flow that charges your saved payment method.
Hosted Remote Server
The easiest way to connect. Add the server URL to your client and sign in with your Chorus Research account — no installation, no API key. Works with Claude.ai, Claude Desktop, ChatGPT, and any client that supports remote MCP servers with OAuth.
Server URL
https://mcp.chorusresearch.io/mcpClaude.ai / Claude Desktop
- Go to Settings → Connectors → Add custom connector
- Enter the server URL:
https://mcp.chorusresearch.io/mcp - Click Connect and sign in with your Chorus Research account when prompted
Claude Code
Add the remote server from your terminal:
claude mcp add --transport http chorus-research https://mcp.chorusresearch.io/mcpChatGPT
Add the server URL as a connector in Settings → Connectors (requires a plan with connector support) and complete the OAuth sign-in.
estimate_launch returns a secure checkout link. You review the cost and pay on the Chorus website — the connector itself never charges anything.Local stdio Server
For coding agents like Claude Code, Cursor, and Windsurf, you can run the server locally. No manual installation is needed — MCP clients launch it automatically using npx.
npx @chorus-research/mcpnpm install -g @chorus-research/mcp
chorus-research-mcpEnvironment Variables
The local server requires a CHORUS_API_KEY. You can obtain a key from the API Keys section in the Chorus Research app.
| Parameter | Type | Required | Description |
|---|---|---|---|
CHORUS_API_KEY | string | Required | Your Chorus Research API key. Obtain from the API Keys section in the app. (Local stdio only — the remote server uses OAuth.) |
CHORUS_API_BASE_URL | string | Optional | Override the API base URL. Default: https://api.chorusresearch.io |
Claude Code
Add to .mcp.json in your project root:
{
"mcpServers": {
"chorus-research": {
"command": "npx",
"args": [
"-y",
"@chorus-research/mcp"
],
"env": {
"CHORUS_API_KEY": "your-api-key"
}
}
}
}Claude Desktop
Add to your config file:
- macOS:
~/Library/Application Support/Claude/claude_desktop_config.json - Windows:
%APPDATA%\Claude\claude_desktop_config.json
{
"mcpServers": {
"chorus-research": {
"command": "npx",
"args": [
"-y",
"@chorus-research/mcp"
],
"env": {
"CHORUS_API_KEY": "your-api-key"
}
}
}
}Cursor
Add to .cursor/mcp.json in your project root:
{
"mcpServers": {
"chorus-research": {
"command": "npx",
"args": [
"-y",
"@chorus-research/mcp"
],
"env": {
"CHORUS_API_KEY": "your-api-key"
}
}
}
}Windsurf
Add to ~/.codeium/windsurf/mcp_config.json:
{
"mcpServers": {
"chorus-research": {
"command": "npx",
"args": [
"-y",
"@chorus-research/mcp"
],
"env": {
"CHORUS_API_KEY": "your-api-key"
}
}
}
}Tools
The server exposes 15 tools organized into 6 groups. Your AI agent can call these directly — no HTTP setup required. The launch surface differs by mode: the remote server exposes the read-only estimate_launch (browser checkout), while the local stdio server exposes the two-step launch_survey instead.
Surveys
list_surveys
List surveys with optional filtering by status and pagination. Returns survey metadata (id, name, status, dates) but not the full JSON definition.
| Parameter | Type | Required | Description |
|---|---|---|---|
status | string | Optional | Filter by status: draft, live, complete, cancelled |
page | integer | Optional | Page number Default: 1 |
pageSize | integer | Optional | Results per page (max 100) Default: 20 |
sort | string | Optional | Sort field: createdAt, updatedAt, name |
order | string | Optional | Sort order: asc or desc |
get_survey
Get full details of a specific survey including the complete JSON definition, status, and metadata.
| Parameter | Type | Required | Description |
|---|---|---|---|
surveyId | uuid | Required | Survey ID (UUID) |
create_survey
Create a new survey draft. The survey will be created in draft status — nothing launches or charges.
Conditional logic is supported via standard SurveyJS expressions: visibleIf, enableIf, requiredIf, and choicesVisibleIf all work (e.g., visibleIf: "{news_freq} <> 'Never'").
visibleIf, and filter during analysis.| Parameter | Type | Required | Description |
|---|---|---|---|
name | string | Required | Survey name (1-255 characters) |
survey | object | Required | SurveyJS JSON definition. Must include a pages array with question elements. Maximum 10 questions. Conditional logic via visibleIf/enableIf/requiredIf/choicesVisibleIf is supported. |
targetCompletes | integer | Required | Target number of completed responses (5-5000, $5 minimum purchase) |
description | string | Optional | Survey description (max 1000 characters) |
Audiences
list_audiences
List all available audience segments for survey targeting. Each audience includes cost per response, targeting criteria, and estimated fielding times.
No parameters required.
get_audience
Get detailed information about a specific audience segment including targeting criteria, cost, and fielding time estimates.
| Parameter | Type | Required | Description |
|---|---|---|---|
audienceId | string | Required | Audience identifier (e.g., "genpop") |
Custom Audience Builder
Beyond the preset segments, you can build custom audiences from the platform's targeting catalog (thousands of pre-profiled screening qualifications). The flow: search_qualifications → build_audience → save_audience. The saved audience id then works anywhere an audienceId is accepted — pricing and launching included.
search_qualifications
Search the targeting catalog for qualifications (screening questions with pre-profiled answers) matching a keyword, or fetch specific qualifications by id with their complete answer option lists. Search with broad stems ("employment", "income", "education") — answer option text is searched too.
| Parameter | Type | Required | Description |
|---|---|---|---|
query | string | Optional | Keywords to search the catalog (names, question text, and answer options are searched). Provide this or question_ids. |
question_ids | integer[] | Optional | Fetch these qualification ids with complete option lists (max 10) |
country_code | string | Optional | ISO 3166-1 alpha-2 country code Default: US |
language_code | string | Optional | ISO 639-1 language code Default: EN |
build_audience
Build a structured, validated audience specification. Pass structured criteria referencing catalog ids from search_qualifications — criteria are verified against the catalog. With only a natural-language description, a limited offline parser maps age, gender, and parental status.
| Parameter | Type | Required | Description |
|---|---|---|---|
description | string | Required | Natural language description of the target audience (e.g., "US adults 25-44 who are employed") |
criteria | array | Optional | Structured criteria using catalog ids from search_qualifications (max 20). Each criterion: { question_id, buckets: [{ option_ids, target? }] }. When provided, these define the spec's cards. |
completes | integer | Optional | Number of survey completes wanted (min 5) |
country_code | string | Optional | ISO 3166-1 alpha-2 country code Default: US |
validate_audience
Validate an audience specification and return warnings about potential issues like missing criteria, quota sum mismatches, or empty selections. Qualification and option ids are checked against the targeting catalog. Nothing is modified.
| Parameter | Type | Required | Description |
|---|---|---|---|
spec | object | Required | The AudienceSpec JSON object to validate |
save_audience
Save an audience specification to your account. The saved audience gets an id usable as the audienceId in estimate_cost and when launching, and it appears in the audience editor on the Chorus website. The response includes the server-computed price per response.
| Parameter | Type | Required | Description |
|---|---|---|---|
spec | object | Required | The AudienceSpec JSON object from build_audience |
name | string | Optional | Audience name (1-255 characters; defaults to the spec's name) |
list_saved_audiences
List audiences available to your account: the platform's preset segments plus custom audiences saved with save_audience (marked type: "custom").
No parameters required.
Pricing
get_pricing_config
Get the current pricing configuration including cost per response and currency.
No parameters required.
estimate_cost
Calculate the cost to launch a survey to a specific audience. Works with preset segments (flat $1/response, $5 minimum) and saved custom audiences (priced from the audience criteria; the breakdown explains the rate). This is a calculation only — nothing is charged.
| Parameter | Type | Required | Description |
|---|---|---|---|
audienceId | string | Required | Preset audience segment ID (e.g., "genpop") or a saved custom audience id from save_audience |
targetCompletes | integer | Required | Number of completed responses desired (5-5000, $5 minimum purchase) |
projectId | uuid | Optional | Optional survey project ID. When provided, interview length is estimated from that project's survey; when omitted, a 10-minute default is assumed (the total cost is the same either way). |
Launch
estimate_launchremote only
Estimate the cost of launching a survey and get a secure checkout link. Returns a cost breakdown plus a checkoutUrl the user opens in their browser to review and pay on the Chorus website. This tool is read-only and never charges. After checkout, call get_survey_status to confirm fielding started.
| Parameter | Type | Required | Description |
|---|---|---|---|
surveyId | uuid | Required | Survey ID to launch |
audienceId | string | Required | Preset audience segment ID (e.g., "genpop") or a saved custom audience id from save_audience |
targetCompletes | integer | Required | Number of completed responses desired (5-5000, $5 minimum purchase) |
launch_surveystdio only
Launch a survey to collect responses. This is a two-step process to prevent accidental charges.
| Parameter | Type | Required | Description |
|---|---|---|---|
surveyId | uuid | Required | Survey ID to launch |
audienceId | string | Optional | Step 1: Preset audience segment ID (e.g., "genpop") or a saved custom audience id. Required for the estimate step. |
targetCompletes | integer | Optional | Step 1: Number of completed responses desired (5-5000, $5 minimum). Required for the estimate step. |
confirmToken | string | Optional | Step 2: Confirmation token from the estimate step. Provide this to execute the launch. |
paymentMethodId | string | Optional | Step 2: Stripe payment method ID. Uses default payment method if omitted. |
# Step 1: Get estimate and confirmation token
launch_survey(surveyId, audienceId: "genpop", targetCompletes: 100)
→ { estimatedCost: 100.00, confirmToken: "abc123...", expiresAt: "..." }
# Show cost to user, get explicit confirmation
# Step 2: Confirm launch (charges payment, starts fielding)
launch_survey(surveyId, confirmToken: "abc123...")
→ { success: true, workflowId: "launch-...", amountCharged: 100.00 }get_survey_status
Get real-time fielding status including completion count, progress percentage, and estimated completion time. Results are cached for 30 seconds.
| Parameter | Type | Required | Description |
|---|---|---|---|
surveyId | uuid | Required | Survey ID to check status for |
Responses
get_responses
Export survey response data with pagination. Returns individual responses including answer data, metadata (device info, geographic data, and provider demographics when available), and completion status. Each response includes a supplier field indicating the panel source. Only returns responses from published (launched) surveys.
| Parameter | Type | Required | Description |
|---|---|---|---|
surveyId | uuid | Required | Survey ID to export responses for |
page | integer | Optional | Page number Default: 1 |
pageSize | integer | Optional | Results per page (max 1000 on stdio, 200 on remote) Default: 100 stdio / 50 remote |
status | string | Optional | Filter by response status: complete, partial, incomplete Default: complete |
includeDuplicates | boolean | Optional | Include duplicate/flagged responses Default: false |
Resources
MCP resources provide read-only data that your AI agent can access as context.
| URI | Name | Description |
|---|---|---|
chorus://audiences | Audience Catalog | Full catalog of available audience segments with targeting criteria, costs, and estimated fielding times. |
chorus://pricing/config | Pricing Configuration | Current pricing configuration including cost per response and currency. |
Prompts
MCP prompts are reusable templates that guide AI agents through multi-step workflows.
design_survey
Guides an AI agent through survey creation best practices for the Chorus Research platform. Produces a valid SurveyJS JSON definition.
| Parameter | Type | Required | Description |
|---|---|---|---|
topic | string | Required | The research topic or objective for the survey |
audience | string | Optional | Target audience description (e.g., "US adults 18+", "parents with young children") |
numQuestions | string | Optional | Approximate number of questions desired Default: 10 |
launch_checklist
Pre-launch validation checklist. Guides an AI agent through verifying a survey is ready to launch, estimating costs, and confirming with the user before anything is paid.
| Parameter | Type | Required | Description |
|---|---|---|---|
surveyId | uuid | Required | The UUID of the survey to validate for launch |
Quick Start
Here's a typical workflow showing how an AI agent uses the MCP server from start to finish. The examples show the remote-server flow (browser checkout); on the local stdio server, step 6 uses the two-step launch_survey instead.
1. Connect your client
Add the remote server (OAuth sign-in) or the local stdio config (API key) for your MCP client. Verify the server connects by asking your agent to list audiences.
2. Explore audiences
You: "What audiences are available?"
Agent calls: list_audiences()
Agent: "General Population (US adults 18+) is available at $1.00 per
response, plus any custom audiences you've saved. Supports
5-5000 completes ($5 minimum)."3. Build a custom audience (optional)
You: "I want to survey employed US adults aged 25-44"
Agent calls: search_qualifications(query: "employment")
Agent calls: build_audience(description: "Employed US adults 25-44",
criteria: [{ question_id: 642, buckets: [...] }, ...])
Agent calls: save_audience(spec: {...})
Agent: "Saved! Audience 'Employed US adults 25-44' created at $1.85
per response. I'll use it as the audienceId when launching."4. Create a survey
You: "Create a customer satisfaction survey with 5 questions"
Agent calls: create_survey(name: "Customer Satisfaction", survey: {...}, targetCompletes: 100)
Agent: "Done! Survey created in draft status. ID: 550e8400-..."5. Estimate cost
You: "How much would 200 responses cost?"
Agent calls: estimate_cost(audienceId: "genpop", targetCompletes: 200)
Agent: "200 responses × $1.00 each = $200.00 USD total."6. Launch via browser checkout
You: "Launch it"
Agent calls: estimate_launch(surveyId: "550e8400-...", audienceId: "genpop", targetCompletes: 200)
Agent: "The estimated cost is $200.00 USD. Open this secure checkout
link to review and pay — the survey launches after checkout:
https://api.chorusresearch.io/l/AbC123"
You: [complete checkout in browser]
Agent calls: get_survey_status(surveyId: "550e8400-...")
Agent: "Survey is live! Now fielding 200 responses."On the local stdio server, the agent instead calls launch_survey twice (estimate, then confirm) and payment is charged to the default card on file. Manage cards at app.chorusresearch.io/payment-methods.
7. Monitor and export
You: "How's the survey doing?"
Agent calls: get_survey_status(surveyId: "550e8400-...")
Agent: "45 of 200 responses collected (22.5%). Estimated completion: tomorrow."
You: "Export what we have so far"
Agent calls: get_responses(surveyId: "550e8400-...")
Agent: "Here are the 45 completed responses: [data summary]"Troubleshooting
| Issue | Solution |
|---|---|
| OAuth sign-in fails (remote) | Make sure the connector URL is exactly https://mcp.chorusresearch.io/mcp (including the /mcp path). Remove and re-add the connector to restart the sign-in flow. |
| Missing API key error (stdio) | Set CHORUS_API_KEY in your MCP config's env block. Restart your client after changing config. |
| Server not appearing in client | Verify the JSON config is valid (no trailing commas). Check that npx @chorus-research/mcp runs successfully in your terminal. Restart the client. |
| 401 Unauthorized | On stdio, your API key is invalid or has been revoked — generate a new key from the API Keys section in the app. On the remote server, reconnect the connector to sign in again. |
| 429 Too Many Requests | You've hit the rate limit (60 req/min for standard endpoints, 10 req/min for launch). Wait a moment and retry. |
| Expired confirmation token (stdio) | Confirmation tokens are valid for 5 minutes. Call launch_survey again with audienceId and targetCompletes to get a fresh token. |
| Payment method error on launch (stdio) | Add a credit card at app.chorusresearch.io/payment-methods. A default card is required before launching via launch_survey. (The remote server's browser checkout collects payment directly, no saved card needed.) |
| Survey not live after checkout | Complete the checkout page in your browser first, then call get_survey_status. If the checkout link was lost, call estimate_launch again for a fresh one. |
| Tools not showing up | Make sure the package name is @chorus-research/mcp (not chorus-research-mcp). Check your client's MCP logs for errors. |
Need More Help?
- REST API Reference — full HTTP endpoint documentation
- User Guide — getting started with Chorus Research
- Contact Support — reach out for help