What it does
Let an agent decide WHO to connect with while a person decides WHETHER. The target is resolved on LinkedIn first, so the approver sees a real name and headline; the proposal then waits in Approvals. Nothing reaches LinkedIn until someone approves it — an agent cannot burn the account on its own.
This tool drives a real LinkedIn account
Arguments
| Name | Type | Required | Meaning |
|---|---|---|---|
| profile | string | yes | Profile URL, public identifier (the /in/ slug) or provider id of the person to connect with |
| note | string | no | Optional invitation note, under 200 characters. {{firstName}} and {{company}} are filled in. |
| reason | string | no | Why this person, in one or two sentences — shown to the person who approves it |
| account | string | no | Sender account id or name to send from. Defaults to the healthiest connected account. |
| dry_run | boolean | no | Check everything (target, do-not-contact, duplicates, text, limits) and return the verdict without proposing anything |
This table is generated from the literal inputSchema that tools/list returns, so what your client sees and what this page says are the same object:
{
"type": "object",
"properties": {
"profile": {
"type": "string",
"description": "Profile URL, public identifier (the /in/ slug) or provider id of the person to connect with"
},
"note": {
"type": "string",
"description": "Optional invitation note, under 200 characters. {{firstName}} and {{company}} are filled in."
},
"reason": {
"type": "string",
"description": "Why this person, in one or two sentences — shown to the person who approves it"
},
"account": {
"type": "string",
"description": "Sender account id or name to send from. Defaults to the healthiest connected account."
},
"dry_run": {
"type": "boolean",
"description": "Check everything (target, do-not-contact, duplicates, text, limits) and return the verdict without proposing anything"
}
},
"required": [
"profile"
]
}Request
Paste this, swap the key, and you have called the tool.
curl -s https://topclozer.com/api/mcp \
-H "Authorization: Bearer tcz_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "propose_connection_request",
"arguments": {
"profile": "https://www.linkedin.com/in/dana-whitfield",
"note": "Hi {{firstName}} — saw your post on data contracts at {{company}}, would love to connect.",
"reason": "CTO at a Series B fintech; posted about our exact problem last week."
}
}
}'Returns
{ approval_id, status, duplicate, target: { name, headline, providerId, profileUrl }, account, next }. status is pending for a new proposal; duplicate is true when an identical proposal is already pending or approved, and approval_id is that one.
The payload arrives inside an MCP content block — one text block whose body is this JSON, pretty-printed. Parse the string; there is no structured-content field.
{
"approval_id": "apr_mf3k2a9x1",
"status": "pending",
"duplicate": false,
"target": { "name": "Dana Whitfield", "headline": "CTO at Northbeam", "providerId": "ACoAAB1x…", "profileUrl": "https://www.linkedin.com/in/dana-whitfield" },
"account": "Marcus Feld",
"next": "Waiting for a person in the TopClozer console → Approvals. Poll get_approval."
}Worth knowing
Needs the linkedin:propose scope. Refused when the person is already a 1st-degree connection (propose a message instead), when the note is over 200 characters, or when 200 proposals are already waiting. Resolving the profile spends one profile read from the account's Smart Limits. A proposal nobody decides on expires after 7 days.
Rate limit
30 LinkedIn tool calls per 5 minutes, per workspace. Exceeding it returns HTTP 429 with JSON-RPC error -32002 and a Retry-After header. The budget is shared by every LinkedIn tool and counted per workspace, so minting a second key does not buy a second allowance.
The limit exists because an agent retrying in a loop is the request pattern that gets a LinkedIn account restricted, and a restricted account is a much worse outcome for you than a 429. Workspace tools do not spend this budget.
Related tools
get_approval
The status of a proposal made with any propose_* tool: pending, approved, sent, rejected, failed or expired
propose_message
Propose a LinkedIn message to a 1st-degree connection. It is NOT sent: it waits in Approvals until a person approves (and may edit) it.
get_linkedin_profile
Read one LinkedIn profile: identity, current role, followers, job-change signal and latest post
All 65 tools are listed on the tool index. Connecting a client is on the Claude setup page, and the protocol details are on the server page.