LinkedIn & Sales NavigatorTutorial

How to Connect Claude to LinkedIn

One command connects Claude to LinkedIn through Kairon. Here is the real sign-in handshake and a real search, captured end to end.

What we ranA live, end-to-end capture on 2026-08-10 against https://app.heykairon.com/mcp in production: the documented setup command, the raw 401 response and headers from an unauthenticated call, the OAuth discovery document that 401 points to, and a real authenticated search_people call (keywords 'head of growth', one location filter, limit 3), with its response shape and field-level notes, identities redacted.

One command connects Claude to LinkedIn: claude mcp add --transport http kairon https://app.heykairon.com/mcp. Claude then walks itself through a sign-in you approve once. After that, asking Claude to find someone on LinkedIn runs a real search against LinkedIn and returns real people, no API key or cookie file for you to manage.

LinkedIn's User Agreement prohibits automated access to the platform. The numbers below describe behaviour we observed on our own test accounts on the date shown — they are not permission, not a safety guarantee, and not advice to breach that agreement. Your account, your risk.

The one command

This is the setup step from Kairon's own MCP documentation, run as written:

claude mcp add --transport http kairon https://app.heykairon.com/mcp

You need a Kairon account with a LinkedIn seat connected first; the command itself just points Claude at the server. Paste it into a terminal, or into Claude Code or Cursor, and Claude adds Kairon as a tool source. Nothing has signed in yet. The next thing Claude does is try to use it, and that is where the interesting part starts.

What Claude sees before you sign in

The first time Claude asks the Kairon server for its list of tools, with no sign-in done yet, the server answers with a plain refusal:

HTTP/2 401
content-type: application/json; charset=utf-8
access-control-expose-headers: Mcp-Session-Id, WWW-Authenticate
www-authenticate: Bearer resource_metadata="https://app.heykairon.com/.well-known/oauth-protected-resource"
server: cloudflare
via: 1.1 Caddy

A 401 usually just means "no." This one is different in one respect: the www-authenticate line is not decoration, it is an address. It tells Claude exactly where to go to find out how to sign in. Claude reads that line and follows it on its own; you never see the 401 or copy that URL anywhere yourself. It is worth knowing it is there, because it is the entire reason the one command above is enough — nothing about your LinkedIn login is hardcoded into it.

What that address hands back

Fetching the URL from the header returns a small JSON document, not a login page:

{
  "resource": "https://app.heykairon.com/mcp",
  "authorization_servers": ["https://app.heykairon.com"],
  "scopes_supported": ["openid", "profile", "email", "offline_access"],
  "bearer_methods_supported": ["header"],
  "resource_signing_alg_values_supported": ["RS256"]
}

This is the piece doing the actual work. It tells Claude which server to sign in against (app.heykairon.com), and it lists offline_access as a scope Claude can ask for — which is why you approve the connection once and don't have to repeat it every session. Claude uses this document to open the real Kairon sign-in in your browser. You log in, you approve the connection, and control returns to Claude with a token it can use from then on. That is the entire handshake behind step 4b on the setup page: one command out, one browser tab in, and Claude is signed in as your connected LinkedIn seat.

The first call that actually reaches LinkedIn

Once that's done, you don't call a tool by name — you ask for what you want in a sentence, and Claude picks the tool. Asking something like "find heads of growth in Argentina" runs Kairon's search_people tool with a keyword and a location filter behind it. Here is what a real call like that returned, run with keywords: "head of growth", one location filter for Argentina, and a limit of 3 results. Names, profile URLs and identifying details are removed below — these were three real people, not test data:

{
  "hits": [
    // 3 people. Each carries: providerId, profileUrl, publicIdentifier,
    // name, headline, location, avatarUrl, networkDistance, and
    // sharedConnectionsCount.
    // location: "Buenos Aires" on all three.
    // networkDistance: 2 on all three.
    // sharedConnectionsCount: 84 on one, 47 on one, null on one.
    // company: null, companyId: null, industry: null — on all three.
  ],
  "cursor": "<opaque, carries account_id, limit, start and the resolved params>",
  "total": 1000,
  "filters": [
    { "type": "location", "query": "Argentina", "urn": "100446943", "label": "Argentina" }
  ],
  "providerCalls": 1
}

A few things worth pointing out, because they show what "Claude uses your LinkedIn seat" actually means underneath the sentence you typed:

  • You typed "Argentina." LinkedIn wanted a numeric ID. The word got resolved to LinkedIn's own location code, 100446943, on Kairon's server before the search ran, and that resolved value is echoed back in filters so you can see what was actually searched. You never handle the ID yourself.
  • One page is one metered action, whatever its size. providerCalls: 1 is the count for this entire request, not per result.
  • total: 1000 is LinkedIn's count for the query, not what came back. Three hits were returned because the call asked for a limit of 3; the total tells you how large the underlying result set is.

The honest negative: three fields came back empty

All three hits in this call had company: null, companyId: null and industry: null, even though a "head of growth" headline usually names an employer somewhere in the person's profile. That's what this specific call returned on 2026-08-10 — we're reporting it as observed on that request, not as a general property of the tool. A different search, a different profile's completeness, or a change on LinkedIn's side could return those fields filled. If you're building something that depends on company being populated, check it on your own query rather than assuming it from this one.

One more thing this call didn't need: a Sales Navigator seat. This was a plain search_people call, and the tool's own description states that classic people search works without one — this account has no Sales Navigator subscription attached, and the call above still returned results.

Where this fits

The command at the top gets Claude signed in; what it can then do is search, message and run outreach as the LinkedIn seat you connected — the same tool surface we audited across eleven LinkedIn MCP servers, Kairon's included, reading each one's actual capabilities rather than its marketing copy. Once you're connected, the thing that actually restricts a LinkedIn account isn't which tier you're on — we measured that separately in Premium vs. Sales Navigator. The full list of tools Claude can use after this handshake, with every parameter, is on the setup page itself.