Tool Catalog

Complete reference for all 10 DealSurface MCP tools. Each tool maps to a REST API endpoint.

For detailed request/response schemas, full filter vocabularies, and code examples, see the REST API Reference. Line-of-business, state, sort, and entity-type vocabularies are embedded in the tool schemas as enums, so an invalid value is rejected by your client with the accepted set — it never silently matches nothing.

list_products

scope: readFree

List active products configured for your team, including which kinds of insurance company each one sells to. This is typically the first tool called in any workflow. Disabled products are hidden unless include_disabled is true.

Inputs

ParameterTypeDescription
include_disabledbooleanInclude disabled product metadata. Defaults to false.

Output

{
  products: Array<{
    product_id: number
    name: string
    description: string
    is_active: boolean
    keywords: Array<{ keyword_id, name, auto_extracted }>
    sources: Array<{ source_id, url, title, source_type }>
    industries: Array<{ industry_name, industry_description, industry_code }>
    segment_targeting: "all" | "selected"
    target_segments: Array<{
      insurance_entity_type: "carrier" | "reinsurer" | "agency" | "mga"
        | "brokerage" | "unclassified_intermediary" | "unknown"
      company_ownership: "public" | "private" | "any"
      carrier_facts: {
        lines_of_business: Array<{ line_of_business, premium_min,
                                   premium_max, unknown_premium }>
        licensed_footprint: { min, max } | null
        include_unknown: boolean
      } | null
    }>
  }>
}

Common failures

  • 401 — Invalid API key.
  • 403 — Key lacks `read` scope.

Sequencing

Start here. Use the returned product_id with every other tool. Read target_segments to know what a product is meant to sell to before you judge whether a prospect fits.

get_product

scope: readFree

Get detailed information about a specific active product, including its keywords, sources, target industries, and target segments. Disabled products are hidden unless include_disabled is true.

Inputs

ParameterTypeDescription
product_idrequirednumberThe product ID.
include_disabledbooleanInclude disabled product metadata. Defaults to false.

Output

{
  product: { ...same shape as one element of list_products }
}

Common failures

  • 404 — Product not found, disabled without include_disabled, or belongs to a different team.

Sequencing

Use after list_products if you need full details on a single product.

list_prospects

scope: readFree

List prospects for a product, one row per corporate family, with NAIC premium and complaint data. Covers the full candidate universe — assessed and unassessed families alike, labeled by assessment_status. Filter by book of business, licensed footprint, entity type, ownership, and score.

Inputs

ParameterTypeDescription
product_idrequirednumberProduct to get prospects for.
min_deal_scorenumberMinimum deal score (1-5). Implies assessed-only: unscored rows can't match a score floor.
12345
min_buying_signalnumberMinimum buying signal (0.0-1.0). Same assessed-only implication.
assessment_statusstring[]Optional narrowing to one or more assessment buckets.
assessedpending_scoreunassessed
entity_typestring[]Match families whose companies include any of these insurance entity types. "unknown" matches unclassified rows.
carrierreinsureragencymgabrokerageunclassified_intermediaryunknown
ownershipstring= anyFilter on family ownership. Distinct from include_private, which is an entitlement gate.
publicprivateany
include_privatebooleanInclude private companies, when your team is entitled to them. Defaults to false.
min_premiumnumberMinimum annual premium in USD. Applies per line when lines_of_business is supplied, otherwise to total all-lines premium.
max_premiumnumberMaximum annual premium in USD. Same rule as min_premium.
lines_of_businessstring[]Lines of business written. Matches families writing ANY of them. The 30 filterable NAIC line keys are enumerated in this tool's schema, so your client rejects an invalid one. total_all_lines, aggregate_write_ins, and international appear in premium output but are report roll-ups and cannot be filtered on.
min_licensed_statesnumberMinimum family-union licensed-state footprint (0-50).
states_licensed_instring[]Two-letter codes for the 50 US states, enumerated in the schema (DC and territories cannot appear in the data and are rejected). Matches families licensed in ALL of them.
qstringName search. Matches family names, tickers, aliases, and subsidiary names — use it when you were given a company name rather than a ticker.
include_childrenbooleanInline each family's subsidiaries with the results. Forces limit to 50 or fewer.
sort_bystring= relevanceServer-side sort. Prefer it over ranking a page yourself: a sorted first page is the top of the whole filtered set, not the top of one page. premium_line requires exactly one lines_of_business value. Rows with no value for the key sort last, never as zero.
relevancedeal_scorebuying_signalpremium_totalpremium_linecomplaint_indexlicensed_state_count
sort_dirstringSort direction; defaults to the sensible one per key.
ascdesc
limitnumber= 100Max results (1-500).
offsetnumber= 0Pagination offset.

