MCP Server
Canonical is a verified company graph for the long tail — the companies others miss. Unlike a web search that returns links to crawl and rank, describe what you want (or pass structured filters) and get a precise, LLM-verified, domain-keyed shortlist your agent can act on directly. Connect via the Model Context Protocol with Claude Desktop, Claude Code, ChatGPT, Cursor, or Windsurf.
What is MCP?
The Model Context Protocol (MCP) is an open standard that lets AI assistants use external tools. When you connect the Canonical MCP server, your AI assistant can search for companies directly during a conversation — no manual API calls needed.
Connect with One Click
No package install needed. No API key needed. Just add the remote server URL — OAuth handles authentication automatically.
Claude Desktop Recommended
Add Canonical as a Connector — no config files needed:
- Open Claude Desktop → Settings → Connectors
- Click Add Connector
- Enter the URL: https://trycanonical.ai/mcp/
- Sign in to your Canonical account when prompted
Alternative: config file method
Edit your config file:
- macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
- Windows: %APPDATA%\Claude\claude_desktop_config.json
{
"mcpServers": {
"canonical": {
"command": "npx",
"args": ["-y", "mcp-remote", "https://trycanonical.ai/mcp/"]
}
}
}
Requires Node.js installed. Fully quit and restart Claude Desktop after saving.
Claude Code
claude mcp add canonical --transport http https://trycanonical.ai/mcp/
ChatGPT
Add as a remote tool in ChatGPT settings with the following URL:
https://trycanonical.ai/mcp/
Cursor
Add to .cursor/mcp.json in your project or ~/.cursor/mcp.json globally:
{
"mcpServers": {
"canonical": {
"type": "streamable-http",
"url": "https://trycanonical.ai/mcp/"
}
}
}
Windsurf
Same JSON format as Cursor — add to your Windsurf MCP config:
{
"mcpServers": {
"canonical": {
"type": "streamable-http",
"url": "https://trycanonical.ai/mcp/"
}
}
}
Smithery
Canonical is listed on Smithery, the developer MCP registry. Install it from your Smithery dashboard, or via the CLI:
npx -y @smithery/cli install canonical-ai/company-search
First use: When you first use the tool, you'll be prompted to sign in to your Canonical account. Don't have one? Sign up for free — you'll get 250 credits to start.
Authentication & Permissions
Canonical uses OAuth 2.0 with Dynamic Client Registration — there are no manual API keys or client credentials to manage. Your MCP client (Claude, Cursor, ChatGPT, etc.) handles the OAuth handshake automatically on the first call.
What happens on first connection
- Your client opens trycanonical.ai in your browser.
- You sign in to your Canonical account (or create one).
- You authorize the client for the search scope.
- The client receives an access token and is ready to call tools. No further sign-ins are needed unless the token expires or you revoke it.
Permissions
The connector is read-only. With the search scope it can:
- Run searches and similarity lookups against Canonical's company catalogue.
- Fetch the structured profile of a company by domain.
- Surface your remaining credit balance in tool responses so the model can warn you when you're running low.
It cannot:
- Modify, delete, or create any data in your Canonical account.
- Access saved searches, payment methods, team members, or other account data.
- Reach files, browser data, or anything outside Canonical.
Disconnecting
Remove the connector from your client to revoke its access — in Claude Desktop: Settings → Connectors → Canonical → Remove. The client calls Canonical's OAuth revocation endpoint and the token is invalidated immediately.
See our Privacy Policy for how Canonical handles queries and tool calls made through the MCP server.
Limits & Pricing
MCP tool calls share the same credit balance and rate limits as the REST API. See pricing for plan tiers.
Credit cost per tool
- search_companies / find_similar_companies: 1 credit per strong-match result returned. Partials are never charged.
- get_company_details: 1 credit per call, charged only when the domain resolves to a real company (a not-found lookup is free).
- lookup_companies: 1 credit per call when at least one candidate is returned, regardless of how many names or candidates (a no-match lookup is free).
- get_account_status: free (read-only).
Rate limits
Applied per organization across every MCP tool call:
- Free: 20 calls / minute · 1,000 / day
- Starter: 30 calls / minute · 5,000 / day
- Pro: 100 calls / minute · 50,000 / day
When a limit is hit the tool returns a structured error with retry_after_seconds, so the model can back off and retry rather than fail the user's turn.
Tool Reference
The MCP server exposes five tools: search_companies, find_similar_companies, get_company_details, lookup_companies, and get_account_status. Domains (not internal numeric ids) are the public handle — pass a domain from any search result to get_company_details, find_similar_companies, or exclude_company_domains.
search_companies
Search the catalogue using structured parameters. Pass a free-text description for the semantic core (the only fuzzy field) plus typed filters for everything else. Constraints the engine can't enforce are reported in warnings — never silently dropped. Returns LLM-verified strong matches by default.
| Parameter | Type | Default | Description |
|---|---|---|---|
| description | string | null | null | Free-text semantic description of what the company does (e.g. "B2B fintech companies in the payments space"). The only fuzzy field — drives ColBERT retrieval and LLM verification. Omit when searching by filters only. |
| cities | list[string] | null | null | HQ city names (e.g. ["New York", "San Francisco"]). Most-granular filter wins. |
| states | list[string] | null | null | HQ state/province names (e.g. ["California", "New York"]). |
| countries | list[string] | null | null | HQ country names (e.g. ["United States", "India"]). |
| employee_size | string | null | null | Headcount bucket. One of: 1-10, 11-50, 51-100, 101-500, 501-1000, 1001-5000, 5001+. |
| founding_year_min | integer | null | null | Lowest founding year to include (inclusive). E.g. 2015 means "founded in 2015 or later". |
| founding_year_max | integer | null | null | Highest founding year to include (inclusive). For an exact year, set founding_year_min == founding_year_max. |
| founding_year_exclude_min | integer | null | null | Lowest year of a contiguous range to exclude (inclusive). Both exclude_min and exclude_max must be set together. For a single-year exclusion ("not founded in 2020"), set both to the same year. Companies with unknown founding_year are kept when excluding (NULL-inclusive), dropped when including (NULL-exclusive). |
| founding_year_exclude_max | integer | null | null | Highest year of the exclude range (inclusive). |
| funding_series | list[string] | null | null | Funding stages. Values: pre_seed, seed, series_a … series_g_plus, growth, late, bridge, venture, angel, other. |
| funding_min_usd | integer | null | null | Minimum latest-round funding in USD. |
| funding_post_money_min_usd | integer | null | null | Minimum post-money valuation in USD. |
| funded_after | string | null | null | ISO date string (e.g. "2024-01-01"). Only companies funded on or after this date are returned. |
| funding_investor | list[string] | null | null | Investor firm name variants (e.g. ["Sequoia", "Sequoia Capital"]). Any matching variant satisfies the filter. |
| has_repeat_founder | boolean | null | null | When true, restrict to companies with at least one repeat founder. |
| has_technical_cofounder | boolean | null | null | When true, restrict to companies with a technical cofounder. |
| requires_role_types | list[string] | null | null | Require companies with leadership in these role categories (e.g. ["cto", "exec_other"]). Valid values: founder, cofounder, ceo, cto, cfo, coo, chief_other, exec_other. |
| founder_prior_categories | list[string] | null | null | Prior-employer tier of at least one founder. Values: faang, big_tech, unicorn, top_startup, mbb. |
| founder_prior_companies | list[string] | null | null | Specific prior-employer company names (e.g. ["Google", "Stripe"]). At least one founder must have worked there. |
| exclude_company_domains | list[string] | null | null | Domains to exclude from results (e.g. ["stripe.com"]). Unresolvable domains appear in warnings. |
| exclude_description | string | null | null | Semantic exclusion: exclude companies whose description matches this text (e.g. "consulting"). |
| intent | string | null | null | Optional ranking profile. Allowed slugs: sales_prospecting, sales_timing, sales_expansion, competitive_tracking, emerging_competitor_scan, talent_source, recruiter_employer_vet, jobseeker_stability, jobseeker_growth. |
| top_k | integer | 20 | Number of results (1–1000). Strictly honored — never over-delivers. |
| include_partials | boolean | false | When true, also returns LLM-evaluated partial matches (close but not strong). Off by default because partials aren't billed; opt in for exploratory context. |
find_similar_companies
Given a seed company's domain, return canonically similar companies.
| Parameter | Type | Default | Description |
|---|---|---|---|
| company_domain | string | required | Seed company domain (e.g. "stripe.com"). Case- and scheme-insensitive — "https://Stripe.com" works too. |
| top_k | integer | 20 | Number of similar companies (1–1000). |
| intent | string | null | null | Optional ranking profile that reorders the similar set after relevance (same slugs as search_companies, e.g. sales_timing). Omit for relevance-only ordering. |
| include_partials | boolean | false | Same as search_companies — opt in to receive partials. |
| exclude_company_domains | list[string] | null | null | Optional list of domains to exclude from similar results. |
get_company_details
Drill into one company. Returns full canonical fields (name, description, hq, employees, funding, dimensions) plus a people list (founders + C-suite/execs) when leadership data is available. Response includes credits_used and credits_remaining. Costs 1 credit when the company is found (a not-found lookup is free), rate-limited.
| Parameter | Type | Default | Description |
|---|---|---|---|
| company_domain | string | required | Domain of the company (the same handle returned in search results). Returns an error when the domain doesn't match any canonical company. |
Response also includes a leadership_data flag: "available" (people populated), "not_available" (company is in our DB but not in the leadership subset — most companies fall here), or "error" (transient lookup failure).
lookup_companies
Look up companies by name to disambiguate before passing a domain to other tools (e.g. as an exclusion or seed). Each input name returns ranked candidates plus a recommendation: when auto_resolve_recommended is true the match is unambiguous (use primary_candidate_domain); when false the name is a genuine toss-up — present the candidates and let the user pick. Costs 1 credit when at least one candidate is returned (a no-match lookup is free), rate-limited. Response includes credits_used and credits_remaining.
| Parameter | Type | Default | Description |
|---|---|---|---|
| names | list[string] | required | One or more free-text company names. Max 20 per call. |
| k | integer | 5 | Candidates to return per name (1–25). |
| disambiguation_mode | string | auto_when_confident | Override the recommendation for non-interactive callers: auto_when_confident (default), always_auto (never ask), or always_ask. |
Per name: {confidence, auto_resolve_recommended, primary_candidate_domain, candidates: [{name, domain, headquarters, description, is_primary, payload_richness}]}. Follow auto_resolve_recommended — proceed silently when true, ask the user when false.
confidence: high = one candidate or all candidates are alias domains of one entity; medium = distinct entities but the top one dominates (≥5× the next entity's headcount and ≥100 employees, or the only candidate with a description); low = comparable distinct entities. Under auto_when_confident, high+medium auto-resolve and low asks. primary_candidate_domain is set and one candidate is is_primary: true only when auto-resolving; when asking, primary_candidate_domain is null and all candidates are is_primary: false (still ranked best-guess-first, but none authoritative).
get_account_status
Returns the org's credit balance, current plan, and search rate limits. Takes no parameters. Read-only, free — charges no credits. Use it to check remaining credits or pace requests before a large batch of searches.
| Response field | Type | Description |
|---|---|---|
| credits.total | integer | Total credits currently available (subscription + extra). |
| credits.subscription | integer | Credits from the current billing-period subscription allowance. |
| credits.extra | integer | Credits purchased as top-ups (don't expire with the billing period). |
| credits.subscription_resets_at | string | null | ISO timestamp when the subscription credit allowance next resets, or null for free-tier orgs. |
| plan | string | Current plan slug: free, starter, or pro. |
| rate_limits.per_minute | integer | Max search calls allowed per minute for the org's plan. |
| rate_limits.per_day | integer | Max search calls allowed per day for the org's plan. |
| billing_url | string | URL to the Canonical billing page to top up credits or upgrade your plan. |
Example Call & Response (search_companies)
Tool responses are structured JSON, not prose — the model can branch on fields directly:
# Example structured call { "description": "AI diagnostic platforms for hospitals", "countries": ["United States"], "employee_size": "51-100", "founding_year_min": 2018, "funding_series": ["series_a", "series_b"], "top_k": 5, "intent": "sales_prospecting" } # Response { "count": 2, "credits_used": 2, "credits_remaining": 980, "warnings": [], "results": [ { "name": "Acme Health AI", "domain": "acmehealthai.com", "description": "AI-powered diagnostic platform...", "headquarters": "San Francisco, CA, United States", "employee_count": 75, "founding_year": 2019, "funding": { "latest_series": "series_b", "latest_amount_usd": 45000000 }, "dimensions": { "industry": ["Healthcare"], "offering_type": ["Software"] }, "verdict": "relevant", "verdict_reason": "1. Products...: AI diagnostic platform matches..." } ] }
Note: the domain field is the public handle for a company — pass it to get_company_details, find_similar_companies, or exclude_company_domains. Internal numeric ids aren't exposed.
Troubleshooting
Client can't reach the server
Confirm the URL is exactly https://trycanonical.ai/mcp/ — the trailing slash matters. The transport is streamable HTTP (stateless); older MCP URL shapes won't connect.
Stuck in a sign-in loop or seeing "Authentication required"
Remove the connector from your client and re-add it. The OAuth handshake will run again from scratch and a fresh token will be issued.
"Insufficient credits"
Check your balance at billing. Top up, upgrade, or wait for your daily refresh.
Still stuck?
Email support@trycanonical.ai with the client you're using, the exact error message, and the server URL you configured.