adloop 0.13.3__tar.gz → 0.14.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.
Files changed (59) hide show
  1. adloop-0.13.3/README.md → adloop-0.14.0/PKG-INFO +61 -3
  2. adloop-0.13.3/PKG-INFO → adloop-0.14.0/README.md +34 -29
  3. {adloop-0.13.3 → adloop-0.14.0}/pyproject.toml +4 -2
  4. {adloop-0.13.3 → adloop-0.14.0}/pyproject.toml.orig +6 -3
  5. adloop-0.14.0/src/adloop/ads/conversion_actions.py +558 -0
  6. {adloop-0.13.3 → adloop-0.14.0}/src/adloop/ads/write.py +339 -20
  7. {adloop-0.13.3 → adloop-0.14.0}/src/adloop/auth.py +23 -0
  8. {adloop-0.13.3 → adloop-0.14.0}/src/adloop/cli.py +110 -0
  9. {adloop-0.13.3 → adloop-0.14.0}/src/adloop/config.py +27 -0
  10. adloop-0.14.0/src/adloop/reddit/__init__.py +9 -0
  11. adloop-0.14.0/src/adloop/reddit/auth.py +504 -0
  12. adloop-0.14.0/src/adloop/reddit/client.py +270 -0
  13. adloop-0.14.0/src/adloop/reddit/read.py +1344 -0
  14. adloop-0.14.0/src/adloop/reddit/schedule.py +200 -0
  15. adloop-0.14.0/src/adloop/reddit/write.py +1684 -0
  16. {adloop-0.13.3 → adloop-0.14.0}/src/adloop/rules/adloop.md +75 -7
  17. {adloop-0.13.3 → adloop-0.14.0}/src/adloop/safety/preview.py +4 -0
  18. {adloop-0.13.3 → adloop-0.14.0}/src/adloop/server.py +1006 -5
  19. {adloop-0.13.3 → adloop-0.14.0}/src/adloop/__init__.py +0 -0
  20. {adloop-0.13.3 → adloop-0.14.0}/src/adloop/__main__.py +0 -0
  21. {adloop-0.13.3 → adloop-0.14.0}/src/adloop/_mcp_patches.py +0 -0
  22. {adloop-0.13.3 → adloop-0.14.0}/src/adloop/ads/__init__.py +0 -0
  23. {adloop-0.13.3 → adloop-0.14.0}/src/adloop/ads/client.py +0 -0
  24. {adloop-0.13.3 → adloop-0.14.0}/src/adloop/ads/currency.py +0 -0
  25. {adloop-0.13.3 → adloop-0.14.0}/src/adloop/ads/enums.py +0 -0
  26. {adloop-0.13.3 → adloop-0.14.0}/src/adloop/ads/forecast.py +0 -0
  27. {adloop-0.13.3 → adloop-0.14.0}/src/adloop/ads/gaql.py +0 -0
  28. {adloop-0.13.3 → adloop-0.14.0}/src/adloop/ads/pmax.py +0 -0
  29. {adloop-0.13.3 → adloop-0.14.0}/src/adloop/ads/read.py +0 -0
  30. {adloop-0.13.3 → adloop-0.14.0}/src/adloop/crossref.py +0 -0
  31. {adloop-0.13.3 → adloop-0.14.0}/src/adloop/diagnostics.py +0 -0
  32. {adloop-0.13.3 → adloop-0.14.0}/src/adloop/ga4/__init__.py +0 -0
  33. {adloop-0.13.3 → adloop-0.14.0}/src/adloop/ga4/client.py +0 -0
  34. {adloop-0.13.3 → adloop-0.14.0}/src/adloop/ga4/reports.py +0 -0
  35. {adloop-0.13.3 → adloop-0.14.0}/src/adloop/ga4/tracking.py +0 -0
  36. {adloop-0.13.3 → adloop-0.14.0}/src/adloop/ga4/write.py +0 -0
  37. {adloop-0.13.3 → adloop-0.14.0}/src/adloop/gsc/__init__.py +0 -0
  38. {adloop-0.13.3 → adloop-0.14.0}/src/adloop/gsc/client.py +0 -0
  39. {adloop-0.13.3 → adloop-0.14.0}/src/adloop/gsc/reports.py +0 -0
  40. {adloop-0.13.3 → adloop-0.14.0}/src/adloop/gtm/__init__.py +0 -0
  41. {adloop-0.13.3 → adloop-0.14.0}/src/adloop/gtm/client.py +0 -0
  42. {adloop-0.13.3 → adloop-0.14.0}/src/adloop/gtm/read.py +0 -0
  43. {adloop-0.13.3 → adloop-0.14.0}/src/adloop/merchant/__init__.py +0 -0
  44. {adloop-0.13.3 → adloop-0.14.0}/src/adloop/merchant/client.py +0 -0
  45. {adloop-0.13.3 → adloop-0.14.0}/src/adloop/merchant/read.py +0 -0
  46. {adloop-0.13.3 → adloop-0.14.0}/src/adloop/pagespeed.py +0 -0
  47. {adloop-0.13.3 → adloop-0.14.0}/src/adloop/rules/__init__.py +0 -0
  48. {adloop-0.13.3 → adloop-0.14.0}/src/adloop/rules/commands/analyze-performance.md +0 -0
  49. {adloop-0.13.3 → adloop-0.14.0}/src/adloop/rules/commands/budget-plan.md +0 -0
  50. {adloop-0.13.3 → adloop-0.14.0}/src/adloop/rules/commands/create-ad.md +0 -0
  51. {adloop-0.13.3 → adloop-0.14.0}/src/adloop/rules/commands/create-campaign.md +0 -0
  52. {adloop-0.13.3 → adloop-0.14.0}/src/adloop/rules/commands/diagnose-tracking.md +0 -0
  53. {adloop-0.13.3 → adloop-0.14.0}/src/adloop/rules/commands/optimize-campaign.md +0 -0
  54. {adloop-0.13.3 → adloop-0.14.0}/src/adloop/rules_install.py +0 -0
  55. {adloop-0.13.3 → adloop-0.14.0}/src/adloop/runtime.py +0 -0
  56. {adloop-0.13.3 → adloop-0.14.0}/src/adloop/safety/__init__.py +0 -0
  57. {adloop-0.13.3 → adloop-0.14.0}/src/adloop/safety/audit.py +0 -0
  58. {adloop-0.13.3 → adloop-0.14.0}/src/adloop/safety/guards.py +0 -0
  59. {adloop-0.13.3 → adloop-0.14.0}/src/adloop/tracking.py +0 -0
