Research
researchRun prospect and company research by finding LinkedIn profiles, emails, and company data, then save the findings to your records.
Instructions
Research
Run prospect/company research and save the results — the consolidated research tool.
Lookup actions (external providers — results are returned, not stored, unless noted):
find_linkedin: locate a person's LinkedIn URL (id = person UUID;
payloadoptional {name_override?, company_override?, auto_save?} — auto_save stores a high-confidence match).enrich_company: scrape a company website (
payload= {domain, page_type?}).find_email: find a work email (
payload= {first_name, last_name, domain}).linkedin_fetch: pull a LinkedIn profile (
payload= {linkedin_url, include_company?, include_posts?, posts_limit?}).careers_parse: parse a careers page for hiring signals (
payload= {domain}).
Save actions (write research rows):
save_person: UPDATE research on an EXISTING person — pass the person UUID as
payload.person_id(preferred; refreshes researched_at and the research fields in place), or matching email/linkedin anchors. Cannot create: new prospects go through manage_person action=save_discovered withpayload.person+payload.assessment. Never pass the person UUID asid— this action takes no id.save_company: atomically patch sourced public company research. Pass
payload={idempotency_key, name, person_id?, website?, linkedin_url?, company_summary?, company_stage?, current_priorities?, funding_data?, growth_metrics?, sources_by_field}. Omitted fields are preserved; explicit null clears. When researching a specific person's employer, ALWAYS pass their UUID aspayload.person_id— the response'sperson_linkconfirms the write landed on that person's linked company (repointing an anchorless duplicate link when needed); amismatchstatus means the person's touches will NOT see this research, and aconflictstatus is a transient race — replay the identical payload (person_id is exempt from the idempotency hash, so adding it to a replay is the supported repair).sources_by_fieldmust contain exactly every supplied non-null research field, with entries{url, title?, observed_at}. Example:{"idempotency_key":"pipeline/example.com/save-v1","name":"Example", "website":"https://example.com","company_summary":"Example sells …", "sources_by_field":{"company_summary":[{"url":"https://example.com/about", "title":"About","observed_at":"2026-07-30T20:00:00Z"}]}}.
Batch research: every action accepts the facade's backward-compatible request cap of 100 with per-item results (partial failure is reported per item, never silent). Operators should execute the smaller policy waves documented by pipeline-fill (10 companies or 5 people at a time) so progress and retries stay bounded. find_linkedin also takes person-id arrays. Payloads are validated by the underlying route's own schema.
Responses:
200: Successful Response (Success Response) Content-Type: application/json
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| id | No | Target entity id, or an ARRAY of ids to apply the same action+payload to each (max 100; see the tool description for which entity the id names per action). | |
| items | No | For create-like actions only: an array of per-item payloads processed in order with per-item results (max 100). Mutually exclusive with `id` and `payload`. | |
| action | Yes | The operation to perform — see the tool description for the action vocabulary and each action's id/payload semantics. | |
| payload | No | Action-specific fields, validated by the underlying route's own schema (a bad field 422s with that route's precise errors). See the tool description per action. | |
| for_company | No | 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). |