in LinkedIn API Live in production. Email, messengers & calendars next
Pricing Blog
Get API key Sign in

Connect LinkedIn to Claude in 2026: The MCP Setup, and Why the Config File Fails

Developer Guide · MCP

Connect LinkedIn to Claude in 2026: The MCP Setup, and Why the Config File Fails

The obvious move is to paste the server into Claude’s config file. Claude Desktop quietly discards it, and nothing in the app tells you why.

Updated August 2026 · 12 min read

Claude reaches LinkedIn through a remote MCP server, and every Claude surface connects to one through Settings, not through a file on disk. In Claude Desktop and on claude.ai you paste the server URL under Connectors and approve a consent screen. Claude Code takes a single command. Neither one asks for an API key.

That last sentence is where most setups break. The snippet that circulates for MCP servers carries a bearer key in a header, and the gtm-api.com endpoint answers a key with 401 invalid_token. It authorizes over OAuth, and the browser consent screen does the work the key was meant to do.

Which route your Claude surface takes

Three surfaces take a URL and one takes a command. claude.ai and Claude Desktop share a single connector list, so adding the server on either one lights it up on both. Claude Code keeps its own configuration and runs the same OAuth flow from the terminal. Only a client that cannot accept a URL at all needs the stdio launcher.

Surface What you give it Where that lives
claude.ai The server URL Settings → Connectors → Add → Add custom connector
Claude Desktop The server URL The same connector list, opened with Ctrl+Comma or the menu icon → File → Settings
Claude Code claude mcp add --transport http Its own config, scoped with --scope local, project or user
Cursor, VS Code A one-click install link The editor’s MCP config, then the same consent screen
Command-only clients npx -y @gtm-api/linkedin-mcp That client’s config file, with tokens cached under ~/.mcp-auth

Claude Desktop and claude.ai, in four steps

Both surfaces read one connector list held on your Claude account, which is why the steps are identical and why connecting once is enough for both.

  • Open Settings. In Claude Desktop press Ctrl+Comma, or click the menu icon, hover File and choose Settings. In the browser press ⌘⇧, or open Settings from your profile icon.
  • Open Connectors in the sidebar. This is the account-level list, and it is separate from the Developer tab that edits a local config file.
  • Click Add, then “Add custom connector”. Paste https://mcp.gtm-api.com/mcp into the dialog and click Add.
  • Approve the consent screen. A browser window opens on gtm-api.com for you to sign in and approve the scopes the client asked for. The tool list appears once consent completes.

Two constraints are worth knowing before you plan a rollout. Free accounts can hold one custom connector. And Anthropic brokers the connection from its own infrastructure, so a server on localhost, on a private corporate network or behind a VPN will not connect this way even though your own machine can reach it.

💡 Where the tools show upOnce the connector is live, open the “Add files, connectors, and more” control at the bottom of the message box, hover Connectors, and the server’s tools and resources are listed there. The same panel is where you switch individual tools off.

The config file, and what it is actually for

claude_desktop_config.json is real and it does work, for local servers that Claude Desktop starts as a child process. Its schema validates a command and an args array. A remote server is described by a url, and that field belongs to a different client’s schema, so Claude Desktop has nothing to do with the entry.

The file sits at ~/Library/Application Support/Claude/claude_desktop_config.json on macOS and %APPDATA%\Claude\claude_desktop_config.json on Windows, and the Claude menu opens it under Settings → Developer → Edit Config.

What developers report when a url entry lands in it: older builds crashed at startup with a TypeError, and newer builds rewrite the file on the next save and drop the whole mcpServers block. Either way there is no dialog and no log line naming the cause, which is what makes this the most expensive ten minutes in an MCP setup.

The one place a command belongs is a client that cannot take a URL. The @gtm-api/linkedin-mcp launcher bridges stdio to the same hosted endpoint and runs the same OAuth flow, opening the consent page on first use.

stdio-only clientsjson
{
  "mcpServers": {
    "gtm-api": {
      "command": "npx",
      "args": ["-y", "@gtm-api/linkedin-mcp"]
    }
  }
}
⚠️ Two versions of the same trapLauncher releases up to 1.1.0 required a GTM_API_KEY and sent it as a bearer token, which the endpoint refuses with 401 invalid_token. From 1.2.0 the variable is ignored and the launcher authorizes over OAuth. A pin to an older version keeps failing on the first call, with the same error text you get from pasting a key by hand.

Claude Code takes one command

Claude Code speaks the streamable HTTP transport natively, so the server goes in with one line and authorizes in a session.

add the server, then authorizebash
claude mcp add --transport http gtm-api https://mcp.gtm-api.com/mcp

# available in every project on this machine
claude mcp add --transport http gtm-api --scope user https://mcp.gtm-api.com/mcp

# then, inside a session
/mcp

Run /mcp in any session and authenticate when prompted. After that, claude mcp list prints a health status beside each server: ✔ Connected, ! Needs authentication or ✘ Failed to connect, and a failure line carries the HTTP status and whatever text the server returned. claude mcp get gtm-api shows the same detail on an Issue: row.

A remote server you have used before can show as cached in the /mcp panel, with a tool count and a note that it connects on first use. The tools are usable from your first message, so nothing needs doing about it.

How the connection authorizes itself

Nothing is pasted because the client discovers the whole flow from a single refusal. The first unauthenticated call comes back 401 with a challenge header naming a metadata document, and every step after that is the client following links.

the refusal that starts the flowbash
curl -i -X POST https://mcp.gtm-api.com/mcp \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{}}'

