Skip to main content

LinkedIn Ads MCP — MCP server for the LinkedIn Marketing API. Read + write campaigns, analytics, and creatives from any MCP client. Maintained by Nuraveda Lab.

Project description

LinkedIn Ads MCP

PyPI Python 3.10+ License: FSL-1.1-MIT Part of Mesh Pilot

Model Context Protocol (MCP) server for the LinkedIn Marketing API. Read campaigns, pull analytics, create campaign groups + campaigns, flip statuses — all from any MCP client (Claude Desktop, Cursor, Continue, or your own agent).

There's no official LinkedIn MCP. This fills the gap with a thin, correctness-first wrapper that handles LinkedIn's quirky restli encoding rules so you don't have to.

Maintained by Nuraveda Lab as source-available tooling alongside the Mesh Pilot agent suite. Free to use under FSL-1.1-MIT — converts to MIT after two years.


⚡ Skip the setup — connect LinkedIn through Mesh Pilot

LinkedIn's Marketing API gate is the real hassle: you apply for the Advertising API product, wait for approval (days, not always granted), run an OAuth dance, and manage refresh-token rotation yourself.

Don't want any of that? Mesh Pilot runs this MCP for you behind an already-approved LinkedIn Marketing app. Connect your LinkedIn account in one click and you're driving your ad accounts from your AI client immediately — no API application, no OAuth setup, no token management.

Connect LinkedIn via Mesh Pilot

Self-host (this repo) Mesh Pilot (hosted)
LinkedIn Marketing API approval you apply + wait already approved
OAuth + token rotation you manage handled for you
Setup time hours–days one click
Cost free (FSL-1.1-MIT) see meshpilot.app
Runs in your own infra hosted

Prefer to run it yourself? Keep reading — the full self-host path is below.


Why this exists

