Play Video

MCP Server

Connect Claude, Cursor, and other Model Context Protocol clients directly to Oppora. 51 tools spanning the full outbound pipeline — discovery, bulk upsert, contact resolution, AI enrichment & scoring, async tasks, workflows, campaigns, research.

51 toolsSame key as REST APIPro / Max plan
Endpoint
https://api.oppora.ai/mcp

Streamable HTTP transport. Authenticate with ?api_key=…, X-API-Key, or Authorization: Bearer.

Quick start

60 seconds
1

Generate a key

In Oppora, open Integrations → Oppora API and click Create API key. Copy the opp_live_… secret (shown once).

Open Integrations
2

Add the connector

Pick your MCP client below and paste the connection URL. Both query-string and Authorization-header auth work.

3

Try a tool

Ask the assistant "what lists do I have?" — it calls my_lists. Then try discover_companies + add_companies_to_list.

Connect a client

Same endpoint, same key

Pro/Max plans: Settings → Customize → Connectors → + → Add custom connector. Paste the URL below:

https://api.oppora.ai/mcp?api_key=YOUR_KEY

Team/Enterprise: Owner adds via Organization settings → Connectors → Add → Custom → Web, then members enable under Customize.

Anthropic's servers (not your browser) connect to this URL, so it must be reachable from the public internet. localhost won't work.

Tools reference

51 total

All tools return TOON-encoded text except discover_companies and discover_people (JSON). Filter below to jump to a tool.

51

Discovery (companies & people)

2

Search Oppora's global databases. Both auto-save results into Oppora's DB so every returned row carries an Oppora `id` you can pass straight to the add-to-list tools. 1 data credit per non-empty call.

discover_companiesSearch the global company DB by industry, size, location, revenue, funding, growth. Auto-saved.
1 data credit
Arguments
industry?: string[], size?: string[] (bucket), hq_country?: string[] (ISO 3-alpha), location?: string[], company_type?: string[], year_founded?: string, revenue_range_min/max?: int (USD), last_funding_round_type?: string[], employee_growth_6m_min?: int (percent), exclude_*?: string[], limit?: int, next_cursor?: string
Returns

JSON `{ results: [{id, name, domain, …}], next_cursor, has_more, count, credit_charged, credits_remaining }`. `id` is Oppora's saved Company.id — reuse it directly.

Example
discover_companies(
  hq_country=["USA"],
  industry=["Software Development"],
  size=["51-200","201-500"],
  revenue_range_min=5_000_000,
  limit=25,
)
discover_peopleSearch the global people DB by title, dept, mgmt level, company, skills, location. Auto-saved with `id`.
1 data credit
Arguments
title?: string, departments?: string[], management_levels?: string[], company_name?: string|string[], company_industry?: string, employee_count?: string (bucket), years_experience?: string ("Less than 1 year"|"1 to 2 years"|"3 to 5 years"|"6 to 10 years"|"More than 10 years"), location?: string, skills?: string[], limit?: int
Returns

JSON `{ results: [{id, first_name, last_name, …}], credit_charged, credits_remaining }`

Example
discover_people(
  title="VP Sales",
  departments=["Sales"],
  management_levels=["VP","Director"],
  company_name=["Stripe","Plaid"],
  limit=25,
)

Filter helpers

7

Resolve exact valid values before calling discover_* or find_leads_for_companies. Wrong values match nothing — these are essential.

get_available_industries~435 LinkedIn industry names.
Free
get_available_countriesCountry names + ISO 3-alpha codes. Pass `iso_alpha3` to `hq_country`.
Free
get_available_company_typesPrivately Held, Public Company, Nonprofit, etc.
Free
get_available_last_funding_round_typesseed, series_a, series_b, etc.
Free
get_available_departmentsFor `discover_people.departments`.
Free
get_available_management_levelsFor `discover_people.management_levels`.
Free
search_locationsAutocomplete city/region names for the `location` filter.
Free

