/mcp) and 42 tools on the Claude OAuth endpoint
(/mcp/directory). Every tool operates within the workspace selected during OAuth consent or bound
to the API key.
Most read tools work for an OAuth member or a read-capable key. Write tools (create_campaign,
update_campaign, start_campaign, pause_campaign, resume_campaign, add_contacts,
add_webhook, remove_webhook, chat_project, start_full_corpus_analysis,
cancel_full_corpus_analysis, retry_full_corpus_analysis) require the write capability. An OAuth
member receives admin_required; a read-only key receives read_only_key. OAuth workspace admins and
full-access keys can use write tools. Legacy mcp-scoped keys keep their ordinary tool access.
The three confidential-corpus read tools are intentionally stricter. get_corpus_manifest,
get_corpus_manifest_page, and get_corpus_record require the exact
protected_corpus:<campaign UUID> scope for that campaign.
Ordinary read-only, full-access, *, and legacy keys do not grant this access. A workspace admin must
create the short-lived Confidential analysis key, which pairs normal read access with the exact
campaign grant and no write capability. These three tools are available only on /mcp; the Claude
Directory endpoint never registers them, including for OAuth admins.
Errors are structured: {"error": "<human message>", "code": "<stable code>", "hint": "<what to do next>"}.
Exceeding the per-connection or API-key tool-call budget returns code rate_limited; retry after a
minute.
Workspace and permissions
get_my_permissions
Returns the authenticated principal’s workspace, authentication type, role, and effective
capabilities. Use it after connecting to confirm that Claude selected the intended organization and
whether the current connection can perform write actions. The response contains no access-token or
API-key material.
Campaigns
list_campaigns
Lists campaigns in the workspace, most recently updated first.
Returns:
{"campaigns": [...], "limit", "offset", "has_more"} — each campaign summary carries id, name, status, channel, language, schedule (timeframe_start, response_deadline, timezone, invitations_scheduled_for), contact counts, and completion_threshold_percent.
get_campaign
Fetches a single campaign by id: full config, schedule, topics with typed questions (type, options, component_config), contacts (with invitation_sent_at), and progress counts.
create_campaign
Creates a new campaign in draft status. Call start_campaign to launch it.
Topic shape:
{name, goal, priority, success_threshold, sub_topics, questions}. Question shape: {text, required, type, options, component_config} with types open_ended (default), single_choice, multiple_choice, likert_scale, ranking, statement, range_slider, matrix. Ranking/matrix/range_slider questions need a component_config (e.g. ranking {items: [{id, label}]}, matrix {rows, columns}, range_slider {min, max, step}).
update_campaign
Partially updates a campaign — only the fields you pass change. Works on draft, active, and paused campaigns (completed ones are read-only; the channel is locked after launch). Schedule changes on an active campaign retarget the pending invitation send; already-sent invitations are never re-sent.
Takes interview_id plus any of the create_campaign fields above (except topics/contacts).
start_campaign
Launches a campaign: validates, marks it active, and sends the invitations on the campaign’s channel — or, when the campaign has a future start date, schedules them (invitations_scheduled_for in the response tells you when). Validation failures leave the campaign in draft and say what to fix.
pause_campaign / resume_campaign
Lifecycle controls. Each takes interview_id and returns the new status.
add_contacts
Bulk-adds contacts. On an active campaign the new contacts are invited right away — unless the campaign’s start date is still in the future, in which case their invitations are held with everyone else’s.
Returns
{created, invitations_sent, invitations_scheduled_for, message}.
get_progress
Returns per-status contact counts, completion percent vs. completion_threshold_percent, the soft response_deadline, and invitations_scheduled_for when the send is still pending.
Transcripts
list_conversations
Lists individually accessible conversations in a campaign, newest first. Report-only responses do not appear here;
use start_full_corpus_analysis when they should contribute through protected aggregate patterns.
Returns:
{"conversations": [...], "limit", "offset", "has_more"}.
get_transcript
Returns full transcript text plus contact metadata (respecting the campaign’s anonymity settings).
get_corpus_manifest
Returns the complete, untruncated index of every completed or contentful non-test response in one
campaign (scope: "completed_or_contentful_conversations"). Completed responses remain represented
even when no transcript content is available; unfinished responses enter only after they contain
source material. Use this when a specifically authorized agent must analyze protected interviews
without Ontora first summarizing or cutting their source material.
Each record reference carries a stable pseudonymous
response_id, completion and transcript state,
release status, transcript source/revision/turn count, answered-question count, guide_hash,
question_mapping_status, question_mapping_conflict_count, and record_hash. The manifest also reports
complete coverage counts, counts by transcript source, how many records contain question-mapping gaps or
source/resolution conflicts, exclusions, the interview guide and its hash, manifest_hash,
max_record_count: 500, max_turns_per_record, max_record_bytes, max_export_bytes, and
truncated: false. A corpus over any advertised bound fails as a whole; it never returns a misleading
prefix or partial record.
This is the full manifest contract used by REST clients, the Ontora CLI, and local export integrity
checks. In LangDock, prefer the compact paginated tool below so a large record index does not consume
the analysis context.
get_corpus_manifest_page
Returns one compact, ordered window of the same canonical manifest. It omits the full guide and
nonessential reference fields while retaining the snapshot hash, complete-corpus coverage totals,
release-status counts, mapping quality counts, exclusions, guide hash, and the stable IDs/hashes needed
to fetch records.
The response includes
schema_version, campaign_id, manifest_hash, truncated,
total_records, completion and transcript coverage, counts_by_release_status, question-mapping gap
and conflict totals, excluded_by_reason, guide_hash, and pagination fields offset, limit,
returned_count, has_more, and next_offset. records contains compact references with each
response_id and record_hash.
truncated: false describes the complete source corpus; a page with has_more: true is intentionally
partial, not truncated. Follow next_offset until has_more is false and verify that the collected set
contains exactly total_records unique response IDs.
get_corpus_record
Returns one full available source record with minimal preprocessing: campaign-guide fields, raw
response text, structured choice metadata when captured, and ordered transcript turns. A guide field’s
question_type remains authoritative—do not treat every field as mechanically closed-choice. Name,
email, person id, contact id, conversation id, and person-profile seniority_level metadata are not part of this
wire contract. Campaign-specific answers such as Q1 and Q2 remain in questions and the transcript. Job title and
department appear only when participant_metadata_output_allowed is true on an eligible
raw_citable record. metadata_sources gives field-level provenance: either
stored_interview_contact, linked_person, or null. The compatibility field
contact_metadata_source is one of those sources, mixed when the two fields came from different
sources, or null. audience_filter_attributes is a strict allowlist of the linked Personio
participant’s raw workgroup1, workgroup2, and workgroup3 values; Ontora does not map or derive
them. It may be populated for raw_citable and named, transcript-hidden aggregate_only records.
Anonymous-citable, name-hidden, report-only, and contactless records use an empty object. For
aggregate_only, workgroups are analysis dimensions only and must
not be reproduced as an individual attribution. The stable pseudonymous response_id remains
available for support and deduplication.
question_mapping_status: "gaps_present" and unmapped_response_turn_indexes explicitly identify
nonblank participant turns that could not be tied to the current guide. Do not silently assign those
turns to the nearest question. For every transcript turn, source_question_id preserves its stored
provenance while question_id and question_key are the resolved guide mapping;
question_mapping_source says whether that resolution came from a structured choice, an interviewer
prompt, surrounding context, or remained unmapped. Each question repeats this provenance as
mapping_source_counts and mapping_conflict_turn_indexes; structured_answer_present distinguishes
a captured choice/component answer from transcript-only content. The record-level
question_mapping_conflict_turn_indexes marks turns
where stored question/topic provenance conflicts with that independently resolved mapping. A record can
therefore have a complete mapping and still report conflicts. Use the resolved question_id/question_key
for Q grouping, retain the source/conflict fields for audit, and never overwrite or guess either. The
record and manifest guide_hash bind all Q1/Q2 aliases to the exact guide used for extraction.
Every record includes
release_status, verbatim_output_allowed, and output_policy:
raw_citablemay be quoted and cited under the approved analysis purpose.anonymous_citableandaggregate_onlyboth haveverbatim_output_allowed: falseandoutput_policy: "aggregate_paraphrase_only". Never quote, reproduce, attribute, expose, or make their individual answers reconstructable. Never infer or output participant department, job title, seniority, identity, or missing workgroups. They may contribute only non-reconstructable paraphrases and aggregates; their pseudonymous response IDs may be listed as support IDs.
get_corpus_manifest_page to collect the complete compact ID/hash
set in pages of 10–15 and pin every later page to the first manifest_hash. Then process one record per
Workflow Loop Agent execution. Visit every record exactly once with its expected_record_hash and
reduce only compact structured codings. Coverage is proven only when the Loop iteration count equals
total_records and its unique processed-ID set exactly equals the paged manifest ID set.
Finally, call page zero with the original expected_manifest_hash; any page, record, or snapshot hash
failure invalidates the partial analysis. A normal long chat cannot prove complete processing because
tool results consume context and older context may be optimized into summaries. Returning NDJSON as an
MCP file does not bypass that context constraint. For a verified local NDJSON snapshot, use ontora corpus export instead. See Connect Ontora to LangDock for the complete Workflow.
export_transcript_markdown
Returns the transcript rendered as Markdown.
export_report_markdown
Returns the full synthesis report (cartography + roadmap + personas) as Markdown. Takes interview_id.
Synthesis
get_roadmap
Returns solutions grouped by horizon. Takes interview_id.
get_personas
Returns per-contact personas, optionally filtered by department.
query_campaign
Runs a GraphRAG query across the campaign’s transcripts.
Returns:
{answer, patterns[], divergences[]}.
start_full_corpus_analysis
Starts a durable exhaustive analysis over every eligible completed answer in one campaign. Transcript-visible
answers may be cited. Responses marked report only also influence shared aggregate patterns, but their raw
turns, identities, conversation ids, and individual observations are never returned. Starting a run persists an
internal audit chat and consumes analysis compute, so this tool requires a write-capable key.
Returns the durable
run_id, internal audit session_id, status/phase, model, and coverage. Coverage separates
processed, usable, contributing, suppressed, citable, and aggregate-only answers.
get_full_corpus_analysis
Reads progress for a queued/running run or one paginated section of a completed result. It applies the same
serve-time privacy and source-freshness checks as Insights Chat. If transcript content or privacy changed after the
snapshot, it returns rerun_required: true instead of serving a stale result.
Ready results return
items, pagination metadata, citation keys, and coverage. Evidence can only contain sources
that are currently citable; report-only source material remains aggregate-only. If more answers finish after the
run snapshot, the response keeps the immutable result but also returns rerun_required: true,
rerun_reason: "new_responses_since_snapshot", coverage.added_since_snapshot, and current_completed. Start a
new run to include the current total.
list_full_corpus_analyses
Lists full-corpus analysis runs in the workspace, newest first.
Returns:
{"runs": [...], "has_more", "next_cursor"} — keep paging via next_cursor for complete coverage.
cancel_full_corpus_analysis
Cancels a queued or running analysis run; already-finished runs are returned unchanged. Takes run_id.
Requires a write-capable key.
retry_full_corpus_analysis
Re-queues a cancelled, failed, or partial run on its immutable source snapshot. Takes run_id. Runs whose
snapshot or privacy went stale return code rerun_required — start a new run instead. Requires a
write-capable key.
Campaign research (Insights Chat toolbox)
These tools construct the same privacy-aware toolbox as the product’s Insights Chat: campaign anonymity levels and participant-level privacy picks are enforced identically. Every response has the shape{"result": ..., "citations": {...}}, where citations maps the citation keys inside result to
privacy-sanitized source metadata.
get_research_corpus_manifest
Coverage statistics for campaign transcript corpora: eligible, citable, and indexed conversation counts.
Use it first when a question depends on corpus size or coverage. Takes an optional interview_id — with
it you get one campaign’s manifest; omit it for a workspace-wide manifest that aggregates every campaign
the key can see and adds campaigns_in_scope plus a per-campaign campaigns breakdown
(interview_id, name, completed_conversations, citable_conversations, aggregate_only — counts
only, never conversation ids).
get_transcript_page
Reads one conversation transcript as resumable raw-turn pages with per-turn citation keys (unlike
get_transcript, which returns the whole transcript at once).
Follow
has_more/next_cursor — keep paging for complete coverage of the conversation.
search_transcript_passages
Hybrid semantic + keyword search over raw transcript turns with real-turn citations. Takes query (max
4000 characters) and an optional interview_id: pass it to search one campaign, or omit it to search
every campaign the key can see in one fused pass — the result coverage then reports campaigns_searched
of campaigns_in_scope, and scopes over 12 campaigns return code scope_too_broad (narrow to specific
campaigns or ask a synthesis question over the campaign reports). Top-k relevance search — never
sufficient for “all/every/how many” questions; use start_full_corpus_analysis for those. Hybrid
search is available by default; in the rare case a workspace has been explicitly disabled by Ontora
staff it returns code hybrid_search_disabled — use search_quotes instead.
search_quotes
Keyword search for participant quotes across campaign transcripts; works in every workspace. Top-k
relevance search — never sufficient for “all/every/how many” questions; use start_full_corpus_analysis
for those. Takes query and an optional interview_id (omit to search every non-draft campaign).
Returns quotes plus coverage fields (conversations_matched, conversations_considered,
selection_exhaustive: false).
find_participants
Finds interview participants by case-insensitive name, email, or department substring; omit query to
list every visible participant.
Returns
participants (each with contact_id, display_name, department, campaigns —
interview_id/campaign_name/conversation_id per visible conversation — and conversation_count),
paginated ~25 per page; follow has_more/next_cursor. Privacy is fail-closed: participants whose
identity is hidden (anonymous campaigns, participant privacy picks, aggregate-only or report-only
responses) are absent entirely — never anonymized — so absence is not evidence someone did not
participate.
get_question_results
Verified per-question results from the campaign’s latest synthesis report. Takes interview_id and
question_id (from get_interview_guide). Prefer this over transcript search for guide questions — it
covers every eligible answer.
get_report_outline
Manifest of the campaign’s latest synthesis report: every section with kind and size. Call it before
get_report_section; when no report exists it says so explicitly. Takes interview_id.
get_report_section
Reads one report section as paginated JSON fragments with verified real-turn citations.
Follow
has_more/next_cursor — keep paging for complete coverage of the section.
get_interview_guide
The campaign’s interview guide: sections, questions, and the question_id values that
get_question_results consumes. Takes interview_id.
list_campaign_conversations
Privacy-aware conversation list with speaker labels and redacted summaries, cursor-paginated (unlike the
offset-based list_conversations). Takes optional interview_id and cursor. Follow
has_more/next_cursor — keep paging for complete coverage.
People
list_people
Lists people in the workspace people directory, newest first.
Returns:
{"people": [...], "limit", "offset", "has_more"}.
get_person
Returns one person with their campaign participation and transcripts. Takes person_id.
list_people_groups
Returns the workspace’s people groups with member counts.
Knowledge graph
query
Full GraphRAG over the workspace knowledge graph: vector search → graph traversal → answer with citations. Takes prompt, optional vault_ids, depth, top_k.
search_documents
Semantic document search without LLM generation. Takes query, optional vault_ids, top_k, source_type.
get_entities
Browse entities and relationships. Optional entity_type, name_query, limit, include_relationships.
chat_project
Chat within a project context using the project’s vaults for retrieval. Takes project_id, message, optional session_id for follow-ups. Persists the chat session, so it requires the write capability — for stateless analysis use query or query_campaign.
Webhooks
list_webhooks
Returns the workspace’s webhook subscriptions.
add_webhook
Creates a subscription.
Returns
{id, secret, url, events} — the secret is only shown here.
remove_webhook
Deletes a subscription. Takes endpoint_id.