Tool reference · LinkedIn

propose_connection_request

Propose a LinkedIn connection request. It is NOT sent: it waits in the workspace's Approvals queue until a person approves it, then goes out under the account's Smart Limits.

writesreaches LinkedInrate limited

Updated 2026-09-18 · Server 2.0.0

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

It runs through a connected sender account in your workspace — not through a scraper and not through your own profile. Call list_sender_accounts first to see which identities are connected and healthy. If the workspace has none, this tool returns an error telling you so; accounts for agents covers how teams get one without risking their own profile.

Arguments

NameTypeRequiredMeaning
profilestringyesProfile URL, public identifier (the /in/ slug) or provider id of the person to connect with
notestringnoOptional invitation note, under 200 characters. {{firstName}} and {{company}} are filled in.
reasonstringnoWhy this person, in one or two sentences — shown to the person who approves it
accountstringnoSender account id or name to send from. Defaults to the healthiest connected account.
dry_runbooleannoCheck 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:

inputSchema
{
  "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
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.

payload
{
  "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

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.