Skip to main content

LinkedIn Ads MCP

PyPI Python 3.10+ License: MIT

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 open-source tooling. Free to use, modify, and redistribute under the MIT License.


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/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

MIT. Free to use, copy, modify, merge, publish, distribute, sublicense, and sell — for any purpose, commercial or not. No strings attached.

Versions 0.3.0–0.3.x were released under FSL-1.1-MIT. As of 0.4.0 the project is MIT — the copyright holder (Nuraveda Lab) relicenses it as MIT going forward, so anyone can use it, including in a commercial product.

About

Built and maintained by Nuraveda Lab as open-source tooling. 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.

Metadata

Release files for linkedin-ads-mcp 0.4.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for linkedin-ads-mcp 0.4.1
File Size Uploaded
linkedin_ads_mcp-0.4.1.tar.gz 11.8 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for linkedin-ads-mcp 0.4.1
File Interpreter ABI Platform
linkedin_ads_mcp-0.4.1-py3-none-any.whl Python 3 none any Details

Total release size: 23.5 kB

Release files / linkedin_ads_mcp-0.4.1.tar.gz

Download URL linkedin_ads_mcp-0.4.1.tar.gz
Size 11.8 kB
Tags Source
SHA-256 checksum
How to use checksums
958ef2aac18e6b27183c894108487568e43f9ceba7c1818afc324ff7b8f772ee
BLAKE2b-256 checksum
How to use checksums
92f66c180eef1d09c5188e1a9bb6d03be00de706d1deea785002535d1aa7c2c3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 1, 2026.

Transparency log

Release files / linkedin_ads_mcp-0.4.1-py3-none-any.whl

Download URL linkedin_ads_mcp-0.4.1-py3-none-any.whl
Size 11.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
677ca37490adaa7ae2e914e0cc7f4f7bb7f24621c7a6cfdc5e9066b9f15583b4
BLAKE2b-256 checksum
How to use checksums
364ee97d0a4a6a0c457ed5228f3b3346531416f2a634c952cd246f84ffc0ead6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 1, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.4.1 This release

2 release files

0.4.0

2 release files

0.3.0

2 release files

0.2.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page