@@ -1,10 +1,37 @@
1
+ Metadata-Version: 2.3
2
+ Name: adloop
3
+ Version: 0.14.0
4
+ Summary: The AI command center for Google Ads, Reddit Ads, GA4, and tracking code.
5
+ Keywords: mcp,google-ads,reddit-ads,google-analytics,ga4,cursor,marketing
6
+ Author: Daniel Klose
7
+ Author-email: Daniel Klose <info@daniel-klose.com>
8
+ License: MIT
9
+ Requires-Dist: fastmcp>=3.0.0
10
+ Requires-Dist: google-ads>=31.1.0
11
+ Requires-Dist: google-analytics-data>=0.20.0
12
+ Requires-Dist: google-analytics-admin>=0.27.0
13
+ Requires-Dist: google-api-python-client>=2.100.0
14
+ Requires-Dist: google-auth-oauthlib>=1.0.0
15
+ Requires-Dist: google-api-python-client>=2.0.0
16
+ Requires-Dist: pyyaml>=6.0
17
+ Requires-Dist: requests>=2.31
18
+ Requires-Dist: pytest>=8.0 ; extra == 'dev'
19
+ Requires-Dist: pytest-asyncio>=0.23 ; extra == 'dev'
20
+ Requires-Python: >=3.11
21
+ Project-URL: Homepage, https://github.com/kLOsk/adloop
22
+ Project-URL: Repository, https://github.com/kLOsk/adloop
23
+ Project-URL: Issues, https://github.com/kLOsk/adloop/issues
24
+ Project-URL: Changelog, https://github.com/kLOsk/adloop/releases
25
+ Provides-Extra: dev
26
+ Description-Content-Type: text/markdown
27
+
1
28
  <!-- mcp-name: com.getadloop/adloop -->
2
29
 
3
30
  <div align="center">
4
31
 
5
32
  # AdLoop
6
33
 
7
- **The AI command center for Google Ads, GA4, and tracking code.**
34
+ **The AI command center for Google Ads, Reddit Ads, GA4, and tracking code.**
8
35
 
