Skip to content

MCP Interface

Askalot supports the Model Context Protocol (MCP)—an open standard that enables AI assistants to interact directly with the platform. This allows AI agents to create surveys, manage campaigns, execute questionnaire flows, and analyze results through natural language conversations.

What is MCP?

MCP is a standardized protocol that lets AI systems like Claude interact with external tools and data sources. With Askalot's MCP interface, you can:

  • Automate survey workflows - Create projects, questionnaires, and campaigns through AI conversations
  • Execute surveys programmatically - Navigate questionnaire flows and submit responses
  • Manage respondents - Import, organize, and assign survey targets to campaigns
  • Query audit trail - Track changes and ensure compliance
  • Access documentation - AI agents can read platform documentation for context

Connecting to the MCP Interface

Endpoint

https://portor.<tenant>.askalot.io/mcp

Replace <tenant> with your organization's tenant name.

Authentication

The MCP interface authenticates with OAuth 2.1, not a pasted API token. On the first tool call, Portor returns 401 with an OAuth discovery hint and your MCP client (for example, the Askalot plugin for Claude Code) walks you through a browser sign-in against the platform OIDC provider. The client then stores the resulting access + refresh tokens and sends the access token as Authorization: Bearer on every call — you never handle the bearer value yourself.

Configuring the endpoint (URL only):

The only thing you configure is the server URL. The Askalot plugin reads it from the ASKALOT_MCP_URL environment variable; a plain .mcp.json entry carries the same URL and nothing else — no token field:

{
  "mcpServers": {
    "askalot": {
      "type": "http",
      "url": "https://portor.<tenant>.askalot.io/mcp"
    }
  }
}