Saved companies & leads

8

Manage records the user has already saved into Oppora lists.

my_listsUser's lists with company + lead counts. Call this BEFORE add/remove tools.
Free
create_listCreate a new list or return the existing one with that name (idempotent, per-user-per-org dedup).
Free
Arguments
name: string
Returns

TOON `{ id, name, is_existing, message, list_url }`

Example
create_list(name="Top Prospects Q2")
list_my_saved_companiesSaved companies (optionally scoped to one list).
Free
list_my_saved_leadsSaved leads (ListLeadContact rows).
Free
add_companies_to_listAdd EXISTING Oppora company IDs to a list. Use after discover_companies / create_companies_bulk.
1 data credit per added
remove_companies_from_listBulk-remove company memberships.
Free
add_leads_to_listAdd EXISTING Oppora lead IDs to a list. Use after discover_people / create_leads_bulk.
1 data credit per added
remove_leads_from_listBulk-remove lead memberships.
Free

Bulk upsert (external data → Oppora DB)

2

For data from web scrapes, news search, user input, CSV imports — anything NOT from discover_*. Both tools dedup against the global DB and optionally add to a list in one call. Free — credits hit at discover/enrich time.

create_companies_bulkUpsert ≤100 company dicts. Dedups by name / linkedin / website / domain. Returns Oppora IDs.
Free
Arguments
companies: list[{name (required), domain?, website?, linkedin?, industry?, approx_employee_size?, meta?}], list_id?: int
Returns

TOON `{ company_ids, added_to_list, list_id, list_url, message }`

Example
create_companies_bulk(
  companies=[
    {"name": "Acme", "domain": "acme.com"},
    {"name": "Globex", "linkedin": "https://linkedin.com/company/globex"},
  ],
  list_id=12,  # optional — save + add to list in one call
)
create_leads_bulkUpsert ≤100 leads. Dedup: email → linkedin → first_name+last_name+company. Auto-creates employer Company from company_name.
Free
Arguments
leads: list[{first_name OR email (one required), last_name?, linkedin?, title?, phone?, location?, company_name?, company_domain?, company_linkedin?, company_industry?}], list_id?: int
Returns

TOON `{ created, existing, failed, lead_ids, failed_details, list_id, message }`

Example
create_leads_bulk(
  leads=[
    {"first_name": "Alice", "email": "[email protected]", "company_name": "Stripe"},
    {"linkedin": "https://linkedin.com/in/bob-smith"},
  ],
  list_id=12,
)

Async list operations

4

Long-running per-list operations. Each returns a task_id immediately; the work runs on Celery. Every response carries an oppora_url so the user can open the affected list.

enrich_companiesAI enrichment for companies in a list (website, industry, size, description, etc.).
1 data credit per enriched company
Arguments
list_id: int (required), company_ids?: int[] (omit = whole list)
Returns

TOON `{ task_id, message, list_id, list_name, counts, oppora_url }`

Example
enrich_companies(list_id=12)  # enrich every company in the list
find_leads_for_companiesFind people at companies in a list. Requires departments + management_level — resolve via get_available_*. Provide a comprehensive title list.
1 / 3 / 5 credits per saved lead (Standard / Premium / Deep)
Arguments
list_id: int, departments: string[], management_level: string[], company_ids?: int[], title?: string[], lead_limit?: int (≤1000), country?/country_full_name?/location?/experience?/employee_count? string[], source_tiers?: ["standard"|"premium"|"deep"], exclude_location?: string[], main_objective?: string
Returns

TOON `{ task_id, message, list_id, list_name, oppora_url }`

Example
find_leads_for_companies(
  list_id=12,
  departments=["sales", "business_development"],
  management_level=["vp", "director"],
  title=["AE", "Account Executive", "BDR", "SDR"],
  lead_limit=100,
  source_tiers=["standard", "premium"],
)
score_leadsRank every lead in a list against the user's offer/ICP. Returns "Yes" / "No" + reason per lead.
AI credits per scored lead
Arguments
list_id: int, service_type: string, leads_per_company: int, priority_departments: string, specific_leads_per_department: string, additional_requirements?: string
Returns