Output

{
  prospects: Array<{
    ticker, company_name,
    assessment_status: "assessed" | "pending_score" | "unassessed",
    deal_score,           // null unless assessed
    buying_signal_score,  // null unless assessed
    rank, rank_total,
    entity_count,         // companies in this corporate family
    matched_entity_count, // how many of them matched your filters
    insurance_entity_types,  // key omitted when unclassified
    ownership, lines_of_business,
    licensed_states, licensed_state_count,
    premium: { currency, report_years, total_all_lines_usd,
               by_line_of_business, contributing_entity_count } | null,
    complaints: { report_years, total_complaints,
                  complaint_index, complaint_index_status } | null,
    children: [...]       // only when include_children=true
  }>
  total_groups: number             // corporate families in the filtered universe
  total_entities: number           // companies inside them
  excluded_no_data_groups: number  // dropped for lacking the data a filter required
  limit: number
  offset: number
}

Common failures

  • 400 — Invalid product_id, or an unrecognized lines_of_business, states_licensed_in, entity_type, or sort_by value. The error names the accepted set; an unknown value is never ignored.
  • 404 — Product not found.
  • 503 — Prospect data is rebuilding, or has not been rebuilt since the product's keywords changed. The body carries reason: 'rebuilding' is worth retrying in seconds, 'stale_keywords' waits on a pipeline run. Either way it means "not ready", never "no prospects found".

Sequencing

Call after list_products. Use a returned ticker with get_prospect for a deep dive, or get_dealmap to see who to contact.

Reading the results correctly

A result is a corporate family, not one company. It can appear because a subsidiary matched, so the ticker may not be the company that satisfied your filter. matched_entity_count says how many did; use get_prospect and read hierarchy.children to find which.

Premium figures blend report years across a family and the total does not reconcile with the per-line breakdown — use the total for scale, the breakdown for mix. The family complaint index is a ratio against premium-share expectation; a small carrier can top a complaint_index sort on little evidence, so corroborate with get_prospect's full series.

get_prospect

scope: readFree

Full analysis for one company: findings, recommendations, evidence excerpts, firmographics, premium by line of business, complaint history, and its corporate family.

Inputs

ParameterTypeDescription
tickerrequiredstringCompany serving alias: letters, numbers, dots or hyphens, up to 12 characters. Also accepts any hierarchy.children[].ticker from a previous call.
product_idrequirednumberProduct to get the analysis for.
include_privatebooleanRank within the private-inclusive population, when entitled. The prospect's identity never changes.
report_yearnumberNarrow the premium and complaint series to a single year. Omit it to receive every available year, which is the default — the trend is usually the actionable half.

Output

{
  ticker, company_name,
  assessment_status, deal_score, rank, rank_total,
  company_info: { public_or_private, family_public_or_private,
                  sic_codes, insurance_entity_types,
                  primary_naic_cocode, all_naic_cocodes,
                  licensed_states, insurance_types,
                  website, primary_domain },
  premium: { currency, report_years, total_all_lines_usd, by_line_of_business,
             observations: Array<{ report_year, line_of_business,
                                   annual_premium_usd }> } | null,
  complaints: { cocode, available_years,
                observations: Array<{ report_year, line_of_business,
                                      total_complaints, complaint_index,
                                      complaint_index_status }> } | null,
  hierarchy: { prospect_kind, child_count, eligible_child_count,
               coverage_ratio,
               group: { ticker, company_name, is_self },
               children: Array<{ ticker, company_name,
                                 deal_score, has_assessment }> } | null,
  narrative_scope: "company" | "group",
  findings_summary, recommendation_summary,
  key_opportunity, primary_challenge,
  impact_score_distribution,
  findings: Array<{ finding_id, text, evidence_excerpt_ids }>,
  excerpt_count: number,
  excerpts: Array<{ excerpt_id, text, impact_score, source,
                    pain_points, sales_summary, buying_signal_present }>
}