If you've tried calling LinkedIn's /rest/adAnalytics endpoint by hand you've probably hit walls like:

  • Commas in fields= get URL-encoded by default HTTP clients → 400 not present in schema
  • URN colons inside accounts=List(urn:li:sponsoredAccount:NNN) need to be %3A but date-tuple colons must stay literal
  • Partial updates need X-RestLi-Method: PARTIAL_UPDATE or they get silently ignored
  • runSchedule.start must be ≥ now-ish, totalBudget.amount must be ≥ $100
  • New campaigns need politicalIntent (LinkedIn's EU political-ad declaration)

This server has all those rules already encoded.

Install

pip install linkedin-ads-mcp
# or:
uv add linkedin-ads-mcp

From source:

git clone https://github.com/Nuraveda-Labs/linkedin-ads-mcp.git
cd linkedin-ads-mcp
uv pip install -e .          # or: pip install -e .

On PyPI as linkedin-ads-mcp. The prior package name glitch-grow-linkedin-ad-mcp (v0.1.1) is legacy and frozen — use linkedin-ads-mcp going forward.

OAuth setup (self-host path)

  1. Create a LinkedIn app at https://www.linkedin.com/developers/apps.

  2. On the Products tab, request Advertising API (auto-approved if you have an active Campaign Manager account).

  3. Run any OAuth flow that grants the scopes r_ads, rw_ads, r_ads_reporting — for example:

    https://www.linkedin.com/oauth/v2/authorization?response_type=code
      &client_id=$YOUR_CLIENT_ID
      &redirect_uri=$YOUR_REDIRECT_URI
      &scope=r_ads%20rw_ads%20r_ads_reporting
    
  4. Exchange the code for tokens; save the access + refresh tokens.

  5. Copy .env.example to .env and paste them.

Run

# stdio (Claude Desktop, Cursor, Continue, etc.)
linkedin-ads-mcp

# SSE on :8000
linkedin-ads-mcp --transport sse --port 8000

Claude Desktop config

{
  "mcpServers": {
    "linkedin-ads": {
      "command": "linkedin-ads-mcp",
      "env": {
        "LINKEDIN_CLIENT_ID": "...",
        "LINKEDIN_CLIENT_SECRET": "...",
        "LINKEDIN_REFRESH_TOKEN": "..."
      }
    }
  }
}

Tools

Read

Tool What it does
list_ad_accounts() Every ad account the OAuth user can access
list_account_users(account_id) User → role assignments
list_campaign_groups(account_id) Campaign groups + total budgets
list_campaigns(account_id) All campaigns + structure (no metrics)
list_creatives(account_id) Creative roster
get_account_analytics(account_id, days=14) Account-level totals
get_campaign_analytics(account_id, days=14) Per-campaign metrics, sorted by spend

Write

Tool What it does
create_campaign_group(account_id, name, total_budget=100, days=30, status="DRAFT") Create a group
create_campaign(account_id, name, campaign_group_urn, daily_budget=10, …) Create a campaign (defaults to safe DRAFT TEXT_AD)
update_campaign_status(account_id, campaign_id, status) DRAFT / ACTIVE / PAUSED / ARCHIVED
update_campaign_group_status(account_id, group_id, status) Same set + CANCELED

All write tools default to DRAFT so nothing goes live by accident. Promote a group → ACTIVE first, then promote campaigns → PAUSED → ACTIVE in two explicit steps.

Multi-tenant pattern

LinkedIn has no MCC, but Campaign Manager has equivalent "Manage Access" sharing. To run this MCP across multiple advertisers:

  1. Each client adds your OAuth user as CAMPAIGN_MANAGER on their ad account (Campaign Manager → Account Settings → Manage Access).
  2. After they accept, list_ad_accounts() returns their account.
  3. Pass that account_id to any tool call. One OAuth dance, N advertiser accounts — same model as the Google Ads MCC pattern.

Status

Read API + write API for groups + campaigns are battle-tested in production. Sponsored-creative creation (image/video upload via initializeUpload → bind to /rest/creatives → attach to a campaign) reuses a proven /rest/documents + /rest/posts upload pattern; porting it to the sponsored-ad surface is on the roadmap. PRs welcome.

License

FSL-1.1-MIT (Functional Source License). Free for any use except building a competing product or service — including a competing LinkedIn-ads MCP, agent platform, or hosted offering that substitutes for this software or for Mesh Pilot.

Permitted: internal use, modification, redistribution, client/professional services, and non-commercial research/education. Each released version automatically converts to the MIT License two years after its release, so the restriction is time-boxed, not permanent.

Earlier 0.2.0 (and the legacy glitch-grow-linkedin-ad-mcp 0.1.1) were published under MIT and remain MIT — the FSL terms apply to 0.3.0 onward.

About

Built and maintained by Nuraveda Lab as source-available tooling in the Mesh Pilot growth suite. Hardened against real LinkedIn Marketing API behavior in production. If you hit a restli encoding edge case we missed, open an issue with the offending URL and we'll codify the fix.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

linkedin_ads_mcp-0.3.0.tar.gz (14.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

linkedin_ads_mcp-0.3.0-py3-none-any.whl (14.8 kB view details)

Uploaded Python 3

File details

Details for the file linkedin_ads_mcp-0.3.0.tar.gz.

File metadata

  • Download URL: linkedin_ads_mcp-0.3.0.tar.gz
  • Upload date:
  • Size: 14.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for linkedin_ads_mcp-0.3.0.tar.gz
Algorithm Hash digest
SHA256 6bc427620b2c4834701addce68c16826a2455659956b9d7f998a3d3948e2d1d8
MD5 d70f62a6b3300144cafc385e4cab1c55
BLAKE2b-256 19cbc80b90bb03bc59f9e988965ac51301a208cd2c9c0cd0d483ee4f2193ed47

See more details on using hashes here.

Provenance

The following attestation bundles were made for linkedin_ads_mcp-0.3.0.tar.gz:

Publisher: release.yml on Nuraveda-Labs/linkedin-ads-mcp

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file linkedin_ads_mcp-0.3.0-py3-none-any.whl.

File metadata

File hashes

Hashes for linkedin_ads_mcp-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 e1a3478ed9912264c9a3c477f2496013612c016b8d36e33f9e02a8d1d9904510
MD5 4f8a54ace32250de79a24ecb9f128e2f
BLAKE2b-256 e8510266e918216dc0407b7e993698808c6412a3fb0ab23192ee196c056adfe8

See more details on using hashes here.

Provenance

The following attestation bundles were made for linkedin_ads_mcp-0.3.0-py3-none-any.whl:

Publisher: release.yml on Nuraveda-Labs/linkedin-ads-mcp

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page