Skip to Content

MCP API (Model Context Protocol)

The MCP endpoint exposes The Org API as Model Context Protocol  (MCP) tools. Use it from MCP-compatible clients (Cursor, Claude, ChatGPT, and others) to query companies, people, open jobs, org charts, reporting lines, positions, contact details, people/lead lists, and usage over JSON-RPC 2.0.

For setup instructions (Claude Desktop, Cursor), see MCP Integration.

Endpoint

POST https://api.theorg.com/v1.1/mcp
ParameterValue
Urlhttps://api.theorg.com/v1.1/mcp 
MethodPOST
AuthOAuth (Authorization: Bearer) or X-Api-Key
CostSame credits as underlying APIs. Org-chart exploration is 10 credits per company per API key for 30 minutes
Server1.2 (serverInfo.version on initialize)

Authentication

The MCP server supports OAuth in full, and it also accepts an API key. Credit costs match the underlying operations (list tools are free). An OAuth connection is issued its own API key, so credits, rate limits, and the 30-minute org-chart exploration pass are tracked on that connection separately from a key you paste yourself.

OAuth

Clients that implement MCP authorization  connect with the server URL alone. A request without credentials returns 401 and a WWW-Authenticate header pointing at the protected-resource metadata, which is how the client starts the flow.

StepEndpoint
Protected resourceGET https://api.theorg.com/.well-known/oauth-protected-resource/v1.1/mcp
Authorization serverGET https://api.theorg.com/.well-known/oauth-authorization-server (also …/oauth-authorization-server/v1.1/mcp)
OpenID configurationGET https://api.theorg.com/.well-known/openid-configuration
Dynamic client registrationPOST https://api.theorg.com/oauth/register
AuthorizeGET https://api.theorg.com/oauth/authorize
TokenPOST https://api.theorg.com/oauth/token
UserinfoGET https://api.theorg.com/oauth/userinfo

The grant is authorization code with PKCE. code_challenge_method must be S256. Clients are public (token_endpoint_auth_method is none). Supported scopes are openid, email, and mcp. Client ID metadata documents are accepted. After you approve the connection on The Org, the token response is a Bearer access token with expires_in of 365 days. Send it on MCP calls as Authorization: Bearer.

Userinfo returns sub, email, and email_verified.

API key

Pass the same API key as the rest of the API in the X-Api-Key header, or as the api_key query parameter (apikey and x-api-key are also accepted). The examples below use the header.

Optional: send MCP-Protocol-Version: 2025-11-25 (or 2025-03-26) on requests.

Protocol

The transport is Streamable HTTP : each JSON-RPC message is a separate POST with a JSON body.

  1. Initialize – Send an initialize request; the server returns capabilities and server info.
  2. Initialized – Send a notifications/initialized notification (server responds 202 Accepted).
  3. Tools – Use tools/list to discover tools and tools/call to invoke them.

HEAD, and GET without Accept: text/event-stream, return 200 so clients can probe the URL. SSE streaming is not supported. Send JSON-RPC messages with POST.

Tools

ToolDescriptionCreditsRate limit
search_companiesLook up companies by name, domain, email, or LinkedIn URL/slugFree30 / 60s
get_companyEnriched company profile by company ID, domain, or LinkedIn URL/slugFree60 / 60s
get_org_chartIframe embed URL for a company org chart (by domain or LinkedIn URL/slug)Free60 / 60s
get_company_executive_positionsCompany context plus L1, L2, and advisers. Each entry can be a person, a job, or a group10 / company / key / 30 minGlobal 15/s
get_company_position_reportsDirect reports of one chart position (p-… person or job, g-… group)Same exploration passGlobal 15/s
search_company_positionsSearch one company’s chart by name or title. Results can be people, jobs, or groupsSame exploration passGlobal 15/s
find_personLook up a person by LinkedIn URL/slug, or full name + company name/domainFree30 / 60s
find_jobsSearch open jobs by URL/slug, title, company, or filters (max 25)Free30 / 60s
get_managerManager of a person (position ID/email/LinkedIn URL/slug)1 per findGlobal 15/s
get_reportsDirect reports of a person (position ID/email/LinkedIn URL/slug)1 when reports are foundGlobal 15/s
find_positionsSearch positions/people with filters (max 25 results per call)1 per rowGlobal 15/s
resolve_contactsActively resolve work emails for up to 25 people from prior lookups1 per person newly resolvedGlobal 15/s
get_listsList people/lead lists for the account (owned and shared)Free30 / 60s
add_to_listAdd position IDs from lookups to an existing list (max 25)FreeGlobal 15/s
create_listCreate a people/lead list and optionally add position IDs (max 25)FreeGlobal 15/s
get_usageCurrent account usage/creditsFree30 / 60s

