linkedin-ads-mcp-py 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,148 @@
1
+ Metadata-Version: 2.4
2
+ Name: linkedin-ads-mcp-py
3
+ Version: 0.1.0
4
+ Summary: LinkedIn Ads MCP server with MCC client-switching support
5
+ Keywords: mcp,ai,tools,linkedin,ads
6
+ Author: LOCOMOTIVE Agency
7
+ Author-email: LOCOMOTIVE Agency <erick@locomotive.agency>
8
+ License-Expression: MIT
9
+ Classifier: Development Status :: 4 - Beta
10
+ Classifier: Intended Audience :: Developers
11
+ Classifier: License :: OSI Approved :: MIT License
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Programming Language :: Python :: 3.12
14
+ Requires-Dist: fastmcp>=0.1.0
15
+ Requires-Dist: httpx>=0.27.0
16
+ Requires-Dist: loguru>=0.7.3
17
+ Requires-Dist: pydantic>=2.11.7
18
+ Requires-Dist: pydantic-settings>=2.10.1
19
+ Requires-Python: >=3.12
20
+ Description-Content-Type: text/markdown
21
+
22
+ # linkedin-ads-mcp
23
+
24
+ MCP server for the LinkedIn Marketing API, with built-in MCC-style client switching across every
25
+ ad account your LinkedIn login can access.
26
+
27
+ ## Installation
28
+
29
+ Once published to PyPI:
30
+
31
+ ```bash
32
+ uv tool install linkedin-ads-mcp-py
33
+ ```
34
+
35
+ This installs the `linkedin-ads-mcp` and `linkedin-ads-auth` commands. Or run it directly without
36
+ installing:
37
+
38
+ ```bash
39
+ uvx --from linkedin-ads-mcp-py linkedin-ads-mcp
40
+ ```
41
+
42
+ Point your MCP client (e.g. `.mcp.json` or Claude Desktop's config) at the `linkedin-ads-mcp`
43
+ command.
44
+
45
+ ## Setup
46
+
47
+ 1. Create an app at [LinkedIn Developers](https://www.linkedin.com/developers/apps) with access to
48
+ the **Advertising API** product (requires LinkedIn's approval — see their docs, no published
49
+ SLA).
50
+ 2. Add `http://localhost:3000/callback` (or your own `LINKEDIN_REDIRECT_URI`) to the app's
51
+ authorized redirect URLs.
52
+ 3. Set the following environment variables (e.g. in a `.env` file in your working directory, or
53
+ directly in your MCP client's server config):
54
+
55
+ ```bash
56
+ LINKEDIN_CLIENT_ID=your_client_id
57
+ LINKEDIN_CLIENT_SECRET=your_client_secret
58
+ # Optional overrides:
59
+ # LINKEDIN_REDIRECT_URI=http://localhost:3000/callback
60
+ # LINKEDIN_TOKEN_PATH=/path/to/tokens.json
61
+ ```
62
+
63
+ 4. Authenticate (opens a browser for the LinkedIn OAuth consent screen):
64
+
65
+ ```bash
66
+ uvx --from linkedin-ads-mcp-py linkedin-ads-auth
67
+ ```
68
+
69
+ Tokens are saved to `~/.linkedin-ads-mcp/tokens.json` by default and refreshed automatically
70
+ when a refresh token is available.
71
+
72
+ 5. Run the server:
73
+
74
+ ```bash
75
+ uvx --from linkedin-ads-mcp-py linkedin-ads-mcp
76
+ ```
77
+
78
+ ## MCC / multi-account support
79
+
80
+ Unlike the original TypeScript `linkedin-ads-mcp`, this server exposes every ad account your
81
+ LinkedIn login can access and lets you switch between them by name or ID:
82
+
83
+ - `list_clients` — list all accessible ad accounts (call this first)
84
+ - `set_active_client` — select a default account (by name or numeric ID) for subsequent calls
85
+ - `get_active_client` — show which account is currently active
86
+
87
+ Every account-specific tool also accepts an optional `account` argument to target a client
88
+ directly without changing the active selection.
89
+
90
+ ## Tools
91
+
92
+ | Tool | Notes |
93
+ |---|---|
94
+ | `list_clients` | MCC view — call first |
95
+ | `set_active_client` | select account by name or ID |
96
+ | `get_active_client` | show current selection |
97
+ | `get_account_details` | account metadata |
98
+ | `list_campaign_groups` | |
99
+ | `list_campaigns` | |
100
+ | `get_campaign_performance` | report |
101
+ | `get_campaign_groups_performance` | report |
102
+ | `get_creative_performance` | report |
103
+ | `get_audience_demographics` | report |
104
+ | `get_audience_reach` | reach / frequency |
105
+ | `compare_performance` | compare two time windows or entity sets |
106
+ | `get_daily_trends` | daily time series |
107
+ | `list_creatives` | |
108
+ | `get_conversion_performance` | report |
109
+ | `list_conversions` | |
110
+ | `get_lead_gen_performance` | report |
111
+ | `list_lead_forms` | |
112
+ | `list_saved_audiences` | |
113
+
114
+ ## Architecture
115
+
116
+ - `auth/oauth.py` — OAuth 2.0 authorization-code flow, browser + local callback server
117
+ - `auth/token_store.py` — persistent token storage with automatic refresh
118
+ - `api/client.py` — `LinkedInClient`, async wrapper around the LinkedIn Marketing REST API
119
+ - `api/types.py` — Pydantic models for API entities and responses
120
+ - `context.py` — `ServerContext` singleton holding the active client and name→ID cache
121
+ - `tools/accounts.py` — MCC tools (`list_clients`, `set_active_client`, `get_active_client`)
122
+ - `server.py` — MCP stdio server, tool registration
123
+
124
+ ## Development
125
+
126
+ ```bash
127
+ uv sync
128
+ uv run pre-commit install
129
+
130
+ uv run ruff format
131
+ uv run ruff check
132
+ uv run mypy src/
133
+ uv run pytest
134
+ ```
135
+
136
+ ## Building and publishing
137
+
138
+ ```bash
139
+ uv build
140
+ ```
141
+
142
+ Publishing to PyPI is handled by `.github/workflows/pypi-publish.yml` via
143
+ [PyPI trusted publishing](https://docs.pypi.org/trusted-publishers/) whenever a GitHub release is
144
+ published — no API token needed once the trusted publisher is configured on the PyPI project.
145
+
146
+ ## License
147
+
148
+ MIT License - see LICENSE file for details.
@@ -0,0 +1,127 @@
1
+ # linkedin-ads-mcp
2
+
3
+ MCP server for the LinkedIn Marketing API, with built-in MCC-style client switching across every
4
+ ad account your LinkedIn login can access.
5
+
6
+ ## Installation
7
+
8
+ Once published to PyPI:
9
+
10
+ ```bash
11
+ uv tool install linkedin-ads-mcp-py
12
+ ```
13
+
14
+ This installs the `linkedin-ads-mcp` and `linkedin-ads-auth` commands. Or run it directly without
15
+ installing:
16
+
17
+ ```bash
18
+ uvx --from linkedin-ads-mcp-py linkedin-ads-mcp
19
+ ```
20
+
21
+ Point your MCP client (e.g. `.mcp.json` or Claude Desktop's config) at the `linkedin-ads-mcp`
22
+ command.
23
+
24
+ ## Setup
25
+
26
+ 1. Create an app at [LinkedIn Developers](https://www.linkedin.com/developers/apps) with access to
27
+ the **Advertising API** product (requires LinkedIn's approval — see their docs, no published
28
+ SLA).
29
+ 2. Add `http://localhost:3000/callback` (or your own `LINKEDIN_REDIRECT_URI`) to the app's
30
+ authorized redirect URLs.
31
+ 3. Set the following environment variables (e.g. in a `.env` file in your working directory, or
32
+ directly in your MCP client's server config):
33
+
34
+ ```bash
35
+ LINKEDIN_CLIENT_ID=your_client_id
36
+ LINKEDIN_CLIENT_SECRET=your_client_secret
37
+ # Optional overrides:
38
+ # LINKEDIN_REDIRECT_URI=http://localhost:3000/callback
39
+ # LINKEDIN_TOKEN_PATH=/path/to/tokens.json
40
+ ```
41
+
42
+ 4. Authenticate (opens a browser for the LinkedIn OAuth consent screen):
43
+
44
+ ```bash
45
+ uvx --from linkedin-ads-mcp-py linkedin-ads-auth
46
+ ```
47
+
48
+ Tokens are saved to `~/.linkedin-ads-mcp/tokens.json` by default and refreshed automatically
49
+ when a refresh token is available.
50
+
51
+ 5. Run the server:
52
+
53
+ ```bash
54
+ uvx --from linkedin-ads-mcp-py linkedin-ads-mcp
55
+ ```
56
+
57
+ ## MCC / multi-account support
58
+
59
+ Unlike the original TypeScript `linkedin-ads-mcp`, this server exposes every ad account your
60
+ LinkedIn login can access and lets you switch between them by name or ID:
61
+
62
+ - `list_clients` — list all accessible ad accounts (call this first)
63
+ - `set_active_client` — select a default account (by name or numeric ID) for subsequent calls
64
+ - `get_active_client` — show which account is currently active
65
+
66
+ Every account-specific tool also accepts an optional `account` argument to target a client
67
+ directly without changing the active selection.
68
+
69
+ ## Tools
70
+
71
+ | Tool | Notes |
72
+ |---|---|
73
+ | `list_clients` | MCC view — call first |
74
+ | `set_active_client` | select account by name or ID |
75
+ | `get_active_client` | show current selection |
76
+ | `get_account_details` | account metadata |
77
+ | `list_campaign_groups` | |
78
+ | `list_campaigns` | |
79
+ | `get_campaign_performance` | report |
80
+ | `get_campaign_groups_performance` | report |
81
+ | `get_creative_performance` | report |
82
+ | `get_audience_demographics` | report |
83
+ | `get_audience_reach` | reach / frequency |
84
+ | `compare_performance` | compare two time windows or entity sets |
85
+ | `get_daily_trends` | daily time series |
86
+ | `list_creatives` | |
87
+ | `get_conversion_performance` | report |
88
+ | `list_conversions` | |
89
+ | `get_lead_gen_performance` | report |
90
+ | `list_lead_forms` | |
91
+ | `list_saved_audiences` | |
92
+
93
+ ## Architecture
94
+
95
+ - `auth/oauth.py` — OAuth 2.0 authorization-code flow, browser + local callback server
96
+ - `auth/token_store.py` — persistent token storage with automatic refresh
97
+ - `api/client.py` — `LinkedInClient`, async wrapper around the LinkedIn Marketing REST API
98
+ - `api/types.py` — Pydantic models for API entities and responses
99
+ - `context.py` — `ServerContext` singleton holding the active client and name→ID cache
100
+ - `tools/accounts.py` — MCC tools (`list_clients`, `set_active_client`, `get_active_client`)
101
+ - `server.py` — MCP stdio server, tool registration
102
+
103
+ ## Development
104
+
105
+ ```bash
106
+ uv sync
107
+ uv run pre-commit install
108
+
109
+ uv run ruff format
110
+ uv run ruff check
111
+ uv run mypy src/
112
+ uv run pytest
113
+ ```
114
+
115
+ ## Building and publishing
116
+
117
+ ```bash
118
+ uv build
119
+ ```
120
+
121
+ Publishing to PyPI is handled by `.github/workflows/pypi-publish.yml` via
122
+ [PyPI trusted publishing](https://docs.pypi.org/trusted-publishers/) whenever a GitHub release is
123
+ published — no API token needed once the trusted publisher is configured on the PyPI project.
124
+
125
+ ## License
126
+
127
+ MIT License - see LICENSE file for details.
@@ -0,0 +1,72 @@
1
+ [project]
2
+ name = "linkedin-ads-mcp-py"
3
+ version = "0.1.0"
4
+ description = "LinkedIn Ads MCP server with MCC client-switching support"
5
+ authors = [{ name = "LOCOMOTIVE Agency", email = "erick@locomotive.agency" }]
6
+ license = "MIT"
7
+ readme = "README.md"
8
+ keywords = ["mcp", "ai", "tools", "linkedin", "ads"]
9
+ classifiers = [
10
+ "Development Status :: 4 - Beta",
11
+ "Intended Audience :: Developers",
12
+ "License :: OSI Approved :: MIT License",
13
+ "Programming Language :: Python :: 3",
14
+ "Programming Language :: Python :: 3.12",
15
+ ]
16
+ requires-python = ">= 3.12"
17
+ dependencies = [
18
+ "fastmcp>=0.1.0",
19
+ "httpx>=0.27.0",
20
+ "loguru>=0.7.3",
21
+ "pydantic>=2.11.7",
22
+ "pydantic-settings>=2.10.1",
23
+ ]
24
+
25
+ [dependency-groups]
26
+ dev = [
27
+ "mypy>=1.15.0",
28
+ "pre-commit>=4.1.0",
29
+ "pytest>=8.3.4",
30
+ "pytest-asyncio>=0.25.3",
31
+ "ruff>=0.9.7",
32
+ ]
33
+
34
+ [project.scripts]
35
+ linkedin-ads-mcp = "linkedin_ads_mcp.server:main"
36
+ linkedin-ads-auth = "linkedin_ads_mcp.auth.oauth:main"
37
+
38
+ [tool.uv.build-backend]
39
+ module-name = "linkedin_ads_mcp"
40
+
41
+ [build-system]
42
+ requires = ["uv_build>=0.8.11,<0.9.0"]
43
+ build-backend = "uv_build"
44
+
45
+ [tool.pytest.ini_options]
46
+ pythonpath = ["src"]
47
+ asyncio_mode = "auto"
48
+
49
+ [tool.ruff]
50
+ line-length = 88
51
+ src = ["src"]
52
+ output-format = "concise"
53
+
54
+ [tool.ruff.lint]
55
+ select = ["E", "F", "I", "B", "N", "ANN", "TRY", "PD", "RUF200", "UP", "G"]
56
+ ignore = ["E501", "ANN003", "ANN401", "TRY003", "TRY301", "TRY300"]
57
+
58
+ [tool.ruff.lint.extend-per-file-ignores]
59
+ "__init__.py" = ["F401", "F403", "E402"]
60
+ "tests/**/*.py" = ["D", "ANN"]
61
+
62
+ [tool.ruff.lint.pydocstyle]
63
+ convention = "google"
64
+
65
+ [tool.ruff.lint.mccabe]
66
+ max-complexity = 6
67
+
68
+ [tool.mypy]
69
+ python_version = "3.12"
70
+ warn_return_any = true
71
+ warn_unused_configs = true
72
+ disallow_untyped_defs = true
@@ -0,0 +1 @@
1
+ """LinkedIn Ads MCP server with MCC client-switching support."""
@@ -0,0 +1 @@
1
+ """LinkedIn Marketing API client and type definitions."""