Raw schema
{
"properties": {
"filters": {
"anyOf": [
{
"additionalProperties": false,
"description": "List-mode filters for ``type='people'`` (routes to ``get_user_people``).\n\nMutually exclusive with ``query`` — pass one or the other, never both.",
"properties": {
"campaign": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "Outreach campaign UUID, exact name, slug, or 'unassigned' for people with no campaign.",
"title": "Campaign"
},
"custom": {
"anyOf": [
{
"additionalProperties": {
"type": "string"
},
"type": "object"
},
{
"type": "null"
}
],
"description": "Custom-attribute filters from CSV-import custom columns; every key=value pair must match (e.g. {'sorted_company_size': 'small'}).",
"title": "Custom"
},
"enrollment": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "Outreach enrollment filter: all, enrolled, paused, not_enrolled.",
"title": "Enrollment"
},
"list": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "Only people in this list — people_lists UUID or exact name (CSV-import list mirroring). Unknown list returns an empty result.",
"title": "List"
},
"persona": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "Buying-role filter: influencer, decision_maker, economic_buyer, unknown, or 'unclassified' (no classification run yet).",
"title": "Persona"
},
"relationship_type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "Relationship filter: outbound_prospect, inbound_buyer, inbound_seller, networking, or all.",
"title": "Relationship Type"
},
"research_status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "'researched', 'shallow', 'deep', 'stub', or 'all'. When omitted, matches the underlying endpoint's default: 'researched' for browsing, but 'all' when `search` is set (a search must find stubs too).",
"title": "Research Status"
},
"score_max": {
"anyOf": [
{
"maximum": 100,
"minimum": 0,
"type": "integer"
},
{
"type": "null"
}
],
"description": "Maximum match score (0-100, inclusive).",
"title": "Score Max"
},
"score_min": {
"anyOf": [
{
"maximum": 100,
"minimum": 0,
"type": "integer"
},
{
"type": "null"
}
],
"description": "Minimum match score (0-100, inclusive).",
"title": "Score Min"
},
"search": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "Free-text search across email, first/last name, title, company name.",
"title": "Search"
},
"sort_by": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": "score",
"description": "Sort by recent, score, name, or company (default: score — same as the underlying endpoint).",
"title": "Sort By"
},
"stage": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "Pipeline stage: new, warming, enrolled, contacted, replied, met, opportunity, closed_won, closed_lost.",
"title": "Stage"
},
"status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "Legacy filter — 'meeting_booked' (stage=met) or 'all' (default).",
"title": "Status"
}
},
"title": "FacadePeopleFilters",
"type": "object"
},
{
"additionalProperties": false,
"description": "Filters for ``type='companies'`` — EXTERNAL Hunter.io domain search via ``find_people_at_company``.",
"properties": {
"domain": {
"description": "Company domain to search (e.g. 'acme.com'). Required.",
"title": "Domain",
"type": "string"
},
"seniority": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "Seniority filter: executive (C-level/VP), senior (directors/managers), or junior.",
"title": "Seniority"
}
},
"required": [
"domain"
],
"title": "FacadeCompaniesFilters",
"type": "object"
},
{
"additionalProperties": false,
"description": "Filters for ``type='deals'`` (routes to ``get_deals``).",
"properties": {
"outcome": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "Deal outcome filter: won, lost, stalled.",
"title": "Outcome"
},
"query": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "Free-text search for a specific deal — case-insensitive, every whitespace-separated word must match. Spans the deal name, the associated company name, and the primary contact's name/email/title. Combine with stage/outcome to scope further.",
"title": "Query"
},
"stage": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "Deal stage filter. Matches the deal's pipeline-stage label LITERALLY (exact, case-sensitive string — not a closed enum). Native pipelines use met, qualified, proposal, negotiation, verbal_yes, closed_won, closed_lost; HubSpot-imported pipelines carry their own custom labels (e.g. 'Hot Leads', 'Prospecting', 'Trial Signup', 'Closed lost'). Pass the literal label exactly as stored. Discover the labels a tenant's pipeline actually uses via inspect_pipeline (groups deals by stage) or by listing deals (with no stage filter) and reading each deal's 'stage'.",
"title": "Stage"
}
},
"title": "FacadeDealsFilters",
"type": "object"
},
{
"additionalProperties": false,
"description": "Filters for ``type='campaigns'`` (routes to ``get_campaigns``).",
"properties": {
"fields": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "Projection: omit for the default compact list (the prose-heavy fields — ai_tone_instructions, ai_selling_strategy, touch_sequence, value_proposition, primary_problem_solved, differentiators, positioning_angle, notable_customers_override — come back null; a null there does NOT mean the campaign lacks the value); 'minimal' for id/name/slug only (dropdowns/selection); 'full' to include the prose for EVERY campaign (10KB+ each — a multi-campaign tenant can exceed client output limits and get silently truncated; prefer fetch type='campaign' for one campaign's full config).",
"title": "Fields"
}
},
"title": "FacadeCampaignsFilters",
"type": "object"
},
{
"additionalProperties": false,
"description": "Filters for ``type='messages'`` (routes to ``get_message_queue``).",
"properties": {
"campaign_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "Campaign UUID, or '__none__' for people with no campaign assigned (resolved via the queue's campaign_id resolver).",
"title": "Campaign Id"
},
"category": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "Message category: initial, followup, reply_response.",
"title": "Category"
},
"channel": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "Channel filter (email, linkedin_connection, linkedin_message, …).",
"title": "Channel"
},
"fields": {
"anyOf": [
{
"const": "compact",
"type": "string"
},
{
"type": "null"
}
],
"description": "Set to 'compact' for a lightweight projection WITHOUT message body — keeps message_id, person_name, category, sequence_number, channel, status, match_score, touches_completed, campaign_id, first_content_touch, channel_rewrite_reason, expires_at, connection_status. first_content_touch=true = the person has never received a content-bearing message (connection requests don't count): treat the item as an OPENER regardless of sequence_number; null = row predates the conversation_state brief (fall back to the sequence_number heuristic). expires_at (needs_draft rows only) = when the nightly sweep auto-rejects the row if still unauthored (regenerate grants a fresh window) — author nearest-deadline-first (sort_by=expiring) to beat it. connection_status = the linked plan's LinkedIn connection state: a linkedin_message row with connection_status='connected' is a WARM follow-up (they accepted the invite) — dispatch these first. Cheap on tokens for triage. An unrecognized value 422s.",
"title": "Fields"
},
"has_reply": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"description": "Only messages that have (true) / have not (false) received a reply.",
"title": "Has Reply"
},
"person_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "Filter by a specific person ID.",
"title": "Person Id"
},
"score_max": {
"anyOf": [
{
"maximum": 100,
"minimum": 0,
"type": "integer"
},
{
"type": "null"
}
],
"description": "Maximum match score (0-100).",
"title": "Score Max"
},
"score_min": {
"anyOf": [
{
"maximum": 100,
"minimum": 0,
"type": "integer"
},
{
"type": "null"
}
],
"description": "Minimum match score (0-100).",
"title": "Score Min"
},
"search": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "Search across subject, person email, person name.",
"title": "Search"
},
"sequence_number_max": {
"anyOf": [
{
"minimum": 1,
"type": "integer"
},
{
"type": "null"
}
],
"description": "Max sequence number, inclusive (T1=1).",
"title": "Sequence Number Max"
},
"sequence_number_min": {
"anyOf": [
{
"minimum": 1,
"type": "integer"
},
{
"type": "null"
}
],
"description": "Min sequence number, inclusive (T1=1).",
"title": "Sequence Number Min"
},
"sort_by": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": "recent",
"description": "Sort: recent (default), expiring (created_at asc — nearest sweep deadline first, pair with status='needs_draft'), person_name, subject, priority, or match_score.",
"title": "Sort By"
},
"status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "Message status: needs_draft (unauthored — author via manage_messages edit), draft, approved, rejected, sent (expands to post-send statuses), or all. Omit for default (needs_draft + draft + approved).",
"title": "Status"
},
"view": {
"anyOf": [
{
"const": "breakdown",
"type": "string"
},
{
"type": "null"
}
],
"description": "Set to 'breakdown' for a queue-composition summary: grouped counts (by campaign × category × sequence × channel × status, plus per-dimension marginals) over the full matching set, alongside a compact items page. Implies fields='compact'. An unrecognized value 422s.",
"title": "View"
},
"warm_only": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"description": "true = only WARM follow-ups: linkedin_message rows whose plan has connection_status='connected' (the person ACCEPTED the connection request — highest-EV rows in the queue). Forces channel=linkedin_message. warm_only=true + status='needs_draft' + sort_by='expiring' pulls the warm authoring lane in one call, nearest sweep deadline first.",
"title": "Warm Only"
}
},
"title": "FacadeMessagesFilters",
"type": "object"
},
{
"additionalProperties": false,
"description": "Filters for ``type='engagements'`` (routes to ``get_engagement_queue``).",
"properties": {
"campaign": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "Campaign NAME or UUID (resolved via the engagement queue's campaign-ref resolver — distinct from the messages campaign_id resolver).",
"title": "Campaign"
},
"sort_by": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": "priority",
"description": "Sort: priority (default), created_at, or status.",
"title": "Sort By"
},
"source": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "Engagement source: comment_reply, warming, nurture, or marketing.",
"title": "Source"
},
"status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "Engagement status: draft, approved, sent, failed, skipped.",
"title": "Status"
}
},
"title": "FacadeEngagementsFilters",
"type": "object"
},
{
"additionalProperties": false,
"description": "Filters for ``type='content'`` (routes to ``get_content_calendar``).",
"properties": {
"days": {
"default": 14,
"description": "Number of days of calendar history to show (default 14 — same as the underlying endpoint).",
"minimum": 1,
"title": "Days",
"type": "integer"
}
},
"title": "FacadeContentFilters",
"type": "object"
},
{
"additionalProperties": false,
"description": "Filters for ``type='kb'`` (routes to ``search_knowledge_base``).",
"properties": {
"doc_type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "Filter by type: positioning, case_study, objection_handling, battlecard, process, other (authored docs), or 'connector' for synced Drive/Notion documents only. Omit to search both.",
"title": "Doc Type"
},
"document_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "Fetch full content of one document (ignores query/doc_type). Accepts an authored-doc UUID or a connector id of the form '<connection_uuid>:<source_record_id>' (as returned in search results).",
"title": "Document Id"
},
"include_content": {
"default": false,
"description": "Include full document text in search results (default false for a compact catalog). Connector docs return snippets in search mode regardless; read one in full via document_id.",
"title": "Include Content",
"type": "boolean"
},
"query": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "Fuzzy keyword search. Matches authored docs (name/summary/keywords, typo-tolerant) AND synced connector documents (Google Drive / Notion) by title + body — e.g. meeting transcripts.",
"title": "Query"
}
},
"title": "FacadeKbFilters",
"type": "object"
},
{
"additionalProperties": false,
"description": "Filters for ``type='skills'`` (routes to the MCP ``list_skills`` route).",
"properties": {
"scope": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "Skill scope filter: private, company, or operator. Omit for every scope the caller can see.",
"title": "Scope"
}
},
"title": "FacadeSkillsFilters",
"type": "object"
},
{
"additionalProperties": false,
"description": "Filters for ``type='cta_links'`` (routes to ``get_cta_links``).\n\nThe underlying endpoint takes no filters and no pagination — this model is\nintentionally empty (pagination on ``cta_links`` is rejected at the\nrequest level, never silently ignored).",
"properties": {},
"title": "FacadeCtaLinksFilters",
"type": "object"
},
{
"additionalProperties": false,
"description": "Filters for durable web/MCP relationship actions.",
"properties": {
"target_ref": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "Opaque entity_ target reference.",
"title": "Target Ref"
}
},
"title": "FacadeRelationshipAttemptsFilters",
"type": "object"
},
{
"type": "null"
}
],
"description": "Type-specific filters — the object shape is determined by `type` (e.g. {domain} for companies, {stage, outcome, query} for deals). Unknown keys are rejected with 422.",
"title": "filters",
"type": "object"
},
"for_company": {
"description": "Optional company ID or name (UUID, or case-insensitive EXACT name match — partial / substring matches are NOT supported; ambiguous names raise 400) to execute this tool as. Use get_operator_overview with view='companies' to list available companies. Only needed if you manage multiple companies. Access is enforced server-side: the tool resolves the value to a user_company_id and verifies the caller's membership in `company_users` — a 403 'Company not found or access denied' means EITHER the value did not match a known company OR the caller is not a member of it. The MCP operator role itself is NOT auto-granted — operators get this access by being members of each client company via `company_users` (the same row that grants any normal user access).",
"title": "for_company",
"type": "string"
},
"limit": {
"anyOf": [
{
"minimum": 1,
"type": "integer"
},
{
"type": "null"
}
],
"description": "Page size. Supported for people, deals, messages, warm_paths, and relationship_attempts (max 100), plus engagements (max 200); people keyword-query mode caps at 40. Rejected (422) for other types.",
"title": "limit",
"type": "integer"
},
"offset": {
"anyOf": [
{
"minimum": 0,
"type": "integer"
},
{
"type": "null"
}
],
"description": "Pagination offset. Supported for people (list mode), deals, messages, engagements, warm_paths, and relationship_attempts. Rejected (422) for other types and for people query mode.",
"title": "offset",
"type": "integer"
},
"query": {
"anyOf": [
{
"type": "string"
},
{
"items": {
"additionalProperties": false,
"description": "One candidate in a people batch lookup (maps to ``BatchSearchRequest.queries``).",
"properties": {
"company": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "Company name to look up alongside the person name.",
"title": "Company"
},
"linkedin_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "LinkedIn profile URL — strongest dedup signal; exact-matched first when present.",
"title": "Linkedin Url"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "Person full name to look up in the existing pipeline.",
"title": "Name"
}
},
"title": "FacadeBatchPersonQuery",
"type": "object"
},
"type": "array"
},
{
"type": "null"
}
],
"description": "Only for type='people'. A keyword string searches the existing pipeline (name/title/company); an array of {name?, company?, linkedin_url?} objects runs a batch dedup lookup (results in original order). Mutually exclusive with `filters`. For type='kb' or type='deals', use filters.query instead.",
"title": "query"
},
"type": {
"description": "The relationship-aware entity types the ``search`` facade can read.",
"enum": [
"people",
"companies",
"deals",
"campaigns",
"messages",
"engagements",
"content",
"kb",
"skills",
"cta_links",
"warm_paths",
"relationship_attempts"
],
"title": "type",
"type": "string"
}
},
"required": [
"type"
],
"title": "searchArguments",
"type": "object"
}