9
36
  [![PyPI](https://img.shields.io/pypi/v/adloop.svg)](https://pypi.org/project/adloop/)
10
37
  [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
@@ -14,7 +41,7 @@
14
41
  [![GA4 Data API](https://img.shields.io/badge/GA4-Data%20API-E37400.svg?logo=google-analytics&logoColor=white)](https://developers.google.com/analytics/devguides/reporting/data/v1)
15
42
  [![GitHub stars](https://img.shields.io/github/stars/kLOsk/adloop?style=social)](https://github.com/kLOsk/adloop)
16
43
 
17
- An MCP server that gives your AI assistant read + write access to Google Ads and GA4 — with safety guardrails that prevent accidental spend.
44
+ An MCP server that gives your AI assistant read + write access to Google Ads, Reddit Ads and GA4 — with safety guardrails that prevent accidental spend.
18
45
 
19
46
  **[☁️ Skip the setup — use AdLoop Cloud (free plan, no card)](https://getadloop.com)** &nbsp;·&nbsp; or self-host: `pip install adloop`
20
47
 
@@ -171,6 +198,27 @@ These tools read the live GTM container and join it with the codebase + GA4 to f
171
198
 
172
199
  > **Setup for GSC tools** — Enable the **Search Console API** in your GCP project. Upgrading OAuth users must re-authorize once for the new scope (delete `~/.adloop/token.json`, run any tool). The killer combo: cross-reference organic queries with `get_keyword_performance` to find paid/organic cannibalization and untapped keyword opportunities.
173
200
 
201
+ ### Reddit Ads Tools
202
+
203
+ A second ad platform, same safety model. Reddit is a separate connection: its own developer app, its own OAuth, no developer token and no approval process. Every tool takes `ad_account_id` (defaults to `reddit.ad_account_id`).
204
+
205
+ | Tool | What It Does |
206
+ |------|-------------|
207
+ | `list_reddit_accounts` | Discover businesses and ad accounts (currency, time zone, approval state) |
208
+ | `list_reddit_funding_instruments` | Billing instruments and posting profiles — prerequisites for creating campaigns and ads |
209
+ | `get_reddit_campaigns` / `get_reddit_ad_groups` / `get_reddit_ads` | Structure with configured vs effective status, budgets, bids, pixel, targeting, weekly schedule, rejection reasons; `include_copy` returns each ad's post (headline, body, destination, media) |
210
+ | `get_reddit_performance` | Spend, clicks, CTR, CPC, conversions, CPA, ROAS per account/campaign/ad group/ad, optional breakdown (date, country, community, keyword, placement, …), compact mode with insights |
211
+ | `run_reddit_report` | Raw reports endpoint for any metric (REACH, video, per-event conversions) |
212
+ | `get_reddit_pixels` | Pixels and when each event last fired — flags ad groups optimizing for events the pixel never sent |
213
+ | `search_reddit_targeting` | Communities, interests, geolocations, languages, keyword suggestions, and Reddit's related-community suggestions (by seed communities or website) |
214
+ | `get_reddit_account_history` | Who changed what and when: field, before/after, member |
215
+ | `estimate_reddit_ad_group` | Audience size, delivery estimate and suggested bid range for a planned ad group (Reddit's counterpart of `estimate_budget`) |
216
+ | `pause_reddit_entity` / `enable_reddit_entity` / `remove_reddit_entity` | Status changes through the preview gate (remove = ARCHIVE, irreversible, double-confirmed) |
217
+ | `update_reddit_campaign` / `update_reddit_ad_group` / `update_reddit_ad` | Budget, bid, run dates, weekly schedule (day names, viewer-local hours), targeting and placements (validated with Reddit at draft time), landing URL and comment changes with old → new previews, budget cap and bid-increase guards |
218
+ | `draft_reddit_campaign` / `draft_reddit_ad_group` / `draft_reddit_ad` | Create campaign → ad group (pixel + targeting required) → post + ad, or promote an existing post with `post_id`. Everything is created **PAUSED**. |
219
+
220
+ > **Setup for Reddit Ads tools** — In Reddit Ads Manager open **Business Manager → Developer Application → Create app** (business admins only; no approval wait). Register the redirect URL exactly as `http://localhost:8765/callback`, then run `adloop init` and complete the Reddit Ads step: it opens Reddit's consent page (scopes `adsread` + `adsedit`, permanent grant), stores the refresh token at `~/.adloop/reddit_token.json`, and lets you pick the default ad account. Reddit rate-limits per user (reporting: 60 requests/min) and requires a descriptive User-Agent, which AdLoop builds from your app id and Reddit username. Reddit has no validate-only mode, so `confirm_and_apply(dry_run=true)` re-reads the target and re-checks the safety caps instead.
221
+
174
222
  ### Planning Tools
175
223
 
176
224
  | Tool | What It Does |
@@ -420,6 +468,10 @@ All configuration lives in `~/.adloop/config.yaml`. See [`config.yaml.example`](
420
468
  | `ads` | `developer_token` | — | Your Google Ads API developer token |
421
469
  | `ads` | `customer_id` | — | Default Google Ads customer ID (auto-discovered by `adloop init`) |
422
470
  | `ads` | `login_customer_id` | — | Your MCC account ID |
471
+ | `reddit` | `client_id` / `client_secret` | *(empty)* | Your Reddit developer app (Business Manager → Developer Application) |
472
+ | `reddit` | `ad_account_id` | *(empty)* | Default Reddit ad account for every Reddit tool (picked by `adloop init`) |
473
+ | `reddit` | `username` | *(empty)* | Your Reddit username, used only in the User-Agent Reddit requires |
474
+ | `reddit` | `token_path` | `~/.adloop/reddit_token.json` | Where the Reddit refresh token is stored |
423
475
  | `safety` | `max_daily_budget` | `50.00` | Maximum allowed daily budget per campaign |
424
476
  | `safety` | `require_dry_run` | `true` | Force all writes to dry-run mode |
425
477
  | `safety` | `two_phase_apply` | `false` | Refuse real applies until the plan had a dry-run pass |
@@ -442,6 +494,7 @@ Most MCP clients (claude.ai, ChatGPT, Cursor, …) load **every tool schema into
442
494
  | `gsc` | Search Console reads |
443
495
  | `web` | PageSpeed / Core Web Vitals |
444
496
  | `merchant` | Merchant Center feed health |
497
+ | `reddit` | Reddit Ads reads, writes, and planning |
445
498
 
446
499
  `health_check` and `confirm_and_apply` are always included, whatever you select. Unset = the full catalog; unknown names fail at startup with the valid list. The effect is real: `ads,ga4` drops the session cost to ~13k tokens, and a `ga4`-only client pays ~2k — nearly 90% less. Toolsets are per *client*, not per install: one AdLoop config can serve a trimmed Cursor and a full-catalog Claude Code side by side.
447
500
 
@@ -452,7 +505,7 @@ On [AdLoop Cloud](https://getadloop.com), the same feature is per API key: pick
452
505
  ```
453
506
  src/adloop/
454
507
  ├── __init__.py # Entry point — routes 'adloop init' to wizard, otherwise starts MCP server
455
- ├── server.py # FastMCP server — 67 tool registrations with safety annotations
508
+ ├── server.py # FastMCP server — every tool registration with safety annotations and toolset tags
456
509
  ├── config.py # Config loader (~/.adloop/config.yaml)
457
510
  ├── auth.py # OAuth 2.0 flow (user-supplied credentials, headless fallback) + service accounts; GA4 / Ads / GTM scopes
458
511
  ├── cli.py # Interactive 'adloop init' setup wizard
@@ -472,6 +525,11 @@ src/adloop/
472
525
  ├── gtm/
473
526
  │ ├── client.py # Google Tag Manager API v2 client
474
527
  │ └── read.py # Live container fetching, tag/trigger/variable parsing, workspace diff, version history
528
+ ├── reddit/
529
+ │ ├── auth.py # Reddit OAuth2 (own app, permanent refresh token, loopback flow for adloop init)
530
+ │ ├── client.py # Reddit Ads API v3 REST client — bearer refresh, per-user rate limits, pagination
531
+ │ ├── read.py # Accounts, campaigns, ad groups, ads, performance reports, pixels, targeting lookups
532
+ │ └── write.py # Draft/preflight/apply for status, budget, bid, targeting, and PAUSED creation
475
533
  └── safety/
476
534
  ├── guards.py # Budget caps, bid limits, blocked operations, Broad Match safety
477
535
  ├── preview.py # Change plans and previews
@@ -1,36 +1,10 @@
1
- Metadata-Version: 2.3
2
- Name: adloop
3
- Version: 0.13.3
4
- Summary: The AI command center for Google Ads, GA4, and tracking code.
5
- Keywords: mcp,google-ads,google-analytics,ga4,cursor,marketing
6
- Author: Daniel Klose
7
- Author-email: Daniel Klose <info@daniel-klose.com>
8
- License: MIT
9
- Requires-Dist: fastmcp>=3.0.0
10
- Requires-Dist: google-ads>=31.1.0
11
- Requires-Dist: google-analytics-data>=0.20.0
12
- Requires-Dist: google-analytics-admin>=0.27.0
13
- Requires-Dist: google-api-python-client>=2.100.0
14
- Requires-Dist: google-auth-oauthlib>=1.0.0
15
- Requires-Dist: google-api-python-client>=2.0.0
16
- Requires-Dist: pyyaml>=6.0
17
- Requires-Dist: pytest>=8.0 ; extra == 'dev'
18
- Requires-Dist: pytest-asyncio>=0.23 ; extra == 'dev'
19
- Requires-Python: >=3.11
20
- Project-URL: Homepage, https://github.com/kLOsk/adloop
21
- Project-URL: Repository, https://github.com/kLOsk/adloop
22
- Project-URL: Issues, https://github.com/kLOsk/adloop/issues
23
- Project-URL: Changelog, https://github.com/kLOsk/adloop/releases
24
- Provides-Extra: dev
25
- Description-Content-Type: text/markdown
26
-
27
1
  <!-- mcp-name: com.getadloop/adloop -->
28
2
 
29
3
  <div align="center">
30
4
 
31
5
  # AdLoop
32
6
 
33
- **The AI command center for Google Ads, GA4, and tracking code.**
7
+ **The AI command center for Google Ads, Reddit Ads, GA4, and tracking code.**
34
8
 
35
9
  [![PyPI](https://img.shields.io/pypi/v/adloop.svg)](https://pypi.org/project/adloop/)
36
10
  [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
@@ -40,7 +14,7 @@ Description-Content-Type: text/markdown
40
14
  [![GA4 Data API](https://img.shields.io/badge/GA4-Data%20API-E37400.svg?logo=google-analytics&logoColor=white)](https://developers.google.com/analytics/devguides/reporting/data/v1)
41
15
  [![GitHub stars](https://img.shields.io/github/stars/kLOsk/adloop?style=social)](https://github.com/kLOsk/adloop)
42
16
 
43
- An MCP server that gives your AI assistant read + write access to Google Ads and GA4 — with safety guardrails that prevent accidental spend.
17
+ An MCP server that gives your AI assistant read + write access to Google Ads, Reddit Ads and GA4 — with safety guardrails that prevent accidental spend.
44
18
 
45
19
  **[☁️ Skip the setup — use AdLoop Cloud (free plan, no card)](https://getadloop.com)** &nbsp;·&nbsp; or self-host: `pip install adloop`
46
20
 
@@ -197,6 +171,27 @@ These tools read the live GTM container and join it with the codebase + GA4 to f
197
171
 
198
172
  > **Setup for GSC tools** — Enable the **Search Console API** in your GCP project. Upgrading OAuth users must re-authorize once for the new scope (delete `~/.adloop/token.json`, run any tool). The killer combo: cross-reference organic queries with `get_keyword_performance` to find paid/organic cannibalization and untapped keyword opportunities.
199
173
 
174
+ ### Reddit Ads Tools
175
+
176
+ A second ad platform, same safety model. Reddit is a separate connection: its own developer app, its own OAuth, no developer token and no approval process. Every tool takes `ad_account_id` (defaults to `reddit.ad_account_id`).
177
+
178
+ | Tool | What It Does |
179
+ |------|-------------|
180
+ | `list_reddit_accounts` | Discover businesses and ad accounts (currency, time zone, approval state) |
181
+ | `list_reddit_funding_instruments` | Billing instruments and posting profiles — prerequisites for creating campaigns and ads |
182
+ | `get_reddit_campaigns` / `get_reddit_ad_groups` / `get_reddit_ads` | Structure with configured vs effective status, budgets, bids, pixel, targeting, weekly schedule, rejection reasons; `include_copy` returns each ad's post (headline, body, destination, media) |
183
+ | `get_reddit_performance` | Spend, clicks, CTR, CPC, conversions, CPA, ROAS per account/campaign/ad group/ad, optional breakdown (date, country, community, keyword, placement, …), compact mode with insights |
184
+ | `run_reddit_report` | Raw reports endpoint for any metric (REACH, video, per-event conversions) |
185
+ | `get_reddit_pixels` | Pixels and when each event last fired — flags ad groups optimizing for events the pixel never sent |
186
+ | `search_reddit_targeting` | Communities, interests, geolocations, languages, keyword suggestions, and Reddit's related-community suggestions (by seed communities or website) |
187
+ | `get_reddit_account_history` | Who changed what and when: field, before/after, member |
188
+ | `estimate_reddit_ad_group` | Audience size, delivery estimate and suggested bid range for a planned ad group (Reddit's counterpart of `estimate_budget`) |
189
+ | `pause_reddit_entity` / `enable_reddit_entity` / `remove_reddit_entity` | Status changes through the preview gate (remove = ARCHIVE, irreversible, double-confirmed) |
190
+ | `update_reddit_campaign` / `update_reddit_ad_group` / `update_reddit_ad` | Budget, bid, run dates, weekly schedule (day names, viewer-local hours), targeting and placements (validated with Reddit at draft time), landing URL and comment changes with old → new previews, budget cap and bid-increase guards |
191
+ | `draft_reddit_campaign` / `draft_reddit_ad_group` / `draft_reddit_ad` | Create campaign → ad group (pixel + targeting required) → post + ad, or promote an existing post with `post_id`. Everything is created **PAUSED**. |
192
+
193
+ > **Setup for Reddit Ads tools** — In Reddit Ads Manager open **Business Manager → Developer Application → Create app** (business admins only; no approval wait). Register the redirect URL exactly as `http://localhost:8765/callback`, then run `adloop init` and complete the Reddit Ads step: it opens Reddit's consent page (scopes `adsread` + `adsedit`, permanent grant), stores the refresh token at `~/.adloop/reddit_token.json`, and lets you pick the default ad account. Reddit rate-limits per user (reporting: 60 requests/min) and requires a descriptive User-Agent, which AdLoop builds from your app id and Reddit username. Reddit has no validate-only mode, so `confirm_and_apply(dry_run=true)` re-reads the target and re-checks the safety caps instead.
194
+
200
195
  ### Planning Tools
201
196
 
202
197
  | Tool | What It Does |
@@ -446,6 +441,10 @@ All configuration lives in `~/.adloop/config.yaml`. See [`config.yaml.example`](
446
441
  | `ads` | `developer_token` | — | Your Google Ads API developer token |
447
442
  | `ads` | `customer_id` | — | Default Google Ads customer ID (auto-discovered by `adloop init`) |
448
443
  | `ads` | `login_customer_id` | — | Your MCC account ID |
444
+ | `reddit` | `client_id` / `client_secret` | *(empty)* | Your Reddit developer app (Business Manager → Developer Application) |
445
+ | `reddit` | `ad_account_id` | *(empty)* | Default Reddit ad account for every Reddit tool (picked by `adloop init`) |
446
+ | `reddit` | `username` | *(empty)* | Your Reddit username, used only in the User-Agent Reddit requires |
447
+ | `reddit` | `token_path` | `~/.adloop/reddit_token.json` | Where the Reddit refresh token is stored |
449
448
  | `safety` | `max_daily_budget` | `50.00` | Maximum allowed daily budget per campaign |
450
449
  | `safety` | `require_dry_run` | `true` | Force all writes to dry-run mode |
451
450
  | `safety` | `two_phase_apply` | `false` | Refuse real applies until the plan had a dry-run pass |
@@ -468,6 +467,7 @@ Most MCP clients (claude.ai, ChatGPT, Cursor, …) load **every tool schema into
468
467
  | `gsc` | Search Console reads |
469
468
  | `web` | PageSpeed / Core Web Vitals |
470
469
  | `merchant` | Merchant Center feed health |
470
+ | `reddit` | Reddit Ads reads, writes, and planning |
471
471
 
472
472
  `health_check` and `confirm_and_apply` are always included, whatever you select. Unset = the full catalog; unknown names fail at startup with the valid list. The effect is real: `ads,ga4` drops the session cost to ~13k tokens, and a `ga4`-only client pays ~2k — nearly 90% less. Toolsets are per *client*, not per install: one AdLoop config can serve a trimmed Cursor and a full-catalog Claude Code side by side.
473
473
 
@@ -478,7 +478,7 @@ On [AdLoop Cloud](https://getadloop.com), the same feature is per API key: pick
478
478
  ```
479
479
  src/adloop/
480
480
  ├── __init__.py # Entry point — routes 'adloop init' to wizard, otherwise starts MCP server
481
- ├── server.py # FastMCP server — 67 tool registrations with safety annotations
481
+ ├── server.py # FastMCP server — every tool registration with safety annotations and toolset tags
482
482
  ├── config.py # Config loader (~/.adloop/config.yaml)
483
483
  ├── auth.py # OAuth 2.0 flow (user-supplied credentials, headless fallback) + service accounts; GA4 / Ads / GTM scopes
484
484
  ├── cli.py # Interactive 'adloop init' setup wizard
@@ -498,6 +498,11 @@ src/adloop/
498
498
  ├── gtm/
499
499
  │ ├── client.py # Google Tag Manager API v2 client
500
500
  │ └── read.py # Live container fetching, tag/trigger/variable parsing, workspace diff, version history
501
+ ├── reddit/
502
+ │ ├── auth.py # Reddit OAuth2 (own app, permanent refresh token, loopback flow for adloop init)
503
+ │ ├── client.py # Reddit Ads API v3 REST client — bearer refresh, per-user rate limits, pagination
504
+ │ ├── read.py # Accounts, campaigns, ad groups, ads, performance reports, pixels, targeting lookups
505
+ │ └── write.py # Draft/preflight/apply for status, budget, bid, targeting, and PAUSED creation
501
506
  └── safety/
502
507
  ├── guards.py # Budget caps, bid limits, blocked operations, Broad Match safety
503
508
  ├── preview.py # Change plans and previews
@@ -1,12 +1,13 @@
1
1
  [project]
2
2
  name = "adloop"
3
- version = "0.13.3"
4
- description = "The AI command center for Google Ads, GA4, and tracking code."
3
+ version = "0.14.0"
4
+ description = "The AI command center for Google Ads, Reddit Ads, GA4, and tracking code."
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.11"
7
7
  keywords = [
8
8
  "mcp",
9
9
  "google-ads",
10
+ "reddit-ads",
10
11
  "google-analytics",
11
12
  "ga4",
12
13
  "cursor",
@@ -21,6 +22,7 @@ dependencies = [
21
22
  "google-auth-oauthlib>=1.0.0",
22
23
  "google-api-python-client>=2.0.0",
23
24
  "pyyaml>=6.0",
25
+ "requests>=2.31",
24
26
  ]
25
27
 
26
28
  [[project.authors]]
@@ -1,14 +1,14 @@
1
1
  [project]
2
2
  name = "adloop"
3
- version = "0.13.3"
4
- description = "The AI command center for Google Ads, GA4, and tracking code."
3
+ version = "0.14.0"
4
+ description = "The AI command center for Google Ads, Reddit Ads, GA4, and tracking code."
5
5
  readme = "README.md"
6
6
  authors = [
7
7
  { name = "Daniel Klose", email = "info@daniel-klose.com" }
8
8
  ]
9
9
  requires-python = ">=3.11"
10
10
  license = { text = "MIT" }
11
- keywords = ["mcp", "google-ads", "google-analytics", "ga4", "cursor", "marketing"]
11
+ keywords = ["mcp", "google-ads", "reddit-ads", "google-analytics", "ga4", "cursor", "marketing"]
12
12
  dependencies = [
13
13
  "fastmcp>=3.0.0",
14
14
  "google-ads>=31.1.0",
@@ -18,6 +18,9 @@ dependencies = [
18
18
  "google-auth-oauthlib>=1.0.0",
19
19
  "google-api-python-client>=2.0.0",
20
20
  "pyyaml>=6.0",
21
+ # Reddit Ads has no SDK; the REST client (adloop.reddit.client) and the
22
+ # PageSpeed helper call requests directly.
23
+ "requests>=2.31",
21
24
  ]
22
25
 
23
26
  [project.urls]