TOON `{ task_id, message, list_id, list_name, counts, oppora_url }`

Example
score_leads(
  list_id=12,
  service_type="B2B sales-automation SaaS for outbound teams",
  leads_per_company=3,
  priority_departments="Sales, Marketing",
  specific_leads_per_department="VP Sales x2, Director of Marketing x1",
)
find_emails_for_leadsBulk-resolve work emails for leads in a list. For one-off, use email_search.
1 contact credit per email found (misses free)
Arguments
list_id: int, lead_ids?: int[] (omit = whole list)
Returns

TOON `{ task_id, message, list_id, list_name, counts, oppora_url }`

Example
find_emails_for_leads(list_id=12)

Tasks (poll async work)

2

Read the status of any task created by the async tools above. Every row carries an oppora_url for the affected list/workflow.

get_task_statusFull snapshot: status, progress %, summary, credits used, oppora_url. Cross-user isolated.
Free
Arguments
task_id: int
Returns

TOON `{ task_id, title, status, progress, summary, credits_used, oppora_url, … }`

Example
get_task_status(task_id=1408)
list_my_tasksPaginated list of the user's tasks. Filter by status.
Free
Arguments
status?: "pending"|"in_progress"|"completed"|"stopped", page?: int, limit?: int (≤100)
Returns

TOON `{ total, page, limit, has_more, tasks[N]{task_id, title, status, progress, summary, oppora_url, …} }`

Example
list_my_tasks(status="in_progress", limit=10)

Workflows

3

Chain operations (enrich → lead-find → score → email-find → campaign) into a workflow tied to a list. Run on-demand or on a schedule.

create_workflowCreate a workflow on a list. Optional one-shot schedule (any IANA timezone).
Free
Arguments
name: string, list_id: int, scheduled_time?: "YYYY-MM-DD HH:MM", timezone_str?: string
Returns

TOON `{ workflow_id, message, oppora_url }`

Example
create_workflow(name="Weekly outbound", list_id=12)
add_workflow_nodeAdd ONE agent node to a workflow. Types: company-crawl, ai-enrich, company-filter, lead-search, ai-recommendation, search-contact, verify-contact, generate-campaign.
Free
Arguments
workflow_id: int, list_id: int, prompt: string (node type + any instructions)
Returns

TOON `{ workflow_id, message, oppora_url }`

Example
add_workflow_node(workflow_id=79, list_id=12, prompt="ai-enrich")
start_workflowTrigger a workflow to run now. Nodes execute in sequence on Celery; poll each via list_my_tasks.
Free (nodes charge their own credits)
Arguments
workflow_id: int, list_id: int
Returns

TOON `{ message, oppora_url }`

Example
start_workflow(workflow_id=79, list_id=12)

Contact resolution

3

Single-shot finders + verifier. Credits charged ONLY on success.

email_searchFind email by (first_name + last_name | full_name) + domain. Domain is required.
1 contact credit on success
Example
email_search(
  first_name="Alice",
  last_name="Chen",
  domain="stripe.com",
)
email_verifierStandard SMTP check or advanced (catch-all aware).
1 verify credit on success
Example
email_verifier(email="[email protected]", mode="standard")
phone_searchFind phone via linkedin_url (best) OR name + company/domain. Checks Oppora DB cache first.
1 phone credit on success — DB-cache hits are free
Example
phone_search(linkedin_url="https://linkedin.com/in/alice-chen-vp")

Campaigns

8

Inspect, set up, update, start, and validate campaigns.

