Skip to content

Connect LinkedIn Personal to ChatGPT: Manage Posts and Media Feeds

Learn how to connect LinkedIn Personal to ChatGPT using a managed MCP server. Automate text posts, multi-step media uploads, and feed management via Truto.

Uday Gajavalli Uday Gajavalli · · 9 min read
Connect LinkedIn Personal to ChatGPT: Manage Posts and Media Feeds

If you need to connect a personal LinkedIn account to ChatGPT to automate thought leadership workflows, manage multi-format media posts, or audit feed history, you need a Model Context Protocol (MCP) server. This server acts as the translation layer between ChatGPT's JSON-RPC tool calls and LinkedIn's highly specific RestLi API architecture. You can either build and maintain this infrastructure yourself, or use a managed integration platform like Truto to dynamically generate a secure, authenticated MCP server URL.

If your team uses Claude, check out our guide on connecting LinkedIn Personal to Claude or explore our broader architectural overview on connecting LinkedIn Personal to AI Agents.

Giving a Large Language Model (LLM) read and write access to LinkedIn is a complex engineering task. You have to handle unusual identifier formats, orchestrate multi-step media uploads, and navigate proprietary patch schemas. Every time LinkedIn updates a content standard, your custom server code must adapt.

This guide breaks down exactly how to use Truto to generate a secure, managed MCP server for LinkedIn Personal, connect it natively to ChatGPT, and execute complex publishing workflows using natural language.

The Engineering Reality of the LinkedIn Personal API

A custom MCP server is a self-hosted integration layer. While the open MCP standard provides a predictable way for models to discover tools, implementing it against LinkedIn's API is exceptionally painful.

If you decide to build a custom MCP server for LinkedIn, you own the entire API lifecycle. Here are the specific integration challenges that break standard REST assumptions when working with LinkedIn:

The URN (Uniform Resource Name) System

Unlike most SaaS platforms that use simple integer or UUID strings (e.g., 12345 or abc-xyz), LinkedIn relies entirely on Uniform Resource Names (URNs). A user is not id: 54321, they are urn:li:person:54321. A post is urn:li:share:6844785523593134080.

When passing these identifiers through HTTP paths or query parameters, they must be properly URL-encoded (e.g., urn%3Ali%3Aperson%3A54321). If you build a custom MCP server, you must instruct the LLM on exactly how to format and pass these URNs, and write middleware to encode them before executing upstream requests. Truto's proxy handlers handle this URL-encoding automatically, so the LLM can safely pass the raw URN strings.

Multi-Step Media Uploads

Posting text to LinkedIn is a single API call. Posting an image or video is a complex, multi-stage orchestration problem.

To upload an image, you must first call an initializeUpload endpoint to register the intent. LinkedIn returns a pre-signed URL and a media URN. You must then execute a direct binary PUT or POST to that pre-signed URL (without LinkedIn auth headers, as it is pre-signed). Only after the binary upload succeeds can you use the media URN in the actual post creation payload.

Videos are even worse. They require chunked uploads. You get an array of upload URLs based on file size, must PUT each chunk individually, capture the ETag headers from each response, and then submit a finalizeUpload request containing the ordered ETags. Building MCP schemas to instruct an LLM on how to orchestrate this logic manually is highly error-prone. Truto abstracts this into distinct, reliable tools.

Proprietary RestLi Partial Updates

LinkedIn does not use standard REST PATCH or PUT methods for updating resources. They use a proprietary framework called RestLi.

To update a post, your server must send a POST request, inject a specific X-RestLi-Method: PARTIAL_UPDATE header, and wrap the payload in a highly specific nested object: {"patch": {"$set": {"commentary": "New text"}}}. If your MCP server simply passes standard JSON arguments from the LLM, the request will fail. Truto's MCP architecture automatically translates flat JSON arguments from the LLM into the required RestLi partial-update structure.

Rate Limits and Headers

Factual note on rate limits: Truto does not retry, throttle, or apply backoff on rate limit errors. When the upstream LinkedIn API returns an HTTP 429, Truto passes that error directly to the caller. Truto normalizes the upstream rate limit information into standardized headers (ratelimit-limit, ratelimit-remaining, ratelimit-reset) per the IETF specification. The caller (your LLM client or agent framework) is strictly responsible for handling retry and backoff logic.

Step-by-Step Guide: Connect LinkedIn to ChatGPT

Step 1: Connect the LinkedIn Account

Before generating tools, you need an authenticated connection. In the Truto dashboard, navigate to Integrated Accounts -> New Integrated Account, select LinkedIn Personal, and complete the OAuth flow. Truto securely stores the refresh token and automatically refreshes short-lived access tokens, ensuring ChatGPT never encounters an expired credential.

Copy the resulting integrated_account_id. You will use this to generate the server.

Step 2: Create the MCP Server

You can generate the MCP server URL through the Truto dashboard or programmatically via the API.