Common failures

  • 404 — Unknown ticker for this product, or the alias is ambiguous. Unassessed companies return the facts-only shape, not 404.
  • 400 — Invalid ticker or product_id.
  • 503 — Projection unavailable (same reasons as list_prospects).

Sequencing

Call after list_prospects. To drill into a subsidiary, take a ticker from hierarchy.children and call this tool again. Follow with search_excerpts for finer evidence filtering, or get_dealmap to find who to contact.

Embedded excerpts are capped at 20

The excerpts array carries at most 20, highest impact score first, with excerpt_count reporting how many exist. Call search_excerpts for the rest. Well-covered companies carry hundreds — enough to fill your context window in a single call.

Analysing a subsidiary

Pass any hierarchy.children[].ticker straight back into this tool. A subsidiary reports its family's rank rather than one of its own, and its own premium and complaint record. has_assessment tells you whether we hold an assessment for that company — where it is false, fetching it returns the facts-only shape (null scores, empty findings and excerpts) with the firmographic, premium, and complaint data still populated.

insurance_entity_types is left out entirely when a company has not been classified. A missing key means “we do not know”, which is different from an empty list meaning “we checked and it is none”. And complaint_index_status explains a missing index: no_premium_share means complaints were reported but no index could be computed (total_complaints is still meaningful); not_reported means no complaint data.

search_excerpts

scope: readFree

Search and filter evidence excerpts for one prospect and product. Use this for granular evidence analysis beyond the capped excerpts get_prospect returns.

Inputs

ParameterTypeDescription
product_idrequirednumberThe product the excerpts were assessed against.
tickerrequiredstringCompany serving alias.
min_impact_scorenumberMinimum impact score (1-5).
keywordstringFilter by keyword against the excerpt's pain points (case-insensitive).
limitnumber= 50Max results (1-200).
offsetnumber= 0Pagination offset.

Output

{
  excerpts: Array<{ excerpt_id, text, impact_score, source,
                    pain_points, sales_summary, buying_signal_present }>
  total_count: number
  limit: number
  offset: number
}

Common failures

  • 404 — Unknown ticker for this product. Unassessed companies return an empty page (total_count 0), not 404.
  • 400 — Invalid ticker, product_id, or pagination values.
  • 503 — Projection unavailable (same reasons as list_prospects).

Sequencing

Use after get_prospect for deeper evidence analysis. Excerpt IDs can be referenced in craft_outreach results.

framework_category removed in 2.0.0

framework_category is no longer accepted as an input, and the field is gone from every excerpt result (here and in get_prospect). Narrow with min_impact_score and keyword instead.

get_dealmap

scope: readFree

Get the buying committee DealMap for a prospect company. Shows stakeholders with AI-assigned roles (Economic Buyer, Decision Maker, Champion, etc.), org hierarchy edges, and a buying_committee_summary identifying the top pick for each role.

Inputs

ParameterTypeDescription
product_idrequirednumberProduct context.
tickerrequiredstringCompany serving alias. A subsidiary ticker resolves to the corporate family's DealMap, and the result names the family it resolved to.

Output

{
  status: "empty" | "ready" | "stale"
  chart: { id, generated_at, expires_at, company_name, node_count, relevant_node_count } | null
  stakeholders: Array<{
    node_id, full_name, title, level, level_label,
    linkedin_url, work_email, manager_name,
    stakeholder_role, stakeholder_role_source,
    annotation_score, annotation_reason,
    is_top_pick, top_pick_source
  }>
  edges: Array<{ from_node_id, to_node_id, relationship }>
  buying_committee_summary: {
    economic_buyer, decision_maker, champion,
    executive_sponsor, evaluator, blockers: [...]
  }
}

Common failures

  • 400 — Invalid product_id or ticker.
  • 404 — Product not found.

Sequencing

Call after get_prospect. Returns status 'empty' if no DealMap exists yet — call generate_dealmap first.

generate_dealmap

scope: read, outreach0-10 credits

Generate or refresh the buying committee DealMap for a prospect. Maps the org structure and assigns stakeholder roles using AI analysis. Credits charged only when fresh org-chart data is fetched. Hard-capped at 5 requests per minute.

Inputs

ParameterTypeDescription
product_idrequirednumberProduct context.
tickerrequiredstringCompany serving alias. A subsidiary ticker resolves to the family; a generate that lands on an already-cached family map is not charged.
force_refreshboolean= falseForce fresh org chart fetch. Always charges credits.

Output