Signing in (first use):

  1. Point the client at your tenant (export ASKALOT_MCP_URL=https://portor.<tenant>.askalot.io/mcp).
  2. Trigger any MCP tool. The client opens your browser to Portor's /authorize endpoint, which redirects to the platform OIDC login.
  3. Sign in and approve the consent screen. The client exchanges the code for tokens and retries the original call.
  4. The browser handshake happens once; the refresh token is exchanged transparently afterward.

REST/CI uses a token instead

The browser OAuth flow is for interactive MCP clients. For non-interactive REST or CI use, generate a classic API token in Roundtable → Profile Settings and send it in the X-Api-Token header on the REST API. That token authenticates REST only — it is not the credential for the MCP transport, which resolves OAuth (or synthetic service) bearer tokens exclusively.

Your Active Organization

Your MCP session is always in exactly one organization at a time — its active organization — and every tool call resolves against it. Projects, questionnaires, campaigns, respondents and datasets are all organization-scoped, so this is the single most important thing to know about where a tool is looking.

Where you start. A fresh session lands in your home organization, the one your account belongs to. Nothing asks you to choose during sign-in.

Seeing it. list_organizations returns every organization the session may act in, marks which one is active, and flags any that are read-only. The list is exactly what the Switch Organization menu offers you in the browser — if you belong to one organization, that is the whole list and there is nothing to manage.

Changing it. switch_organization moves the session to another organization from that list. Every later call resolves in the new one, and the change persists: restart your MCP client and you resume where you left off. The tenant is fixed when you sign in and never changes, so switching only ever moves you between organizations inside one tenant.

A not-found tells you where it looked

Because reads are filtered by the active organization, an entity that lives elsewhere is simply absent — which reads exactly like an entity that never existed. Askalot names the organization it searched:

Project 6f2a… not found (searched organization: ACME Corp)

That is the signal to call list_organizations and switch, rather than concluding the project does not exist. The message names only the organization that was searched, never the one that owns the entity.

Sealed Organizations

Some organizations are sealed — a curated demo, or a former customer's data kept available for its retention window. list_organizations marks them, so you can tell before you act.

Inside a sealed organization, reading works and anything that would change data is refused with org_read_only. Listing and fetching projects, campaigns, questionnaires, respondents, pools, datasets and users all keep working, as do the documentation, audit and methodology-library tools; creating, updating and deleting are refused. Each tool declares whether it reads or writes, and that declaration is what the refusal is driven by — so the boundary is a property of the tool, not a guess about its name.

list_organizations and switch_organization both keep working there, so a session can always see where else it may go and leave.

Sealing also disables API tokens for that organization: you cannot generate one, and an existing one stops working. The OAuth sign-in above is unaffected.

Available Tools

The MCP interface provides tools organized by functionality.

Session and Organizations

Tool Description
list_organizations List the organizations this session may switch into, marking the active one and flagging read-only ones
switch_organization Move the session's active organization — every later call resolves against it

Project Management

Tool Description
list_projects List all your projects
get_project Get project details
create_project Create a new project
add_project_owners Add users as project owners (targets must belong to the project's organization)
remove_project_owners Remove users from project ownership (same-organization rule applies)

Questionnaire Operations

Tool Description
list_questionnaires List all questionnaires
get_questionnaire Get questionnaire details
create_questionnaire Create a new questionnaire
rename_questionnaire Rename a questionnaire (address unchanged)
delete_questionnaire Soft-delete a questionnaire
restore_questionnaire Restore a recently soft-deleted questionnaire
list_qml_files List the organization's QML questionnaires
inspect_qml_file Quick summary of a questionnaire's current version
get_qml_content Retrieve a questionnaire's current QML (returns a short-lived download link instead of inline content above 32 KB)
validate_qml_file Run Z3 SMT validation on a questionnaire's current version (reachability, consistency)
qml_quality_report Compute the D2–D8 design-quality scorecard for a questionnaire's current version
save_qml_file Save QML as a questionnaire's new version — never blocks on broken drafts (content over 32 KB is refused; use the upload handle below)
request_upload_url / finalize_upload Two-step handle for saving QML content over save_qml_file's 32 KB limit
publish_qml_file Publish a questionnaire to a campaign — formally validates and pins the exact version (the only gated door)
move_qml_to_project Move a questionnaire to another project (version history preserved)
unpublish_qml_file Soft-delete a questionnaire, retaining its version history (blocked if active campaigns)

Parameter Reference — parameters, return schemas, QML lifecycle, Z3 output structure

Document Discovery

Tool Description
list_indexed_documents List all documents indexed for AI semantic search
get_document_summary Get the stored Markdown summary for a specific document
get_document_chunk Retrieve a specific chunk of an indexed document by index
search_document_chunks_by_keyword Search indexed document chunks by keyword

These two searches cost you nothing and need no setup

get_document_chunk and search_document_chunks_by_keyword match on meaning alone — no AI model is involved — so they work whether or not you have configured a provider, and they never appear on your provider bill.

The knowledge-graph searches are different: search_methodology_library and get_methodology_paper_summary read your question with a model before they can answer. Those run on your own Direct LLM slot, so their (small) cost lands on your provider account, and without a configured slot they return an actionable error. See AI Functions & Model Options.

Research Paper

Tool Description
read_paper Read a project's Research Paper — the assembled chapters, plus each unit's current edit token
edit_paper_unit Replace an exact passage inside one unit of the paper, leaving everything else byte-for-byte unchanged

You cannot edit a chapter you have not just read

There is deliberately no "write the whole chapter" tool. read_paper returns a base_hash per unit, and edit_paper_unit refuses an edit whose base_hash is missing (you never read it) or stale (someone else changed the unit since you did). This is what stops an agent from silently overwriting a researcher's approved text, so read first, every turn — a hash from earlier context is not a read.

An edit names an old_string to find and a new_string to put in its place. If the old_string appears more than once the edit is refused with the match positions rather than guessing which one you meant. On success you get a fresh new_base_hash, so several edits to the same unit in one turn need no re-read in between.

Content is HTML restricted to a small allowlist of tags and classes. Anything outside it is refused, and the refusal names each disallowed construct so you can correct it.

Campaign Management

Tool Description
list_campaigns List campaigns (optionally by project)
get_campaign Get campaign details
create_campaign Create a new campaign
update_campaign Update campaign fields (name, status)
delete_campaign Delete a campaign
add_interviewers_to_campaign Add interviewers (Users with interviewer role)
remove_interviewers_from_campaign Remove interviewers from a campaign
update_campaign_questionnaire Change the questionnaire assigned to a campaign
assign_pool_to_campaign Assign a respondent pool to a campaign
get_campaign_pool Get the respondent pool assigned to a campaign
send_campaign_invitations Send survey invitation emails to respondents

Respondents are not added to a campaign directly — assign a respondent pool with assign_pool_to_campaign, then bulk_create_surveys creates a survey per pool respondent.

Parameter Reference — parameters, return schemas, batch patterns, invitation eligibility

Respondent Management

Tool Description
list_respondents List all respondents (survey targets)
get_respondent Get respondent details
create_respondent Create a new respondent
update_respondent Update respondent information
delete_respondent Remove a respondent
bulk_create_respondents Create multiple respondents at once
bulk_delete_respondents Delete respondents by filter (two-step dry_run workflow)
generate_survey_access_token Mint a magic-link token for a respondent's survey
send_survey_invitation Email a respondent a magic-link survey invitation

Parameter Reference — parameters, return schemas, bulk creation, demographics

Respondent Pools

Respondent pools let you organize respondents into reusable groups for campaigns.

Tool Description
list_respondent_pools List all respondent pools
get_respondent_pool Get pool details including respondent list
create_respondent_pool Create a new respondent pool
add_respondents_to_pool Add respondents to an existing pool
remove_respondents_from_pool Remove respondents from a pool
generate_pool_from_strategy Create a pool using a sampling strategy
preview_pool_generation Preview pool generation without creating it
refresh_pool_from_strategy Re-run selection algorithm on existing pool
delete_respondent_pool Delete a respondent pool

Parameter Reference — parameters, return schemas, duplicate handling, strategy generation

Sampling Strategies

Sampling strategies define target demographic distributions for creating representative respondent samples.

Tool Description
list_sampling_strategies List all sampling strategies
get_sampling_strategy Get strategy details including factors
create_sampling_strategy Create a strategy with custom demographic factors
create_default_strategy Create a strategy with standard gender and age factors
update_sampling_strategy Update an existing strategy
advance_sampling_strategy Clone a strategy and append reality-grounded outcome factors
delete_sampling_strategy Delete a sampling strategy

Example: Creating a Custom Sampling Strategy

AI Assistant: I'll create a sampling strategy targeting your demographics.

→ create_sampling_strategy(
    name="Urban Millennials",
    project_id="...",
    target_size=200,
    factors=[
      {"name": "Gender", "attribute_path": "gender",
       "target_distribution": {"male": 0.48, "female": 0.50, "other": 0.02}},
      {"name": "Age Group", "attribute_path": "age",
       "target_distribution": {"25-34": 0.60, "35-44": 0.40}}
    ]
  )

Strategy created! Now generating a representative pool...
→ generate_pool_from_strategy(strategy_id, "Urban Millennials Pool")

Parameter Reference — parameters, return schemas, factor schema, distribution validation

User Management

Tool Description
list_users List platform users (including interviewers)
get_user Get user details

Note: Interviewers are Users with the interviewer role. They are managed as Users, not as Respondents.

Interviewer Workload

For campaigns with interviewers (Users with interviewer role), manage workload distribution:

Tool Description
assign_respondents_to_interviewer Assign respondents to a specific interviewer (User)
unassign_respondents_from_interviewer Remove interviewer assignments
get_interviewer_workload View assigned respondents and completion status
get_unassigned_respondents Find respondents not yet assigned

Survey Execution

Tool Description
list_surveys List surveys (filter by campaign or respondent)
create_survey Start a new survey session
update_survey Update a survey's status and flow state (bound entities are immutable)
bulk_create_surveys Create surveys for all respondents in a campaign
bulk_delete_surveys Delete surveys by filter (two-step dry_run workflow)
get_survey_current_item Get the current question with its options folded in
submit_survey_response Submit an answer and advance (next step folded in)
finish_survey Explicitly complete a survey
mass_fill_surveys Enqueue an asynchronous background task to fill surveys with synthetic test responses (returns {task_id, status})
get_task_status Poll an async mass_fill_surveys run by task_id (dataset coding jobs are polled via get_dataset instead)

Parameter Reference — parameters, return schemas, state machine, distribution modes, personas

Data Analysis

A Bundle binds a Project, Questionnaire, and Campaign subset to one linear Bronze → Silver → Gold dataset chain. Bundle tools manage that binding and carry the Bundle's quality story; dataset tools run each Bundle-scoped stage — extraction, coding + weighting, refinement, and export.

Tool Description
create_bundle Create a pipeline Bundle
list_bundles List Bundles, optionally filtered to one project
get_bundle Bundle detail, including its stage recipes (Silver Calibration Targets, Gold operations)
clone_bundle Deep-copy a Bundle's ready datasets + recipes into an independent variant
delete_bundle Delete a Bundle and its dataset chain
get_bundle_quality The Bundle's Representativeness story (selection, fielded, weighted, fielding shift, response)
compare_bundle_quality Bronze vs Silver improvement against the Bundle's current Strategy
get_bundle_coding Open-end coding state — the candidates the Bronze offers, the analyst's question selection, and per question the proposed dimensions, their categories and which are selected
set_coding_selection Set which open-text units the Bundle codes (manager role, identified user required)
assign_bundle_strategy Assign (or clear) the Bundle's current Sampling Strategy
set_calibration_targets Edit the Bundle's Calibration Targets — the Silver weighting spec
list_datasets List datasets scoped to a Bundle's chain
get_dataset Get dataset details including schema and metrics
create_bronze_dataset Extract a Bundle's Bronze dataset
code_open_ends (alias derive_silver) Code open-ended text, then weight against Calibration Targets, producing the Bundle's Silver
create_gold_dataset Refine a Bundle's Silver into its Gold, using the Gold operation catalog
export_dataset Export a ready dataset (CSV, XLSX, SPSS, Parquet)
delete_dataset Delete a dataset

Bundle Tools Reference — Bundle lifecycle and quality parameters, return schemas

Dataset Tools Reference — stage parameters, return schemas, export formats

Audit & Compliance

Tool Description
query_audit_events Search audit trail with filters
get_entity_history View complete history of any entity
get_audit_stats Get audit statistics

Documentation Access

Tool Description
list_documentation List available documentation
get_documentation Load a specific document
search_documentation Search documentation by keyword

MCP Resources

Resources provide read-only access to platform data:

Resource URI Description
repository://overview Platform statistics and counts
repository://schema Entity relationships and structure
qml://files The organization's QML questionnaires
docs://primer Platform overview
docs://qml-syntax QML language reference
docs://getting-started Quick start guide

Additional documentation resources mirror the knowledge base (docs://guide, docs://glossary, docs://campaign-management, docs://survey-execution, docs://creating-surveys, docs://data-analysis, docs://quality-metrics).

Example Workflows

Creating a Survey Campaign with AI

AI Assistant: I'll help you set up a customer satisfaction survey.

1. First, let me create a project...
   → create_project("Customer Research 2026", "Annual satisfaction study")

2. Now I'll register your questionnaire...
   → create_questionnaire("CSAT Survey", qml_content, project_id)

3. Creating the campaign...
   → create_campaign("Q1 CSAT", project_id, questionnaire_id)

4. Adding your respondent list...
   → bulk_create_respondents(100, generate_demographics=true)
   → create_respondent_pool("CSAT Sample", respondent_ids=[...])
   → assign_pool_to_campaign(campaign_id, pool_id)
   → bulk_create_surveys(campaign_id)

Your campaign is ready! 100 respondents have surveys waiting.

Creating a Representative Sample

AI Assistant: I'll create a demographically balanced sample for your study.

1. Creating a sampling strategy with your target demographics...
   → create_sampling_strategy(
       name="National Representative",
       project_id,
       target_size=500,
       factors=[
         {"name": "Gender", "attribute_path": "gender",
          "target_distribution": {"male": 0.49, "female": 0.51}},
         {"name": "Age", "attribute_path": "age",
          "target_distribution": {"18-34": 0.30, "35-54": 0.40, "55+": 0.30}}
       ]
     )

2. Generating a pool that matches your targets...
   → generate_pool_from_strategy(strategy_id, "Q1 Sample Pool")

3. Assigning the pool to your campaign...
   → assign_pool_to_campaign(campaign_id, pool_id)

Done! Your campaign now has 500 respondents balanced to match
national demographics.

Executing a Survey Programmatically

AI Assistant: I'll walk through the survey and show you each question.

→ create_survey(questionnaire_id, respondent_id)
→ get_survey_current_item(survey_id)

Question 1: "What is your age?"
Type: Integer input (18-100)

User: 35

→ submit_survey_response(survey_id, "q_age", 35)
→ get_survey_current_item(survey_id)

Question 2: "How satisfied are you with our service?"
Type: Scale (1-5)
...

Managing Interviewer Workload

AI Assistant: Let me distribute the 50 respondents among your 5 interviewers (Users with interviewer role).

→ get_unassigned_respondents(campaign_id)
   Found 50 unassigned respondents

→ assign_respondents_to_interviewer(campaign_id, interviewer_user_1, respondents[0:10])
→ assign_respondents_to_interviewer(campaign_id, interviewer_user_2, respondents[10:20])
...

→ get_interviewer_workload(campaign_id, interviewer_user_1)
   Assigned: 10 respondents
   Completed: 0
   In Progress: 0

Platform Concepts

Understanding the entity model helps when working with the MCP interface:

Entity Hierarchy

Project
├── Questionnaire (owns a QML version chain)
└── Campaign
    ├── Respondents (survey targets)
    ├── Interviewers (Users with interviewer role, optional)
    └── Surveys (individual sessions)

Respondents and Interviewers

  • Respondents: Survey targets with demographic data. Their survey completions determine campaign progress. They access surveys via magic links (no platform authentication required).
  • Interviewers (optional): Users with the interviewer role who facilitate surveys for respondents. They have platform login and help respondents complete surveys but don't fill in surveys themselves.

Interviewers can be assigned to help respondents in person or by phone. When interviewers are assigned, surveys track which interviewer facilitated each respondent's survey.

Respondents vs Users

  • Respondents are survey targets with demographic data (age, gender, location). They don't have platform accounts.
  • Users are platform accounts for authentication and management. Users with the interviewer role can facilitate surveys.
  • Respondents and Users are separate entities. Interviewers are Users, not Respondents.

Error Handling

MCP tools return structured error messages. Two apply across every category:

  • not_found — the entity is not in the session's active organization. The message names the organization it searched; see Your Active Organization.
  • org_read_only — the active organization is sealed. Reads succeed; this refusal only ever comes from a tool that would have written something.

Detailed error patterns are documented per category:

Next Steps

  • REST API


    Traditional REST endpoints for integration

    REST Docs

  • QML Syntax


    Learn the questionnaire markup language

    QML Guide

  • Campaigns


    Configure and manage survey campaigns

    Campaign Guide