Method A: Via the Truto UI

  1. Navigate to the integrated account page for the connected LinkedIn instance.
  2. Click the MCP Servers tab.
  3. Click Create MCP Server.
  4. Select your desired configuration (e.g., name, allowed methods, tags).
  5. Copy the generated MCP server URL (it will look like https://api.truto.one/mcp/<token>).

Method B: Via the API Make a single POST request to generate a secure, scoped MCP endpoint. You can filter the tools using methods and tags to strictly limit what ChatGPT can do.

curl -X POST https://api.truto.one/integrated-account/<INTEGRATED_ACCOUNT_ID>/mcp \
  -H "Authorization: Bearer $TRUTO_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "LinkedIn Post Manager",
    "config": {
      "methods": ["read", "write"],
      "tags": ["posts", "media", "profile"]
    }
  }'

The response contains a url field. This URL contains a cryptographic token that securely maps to your connected LinkedIn account.

Step 3: Connect the MCP Server to ChatGPT

With the URL in hand, you must register it with your ChatGPT environment. You can do this via the UI or a local configuration file.

Method A: Via the ChatGPT UI

  1. In ChatGPT, click your profile picture and navigate to Settings -> Apps -> Advanced settings.
  2. Toggle Developer mode on (MCP support is currently behind this flag).
  3. Under MCP servers / Custom connectors, click Add new server.
  4. Provide a name (e.g., "LinkedIn Personal (Truto)").
  5. Paste the Truto MCP URL into the Server URL field and click Save.

ChatGPT will immediately connect, perform the MCP initialization handshake, and list the available LinkedIn tools.

Method B: Via Manual Config File If you are using a local agent framework, desktop client, or standardizing connector configurations, you can use a JSON config file leveraging the official MCP SSE transport. Create a configuration file pointing to the SSE runtime:

{
  "mcpServers": {
    "linkedin_personal": {
      "command": "npx",
      "args": [
        "-y",
        "@modelcontextprotocol/server-sse",
        "--url",
        "https://api.truto.one/mcp/<YOUR_TOKEN>"
      ]
    }
  }
}

Hero Tools for LinkedIn Personal

Truto derives MCP tools dynamically from the underlying API documentation. Here are the highest-leverage tools available for the LinkedIn Personal integration.

Get Connected Member Profile

list_all_linked_in_personal_me

Retrieves the connected member's OpenID Connect profile from LinkedIn's userinfo endpoint. This is a critical first step for almost all workflows, as it returns the sub claim needed to build the user's person URN (urn:li:person:{sub}). Takes no input.

"Fetch my LinkedIn profile data. Tell me my name, email, and extract my URN so we can use it to create a post."

Create a Text Post

create_a_linked_in_personal_post

Publishes a post to the connected member's LinkedIn feed. Truto sets the author URN automatically based on the authenticated context. You provide the commentary (the text of the post) and a visibility state (PUBLIC or CONNECTIONS). Returns the new post ID, which is the URN copied from LinkedIn's x-restli-id response header.

"Draft a short, engaging post about the future of AI agents in B2B SaaS. Set the visibility to PUBLIC and publish it to my feed."

Update an Existing Post

update_a_linked_in_personal_post_by_id

Edits one of the connected member's posts by its URN. Send only the flat fields you wish to change (e.g., commentary). Truto automatically builds the complex RestLi partial-update request ({"patch": {"$set": {...}}}). You just pass the plain post URN (e.g., urn:li:share:12345).

"I noticed a typo in my last post. Please update the post with URN 'urn:li:share:6844785523593134080'. Change the commentary to read 'MCP servers are the future of AI integration.'"

Initialize Image Upload

create_a_linked_in_personal_image