List tools return a url for each list in the form https://theorg.com/people/lists/{slug} (for example https://theorg.com/people/lists/empty-list). The same lists can be read over HTTP via the Lists API (GET /v1.1/lists).

Free-tool windows are per API key and shared with the matching REST route. Details: Rate Limiting.

Every tool declares a JSON Schema outputSchema in tools/list, and successful tools/call results carry the typed payload in structuredContent alongside the human-readable content text block.

IntentTool
Resolve a company from a name or LinkedInsearch_companies
Tell me about this companyget_company (description, size, location, industries, funding)
Show a company’s org chartget_org_chart, then render the returned embedUrl in an iframe
Who runs this company, then walk the chartsearch_companies, then get_company_executive_positions, then get_company_position_reports or search_company_positions
Look up a named person / LinkedIn profilefind_person
Find open jobsfind_jobs
Who manages this person?get_manager
Who reports to this person?get_reports
Who is the CEO / people in a department?find_positions with companyDomains + jobTitles / departments
Get someone’s work emailfind_person or find_positions, then resolve_contacts with the returned position IDs
Build a lead list from a searchfind_positions then create_list with name + positionIds
Add people to an existing listget_lists (if needed) then add_to_list with listId or slug + positionIds
What lists do I have?get_lists
Remaining creditsget_usage

Filter fields for find_positions match the Position API. Company/org-chart tools match the Company API. MCP find_positions and find_jobs limit results to 25 per call (stricter than the Position API’s page size of up to 1000).

Company tools

search_companies

Look up companies and return ids, names, domains, org-chart URLs, and signed embed URLs. Provide any one of the following:

ArgumentTypeDescription
qstringCompany name search query
domainstringCompany website or email domain (e.g. theorg.com)
emailstringWork email used to resolve the company
linkedInUrlstringLinkedIn company URL or bare slug (e.g. https://www.linkedin.com/company/stripe or stripe)
limitintegerOptional. Max results (1–50, default 10)

get_company

Returns an enriched company profile. Provide exactly one identifier.

ArgumentTypeDescription
companyIdstringCompany UUID from search_companies or find_positions
domainstringCompany website or email domain (e.g. theorg.com)
linkedInUrlstringLinkedIn company URL or bare slug (e.g. stripe)

The response company object includes id, name, slug, description, logoUrl, domains, websiteUrl, linkedInUrl, twitterUrl, industry, industries, legalStatus, stage, foundedYear, employeeRange, location, totalFundingUsd, latestFundingStage, crunchbaseUrl, positionCount, followerCount, verified, orgChartUrl, and embedUrl.

industries, legalStatus, employeeRange, and latestFundingStage use the same vocabulary as the find_positions filters, so a company profile can be fed straight back into a people search.

get_org_chart

Returns an iframe embed URL for a company’s org chart rather than the chart data itself, which keeps large charts out of the model’s context.

ArgumentTypeDescription
domainstringCompany website or email domain (e.g. theorg.com)
linkedInUrlstringLinkedIn company URL or bare slug (e.g. stripe)

The response contains name, embedUrl, and orgChartUrl. Render embedUrl in an iframe; it is signed to your API key. To walk the chart as JSON, use the exploration tools below. The HTTP Company API org chart endpoint is a separate charge (10 credits per request).

Org-chart exploration

get_company_executive_positions, get_company_position_reports, and search_company_positions read one company’s chart. If the question is about that company’s org chart structure, these tools need companyId, a UUID. Identify the company and that id with search_companies (or get_company) first. A name or slug is rejected.

The first call that finds the company, on a given API key and company, costs 10 credits and opens a 30-minute exploration pass. An OAuth connection counts as its own API key. An unknown company id is not charged. Further calls for that pair inside the window are free, including paging get_company_position_reports and search_company_positions. A different company, or the same company on another key or connection, starts a new pass. If fewer than 10 credits remain, the tool result is an error and no pass is stored. This window is separate from the 24-hour replay on metered REST requests.

These tools do not replace get_manager / get_reports, which look a person up by position id, email, or LinkedIn and cost 1 credit per find.

get_company_executive_positions

Company profile fields plus the top of the chart: l1 (roots), l2 (their direct reports), advisers, and section counts (placed, unplaced, board, total). Each entry can be a person, a job, or a group.

ArgumentTypeDescription
companyIdstringCompany UUID (required)

Each entry includes nodeId, title, name, linkedInUrl, theOrgUrl, nodeType (position for a person, job, or coManager for a group), section (orgChart, unplaced, or board), parentNodeId, reportCount, and seniorityScore. name is null for jobs and groups.

get_company_position_reports

Direct reports of one person, job, or group. This is not get_reports, which looks a person up by position id, email, or LinkedIn.

ArgumentTypeDescription
companyIdstringCompany UUID (required)
nodeIdstringId of the person, job, or group from get_company_executive_positions or search_company_positions (p-… or g-…, required)
limitintegerPage size (default 50, max 50)
offsetintegerPage offset (default 0)

The response contains node, reports, totalReports, limit, offset, and hasMore.

search_company_positions

Search that company’s chart by name or title. Matches people, jobs, and groups.

ArgumentTypeDescription
companyIdstringCompany UUID (required)
querystringName or title text
sectionstringOptional filter: orgChart, unplaced, or board
limitintegerPage size (default 50, max 50)
offsetintegerPage offset (default 0)

The response contains companyId, results, and totalCount.

Person and job lookup tools

find_person

Look up a specific person in The Org’s people index. Prefer this over find_positions when you already have a LinkedIn profile or a name+company pair.

Provide either linkedInUrl, or fullName with companyName or companyDomain:

ArgumentTypeDescription
linkedInUrlstringLinkedIn profile URL or bare slug (e.g. https://www.linkedin.com/in/jane-doe or jane-doe)
fullNamestringPerson full name (use with companyName or companyDomain)
companyNamestringEmployer company name (use with fullName)
companyDomainstringEmployer website/email domain (use with fullName)
limitintegerOptional. Max results for name lookups (1–10, default 5)

The response contains people entries with positionId, fullName, title, slug, linkedInUrl, companyId, companyName, companySlug, profileUrl, and orgChartUrl. Use returned positionId values with get_manager, get_reports, resolve_contacts, and list tools.

find_jobs

Search open job vacancies. Resolve a specific posting via jobUrl or companySlug + jobSlug, or search with title/keywords and optional company/filters.

ArgumentTypeDescription
jobUrlstringFull The Org job URL (https://theorg.com/org/{companySlug}/jobs/{jobSlug})
companySlugstringCompany slug (use with jobSlug)
jobSlugstringJob post slug (use with companySlug)
jobTitlestringJob title phrase (e.g. Product Manager)
companyNamestringHiring company name
companyDomainstringHiring company website/email domain
companyIdstringCompany UUID from search_companies
keywordsstring[]Additional job-title keywords
jobTypesstring[]Employment types (snakecase, e.g. full_time)
jobFunctionsstring[]Functional areas (snakecase, e.g. engineering)
countriesstring[]Job-location ISO country codes (e.g. US, GB)
remotebooleanWhen true, only remote jobs; when false, only non-remote
limitintegerOptional. Max results for searches (1–25, default 5)

The response contains jobs and totalResults. Each job includes jobId, title, slug, teaser, remote, jobType, jobFunction, country, company fields, jobUrl, and optional associatedPositionId when the role is placed on the org chart.

Reporting-line tools

get_manager walks one step up the reporting line and get_reports walks one step down. Both accept the same identifiers — provide any one of them.

ArgumentTypeDescription
positionIdintegerPosition ID from find_positions or find_person
emailstringWork email of the person
linkedInUrlstringLinkedIn profile URL or bare slug

get_manager returns data.position and data.manager (null when the person is at the top of the chart). get_reports returns data.position, data.reports, and data.totalReports. At most 50 reports are returned per call; totalReports always carries the true count.

Both cost 1 credit per successful lookup — get_manager when a manager is found, get_reports when at least one report is found.

find_positions arguments

ArgumentTypeDescription
limitintegerRequired. Max results (1–25)
offsetintegerRequired. Pagination offset (0–10000)
filtersobjectSame fields as the Position API (see below)

find_positions filters

filters accepts the same fields as the Position API, including:

FieldTypeDescription
companyDomainsstring[]Company domains (e.g. apple.com)
jobTitlesstring[]Role title phrases (include variants: CEO, Chief Executive Officer)
departmentsstring[]Department snakecase values (e.g. marketing, engineering)
personFullNamesstring[]Named individuals
managerFullNames / managerJobTitlesstring[]People reporting to a manager
industriesstring[]Industry labels
locations{ country, state? }[]Company location filters
employeeRangesstring[]Company size buckets (e.g. 1-10, >10000)
orgChartLevelsstring[]LevelOne … LevelFourPlus, Unplaced
companyLegalStatusesstring[]Legal/entity types
latestFundingStagesstring[]Funding stages
previousCompanyDomainsstring[]Previous employer domains
hiredWithinDaysintegerRecent hires
verifiedWorkEmailbooleanOnly rows with a verified email already stored. Use sparingly — it hides people whose email resolve_contacts could still find
personIdsinteger[]Internal position IDs

resolve_contacts

Actively resolves work emails for people you have already found via find_positions or find_person.

ArgumentTypeDescription
positionIdsinteger[]Position IDs from find_positions or find_person (required, max 25 per call)

The workEmail field on a find_positions row only reflects whether an email is already stored — it is not a resolution attempt. A null there does not mean no email can be found. Call resolve_contacts before concluding that contact details are unavailable.

The response contains data.creditsUsed and data.results, with one entry per requested person holding positionId, emails (each with email, emailType, and verification), and phoneNumbers. A person with no resolvable email comes back with empty arrays rather than being omitted.

Credits: 1 credit per person newly resolved to an email. People this account has resolved before are free, and people for whom no email is found cost nothing. If the batch is larger than your remaining balance, only as many people as you can afford are attempted, so a call never overdraws. Phone numbers are read from existing data and are never charged for.

People / lead list tools

Use find_positions or find_person first, then pass returned position IDs into create_list or add_to_list.

get_lists

ArgumentTypeDescription
limitintegerOptional. Max lists to return (1–100, default 30)
offsetintegerOptional. Pagination offset (default 0)

Response includes lists (each with id, name, slug, url, optional positionCount) and total.

add_to_list

ArgumentTypeDescription
listIdstringList UUID from get_lists (provide listId or slug)
slugstringList slug (e.g. empty-list)
positionIdsinteger[]Position IDs from find_positions (required, max 25 per call)

create_list

ArgumentTypeDescription
namestringDisplay name for the new list (required)
positionIdsinteger[]Optional position IDs to add immediately (max 25)

Response includes the created/updated list (id, name, slug, url) and addedCount.

Example: Initialize

curl --location 'https://api.theorg.com/v1.1/mcp' \ --header 'X-Api-Key: YOUR_API_KEY' \ --header 'Content-Type: application/json' \ --header 'Accept: application/json, text/event-stream' \ --data '{ "jsonrpc": "2.0", "id": 1, "method": "initialize", "params": { "protocolVersion": "2025-11-25", "capabilities": {}, "clientInfo": { "name": "example", "version": "1.0" } } }'

Example: List tools

curl --location 'https://api.theorg.com/v1.1/mcp' \ --header 'X-Api-Key: YOUR_API_KEY' \ --header 'Content-Type: application/json' \ --data '{"jsonrpc":"2.0","id":2,"method":"tools/list"}'

Example: Call a tool (get_usage)

curl --location 'https://api.theorg.com/v1.1/mcp' \ --header 'X-Api-Key: YOUR_API_KEY' \ --header 'Content-Type: application/json' \ --data '{ "jsonrpc": "2.0", "id": 3, "method": "tools/call", "params": { "name": "get_usage", "arguments": {} } }'

Example: Call get_org_chart

curl --location 'https://api.theorg.com/v1.1/mcp' \ --header 'X-Api-Key: YOUR_API_KEY' \ --header 'Content-Type: application/json' \ --data '{ "jsonrpc": "2.0", "id": 4, "method": "tools/call", "params": { "name": "get_org_chart", "arguments": { "domain": "theorg.com" } } }'

Example: Call get_company

curl --location 'https://api.theorg.com/v1.1/mcp' \ --header 'X-Api-Key: YOUR_API_KEY' \ --header 'Content-Type: application/json' \ --data '{ "jsonrpc": "2.0", "id": 5, "method": "tools/call", "params": { "name": "get_company", "arguments": { "domain": "theorg.com" } } }'

Example: Call find_person

curl --location 'https://api.theorg.com/v1.1/mcp' \ --header 'X-Api-Key: YOUR_API_KEY' \ --header 'Content-Type: application/json' \ --data '{ "jsonrpc": "2.0", "id": 12, "method": "tools/call", "params": { "name": "find_person", "arguments": { "fullName": "Patrick Collison", "companyName": "Stripe" } } }'

Example: Call find_jobs

curl --location 'https://api.theorg.com/v1.1/mcp' \ --header 'X-Api-Key: YOUR_API_KEY' \ --header 'Content-Type: application/json' \ --data '{ "jsonrpc": "2.0", "id": 13, "method": "tools/call", "params": { "name": "find_jobs", "arguments": { "jobTitle": "Product Manager", "companyName": "Stripe", "limit": 5 } } }'

Example: Call find_positions

curl --location 'https://api.theorg.com/v1.1/mcp' \ --header 'X-Api-Key: YOUR_API_KEY' \ --header 'Content-Type: application/json' \ --data '{ "jsonrpc": "2.0", "id": 6, "method": "tools/call", "params": { "name": "find_positions", "arguments": { "limit": 5, "offset": 0, "filters": { "companyDomains": ["theorg.com"], "jobTitles": ["CTO", "Chief Technology Officer"] } } } }'

Example: Call get_reports

Use a position id returned by find_positions:

curl --location 'https://api.theorg.com/v1.1/mcp' \ --header 'X-Api-Key: YOUR_API_KEY' \ --header 'Content-Type: application/json' \ --data '{ "jsonrpc": "2.0", "id": 7, "method": "tools/call", "params": { "name": "get_reports", "arguments": { "positionId": 12345 } } }'

Example: Call resolve_contacts

curl --location 'https://api.theorg.com/v1.1/mcp' \ --header 'X-Api-Key: YOUR_API_KEY' \ --header 'Content-Type: application/json' \ --data '{ "jsonrpc": "2.0", "id": 8, "method": "tools/call", "params": { "name": "resolve_contacts", "arguments": { "positionIds": [12345, 12346] } } }'

Example: Call get_lists

curl --location 'https://api.theorg.com/v1.1/mcp' \ --header 'X-Api-Key: YOUR_API_KEY' \ --header 'Content-Type: application/json' \ --data '{ "jsonrpc": "2.0", "id": 9, "method": "tools/call", "params": { "name": "get_lists", "arguments": { "limit": 30, "offset": 0 } } }'

Example: Call create_list

After find_positions, pass returned position IDs:

curl --location 'https://api.theorg.com/v1.1/mcp' \ --header 'X-Api-Key: YOUR_API_KEY' \ --header 'Content-Type: application/json' \ --data '{ "jsonrpc": "2.0", "id": 10, "method": "tools/call", "params": { "name": "create_list", "arguments": { "name": "Fintech CTOs", "positionIds": [12345, 12346] } } }'

Example: Call add_to_list

curl --location 'https://api.theorg.com/v1.1/mcp' \ --header 'X-Api-Key: YOUR_API_KEY' \ --header 'Content-Type: application/json' \ --data '{ "jsonrpc": "2.0", "id": 11, "method": "tools/call", "params": { "name": "add_to_list", "arguments": { "slug": "empty-list", "positionIds": [12345, 12346] } } }'

Error responses use standard JSON-RPC 2.0 errors or tool results with isError: true and a message in the content.

Last updated on