API reference
MCP
The Signals MCP server. One HTTP POST speaks the MCP streamable-HTTP protocol and answers with a server-sent event stream. GET, PUT, PATCH and DELETE answer **405** with `Allow: POST`, even when the key is missing and even while the API is closed. POST without a key, or with an invalid, revoked or `ejk_` key, is **401**. A valid `gtk_` key while the Signals API is closed answers **404**, the same body as an unknown path.
The Signals MCP server. One HTTP POST speaks the MCP streamable-HTTP protocol and answers with a server-sent event stream. GET, PUT, PATCH and DELETE answer 405 with Allow: POST, even when the key is missing and even while the API is closed. POST without a key, or with an invalid, revoked or ejk_ key, is 401. A valid gtk_ key while the Signals API is closed answers 404, the same body as an unknown path.
The assistant server at /api/mcp (key prefix ejk_) is a different server. Connect it from Connect your assistant. An ejk_ key cannot call this URL.
Authentication
Send Authorization: Bearer gtk_…. Create the key under API Access → API Keys. A missing, invalid or revoked key is 401, including while this API is closed. A valid key while the API is closed for your organization answers 404, the same body as an unknown path. Every response includes FounderMCP-Api-Version and FounderMCP-Request-Id. The response is an SSE stream, not a single JSON body. Initialize, then call tools/list and tools/call.
Response
event streamtext/event-stream· required — MCP JSON-RPC messages. Atools/callresult carries the REST body plusdashboard_urlwhere the tool has one.
Credits
The HTTP call is free. A tool spends the credits of the REST endpoint it calls. preview_cost, lookup_company, explain_lead, get_search_results and list_mentions spend nothing.
Errors
- 405
-32000— GET, PUT, PATCH and DELETE answer a JSON-RPC error andAllow: POST, before the key is checked and while the API is closed. POST without a key is 401. - 401
authentication_error— The Authorization header is missing, or the key is unknown or revoked. - 403
permission_error— API access is not part of your plan, or your account is suspended. - 404
not_found— The endpoint does not exist. - 429
rate_limit_error— More than 60 requests per minute, or more than 3 at the same time, on one key. Wait for the Retry-After header. - 500
internal_error— Something went wrong on our side.
Example
cURL
curl -X POST "https://foundermcp.dev/api/v1/mcp" \
-H "Authorization: Bearer $FOUNDERMCP_API_KEY"
JavaScript
const response = await fetch('https://foundermcp.dev/api/v1/mcp', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.FOUNDERMCP_API_KEY}`
}
});
const body = await response.json();
Python
import json
import os
import urllib.request
request = urllib.request.Request(
"https://foundermcp.dev/api/v1/mcp",
headers={
"Authorization": f"Bearer {os.environ['FOUNDERMCP_API_KEY']}"
},
method="POST",
)
with urllib.request.urlopen(request) as response:
body = json.load(response)
Example response
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"tools": [
{
"name": "lookup_company"
},
{
"name": "find_leads"
},
{
"name": "explain_lead"
},
{
"name": "watch_signal"
},
{
"name": "enrich"
},
{
"name": "preview_cost"
},
{
"name": "search_signals"
},
{
"name": "get_search_results"
},
{
"name": "company_leads"
},
{
"name": "create_monitor"
},
{
"name": "list_mentions"
}
]
}
}
preview_cost and max_credits
preview_cost is free. It does not call a source. Send endpoint (searches, leads, person.enrich or monitors) and body, the JSON the real call would use. The result is a cost_preview: credits_per_row, max_rows, max_credits and period (call or day). The REST equivalents are POST /searches/preview, POST /leads/preview, POST /person/enrich/preview and POST /monitors/preview.
max_credits is an integer cap on the real call. The call stops before the next row would pass it. That row is left out (truncated_by max_credits) and is not charged. Below the cost of one row the call is 402 max_credits_exceeded and nothing runs. On people search and people enrich the field is accepted only when the Signals API is open; otherwise it is an unknown field. A monitor uses max_credits_per_day instead.
Tools
The server name is foundermcp. tools/list returns these eleven tools. Each one calls the REST endpoint below with your gtk_ key. A result that has dashboard_url opens the same search, watch, monitor or leads in FounderMCP (/en/gtm/leads or /en/gtm/signals).
lookup_company
Free. Input: name (the company name, or a LinkedIn company page URL). Output: companies whose name matches, or an empty list and a message. REST: GET /companies/lookup.
find_leads
Screened leads: FounderMCP’s own AI checks every person against buyer_profile (and, for listening and events, every post against about). For the same signals without AI, use search_signals. 20 credits per exact lead, 5 per lead just outside. A search that finds nobody costs nothing. tech_adoption is not here: it has no screened mode. Input: signal, buyer_profile, optional exclude_companies, max_leads, just_outside, max_credits. To continue, send search_id instead of signal, and event_id when the user picks an event. Output: leads with lead_id, name, title, company, match, why_fit, why_now, evidence_url and dashboard_url. Still running: search_id and a poll hint. An event name with several matches: requires_action and the candidates. REST: POST /searches with mode screened, then GET /searches/{search_id}/leads.
explain_lead
Free. Input: lead_id (lead_ from find_leads or watch_signal, not a per_ id). Output: the person, fit, why_now and the evidence, plus dashboard_url. REST: GET /leads/{lead_id}.
watch_signal
A run charges like find_leads, up to max_credits_per_month. Creating, reading and pausing are free. Input: action create, status, pause or resume. Create needs signal, schedule (except an event, which can follow its dates), and max_credits_per_month. Optional: name, buyer_profile, exclude_companies, max_leads_per_run, just_outside. Status, pause and resume need watch_id (wtch_). Output: the watch and dashboard_url. Status of one watch also includes latest_leads. REST: POST /watches, GET /watches, GET /watches/{id}, PATCH /watches/{id}.
enrich
A profile is 2 credits when one is found. include_email: true adds 10 when an address is found. A company is 1 credit when one is found. A miss is free. There is no phone field. Input: exactly one of profile_urls, person_ids, lead_id, or company domains / linkedin_urls / names. With lead_id, target is person (default) or company. Optional: include_email, fields, exact_match, max_credits. Output: the enrich body for that person or company. REST: POST /person/enrich or POST /company/enrich.
preview_cost
Free. Input: endpoint and body, optional max_credits. Output: cost_preview. REST: the /preview route for that endpoint.
search_signals
Raw rows: what the source shows, with no AI judging them. A person from engagement, listening, an event or a new role is 5 credits, a funding company 1 credit, a technology company 20. Input: signal (every type; tech_adoption is raw only), optional limit, cursor (the result.next_cursor of an earlier answer, with the same signal), exclude_companies and max_credits. Output: result (rows, has_more, next_cursor), the first 25 rows in results, next_page_cursor for the rest, notes, funnel and dashboard_url. A LinkedIn row is a person with their headline and up to 3 things they did, each with the post: the assistant decides which rows fit, then enriches those with person_ids. about and drop_intents only work in find_leads. An event is never looked up: send its exact name with the year, its hashtags or its organizer page. REST: POST /searches (mode raw is the default), then GET /searches/{search_id}/results.
get_search_results
Free. Input: search_id (srch_ from search_signals), optional page_cursor (the next_page_cursor of the previous page). Output: 25 rows of that raw search per page, next_page_cursor and dashboard_url. Also reads a search that was still running when search_signals answered. REST: GET /searches/{search_id}/results.
company_leads
5 credits per person. A company that does not match costs nothing. Input: companies, filters (roles, seniority, departments, countries), optional limit and max_credits. Output: per_ rows and dashboard_url. Do not pass those ids to explain_lead. REST: POST /leads.
create_monitor
Creating it is free. Each new mention on a run is 5 credits. Input: name, keywords, optional schedule (daily; hourly stays off unless that deployment has turned it on), min_relevance, tags, max_credits_per_day. Output: the monitor and dashboard_url. REST: POST /monitors.
list_mentions
Free. Input: optional monitor_id (mon_) and min_relevance. Output: mentions already delivered. REST: GET /mentions.