{
  status: "ready"
  chart: { id, generated_at, expires_at, company_name, node_count, relevant_node_count }
  stakeholders: Array<{ node_id, full_name, title, level, stakeholder_role, is_top_pick, ... }>
  edges: Array<{ from_node_id, to_node_id, relationship }>
  buying_committee_summary: { economic_buyer, decision_maker, champion, ... }
  generation_source: "org_fresh" | "org_cached" | "annotation_only"
  credits_charged: boolean
}

Common failures

  • 402 — Insufficient credits for fresh generation.
  • 404 — Product not found.
  • 409 — A generation for this prospect is already in flight. Wait, then read the result with get_dealmap.
  • 429 — Hard cap of 5 requests per minute exceeded.
  • 502 — DealMap generation service temporarily unavailable.

Sequencing

Call after get_prospect. Follow with get_dealmap to read the result, or use stakeholders directly with craft_outreach.

Avoid unnecessary force_refresh

Do not use force_refresh unless the user explicitly requests updated org data. Cached org-chart data is reused for free.

override_stakeholder_role

scope: readFree

Override the AI-assigned stakeholder role for a specific person on the buying committee DealMap. This is a team-wide override visible to all team members. Use when the AI role assignment is clearly wrong.

Inputs

ParameterTypeDescription
product_idrequirednumberProduct context.
tickerrequiredstringCompany serving alias.
node_idrequiredstringThe node_id from get_dealmap stakeholders.
stakeholder_rolerequiredstringThe corrected stakeholder role.
Economic BuyerDecision MakerChampionExecutive SponsorEvaluatorEnd UserProcurement / Legal ReviewerBlockerIrrelevant

Output

{
  success: true
  node_id: string
  stakeholder_role: string
}

Common failures

  • 400 — Invalid node_id or stakeholder_role.
  • 404 — Product not found or node not in DealMap.

Sequencing

Call after get_dealmap when an AI-assigned role needs correction.

set_top_pick

scope: readFree

Mark or unmark a stakeholder as the top pick for their role on the buying committee DealMap. Team-wide, like role overrides. New in 2.0.0 — wraps PATCH /dealmap/node-top-pick, so an agent that can correct a role can also mark who to actually approach.

Inputs

ParameterTypeDescription
product_idrequirednumberProduct context.
tickerrequiredstringCompany serving alias.
node_idrequiredstringThe node_id from get_dealmap stakeholders.
is_top_pickrequiredbooleantrue marks this stakeholder as the top pick for their role; false clears a manual top pick.

Output

{
  success: true
  node_id: string
  is_top_pick: boolean
}

Common failures

  • 400 — Invalid node_id.
  • 404 — Product not found or node not in DealMap.

Sequencing

Call after get_dealmap. The top pick per role feeds buying_committee_summary and the { stakeholder_role } lead selector in craft_outreach.

craft_outreach

scope: read, outreach1 credit

Generate an evidence-backed outreach message (email or LinkedIn) for a prospect. Grounded in real evidence from public filings and earnings calls. Hard-capped at 10 requests per minute.

Inputs

ParameterTypeDescription
product_idrequirednumberProduct context.
tickerrequiredstringCompany serving alias. A subsidiary ticker resolves to the family's DealMap for lead selection.
platformrequiredstringTarget platform.
emaillinkedin
tonerequiredstringDesired tone.
hard_sellhelpfulneutral
lengthstring= typicalDesired length.
shortertypicallonger
selected_leadSelectedLeadFull lead object to personalize for.
lead_selectorobjectSelector to resolve a stakeholder: { node_id }, { level }, { full_name, level }, or { stakeholder_role } (picks the top-pick for that role).

Output

{
  subject?: string   // Only for email platform
  body: string
  platform: string
  tone: string
  length: string
  used_excerpt_ids: number[]
  selected_lead?: { full_name, title, level }
  selected_lead_note?: string
}

Common failures

  • 402 — Insufficient credits.
  • 404 — No prospect data.
  • 400 — Invalid platform, tone, or length value.
  • 429 — Hard cap of 10 requests per minute exceeded.

Sequencing

Final step in a workflow. Use stakeholders from get_dealmap and evidence from get_prospect or search_excerpts.

Lead targeting

If both selected_lead and lead_selector are provided, selected_lead takes precedence. Omit both for generic company outreach.

MCP Tool Catalog | DealSurface Docs