Survey Tools — MCP Tool Reference¶
Survey tools handle the survey execution lifecycle: creating survey sessions, navigating questionnaire flows, submitting responses, and generating synthetic test data. Comment items are automatically skipped — callers never receive them.
list_surveys¶
List surveys, optionally filtered by campaign or respondent.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
campaign_id |
string |
No | — | Filter by campaign ID |
respondent_id |
string |
No | — | Filter by respondent ID |
status |
string |
No | — | Filter: "pending", "in_progress", or "completed" |
limit |
integer |
No | 100 |
Maximum results to return |
Returns: { items: [...], count, limit }
create_survey¶
Create a new survey for a respondent.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
questionnaire_id |
string |
Yes | — | Questionnaire to use |
respondent_id |
string |
Yes | — | Respondent UUID |
interviewer_user_id |
string |
No | — | For phone/in-person interviews. Omit for self-completion |
campaign_id |
string |
No | — | Associate with a campaign |
Returns: { id, questionnaire_id, interviewer_user_id, respondent_id, campaign_id, mode }
bulk_create_surveys¶
Create surveys for all respondents in a campaign's assigned pool. Skips respondents who already have surveys.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
campaign_id |
string |
Yes | — | Campaign UUID |
Returns:
{
"status": "success",
"campaign_id": "...",
"created_count": 45,
"skipped_count": 5,
"surveys": [{"id": "...", "respondent_id": "..."}]
}
Requires: Campaign must have both a questionnaire and a respondent pool assigned.
get_survey_current_item¶
Get the current question in a survey. Initializes the survey state on first call.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
survey_id |
string |
Yes | — | Survey UUID |
Returns (question):
{
"survey_id": "...",
"id": "q_age",
"text": "What is your age?",
"kind": "Question",
"input": {"control": "slider", "min": 18, "max": 99},
"required": true,
"isLast": false,
"visited": false
}
Returns (complete): { status: "complete", survey_id, message: "Survey completed" }
Auto-Comment Skipping
Comment items (informational text) are transparently skipped — up to 50 consecutive Comments are auto-processed. Callers only receive actionable items (Question, QuestionGroup, MatrixQuestion).
get_question_options¶
Get the available response options for a question. Useful for understanding what values to submit.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
survey_id |
string |
Yes | — | Survey UUID |
item_id |
string |
No | — | Specific item ID. If omitted, uses current item |
Returns (choice control):
{
"survey_id": "...",
"item_id": "q_gender",
"question_text": "What is your gender?",
"control_type": "radio",
"options": [
{"value": "male", "text": "Male"},
{"value": "female", "text": "Female"},
{"value": "other", "text": "Other"}
],
"required": true
}
Returns (range control):
Control types: radio, dropdown, checkbox, slider, switch, editbox, textarea. Text controls return empty options.
submit_survey_response¶
Submit an answer for the current question and advance to the next item.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
survey_id |
string |
Yes | — | Survey UUID |
item_id |
string |
Yes | — | Item ID being answered |
outcome |
any |
Yes | — | Response value (type depends on control) |
Returns:
The survey_status field only appears when the survey completes after this response. Trailing Comment items are auto-processed after each submission.
Call get_survey_current_item first
The survey must be initialized before submitting responses. If not initialized, returns: {"error": "Survey not initialized. Call get_survey_current_item first."}
finish_survey¶
Explicitly mark a survey as completed. Use for edge cases where auto-completion doesn't trigger.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
survey_id |
string |
Yes | — | Survey UUID |
Returns: { status: "success" | "already_complete", survey_id, message }.
mass_fill_surveys¶
Fill all pending surveys in a campaign with synthetic test responses. Do not use on campaigns with real respondent data.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
campaign_id |
string |
Yes | — | Campaign UUID |
distribution |
string |
No | "realistic" |
Strategy: "realistic", "random", "stratified", or "llm" |
max_surveys |
integer |
No | — | Limit surveys to fill. null = all pending |
profiles |
string[] |
No | ["random"] |
Persona profiles, assigned round-robin |
Returns:
{
"status": "success",
"campaign_id": "...",
"completed": 48,
"failed": 2,
"total_responses": 480,
"total_surveys": 50,
"already_completed": 0,
"distribution": "realistic",
"profiles_used": ["young_single", "retired"],
"failed_surveys": [{"survey_id": "...", "error": "..."}]
}
Distribution Modes¶
| Mode | Engine | Speed | Description |
|---|---|---|---|
realistic |
Weighted random | Fast | Profile-aware demographic weighting (default) |
random |
Uniform random | Fast | Pure random, no demographic influence |
stratified |
Demographic strata | Fast | Quota-balanced responses |
llm |
Claude Haiku API | ~1s/question | AI-generated, persona-consistent responses. Requires ANTHROPIC_API_KEY |
Persona Profiles¶
Assigned round-robin to respondents. Available profiles:
| Profile | Age | Income | Behavior |
|---|---|---|---|
young_single |
25–35 | $65k | Progressive, tech-savvy, favors middle options |
married_family |
30–50 | $80k | Practical, value-oriented |
retired |
65+ | $55k | Conservative, favors early/traditional options |
high_income |
45 | $150k+ | Quality-focused, favors premium options |
random |
40 | $70k | No particular bias |
Item Kind Handling¶
| Item Kind | Outcome Format | Example |
|---|---|---|
Comment |
null (auto-skipped) |
Informational text |
Question |
Single value | "option_a", 42, true |
QuestionGroup |
List of values | ["val1", "val2", "val3"] |
MatrixQuestion |
Dict with _row_col keys |
{"_0_0": "val", "_0_1": "val"} |
Error Handling¶
Common Errors¶
| Scenario | Response |
|---|---|
| Survey not found | {"error": "Survey {id} not found"} |
| Campaign not found | {"error": "Campaign {id} not found"} |
| Questionnaire not found | {"error": "Questionnaire {id} not found"} |
| Survey not initialized | {"error": "Survey not initialized. Call get_survey_current_item first."} |
| No pool assigned | {"error": "Campaign has no respondent pool assigned"} |
| No incomplete surveys | {"status": "no_surveys", "message": "No incomplete surveys found in campaign"} |
Survey State Machine¶
[Not Started] → get_survey_current_item → [In Progress]
[In Progress] → submit_survey_response → [In Progress | Completed]
[In Progress] → finish_survey → [Completed]
- Initialization: First call to
get_survey_current_itemloads the QML and creates the survey state - Auto-completion: Surveys complete automatically when the last item is answered
- Comment skipping: Comment items are transparently processed (up to 50 consecutive) — callers never receive them
- Persistence: Every response is immediately persisted to the database