Skip to content
SearchLeads/DevelopersGet API key
Documentation v1
DEVELOPER DOCUMENTATIONREST API · v1

Hosted MCP

Connect compatible AI clients to SearchLeads tools and resources.

The hosted Streamable HTTP MCP endpoint exposes account capabilities, filter discovery, search, export, prompts, and authenticated resources. Authenticate with the same full API key used for REST calls.

Enable mcp to connect, plus search for search/filter-value lookup and export for creating or checking exports. An MCP-only key can connect and read capabilities but cannot perform those searches or exports. Read the scope matrix and the authenticated keyCapabilities response before selecting tools.

Search uses search_type in MCP and searchType in REST. Nested filterRules use the same field keys, JSON booleans, and effective per-filter defaults as the UI. matchAll: false means ANY; matchAll: true means ALL. Omit it to inherit the catalog default. The string "true" is rejected. See matching rules.

{
  "mcpServers": {
    "searchleads": {
      "type": "http",
      "url": "https://ttzqldekaizydrdmirpn.supabase.co/functions/v1/searchleads-mcp",
      "headers": {
        "x-searchleads-api-key": "sl_live_your_full_api_key_here"
      }
    }
  }
}

MCP clients vary in configuration syntax. Set the HTTP server URL and header using your client's format. The server supports tool discovery, prompts/list, prompts/get, resources/list, and resources/read. Agents can call lookup_filter_options for exact catalog values before searching.

TypeBuilt-in names
Toolsget_account_capabilities, list_filter_catalog, lookup_filter_options, search_prospects, preview_export, start_export, get_export_status, create_saved_search, create_search_share_link, revoke_search_share_link
Promptsplan_filters, explain_search_results, draft_outreach_copy
ResourcesMCP overview, account capabilities, people filters, company filters

Before start_export, optionally call preview_export with search_id, requested_leads, fields, format, and saveContacts. Inspect can_export, blockers, availability.count_exact, and credits.maximum_required_hold. Preview creates no file/job or credit hold and does not save records. It uses one shared request-minute slot; creation/status retain their unlimited customer quotas. A ready preview is not a reservation: creation revalidates the current account and search. See export preflight.

Catalog-backed filters accept exact readable labels. Option IDs remain supported for existing integrations. Typed-input filters accept direct normalized values and report their mode in capabilities.

MCP tool arguments use search_type (for example, { "search_type": "people", "filters": { "account.location": ["United States"] }, "size": 1 } for search_prospects). The corresponding REST search body uses searchType. Keep filter field paths, textFilters, excludedFilters, filterRules, and locationIdentities unchanged. Read each tool's inputSchema from tools/list before calling it. start_export uses a prior search_id, and get_export_status uses the returned job_id.

Exclude saved contacts or companies, and save export results

Use get_account_capabilities first. search.recordScopesBySearchType lists enabled scopes; exports.saveRecordsBySearchType gives independent People/Company saving availability and defaults.

For search_prospects, choose search_type: "people" for contacts or "company" for companies. Both support:

ChoiceTool argument
All matching recordsOmit both scope flags
Exclude this account's saved records"net_new_only": true
Only this account's saved records"saved_only": true

Do not enable both flags. Use real booleans. Omit record_summary to use the account-wide saved set for that search type. People and Company saved sets are separate.

Example search_prospects arguments for new companies:

{
  "search_type": "company",
  "filters": { "account.location": ["United States"] },
  "net_new_only": true,
  "size": 3
}

Use the returned search_id in start_export. Add "saveContacts": true to save completed exported records, or false to leave existing saved membership unchanged. This parameter has the same camelCase spelling for REST and MCP, and saves either contacts or companies according to the search ID. Omitting it uses the corresponding configured default. Saving must be enabled; inspect the capability rather than assuming true will take effect. Search itself does not save records. See export saving and synchronization.

Rate limits and retries

REST and MCP share the customer's rolling minute allowance across API keys. Protocol initialization, discovery, resources and locally handled tools also consume allowance; notifications/initialized does not. Forwarded search and option tools reserve once at the appropriate boundary. Daily API search/option requests remain unlimited. start_export and get_export_status have no customer request quotas and do not consume the shared minute allowance. Export-job concurrency, export size limits, permissions and credit billing still apply.

An MCP quota failure can use HTTP 200 with this JSON-RPC error. Read error before result; HTTP success alone does not mean the operation succeeded:

{
  "jsonrpc": "2.0",
  "id": "quota-example",
  "error": {
    "code": -32029,
    "message": "Rate limit exceeded.",
    "data": { "httpStatus": 429, "retryAfterSeconds": 7, "limit": 60, "current": 60 }
  }
}

Forwarded tool failures instead use result.isError: true. For a quota failure, result.structuredContent contains error, limits, usage and retryAfterSeconds; result.content contains the same payload as JSON text. Inspect that payload before using search results or options. Other tool errors require correction and must not automatically be retried as quota failures.

This bounded JavaScript example accepts a send function that returns a decoded JSON-RPC response from your MCP transport. It retries only quota failures and preserves other error codes. SDKs that throw errors expose equivalent code/data fields; apply the same checks in your catch handler. An HTTP 429 at the transport layer uses Retry-After as described in Rate limits and errors.

async function callWithMcpBackoff(send) {
  for (let attempt = 0; attempt < 3; attempt++) {
    const reply = await send();
    const toolFailure = reply.result?.isError ? reply.result.structuredContent : null;
    const quota = reply.error?.code === -32029 ||
      Boolean(toolFailure?.limits && "retryAfterSeconds" in toolFailure);
    const failure = reply.error || (reply.result?.isError ? {
      code: quota ? -32029 : toolFailure?.code,
      message: toolFailure?.error || "MCP tool failed.",
      data: toolFailure,
    } : null);
    if (!failure) return reply.result;
    if (!quota || attempt === 2) {
      throw Object.assign(new Error(failure.message), { code: failure.code, data: failure.data });
    }
    const seconds = Number(failure.data?.retryAfterSeconds);
    const delay = Number.isFinite(seconds) && seconds > 0 ? seconds : 60;
    await new Promise(resolve => setTimeout(resolve, delay * 1000));
  }
}

Keep the original search/filter arguments on retry. For start_export, retain the same idempotency_key so a transport retry cannot create duplicate jobs. If the bounded retries are exhausted, surface the error and pause the workflow instead of retrying indefinitely.

See saved searches and share links for named reusable definitions, signed-in sharing, expiry and owner-only revocation. These tools reserve the shared minute allowance once at their REST boundary. Searches do not automatically save records.

On this page