# HTTP/2 401
# www-authenticate: Bearer resource_metadata=
#   "https://mcp.gtm-api.com/.well-known/oauth-protected-resource"
  • The resource names its authorization server. That metadata document, defined by RFC 9728, points at https://app.gtm-api.com/id/v4, so the client learns where to send a user without being told.
  • The client registers itself. The authorization server publishes a registration_endpoint, which is RFC 7591 dynamic client registration, so your Claude client does not need to be pre-registered with anyone.
  • PKCE, with no secret to store. The same metadata advertises code_challenge_methods_supported: ["S256"] and token_endpoint_auth_methods_supported: ["none"]. The client is public and proves itself with a code challenge.
  • Read and write are separate grants. Scopes are per domain and per direction, so can_view_linkedin_messages and can_act_linkedin_messages are approved individually, and an agent you only want reading the inbox never receives the send grant.
  • Refresh tokens keep it alive. The grant types include refresh_token, so a working connector does not send you back through consent every session.

256 tools, and the three the agent loads

The server exposes 256 typed tools across 18 toolsets, and it hands the model three of them. list_toolsets returns the domains, get_toolset_tools opens one, and call_tool runs any tool by name. The agent walks that tree when it needs something, so a full context window is never spent on a tool catalogue.

Three server-side behaviours ride along with every call, and they are the reason an agent driving a LinkedIn account is a different proposition from an agent driving a scraper.

  • Preview, then confirm. Outward actions return a preview and require an explicit confirmation step before anything reaches LinkedIn, so an over-eager agent cannot commit a bulk send on its own.
  • Budgets checked below the tool. Per-action daily limits are evaluated before dispatch, under every call. The model does no counting, and the server refuses once a budget is spent.
  • Errors written for a model to read. Failures use the same 16-code taxonomy as the REST API, each carrying a recoverable flag and a suggestion field, so the agent can decide whether to retry, wait or stop.

A first prompt that exercises the whole chain, from discovery through the safety layer:

“Check the smart limits on my LinkedIn account, then draft, preview and send a connection request to the profile at this URL.”

What the account can absorb in a day is a separate question from what the API will accept, and the numbers behind it sit on the LinkedIn limits page.

When Claude cannot see the tools

Almost every failure at this stage is one of six, and each has a tell. Claude Desktop writes MCP logs to ~/Library/Logs/Claude on macOS and %APPDATA%\Claude\logs on Windows, where mcp.log holds connection failures and mcp-server-SERVERNAME.log holds one server’s error output.

What you see What it usually is What fixes it
Connector added, no tools in the picker The browser consent step was closed before it finished Open the connector in Settings and complete the sign-in
401 invalid_token on the first call An API key sent as a bearer token, or a launcher pinned at 1.1.0 or below Remove the key and let OAuth run, and upgrade the launcher to 1.2.0 or later
The mcpServers block disappeared A url entry inside a schema that validates commands Move the server to Connectors, or switch that entry to the npx launcher
Claude Code shows ! Needs authentication The server is configured and consent is pending Run /mcp in a session and authenticate
Nothing connects, and the server is local Remote connectors dial from Anthropic’s infrastructure Reach a public endpoint, or bridge over stdio from the machine itself
A second connector is refused Free accounts hold one custom connector Free the slot or move to a paid plan

To take Claude out of the picture and test the endpoint by hand, run npx @modelcontextprotocol/inspector, choose the streamable HTTP transport, enter https://mcp.gtm-api.com/mcp and complete the consent screen. A tool list there proves the server and your authorization are both fine, which narrows the problem to the client.

The wider picture of what an agent can do once it is connected, and how the account underneath is kept safe, sits on the LinkedIn MCP server page.

Frequently Asked Questions

Where do I add a LinkedIn MCP server in Claude Desktop?

In Settings → Connectors, through the Add button and “Add custom connector”, where you paste https://mcp.gtm-api.com/mcp and approve the consent screen. Open Settings with Ctrl+Comma or from the menu icon under File. That list belongs to your Claude account, so a connector added in the browser shows up in the desktop app too.

Can I put the MCP server URL in claude_desktop_config.json?

No. That file configures local servers Claude Desktop launches itself, and its schema validates a command and args. Developers report that a url entry makes older builds crash at startup and makes newer builds rewrite the file and drop the entire mcpServers block, with no error shown. Remote servers belong in Connectors.

Can I connect Claude with my API key?

Not to the MCP server. A gtm_live_... key authenticates the REST API, and the hosted MCP endpoint takes OAuth tokens only, answering a key sent as a bearer token with 401 invalid_token. Nothing needs pasting: the client registers itself dynamically and you approve access in the browser.

Does Claude Code support remote MCP servers?

Yes, over the streamable HTTP transport. Add it with claude mcp add --transport http gtm-api https://mcp.gtm-api.com/mcp, add --scope user to have it in every project, then run /mcp in a session to authenticate. claude mcp list reports ✔ Connected, ! Needs authentication or ✘ Failed to connect with the server’s own error text.

How do I stop the agent loading every tool?

The server already does it for you. It publishes three meta tools, list_toolsets, get_toolset_tools and call_tool, so the model sees the domains and opens one on demand across 256 tools in 18 toolsets. In Claude you can also switch individual tools off in the connector’s settings, and Claude Code lets you toggle the whole server in the /mcp panel.

Sources & Further Reading

Connect it once, then let the agent work.

One URL in Connectors, one consent screen, and Claude is running search, messaging and enrichment on a LinkedIn account you own, under server-side limits. GTM API reports 20,000+ accounts at under a 1% monthly ban rate. Free plan, then from $10 per account at volume.

Get started free →

Last updated: August 2026 · Client setup paths, transport support, launcher versions and the live OAuth discovery documents verified on 17 August 2026