Connecting an AI agent
LeadAdapter is an MCP server. Your agent gets tools instead of a chat window, and every one of them goes through the same governance layer your automations do.
What this actually is
Model Context Protocol is the standard way an AI assistant is given tools. Point a client at our endpoint, sign in, and it can list your automations, schedule a post, read your leads or send a message — inside your caps, under your autonomy setting, and on your audit log.
The endpoint is https://leadadapter.com/mcp. Opening it in a browser, with no credential at all, returns the catalogue and the tier of each tool, so you can see what the product does before you sign up for anything.
Nothing an agent does bypasses the rules. There is no agent budget, no agent exemption from the do-not-engage list, and no way for a model to raise a cap above the ceiling your plan allows.
Connecting a client
Claude and ChatGPT sign in with OAuth: you paste the endpoint, they register themselves and send you to a LeadAdapter sign-in page where you choose the workspace and approve. Cursor and anything running in a terminal use an API key instead.
Claude
Custom connector · OAuth
- Open Settings, then Connectors, then Add custom connector.
- Paste https://leadadapter.com/mcp as the server URL.
- Claude registers itself and opens a LeadAdapter sign-in page in your browser.
- Sign in, choose the workspace, and approve. The tools appear in the next message.
ChatGPT
Connector · OAuth
- Open Settings, then Connectors, then add a connector by URL.
- Paste https://leadadapter.com/mcp.
- Approve the LeadAdapter sign-in that opens, choosing the workspace you want the agent to act in.
- Enable the connector in the conversation you want to use it in.
Cursor
API key
- Create an API key in LeadAdapter under Settings, then API keys. It is shown once.
- Add the server to your MCP configuration file with the key as a bearer token — the shape is below.
- Reload the window. Cursor lists the tools without a browser round-trip.
Configuration file
For a client that authenticates with an API key rather than a browser sign-in:
{
"mcpServers": {
"leadadapter": {
"url": "https://leadadapter.com/mcp",
"headers": {
"Authorization": "Bearer la_live_…"
}
}
}
}
The server speaks these protocol versions: 2026-07-28, 2025-11-25, 2025-06-18, 2025-03-26. Keys are shown once when they are created and can be revoked at any time.
The tool catalogue
This is generated from the server's own registry when the page loads, so it is exactly what your agent will see.
Tools above your plan stay visible and refuse when called, naming the plan that includes them. Hiding them would make a model tell you the product cannot do something it can — the one failure mode worse than a refusal.
| Tool | What it does | Plan | Runs |
|---|---|---|---|
get_extension_status |
Whether the LeadAdapter Chrome extension is currently connected for each LinkedIn profile on this workspace, plus the depth of its job queue. NOTHING in LeadAdapter executes on LinkedIn while the extension is offline — check this before promising the user that anything has been sent. Read only | Starter | On our server |
get_job |
Poll a queued extension job by its job_id. Returns queued, leased (a browser is running it now), done with the result, failed with the error, or cancelled. Extension work runs in the user's own Chrome, so a job stays queued for as long as that browser is closed. Read only | Starter | On our server |
add_do_not_engage |
Suppress a person, an email address or a whole domain so nothing in LeadAdapter contacts them again. Use this the moment someone asks to be left alone. Suppression cannot be undone from here — that is deliberate. | Pro | On our server |
cancel_scheduled_post |
Call off a scheduled post so it never publishes, and cancel the browser jobs queued for it. DESTRUCTIVE: requires confirm: true, and there is no undo — the post cannot be un-cancelled, only scheduled again. A job already handed to the browser cannot be recalled, so the response says how many were actually stopped; do not tell the user it definitely did not go out unless that count covers it. A pre-attached automation is left alone as a draft. Refused with not_editable if the post already published. Spends no budget. Needs confirm | Pro | On our server |
create_automation |
Create a comment-to-DM automation on a LinkedIn post that is ALREADY PUBLISHED: whoever comments with one of the keywords gets the direct message. Use schedule_post_with_automation instead when the post does not exist yet — an automation needs a post URN before it can be armed. Created as a draft; arm it with edit_automation status: "active" once the blockers listed in the response are clear. Spends no daily budget by itself; every DM it later sends spends one dm slot from the same shared budget as everything else. Refuses when the plan's automation limit is reached (tier_limit_reached) or when a regex keyword is unsafe (invalid_keyword_pattern). | Pro | On our server |
discover_lead_magnets |
Find posts in a niche that look like working lead magnets: high comment velocity plus "comment GUIDE below"-style copy. Runs a LinkedIn post search through the user's own browser (spends one of the daily search budget) and returns a heuristic 0-100 score per post with the signals behind it — this is a ranking to look at, not a classification. Results come back minutes later: either pass wait: true, or call again with the job_id from the first response to rank the finished search for free. Feed the winners to list_post_engagers to turn a magnet into a lead list. | Pro | In your browser |
edit_automation |
Change an existing automation and/or its state. status: "active" arms it (refused, with reasons, if it is not ready), "paused" stops the polling but keeps queued DMs, "archived" ends it and cancels the DMs already queued for this morning's commenters — archived is destructive and requires confirm: true. Every other field is a plain edit and needs no confirmation. Only the fields you pass are changed; passing keywords replaces the whole keyword set. Spends no budget. | Pro | On our server |
edit_scheduled_post |
Change a post that has not gone out yet: its body, its images, its slot, or which automation it arms. Only the fields you pass change, but passing media REPLACES the whole image list. Refused with not_editable once publishing has started — at that point the text may already be inside the browser, so an edit that appeared to save would be a lie. Moving the slot into the past is refused; this is not a publish button. Spends no budget. | Pro | On our server |
enrich |
Look up a person's full LinkedIn profile through the user's own browser and merge it onto their lead record. Identify them with linkedin_urn, public_id, or lead_id for someone already captured. Spends one of the workspace's monthly enrichment allowance AND one profile_view against the daily LinkedIn cap; both remaining figures come back on every response, including refusals. Nothing is returned immediately — the browser fetches it minutes later, so poll get_job or re-read the lead. Refuses with enrichment_cap_reached (upgrade), cap_reached (wait until tomorrow), duplicate (we already enriched them within 30 days — read the stored record instead) or do_not_engage. include_email requires the Operator plan. | Pro | In your browser |
enrich_company |
Look up a LinkedIn company page through the user's own browser and store its firmographics — industry, headcount, HQ, website, follower count. Takes a company URN (urn:li:organization:1234). Spends one of the workspace's monthly enrichment allowance AND one profile_view against the daily LinkedIn cap; both remaining figures come back on every response including refusals. The answer arrives minutes later via the browser, so poll get_job or re-read the company. Refuses with enrichment_cap_reached (upgrade), cap_reached (wait), or duplicate if we already enriched this account within 30 days — the response then names the record to read instead. | Pro | In your browser |
export_leads |
Page through the leads captured by this workspace, newest first. Returns rows the model can read directly, with a next_cursor to continue. Filter by source, tag, or captured-since. Read only | Pro | On our server |
get_automation |
Read one automation in full: the DM template, the follow-up, the public comment reply, the keyword sets, the counters, and activation_blockers — the list of what is stopping it going live. Call this before edit_automation so the edit is a change and not a guess. Read-only, no budget spent. Read only | Pro | On our server |
get_page_leads |
List the people who submitted one lead page, newest first, with their email, the lead record they were matched to, the UTM/referrer they arrived on and whether they ticked marketing consent. consent_marketing=false means they agreed to receive the magnet and nothing else — do not add them to a sequence. Paged with next_cursor. Reads our own database; costs no LinkedIn budget. Read only | Pro | On our server |
get_scheduled_post |
Read one scheduled post in full: body, media and their upload state, the attached automation, and the browser job that will publish it (or already tried). Use this to answer "why has my post not gone out" — the publish_job and error fields carry the reason, which is usually that the extension was offline at the slot. Read-only, no budget spent. Read only | Pro | On our server |
list_automations |
List this workspace's comment-to-DM automations, newest first, with their status, keywords and counters. Start here before creating one: an automation on the post you are about to target may already exist, and two automations on the same post send two DMs to the same commenter. Read-only — no LinkedIn call, no budget spent. Use get_automation for the message templates. Read only | Pro | On our server |
list_companies |
List the LinkedIn Company Pages this workspace knows about, including the ones the connected profile administers — the page URNs that company-voice tools and page scheduling need. Returns the stored records immediately (with firmographics if they have been enriched) and, unless you pass refresh: false, also queues a browser job to refresh the list, which spends one of the daily search budget. Nothing refreshes while the user's browser is closed. | Pro | In your browser |
list_lead_pages |
List this workspace's lead-magnet pages with their public URLs, draft/published state and funnel numbers (views, unique views, submits, conversion rate, traffic sources) over a chosen window, 30 days by default. Use it to find the page id other lead-page tools need, or to decide which magnet to promote. conversion_rate is submits divided by total views. Reads our own database only; costs no LinkedIn budget. Read only | Pro | On our server |
list_recent_posts |
Ask the user's browser extension for the LinkedIn posts they have published recently, so you can pick one to attach a comment-to-DM automation to. This is a browser job: it returns a job_id and nothing runs while that browser is closed — poll with get_job. The response also carries known_posts, the posts LeadAdapter already recorded, which you can act on immediately. Spends no daily budget. For someone ELSE's posts use list_person_posts, not this. Read only | Pro | In your browser |
list_scheduled_posts |
List this workspace's scheduled LinkedIn posts in slot order, soonest first. With no status filter it returns only posts that have not gone out yet. Each row says whether it is still editable, whether an automation is attached, and — for a post that is late or failed — why. Read-only, no budget spent. Use get_scheduled_post for the full body and media. Read only | Pro | On our server |
manage_invitations |
Triage inbound LinkedIn connection requests: action=list queues a fetch of the pending invitations, action=accept or action=ignore decides one by invitation_urn. Everything runs in the user's own browser, so calls return a job_id and nothing happens while that browser is closed. Accepting or ignoring SPENDS ONE connect from the daily cap — LinkedIn meters invitation replies with outbound connects — so a large backlog takes several days and will be refused with cap_reached rather than queued past the cap. Rank the inviters yourself with enrich before deciding. | Pro | In your browser |
manage_lead_magnet_links |
Create, list, edit or delete tracked short links (/l/{slug}) for lead magnets. Pass lead_page_id to point one at a hosted page, or target_url for anywhere else — non-http(s) targets are refused. Listing returns click counts, and with lead_id it also returns per-lead attributed URLs so a click can be traced back to the person who received the message. action=delete requires confirm: true and is permanent: links already sent start 404ing. Costs no LinkedIn budget. | Pro | On our server |
manage_lead_pages |
Create, edit, publish, unpublish or delete a hosted lead-magnet page. Pages are created as drafts; publish is a second call and is refused if the page promises a file it does not have. action=delete requires confirm: true (G12) and soft-deletes — captured leads, consent records and tracked links survive, and the URL stays reserved. Costs no LinkedIn budget; Starter is limited to a few pages, Pro and above unlimited. | Pro | On our server |
schedule_post_with_automation |
Write a LinkedIn post, put it in the calendar, and optionally pre-attach the comment-to-DM automation that will arm itself the moment the post publishes and its URN is known. This is the right tool when the post DOES NOT EXIST YET; use create_automation for a post that is already up. The slot must be in the future. Publishing happens through the user's browser at the slot and spends one post slot from the daily budget then, not now — if no browser is online it retries for two hours and then fails with a notification. Refuses on plans without scheduling (tier_required) and when the plan's automation limit is reached. | Pro | On our server |
set_daily_dm_limit |
Change the daily cap for one channel on a LinkedIn profile — by default direct messages. Lowering a cap always works. Raising one above the ceiling for this workspace's plan is refused with cap_ceiling_exceeded and the ceiling, so the answer is an upgrade and not a retry. Spends no LinkedIn budget itself; it edits the budget every other tool spends. | Pro | On our server |
suggest_automation_settings |
Given the TEXT of a LinkedIn post, propose the keyword, the negative keywords and the DM copy for a comment-to-DM automation, in the post's own language and using this product's placeholder spellings. Pass the result straight to create_automation. Saves nothing and sends nothing. Spends no LinkedIn budget — the server never reads the post, so paste the text in; there is no post_url form of this call. Returns llm_unavailable when the model gateway is down, in which case write the settings yourself. Read only | Pro | On our server |
sync_lead_to_crm |
Push one captured lead into a connected integration (CRM, ESP). Names the provider or uses the workspace's only connected one. Re-syncing an existing contact is a success, not an error. | Pro | On our server |
decide_approval |
Approve or reject one held action. Requires confirm: true. Approving releases the action to be queued for the browser extension; it does not send anything by itself, and the send still passes through the daily caps. Needs confirm | Operator | On our server |
list_actions |
Read this workspace's audit log: every tool call, automation action and approval decision, including the refusals. Filter by result (ok, queued, blocked, failed, approved, rejected), action type, tool, actor, target or date. Use result=blocked to find out why something did not send — the reason column carries the governance code. Reads only our own database; costs no LinkedIn budget and is safe to call repeatedly. Read only | Operator | On our server |
list_approvals |
List the actions waiting for a human decision on this workspace. Under the default autonomy mode, outbound messages and connection requests are held here rather than sent — check this before telling the user something went out. Read only | Operator | On our server |
This table is generated from the server's own registry, so it is the catalogue your agent actually sees. The same list is available without signing in at https://leadadapter.com/mcp. Tool names and descriptions are shown exactly as the server sends them.
What each plan can call
Every tool is listed on every plan. The badge is what decides whether it answers.
Pro
26 of 29 tools
The owned-asset tools: your posts, your commenters, your lead pages, your automations.
Operator
29 of 29 tools
Everything Pro has, plus outbound on other people's audiences and the approval queue.
Agency
29 of 29 tools
Operator's capabilities, sold per seat, with client reporting and white-labelling.
The response contract
Every tool answers in the same shape. The governance block is the part that matters: it says what happened, why, and how much of the budget is left, so an agent can plan rather than guess.
{
"ok": true,
"data": { },
"governance": {
"verdict": "queued",
"reason": null,
"remaining": { "dm": 137 }
},
"action_id": "01J…"
}
A refusal has the same shape. It is a result, not an error, so the model reads it and re-plans:
{
"ok": false,
"error": {
"code": "cap_reached",
"message": "…"
},
"governance": {
"verdict": "blocked",
"reason": "cap_reached",
"remaining": { "dm": 0 }
},
"action_id": "01J…"
}
Anything that touches LinkedIn is executed by your browser, so it answers with a job to poll. Clients that support long calls may ask to wait — the server holds the call for up to 25 seconds:
{
"ok": true,
"status": "queued",
"job_id": "01J…",
"eta_seconds": 45,
"governance": { },
"action_id": "01J…"
}
What each verdict means for an agent
A refusal is a successful answer that says no. It comes back as a result the model reads, never as a protocol error the model cannot see — an invisible error is retried, and a retried LinkedIn write is the thing this whole product exists to avoid.
The complete list of refusal codes, and what to do about each, is on the governance page.
| Verdict | What it means | Will it happen? |
|---|---|---|
executed |
Done, in the same request. Only possible for work that does not touch LinkedIn. | Yes |
queued |
Accepted and handed to your browser. This is the normal answer for anything on LinkedIn. | Yes |
approval_required |
Held for a person to decide. Not a failure — your autonomy setting asked for this. | Not without another step |
blocked |
Refused, with a machine-readable reason so an agent can change its plan instead of retrying. | Not without another step |
Dry runs and confirmations
Every write tool accepts dry_run: true. It returns the exact verdict the real call would produce — including the refusal and the remaining budget — and changes nothing. It is the right first move for an agent that has just been handed a new account.
Destructive tools refuse unless they are called with confirm: true. Cancelling a scheduled post, archiving an automation, deleting a lead page and pausing a channel all need it, so that no single confident sentence from a model can undo work you did not ask it to touch.
Loadouts
A loadout is a named job: a system prompt, a list of tools the agent may use for it, and defaults that already make sense. It is packaging rather than new capability, which is exactly why it works — most of the difference between a useful agent and a dangerous one is scope.
| Loadout | What it does | Stage | Plan |
|---|---|---|---|
| marketing.home.loadout.author.name | marketing.home.loadout.author.body | marketing.home.phases.create | Pro |
| marketing.home.loadout.gatekeeper.name | marketing.home.loadout.gatekeeper.body | marketing.home.phases.capture | Pro |
| marketing.home.loadout.scout.name | marketing.home.loadout.scout.body | marketing.home.phases.capture | Operator |
| marketing.home.loadout.radar.name | marketing.home.loadout.radar.body | marketing.home.phases.capture | Operator |
| marketing.home.loadout.matchmaker.name | marketing.home.loadout.matchmaker.body | marketing.home.phases.convert | Operator |
| marketing.home.loadout.bridge.name | marketing.home.loadout.bridge.body | marketing.home.phases.convert | Operator |
| marketing.home.loadout.shadow.name | marketing.home.loadout.shadow.body | marketing.home.phases.convert | Operator |
| marketing.home.loadout.reviver.name | marketing.home.loadout.reviver.body | marketing.home.phases.convert | Operator |
| marketing.home.loadout.medic.name | marketing.home.loadout.medic.body | marketing.home.phases.operate | Pro |
Rate limits and versions
The endpoint accepts up to 120 requests a minute per session. A client may ask a tool that runs in your browser to wait for the result; the server holds the call for up to 25 seconds and then hands back a job id to poll instead.
Supported protocol versions: 2026-07-28, 2025-11-25, 2025-06-18, 2025-03-26. The server answers with the version your client asked for when it can, and with the newest one it speaks when it cannot.
Every cap, limit, timeout and tool name on this page is read from the running product when the page loads. If the software changes, this page changes with it.