FounderMCPDocs

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.

POSThttps://foundermcp.dev/api/v1/mcp
View Markdown

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 stream text/event-stream · required — MCP JSON-RPC messages. A tools/call result carries the REST body plus dashboard_url where 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 and Allow: 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.