list_campaignsList with sent/opened/clicked/replied + rates.
Free
get_campaignFull config: lists, accounts, templates, schedule, stats.
Free
get_campaign_reportFunnel report (date range).
Free
create_or_update_campaignFull setup — attach lists, templates, schedule, accounts, dates, flags.
Free
update_campaign_statusPause / activate / complete / draft.
Free
start_campaignActivate; refuses if not ready (returns issue list).
Free
check_campaign_readinessValidate setup; returns clickable URLs to fix each missing component.
Free
list_email_accountsConnected Gmail/Outlook/SMTP accounts with status.
Free

Templates & schedules

7

Reusable building blocks for campaigns.

list_templatesEmail + LinkedIn templates (filter by kind).
Free
list_follow_up_templatesFollow-ups ordered by `order` + `after_days`.
Free
list_schedulesSending schedules with timezone + days.
Free
create_email_templateHTML body with personalisation variables.
Free
create_linkedin_templatePlain text, ≤200 chars.
Free
create_follow_up_template`order` + `after_days` + optional subject.
Free
create_scheduleAny pytz/IANA timezone accepted.
Free

Research / web

5

External web/news/maps/AI search. Free for web_search + web_scrape; 1 AI credit on success for the rest.

web_searchGoogle-style web search. Titles, snippets, links, knowledge graph.
Free
web_scrapeFetch + extract readable text from a URL.
Free
smart_web_searchAI semantic search for niche queries.
1 AI credit on success
local_business_searchGoogle Maps (rating, phone, website).
1 AI credit on success
news_searchLatest news (good for intent signals).
1 AI credit on success

End-to-end example

discover → enrich → score → outreach

A realistic flow the AI agent can run in a single conversation. Async steps return a task_id; poll progress with get_task_status or list_my_tasks.

  1. 1
    get_available_industries + get_available_countriesresolve exact values
  2. 2
    discover_companies(industry=[…], hq_country=[…])auto-saved; every row has Oppora id
  3. 3
    my_listspick or ask user to create a list
  4. 4
    add_companies_to_list(list_id, company_ids=[…])pin them
  5. 5
    enrich_companies(list_id)async; returns task_id
  6. 6
    find_leads_for_companies(list_id, departments=[…], management_level=[…], title=[…])async lead search
  7. 7
    score_leads(list_id, service_type, leads_per_company, …)AI ranking
  8. 8
    find_emails_for_leads(list_id)bulk email resolution
  9. 9
    get_task_status(task_id) / list_my_tasks(status="completed")progress + oppora_url links
  10. 10
    create_email_template + create_schedule + list_email_accounts
  11. 11
    create_or_update_campaign(…) → check_campaign_readiness → start_campaign
For repeatable runs: create_workflow + a sequence of add_workflow_node calls (ai-enrich, lead-search, ai-recommendation, search-contact, generate-campaign) → start_workflow. For external data (web scrapes, news, user input): create_companies_bulk / create_leads_bulk upserts in one shot.

FAQ

What format do tool responses use?
TOON-encoded text (token-efficient tabular) for all tools EXCEPT discover_companies and discover_people, which return JSON because their results carry nested fields that benefit from a real object structure.
When am I charged credits?
Only on a successful result. Discovery tools charge when results are non-empty; email/phone finders charge when an email/phone is returned with a non-falsy status; async tools charge per item processed. DB cache hits and misses are always free.
Are MCP and REST API the same key?
Yes. One opp_live_… key authenticates both. Generate keys under Integrations → Oppora API.
Do I need a paid plan?
Yes. Both REST API and MCP are paid features (Pro or Max). API keys cannot be generated on Free.
Why TOON instead of JSON?
TOON's tabular header (results[N]{f1,f2}:) + CSV rows is ~40% fewer tokens than JSON for uniform record arrays — the typical shape these tools return. Less tokens = lower LLM cost + faster response.
How do I validate a key works?
Use MCP Inspector at modelcontextprotocol.io/docs/tools/inspector. Point it at https://api.oppora.ai/mcp?api_key=YOUR_KEY and verify the tools list appears.