
Your agent needs verified contact data. It needs to resolve a LinkedIn URL to a person, check whether that person still works there, reveal a phone number, and do it while a rep is mid-conversation. Lusha ships both a hosted MCP server at mcp.lusha.com and a versioned REST API at api.lusha.com/v3. They are not two front doors to the same building: the tool surface is a subset, the auth model is narrower than most MCP servers you have integrated, and every call spends credits against a key that has its own rate limit and its own monthly cap. Here is how to pick.
These are two different products with two different design centers. One is shaped for a language model reading results in a context window. The other is shaped for a pipeline moving records. Knowing which constraints came from which design center is most of the decision.
Lusha maintains a hosted MCP server at https://mcp.lusha.com, reachable over Streamable HTTP from any MCP-compatible client. Tools are grouped into search and enrich, prospecting, signals, lookalikes, account usage, and recommendations. Tool responses are shaped for LLM consumption: batch sizes are explicitly capped to fit a 25k-token response budget, and several tools carry a reason_for_invocation audit field the model is expected to fill in.
Authentication takes one of two forms. OAuth is available through Lusha's official listings in Claude, ChatGPT, and Codex. Every other client, including anything you build, authenticates with a Lusha API key passed in the x-api-key header. The header name is case-sensitive; Authorization: Bearer is rejected on the standard path.
Official docs: the Lusha MCP Server documentation.
The REST API is versioned and currently on V3, with all endpoints under https://api.lusha.com/v3/. It exposes eight endpoint groups: Enrichment, Prospecting, Signals, Lookalikes, Tables, Webhooks, Decision Makers, and Website Visitors, plus a separate Account Usage endpoint. V3 uses a search-then-enrich pattern where search returns a non-PII preview with a canReveal array and per-field credit cost, and enrich spends the credits.
Authentication is a single mechanism: the API key in the api_key request header. V2 is still operational but is approaching deprecation, so new agent builds should target V3.
Official docs: the Lusha API documentation.
The gap here is not the usual MCP story of "the server exposes the popular endpoints." Lusha's MCP tool surface is genuinely broad on the read-and-enrich side. What is missing is everything stateful and everything event-driven.
The table below maps the capabilities that decide agent architecture, not the full endpoint inventory.
Four API groups have no MCP equivalent, and they are not obscure. Webhooks are the one that reshapes architecture: if your agent should react when a champion changes jobs, MCP gives you polling and the API gives you HMAC-SHA256-signed push with retry and delivery audit logs. Polling the signals tools on a schedule costs credits per matched signal every time you poll.
Tables is the second structural gap. The API lets you pass tableId on prospecting, enrich, signals, and lookalike calls to persist results into a workspace-visible table. Without it, your agent's output lives only in your own store, and the rep never sees the list inside Lusha.
MCP tool descriptions state the reason for their caps directly: batches are capped to fit a 25k-token response budget once results are merged. Company enrichment is capped at 25 IDs per call, contact enrichment at 50, and signals lookups at 25.
The REST API accepts up to 100 records per request across contacts and companies. Enriching 1,000 contacts is 10 API calls or 20 MCP calls. Against a general limit of 25 requests per second and a plan-level per-minute cap, that difference decides whether a nightly enrichment job finishes inside its window. Understanding why MCP can be more expensive than CLI is essential context before committing to an architecture.
This is where Lusha diverges from the Notion and Slack MCP servers you may have integrated against. Both of those let you register an OAuth client and run your own consent flow. Lusha does not document that for MCP.
Lusha's connection-methods table lists OAuth as supported for exactly three clients: Claude, ChatGPT, and Codex. Those are Lusha's own directory listings. For every other client, the documented method is the API key in x-api-key. If you are shipping a product rather than configuring someone's IDE, you are on the API key path whether you chose MCP or REST.
Three facts from Lusha's own documentation compound here. API access requires a key available to Admins and Managers on Premium and Scale plans. The key is created at the account level, and an account can hold several. Rate limits are enforced per API key, and Admins can set a monthly credit cap per key.
Read together, the key is the unit of quota, not the user and not the tenant. One shared key across your customer base means a single tenant's prospecting run consumes the per-minute allowance and the credit pool for everyone else, and a 429 or a "credit limit reached" error surfaces as a silent data gap in an unrelated customer's agent run. This is exactly the kind of challenge that emerges when moving from single-tenant to multi-tenant tool calling.
Lusha's published credit table charges 1 credit for an email, 5 for a phone number, 1 for company info, and 1 credit per request result. Revealing an email and phone for one contact is 7 credits.
An agent that enriches 50 contacts with both data points spends roughly 350 credits per run. That is not a rounding error against a monthly allowance, and it is the specific reason per-user attribution matters more here than on a connector where calls are free.
On the MCP path, Lusha owns the tool schemas, the response shaping, and the token budgeting. You own the key: where it lives, who it maps to, what happens when an Admin rotates it, and how you detect the difference between an expired key and a key that hit its monthly cap. Both return errors your agent will otherwise swallow.
On the REST path you own all of that plus endpoint selection, the search-then-enrich sequencing, pagination, retry with exponential backoff on 429, and an adapter per surface. Webhooks add a receiver that acknowledges with a 2xx and a JSON body inside 10 seconds, and a signature check.
The REST API is versioned and publishes a changelog with semantic versions; V3 is current and V2 is approaching deprecation. You pin, you read the migration guide, you move on your own schedule.
MCP tool schemas carry no such contract, and Lusha's own docs note that available tools may vary depending on the client used to connect. For a deterministic pipeline where an unexpected schema change is an incident, the versioned API is the more predictable dependency.
Both lists below are specific to Lusha, not general MCP advice.
Use Lusha MCP when:
Use the Lusha API directly when:
Whichever path you choose, the credential is a Lusha API key, and it is the same key. MCP does not give you a different security model here; it gives you a different tool surface over the same secret.
In a multi-tenant B2B agent, every customer has their own Lusha account and their own key. Fifty customers is fifty keys to store encrypted, isolate per tenant, and invalidate when a contract ends. Within a single customer, per-user keys are the only way to get per-user rate limits and per-user credit caps, because Lusha enforces both per key.
Neither path stores those keys, rotates them, or tells you when one was revoked in the Lusha dashboard. Your agent finds out on the next 401, and only if you handled it. The broader problem of who holds the token across agent tool-calling patterns is a foundational design question for any production agent.
Scalekit's Lusha MCP connector vaults a Lusha key per connected account, resolves it server-side at request time, and never places it in the agent runtime or the LLM context. The same connected-account model works whether the agent calls execute_tool directly or reaches Lusha through a Virtual MCP endpoint, so the MCP vs API decision does not change your auth infrastructure.
Scalekit currently ships a single Lusha connector rather than separate API and MCP entries. Its connection name is lushamcp, it authenticates with an API key, and it exposes 18 tools; the ICP recommendations tools are not among them, which is consistent with Lusha's note that those tools infer user and account identity from the session and that available tools vary by client.
Lusha uses API key authentication, so there is no redirect URI and no consent screen. You call upsert_connected_account when the user saves their key on your integrations page. The connection_name string must match the connection name configured in the Scalekit dashboard exactly; this is the single most common integration error.
Before the agent sees anything, ask Scalekit which tools this connected account is authorized to call. This is not tool discovery against an unknown surface; it is a deterministic, per-user list derived from what that user actually connected. A user who has not saved a Lusha key gets no Lusha tools, and the model never hallucinates a call it cannot make.
That distinction is what separates a per-user agent from a shared-credential agent. Two of Lusha's tools, lushamcp_prospecting_contact_search and lushamcp_prospecting_company_search, carry 25 and 18 parameters respectively, so the schema payload is dominated by a handful of tools. Filtering the surface is a token decision as well as a permission decision.
actions.langchain.get_tools() returns native StructuredTool objects already bound to this user's connected account, so the LangChain agent needs no Scalekit-specific logic beyond initialization. For a deeper look at how LangChain tool calling works and where it stops, the architecture patterns apply directly to this integration.
A note on credits: lushamcp_contacts_search and lushamcp_companies_search default enrich to true, which reveals premium fields and spends reveal credits in the same call. Set enrich: false to get the preview, then call lushamcp_prospecting_contact_enrich only on the IDs you actually want. That is the search-then-enrich pattern, and it is the difference between a qualifying pass that costs one credit per result and one that costs seven.
The Node.js path is identical in shape. Scalekit returns input_schema in Anthropic's native format, so no conversion is needed between listScopedTools and messages.create.
Read tool output from result.data. The wrapper object is not the Lusha payload, and treating it as one is the most common first-integration bug.
If your agent spans Lusha plus a CRM plus Slack, hand it an endpoint rather than a catalog. A Virtual MCP server declares exactly which connections and which tools an agent role can see, and issues a short-lived session token bound to one user before each run. One server definition serves every user; the endpoint is static, the identity is not.
For a prospecting agent, that means four of Lusha's 18 tools: resolve filters, search, enrich, and check the credit balance. Lookalikes and signals stay out of reach, so the agent cannot spend premium credits nobody budgeted for.
Observability matters more on Lusha than on a read-only connector, because every call has a price. Scalekit resolves the connected account server-side on each tool call, which means the log line carries the identifier of the person who authorized it rather than a service account. Per Scalekit's Lusha connector page, that history is retained for 90 days and is SIEM-exportable.
Lusha's own tool schemas help here too. Most tools accept an optional reason_for_invocation string, capped at 500 characters, and a conversation_id correlation token carried across calls in the same conversation. Combined with per-user attribution, you can answer the question a finance lead will eventually ask: which rep's agent spent 4,000 credits last Tuesday, and on what. Building a robust audit trail for agent auth in B2B SaaS is directly applicable to credit-metered integrations like this one.
The decision splits cleanly along one axis: whether a human is waiting for the answer.
If your Lusha agent is interactive and its job is research, enrichment, and signals lookups on modest volumes, build on the MCP tool surface. The token-budgeted responses and maintained schemas are real leverage, and you skip eight sets of adapter code.
If your agent must react to job changes, write results back into Lusha Tables, rank decision makers, read website-visitor intent, or enrich at bulk volumes, go direct to the V3 API. Those surfaces are not late additions to the MCP server; they are absent from it today, and polling is not a substitute for a webhook.
Most production teams end up running both: MCP for the assistant a rep talks to, REST for the pipeline that runs at 2am. The credential is the same Lusha key on both sides, and that key is the unit of quota, credit spend, and blast radius. That is the part that needs production-grade infrastructure. The patterns for agent tool calling auth in production apply directly to both paths.
Browse the Scalekit Lusha MCP connector docs or the Lusha connector overview to see the full tool list and schemas.
Building something with Lusha and want a second pair of eyes on the credential model? Join the Scalekit Slack community, or talk to an engineer if you need help now.