Starts an image upload for the connected member (LinkedIn's initializeUpload action). This is step 1 of 2. It requires no body. It returns an uploadUrl, expiration timestamp, and an image URN. You must save this URN to use later when creating the final post.

"I need to upload an image. Initialize an image upload request and give me back the upload URL and the image URN."

Execute File Upload

create_a_linked_in_personal_upload

Uploads a file to LinkedIn, acting as step 2 for image and document posts. You pass the uploadUrl obtained from the initialization step unchanged, along with the file data. The URL is pre-signed, so no LinkedIn token is sent with this call.

"Take this local file 'chart.png' and upload it to the pre-signed URL we just generated. Let me know when it succeeds."

Delete a Post

delete_a_linked_in_personal_post_by_id

Deletes a post by its URN. Pass the id as the plain post URN. Truto URL-encodes it automatically. Deletion in the LinkedIn API is idempotent - deleting a post that is already gone still returns an empty 204 success response.

"Please delete the promotional post we made yesterday. The URN is 'urn:li:share:9876543210'."

For the complete tool inventory and detailed schema requirements, visit the LinkedIn Personal integration page.

Workflows in Action

Connecting an LLM to a social media API is only useful if the agent can chain operations together to execute complex workflows. Here are two real-world scenarios showing how ChatGPT uses the Truto MCP server.

Scenario 1: The Executive Thought Leader (Text Publishing)

An executive wants to quickly review their profile context, draft a post, and publish it, all within a natural conversation.

"I want to publish a post about our recent Q3 earnings growth. Check my profile to ensure we are connected to the right account, draft a professional 2-paragraph post, and then publish it to my connections only."

Step-by-step Execution:

  1. ChatGPT calls list_all_linked_in_personal_me to verify the connected identity and extract the user's name and context.
  2. ChatGPT drafts the content locally based on the prompt.
  3. ChatGPT calls create_a_linked_in_personal_post with the drafted commentary and sets visibility to CONNECTIONS.
  4. The agent returns the successful post creation message along with the new post URN.

Scenario 2: The Content Marketer (Multi-Step Media Post)

A marketing manager needs to publish an infographic alongside a text update. This requires the agent to navigate LinkedIn's multi-step media architecture.

"I have a new infographic I want to share. Initialize an image upload, upload this image file, and then publish a public post saying 'Check out our latest architectural metrics!' attached to the image."

Step-by-step Execution:

  1. ChatGPT calls create_a_linked_in_personal_image to start the process. The API returns an uploadUrl and an image URN.
  2. ChatGPT calls create_a_linked_in_personal_upload, passing the uploadUrl and the local file bytes.
  3. Upon receiving a 201 success from the upload step, ChatGPT calls create_a_linked_in_personal_post.
  4. In the post creation payload, it passes the text in commentary and includes the saved image URN in the content.media.id field.
sequenceDiagram
    participant LLM as ChatGPT
    participant Truto as Truto MCP Server
    participant Upstream as LinkedIn API

    LLM->>Truto: call create_a_linked_in_personal_image
    Truto->>Upstream: POST /images?action=initializeUpload
    Upstream-->>Truto: uploadUrl & image URN
    Truto-->>LLM: return uploadUrl & image URN

    LLM->>Truto: call create_a_linked_in_personal_upload (bytes + uploadUrl)
    Truto->>Upstream: PUT bytes to uploadUrl
    Upstream-->>Truto: 201 Created
    Truto-->>LLM: upload successful

    LLM->>Truto: call create_a_linked_in_personal_post (text + image URN)
    Truto->>Upstream: POST /ugcPosts
    Upstream-->>Truto: 201 Created (Post URN)
    Truto-->>LLM: return Post URN

Security and Access Control

When connecting an AI agent to a personal social media account, limiting blast radius is critical. Truto MCP servers include several built-in security features:

  • Method Filtering: When creating the server via the UI or API, use the methods array to restrict access. Passing methods: ["read"] ensures the agent can query profile data but physically cannot execute create, update, or delete tools.
  • Tag Filtering: Use the tags array to restrict the server to specific resource groups. For example, tags: ["posts"] will exclude tools related to raw media uploads or profile editing.
  • Extra Authentication (require_api_token_auth): By default, possessing the MCP URL grants access. By setting require_api_token_auth: true, the client must also supply a valid Truto API token in the Authorization header, preventing unauthorized execution if the URL leaks in logs.
  • Automatic Expiration (expires_at): You can generate ephemeral servers by setting an ISO datetime in the expires_at field. Once the time passes, Truto automatically deletes the server configuration and immediately revokes all access, perfect for contractor workflows or temporary automation runs.

Summary

Building a custom integration for LinkedIn's API means writing custom middleware to handle URN formatting, chunked media uploads, and idiosyncratic RestLi partial updates. Maintaining that code as LinkedIn evolves their schema is a massive drain on engineering resources.

By using Truto to generate a managed MCP server, you offload the authentication lifecycle, rate limit normalization, and protocol translation entirely. You get standardized, documentation-backed JSON-RPC tools that ChatGPT can consume immediately, allowing your engineering team to focus on building great AI workflows instead of maintaining API boilerplate.

FAQ

How does Truto handle LinkedIn API rate limits?
Truto does not retry, throttle, or apply backoff on rate limit errors. When the LinkedIn API returns an HTTP 429, Truto passes that error directly to the caller. Truto normalizes the upstream rate limit information into standardized headers (ratelimit-limit, ratelimit-remaining, ratelimit-reset) per the IETF specification. Your client or AI agent is responsible for handling the retry and backoff logic.
How do media uploads work with the LinkedIn MCP server?
Media uploads require a multi-step process. First, the LLM calls an initialize tool (e.g., create_a_linked_in_personal_image) to register the asset and get a pre-signed URL. Second, it uses the upload tool to send the file bytes to that URL. Finally, it passes the returned asset URN to the post creation tool.
Do I need to manage LinkedIn OAuth tokens myself?
No. When you connect a LinkedIn account via Truto, the platform securely stores the refresh token and automatically refreshes short-lived access tokens before they expire. The generated MCP server URL handles routing requests through this authenticated connection.

More from our Blog