The Populous MCP server lets AI clients plan, launch, monitor, and inspect Populous simulations through a structured tool interface.
Use the MCP server when an AI client needs to turn a user request, audience, and supporting context into a Populous simulation without manually building every resource in the web app. The current server surface is the v2 plan workflow:
| Tool | When to use |
|---|---|
getWorkflowGuide | Start here for current workflow guidance. |
startWebsiteLiveSignIn | Only for private/logged-in website tests. |
completeWebsiteLiveSignIn | Complete private website sign-in after browser login. |
uploadStimulus | Only when the user supplied local files/images. |
listStimuli | Only after uploadStimulus. |
requestPlan | Build the plan before launch. |
bindAsset | Only for explicit saved population reuse. |
runSimulation | Launch the approved plan. |
getSimulationStatus | Monitor run progress. |
getSimulationAnalysis | Fetch the compact analysis for normal answers. |
getSimulationArtifactManifest | Inspect available large artifacts. |
querySimulationArtifact | Filter or page through large artifacts server-side. |
getSimulationResults | Fetch the structured result payload. |
getSimulationResultsCsvDownload | Create a raw CSV export link. |
The MCP server URL for ChatGPT and Claude is:
https://run.populous.app/mcpTools read authentication from the MCP connection's bearer token. Do not ask the user for a token inside tool arguments.
How Populous simulations work
A Populous simulation has three core resources:
- Population: the synthetic audience to simulate.
- Experiment: the task, survey, website test, behavior test, or stimulus the audience should evaluate.
- Simulation run: the execution that connects one or more populations to an experiment and returns results.
The v2 MCP flow creates a temporary plan first. requestPlan compiles the user's description and any supplied context into an internal plan, returns a plan_token, and exposes a slot manifest. runSimulation later executes that stored plan exactly as built and bound.
Plan tokens are in-memory server state, not durable saved resources. If a plan_token is unknown or expired, call requestPlan again.
Quickstart
Standard launch workflow
Use this flow for open-ended user requests, including questions, audiences, websites, documents, images, scenarios, business decisions, product ideas, and exploratory prompts.
getWorkflowGuide
requestPlan
runSimulation
getSimulationStatus
getSimulationAnalysis
getSimulationResultsWorkflow:
- Call
getWorkflowGuideonce so the client has the current tool sequence in context. - Call
requestPlanwith a specificdescriptionand any structured context or stimulus references. - Review the returned
summary,status, andslots. - If the user explicitly wants to reuse a saved population, call
listPopulationsand thenbindAsset. - Call
runSimulationwith theplan_token. - Poll
getSimulationStatusuntil the run is complete. - Call
getSimulationAnalysisfor the compact summary, verdict, and findings. - Call
getSimulationResultswhen you need the structured result payload,getSimulationArtifactManifestandquerySimulationArtifactwhen large table-like artifacts need server-side filtering, orgetSimulationResultsCsvDownloadwhen you need a raw CSV export.
runSimulation does not accept runtime overrides. If the plan is wrong, fix population reuse with bindAsset or call requestPlan again with clearer description and context.
Local files, images, PDFs, or documents
If the user wants to include local files as context or respondent-visible stimulus, upload before planning:
getWorkflowGuide
uploadStimulus
User uploads files through upload_url
listStimuli
requestPlan
runSimulation
getSimulationStatus
getSimulationAnalysis
getSimulationResultsOne uploadStimulus session can hold multiple files. Do not create one upload session per file.
Use stimulus_ids on requestPlan only when every file in the upload session should be shown to simulated respondents. If some files are planning-only context and others are respondent-visible stimulus, call listStimuli and pass explicit file references through planning_context_items and simulation_stimulus_items.
The planner needs stimulus before requestPlan so it can choose the right test type, mode, and arm mapping. Stimulus cannot be attached later through bindAsset.
Private or logged-in websites
If respondents need to test a page behind login, complete the live sign-in flow before planning:
getWorkflowGuide
startWebsiteLiveSignIn
User opens login_link and signs in
completeWebsiteLiveSignIn
requestPlan
runSimulation
getSimulationStatus
getSimulationAnalysisPass the returned website_connection_id on the respondent-visible URL item sent to requestPlan, such as simulation_stimulus_urls=[{url, login_url, website_connection_id}]. Populous restores that authenticated browser session before the website run.
Use listWebsiteConnections only when the user asks to inspect or reuse a saved website connection. Use cancelWebsiteLiveSignIn to cancel a pending sign-in flow.
Read-only discovery
Use discovery tools only when the user explicitly asks to inspect saved resources, prior runs, or reuse an existing resource.
getWorkflowGuide
listPopulations
listExperiments
listSimulationsDo not list saved populations or experiments speculatively before launch. The default path is fresh build from the plan.
MCP server capabilities
| Area | Tools | Purpose |
|---|---|---|
| Workflow guidance | getWorkflowGuide | Returns the supported v2 launch sequence, slot rules, scenarios, and pitfalls. |
| Planning and launch | requestPlan, bindAsset, runSimulation | Convert user intent into a temporary plan, optionally bind explicit population reuse slots, and launch the run. |
| Assets and stimuli | uploadStimulus, listStimuli | Create upload sessions, confirm uploaded files, and pass durable file references into planning. |
| Private websites | listWebsiteConnections, startWebsiteLiveSignIn, completeWebsiteLiveSignIn, cancelWebsiteLiveSignIn | Reuse, create, complete, or cancel authenticated browser sessions for logged-in website tests. |
| Read-only discovery | listPopulations, listExperiments, listSimulations | Inspect saved populations, saved experiments, and prior simulation runs. |
| Monitoring and results | getSimulationStatus, getSimulationAnalysis, getSimulationResults, getSimulationArtifactManifest, querySimulationArtifact, getSimulationResultsCsvDownload | Track a run, fetch compact analysis, inspect structured results and artifacts, and create filtered CSV download links. |
Current exposed tools:
getWorkflowGuide
requestPlan
bindAsset
runSimulation
uploadStimulus
listStimuli
listWebsiteConnections
startWebsiteLiveSignIn
completeWebsiteLiveSignIn
cancelWebsiteLiveSignIn
listPopulations
listExperiments
listSimulations
getSimulationStatus
getSimulationResults
getSimulationAnalysis
getSimulationArtifactManifest
querySimulationArtifact
getSimulationResultsCsvDownloadOlder guide names such as planSimulation, runFromBrief, getAssetUploadLink, listSessionAssets, uploadSimAssets, getSimulationSetup, getSimulationStimuli, getPopulationStats, and importSimulation are not exposed by the current MCP server.
Tool reference
Workflow guidance
getWorkflowGuide
Call this once at the start of a new MCP session. It returns the canonical v2 workflow, slot-kind rules, common scenarios, and tool-ordering pitfalls.
Use it when:
- A new MCP session starts.
- A client needs to confirm the current launch workflow.
- You are debugging a bad tool sequence.
Planning and launch
requestPlan
Use requestPlan as the entry point for most user requests. It asks Populous to compile a simulation plan from a natural-language description.
It returns:
plan_token: temporary token used bybindAssetandrunSimulation.status: usuallyready, or a status such asneeds_stimulusif required slots are unsatisfied.slots: the plan's resource manifest.summary: short reviewable summary of the planned run.
Call it with a concrete description of what the user wants to learn. The planner chooses the test type and mode from the description plus any supplied context or stimulus. Do not decide observe vs intervene yourself; the slot manifest reflects the planner's decision.
Useful inputs include:
description: required natural-language request.stimulus_ids: upload session ids fromuploadStimulus; use only when the entire upload session is respondent-visible stimulus.planning_context_items: background docs, notes, links, or files that should inform planning but should not be shown directly to respondents.simulation_stimulus_items: files, screenshots, ads, PDFs, mockups, URLs, or text that respondents should actually see or interact with.planning_context_urls: planning-only URLs.simulation_stimulus_urls: respondent-visible URLs; these strongly suggest a Website test.context_items: fully explicit mixed context when the client already has the structure.upload_session_idanduploaded_assets_audience: whole-session attach for one upload session.n_per_group: requested respondents per population; the backend can cap this by subscription tier.
Keep planning context separate from respondent-visible stimulus. For example, a strategy memo may belong in planning_context_items, while an ad image should be attached as simulation_stimulus_items.
For local files, call uploadStimulus before requestPlan. Do not pass base64, data: URLs, or raw file bytes through tool arguments.
Slot manifest
requestPlan returns slots with shape:
{slot_id, kind, summary, required, default, bound_to?, read_only?}Slot kinds:
population: bindable when the user explicitly wants to reuse a saved population. Single-population plans usepop; multi-population plans usepop_0,pop_1, and so on.experiment: read-only build-fresh slot. The experiment is generated from the plan; reuse is not supported in the current workflow.stimulus: pre-bound atrequestPlantime when usingstimulus_ids; read-only after planning.arm_stimulus: read-only planner-assigned stimulus for intervention arms.
Treat read_only as authoritative. bindAsset rejects read-only slots, stimulus slots, and arm-stimulus slots.
bindAsset
Use bindAsset only when the user explicitly asks to reuse an existing saved population.
Inputs:
plan_token: fromrequestPlan.slot_id: the slot to override, such aspoporpop_0.asset_id: a realpopulation_keyfromlistPopulations.
Rules:
- Do not fabricate ids.
- Do not pre-list assets unless the user references reuse.
- Do not bind stimulus. Stimulus must be supplied to
requestPlan. - Do not bind read-only slots.
- If the plan token has expired, call
requestPlanagain.
For population reuse, call listPopulations, choose the intended population_key, then bind the relevant population slot.
Do not use bindAsset for saved experiment reuse. The current workflow guide marks experiments as build-fresh plan outputs, and bindAsset rejects read-only slots.
runSimulation
Executes the plan identified by plan_token.
runSimulation:
- Creates fresh populations for unbound population slots.
- Uses bound population keys as-is.
- Creates the experiment from the plan.
- Uses stimulus and arm assignments supplied at
requestPlantime. - Starts the simulation.
- Returns
sim_key, population key data,experiment_key,bindings_applied,results_url, and sometimessample_limit_summary.
Call runSimulation only after the plan status is ready.
Do not pass overrides to runSimulation; it only accepts plan_token.
Assets and stimuli
uploadStimulus
Creates a one-time upload page where the user can drop image or document files.
Use it when:
- The user has local images, ads, screenshots, mockups, PDFs, documents, or other files.
- You generated a file in chat and it needs to become simulation stimulus.
- A chat client cannot send file bytes through MCP tool arguments.
It returns:
stimulus_id: the upload session id.upload_url: the page to share with the user.
After the user uploads files, call listStimuli(stimulus_id) to confirm the assets. Then call requestPlan with either stimulus_ids=[stimulus_id] or explicit planning_context_items and simulation_stimulus_items.
Do not use bindAsset to attach uploaded stimulus after planning. If an older tool hint suggests binding stimulus, ignore that hint; bindAsset rejects stimulus slots post-plan.
listStimuli
Lists the confirmed assets in an upload session.
Use it when:
- The user has finished uploading files.
- You need to verify
asset_count > 0before planning. - You need durable file references to split uploaded files into planning context vs respondent-visible stimulus.
It returns scrubbed asset records. Use stimulus_asset_ref, asset_id, or gcs_path when passing uploaded files back into requestPlan.
Do not treat file preview URLs as website stimulus. Use simulation_stimulus_urls only when the user truly wants respondents to browse or evaluate a website.
Private websites
listWebsiteConnections
Lists saved website connections for the authenticated user. Use it when:
- The user asks whether a saved connection exists.
- The user wants to reuse an authenticated website session.
- You need to filter saved connections by
target_url.
Do not call it speculatively for public website tests.
startWebsiteLiveSignIn
Starts the live sign-in flow for a private or logged-in website test.
Inputs include:
target_url: required private or logged-in page respondents should access.login_url: optional sign-in page; defaults totarget_url.label: optional saved-connection label.connection_id: optional existing connection to refresh.auto_relogin: optional boolean for automatic re-login fallback.
It returns an auth_session_id and a login_link. Show the login_link to the user and wait for them to finish signing in before planning.
completeWebsiteLiveSignIn
Completes and saves a pending sign-in session. Call it after the user confirms they signed in through the login_link.
It takes auth_session_id and returns a website_connection_id. Pass that id inside the respondent-visible URL item sent to requestPlan.
cancelWebsiteLiveSignIn
Cancels a pending live sign-in flow and releases its temporary browser session. Use it when the user abandons or restarts the login flow.
Read-only discovery
listPopulations
Lists the authenticated user's saved populations. Responses are keyed by population_key.
Use it when:
- The user explicitly asks which populations they have.
- The user asks to reuse an existing population.
- You need to identify the correct population key before
bindAsset.
Do not use it as a normal launch step. Fresh population creation is the default.
listExperiments
Lists the authenticated user's saved experiments. Responses are keyed by experiment_key.
Use it when:
- The user explicitly asks which experiments they have.
- The user asks to reuse an existing experiment.
- You need to identify the correct experiment key before
bindAsset.
Do not use it as a normal launch step. Fresh experiment creation is the default.
listSimulations
Lists the authenticated user's simulations with status and keys.
Use it when:
- The user asks what simulations exist.
- You need to find a prior
sim_key. - You are checking whether a run exists before inspecting results.
The current MCP server does not expose a setup-clone tool. To branch a prior idea, use information from the prior run as context for a new requestPlan.
Monitoring and results
getSimulationStatus
Gets the current status for a simulation by sim_key.
Use it after runSimulation.
Typical sequence:
runSimulation
getSimulationStatus
getSimulationStatus
getSimulationAnalysis
getSimulationResultsWait for the simulation to complete before requesting results.
getSimulationAnalysis
Fetches the compact analysis payload for a completed simulation by sim_key.
Use it when:
- The simulation is complete.
- The user wants the plain-English verdict, summary, and findings.
- You need the fastest post-run answer before deciding whether to inspect full results.
This tool takes only sim_key. It is the preferred first results call for normal user-facing answers.
getSimulationResults
Fetches results for a completed simulation by sim_key.
The server checks the run status, chooses the appropriate results endpoint for survey vs website-style runs, and trims oversized fields for MCP response size. It preserves the analytical content an agent needs, including overview counts, findings, hypothesis validation, question-level breakdowns, respondent profile samples, and quote highlights when available.
Use it when:
- The simulation is complete.
- The user asks what the simulation found.
- You need result details for a report or downstream transformation.
If the user needs the full untrimmed payload, use the web UI or the underlying API outside the MCP response-size constraints.
getSimulationArtifactManifest
Lists queryable artifacts for a completed simulation, including raw CSV artifacts and structured result tables.
Use it when:
getSimulationAnalysisorgetSimulationResultsis not enough.- The run is large and you need table-level inspection.
- You need an
artifact_idbefore callingquerySimulationArtifact.
This tool takes only sim_key.
querySimulationArtifact
Queries one simulation artifact server-side. Use it for large runs instead of pulling the whole result payload through MCP.
Inputs include:
sim_key: required simulation key.artifact_id: required id fromgetSimulationArtifactManifest.select: optional columns to return.filters: optional row filters such as{column, op, value}. Supported operators includeeq,in,contains,gt,gte,lt, andlte.sort: optional sort specs such as{column, direction}.limit: optional row cap; default is 50 and max is 200.offset: optional row offset for pagination.
getSimulationResultsCsvDownload
Creates a short-lived direct download URL for the raw results CSV.
Use it when:
- The user asks for the raw data.
- You need to export one population, arm, or stage slice.
- You need columns, filters, or sorting that are easier to express as CSV export options than as a chat answer.
Inputs include:
sim_key: required simulation key.stage_idx: optional stage index for multi-stage runs. When omitted on a multi-stage run, the export combines stages and stamps stage metadata onto the rows.select: optional list of CSV columns.filters: optional row filters such as{column, op, value}. Supported operators includeeq,in,contains,gt,gte,lt, andlte.sort: optional sort specs such as{column, direction}.
Common pitfalls
Using old tool names
The current server does not expose planSimulation, runFromBrief, getAssetUploadLink, listSessionAssets, uploadSimAssets, getSimulationSetup, getSimulationStimuli, getPopulationStats, or importSimulation.
Use the current v2 tools listed above.
Planning before upload
If the user supplied local files/images for the simulation to show, call uploadStimulus and listStimuli before requestPlan. The planner needs stimulus up front to choose the right test type, mode, and arm mapping.
Attaching stimulus through bindAsset
bindAsset is not a stimulus attachment tool. Stimulus slots are pre-bound at plan time or assigned to arms by the planner. To change stimulus, call requestPlan again with corrected stimulus_ids, planning_context_items, or simulation_stimulus_items.
Mixing planning context with respondent-visible stimulus
Background research, notes, decks, and strategic context can help Populous design the simulation, but they are not always assets respondents should see.
Use planning context for design inputs. Use simulation stimulus for material the synthetic audience should evaluate directly.
Listing saved resources speculatively
Do not call listPopulations or listExperiments unless the user explicitly asks to inspect or reuse saved resources. The default plan builds fresh resources.
Fabricating or parsing keys
Treat population_key, experiment_key, sim_key, plan_token, and stimulus_id as opaque strings. Do not parse or construct them.
Passing inline file bytes
Chat clients cannot send local file bytes through MCP tool arguments. Do not pass base64 fields or data: URLs into requestPlan. Use uploadStimulus, then listStimuli, and pass returned asset_id, gcs_path, or stimulus_id references.
Expecting runtime overrides
runSimulation accepts only plan_token. If the user changes the audience, task, uploaded files, arm assignment, or context after planning, call requestPlan again.
Requesting results too early
A simulation must complete before getSimulationResults can return useful output. Poll getSimulationStatus first.
Skipping private-site sign-in
For logged-in websites, do not send only the private URL to requestPlan. Start and complete the live sign-in flow first, then pass the returned website_connection_id with the respondent-visible URL.
Missing the compact analysis step
Use getSimulationAnalysis first for a normal answer. Use getSimulationResults for detailed structured payloads, getSimulationArtifactManifest and querySimulationArtifact for large queryable artifacts, and getSimulationResultsCsvDownload for raw CSV export links.
Examples
New exploratory simulation
User request:
Would mid-market HR leaders trust this onboarding automation product?
Tool flow:
getWorkflowGuide
requestPlan(description="Would mid-market HR leaders trust this onboarding automation product?")
runSimulation(plan_token)
getSimulationStatus(sim_key)
getSimulationAnalysis(sim_key)
getSimulationResults(sim_key)Use this flow because the user starts from a question and audience that Populous should turn into a simulation plan.
Add one ad image as respondent-visible stimulus
Tool flow:
getWorkflowGuide
uploadStimulus(label="Q3 ad creative")
User uploads the image through upload_url
listStimuli(stimulus_id)
requestPlan(description="Test ad recall with US shoppers", stimulus_ids=[stimulus_id])
runSimulation(plan_token)
getSimulationStatus(sim_key)
getSimulationAnalysis(sim_key)
getSimulationResults(sim_key)Use stimulus_ids because the whole upload session is respondent-visible stimulus.
Split uploaded files into planning context and simulation stimulus
User provides a strategy memo and two ad variants.
Tool flow:
getWorkflowGuide
uploadStimulus(label="Memo and ad variants")
User uploads all files through the same upload_url
listStimuli(stimulus_id)
requestPlan(
description="Compare which ad variant is more credible to budget owners.",
planning_context_items=[{asset_id: "<memo_asset_id>", audience: "planning"}],
simulation_stimulus_items=[
{asset_id: "<variant_a_asset_id>", audience: "simulation"},
{asset_id: "<variant_b_asset_id>", audience: "simulation"}
]
)
runSimulation(plan_token)
getSimulationStatus(sim_key)
getSimulationAnalysis(sim_key)
getSimulationResults(sim_key)Use structured context because not every uploaded file should be shown to respondents.
Compare multiple audiences
User request:
Compare urgency for this product across SMB, mid-market, and enterprise buyers.
Tool flow:
getWorkflowGuide
requestPlan(description="Compare urgency for this product across SMB, mid-market, and enterprise buyers.")
runSimulation(plan_token)
getSimulationStatus(sim_key)
getSimulationAnalysis(sim_key)
getSimulationResults(sim_key)The returned slots may include pop_0, pop_1, and pop_2. Do not manually create three separate runs unless the user asks for that.
Reuse an existing population
User request:
Run this on my US millennials population.
Tool flow:
getWorkflowGuide
listPopulations
requestPlan(description="Test ad recall for the proposed campaign.")
bindAsset(plan_token, slot_id="pop", asset_id="<population_key>")
runSimulation(plan_token)
getSimulationStatus(sim_key)
getSimulationAnalysis(sim_key)
getSimulationResults(sim_key)Use this flow because the user explicitly referenced a saved population.
Private website test
User request:
Test whether trial users can find the billing export in our logged-in dashboard.
Tool flow:
getWorkflowGuide
startWebsiteLiveSignIn(target_url="https://app.example.com/dashboard", login_url="https://app.example.com/login")
User opens login_link and signs in
completeWebsiteLiveSignIn(auth_session_id)
requestPlan(
description="Test whether trial users can find the billing export in our dashboard.",
simulation_stimulus_urls=[{url: "https://app.example.com/dashboard", login_url: "https://app.example.com/login", website_connection_id: "<website_connection_id>"}]
)
runSimulation(plan_token)
getSimulationStatus(sim_key)
getSimulationAnalysis(sim_key)Use this flow when the site requires authentication. Do not plan the private website test until the saved website connection exists.
Query a large results artifact
User request:
Show me enterprise-only rows with the strongest objections.
Tool flow:
getSimulationStatus(sim_key)
getSimulationArtifactManifest(sim_key)
querySimulationArtifact(
sim_key,
artifact_id="<artifact_id>",
filters=[{column: "population_key", op: "eq", value: "pop_1"}],
limit=100
)Use this flow when the user wants a focused slice from a large completed run. Get a real artifact_id from the manifest and real filter values from prior metadata or result payloads.
Export one results slice
User request:
Export the results for the enterprise audience.
Tool flow:
getSimulationStatus(sim_key)
getSimulationResultsCsvDownload(sim_key, filters=[{column: "population_key", op: "eq", value: "pop_1"}])Use this flow when the user needs raw rows for a population, A/B arm, or stage. Use the result payload or prior run metadata to choose real filter values; do not invent keys.
Operational notes
- The MCP server implements Streamable HTTP directly at
/mcp. GET /mcpis an SSE keep-alive probe and can be used by clients before auth.POST /mcprequiresAuthorization: Bearer <access_token>.- The server advertises OAuth metadata from the MCP host and proxies OAuth registration/token/authorization paths to the web app.
- Keep tool calls scoped to the v2 workflow unless the server exposes a new tool in
tools/list. - Treat
getWorkflowGuideand the livetools/listresponse as the client-facing source of truth, withmcp/server.pyas the implementation source of truth for this guide.