adloop 0.29.0__tar.gz → 0.29.1__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 (72) hide show
  1. {adloop-0.29.0 → adloop-0.29.1}/PKG-INFO +1 -1
  2. {adloop-0.29.0 → adloop-0.29.1}/pyproject.toml +1 -1
  3. {adloop-0.29.0 → adloop-0.29.1}/pyproject.toml.orig +1 -1
  4. {adloop-0.29.0 → adloop-0.29.1}/src/adloop/server.py +9 -2
  5. {adloop-0.29.0 → adloop-0.29.1}/README.md +0 -0
  6. {adloop-0.29.0 → adloop-0.29.1}/src/adloop/__init__.py +0 -0
  7. {adloop-0.29.0 → adloop-0.29.1}/src/adloop/__main__.py +0 -0
  8. {adloop-0.29.0 → adloop-0.29.1}/src/adloop/_mcp_patches.py +0 -0
  9. {adloop-0.29.0 → adloop-0.29.1}/src/adloop/ads/__init__.py +0 -0
  10. {adloop-0.29.0 → adloop-0.29.1}/src/adloop/ads/ai_max.py +0 -0
  11. {adloop-0.29.0 → adloop-0.29.1}/src/adloop/ads/audiences.py +0 -0
  12. {adloop-0.29.0 → adloop-0.29.1}/src/adloop/ads/brands.py +0 -0
  13. {adloop-0.29.0 → adloop-0.29.1}/src/adloop/ads/client.py +0 -0
  14. {adloop-0.29.0 → adloop-0.29.1}/src/adloop/ads/conversion_actions.py +0 -0
  15. {adloop-0.29.0 → adloop-0.29.1}/src/adloop/ads/currency.py +0 -0
  16. {adloop-0.29.0 → adloop-0.29.1}/src/adloop/ads/custom_conversion_goals.py +0 -0
  17. {adloop-0.29.0 → adloop-0.29.1}/src/adloop/ads/enums.py +0 -0
  18. {adloop-0.29.0 → adloop-0.29.1}/src/adloop/ads/forecast.py +0 -0
  19. {adloop-0.29.0 → adloop-0.29.1}/src/adloop/ads/gaql.py +0 -0
  20. {adloop-0.29.0 → adloop-0.29.1}/src/adloop/ads/image_fetch.py +0 -0
  21. {adloop-0.29.0 → adloop-0.29.1}/src/adloop/ads/pmax.py +0 -0
  22. {adloop-0.29.0 → adloop-0.29.1}/src/adloop/ads/read.py +0 -0
  23. {adloop-0.29.0 → adloop-0.29.1}/src/adloop/ads/shopping.py +0 -0
  24. {adloop-0.29.0 → adloop-0.29.1}/src/adloop/ads/validate_only.py +0 -0
  25. {adloop-0.29.0 → adloop-0.29.1}/src/adloop/ads/write.py +0 -0
  26. {adloop-0.29.0 → adloop-0.29.1}/src/adloop/auth.py +0 -0
  27. {adloop-0.29.0 → adloop-0.29.1}/src/adloop/cli.py +0 -0
  28. {adloop-0.29.0 → adloop-0.29.1}/src/adloop/config.py +0 -0
  29. {adloop-0.29.0 → adloop-0.29.1}/src/adloop/crossref.py +0 -0
  30. {adloop-0.29.0 → adloop-0.29.1}/src/adloop/diagnostics.py +0 -0
  31. {adloop-0.29.0 → adloop-0.29.1}/src/adloop/ga4/__init__.py +0 -0
  32. {adloop-0.29.0 → adloop-0.29.1}/src/adloop/ga4/client.py +0 -0
  33. {adloop-0.29.0 → adloop-0.29.1}/src/adloop/ga4/reports.py +0 -0
  34. {adloop-0.29.0 → adloop-0.29.1}/src/adloop/ga4/tracking.py +0 -0
  35. {adloop-0.29.0 → adloop-0.29.1}/src/adloop/ga4/write.py +0 -0
  36. {adloop-0.29.0 → adloop-0.29.1}/src/adloop/gsc/__init__.py +0 -0
  37. {adloop-0.29.0 → adloop-0.29.1}/src/adloop/gsc/client.py +0 -0
  38. {adloop-0.29.0 → adloop-0.29.1}/src/adloop/gsc/reports.py +0 -0
  39. {adloop-0.29.0 → adloop-0.29.1}/src/adloop/gtm/__init__.py +0 -0
  40. {adloop-0.29.0 → adloop-0.29.1}/src/adloop/gtm/client.py +0 -0
  41. {adloop-0.29.0 → adloop-0.29.1}/src/adloop/gtm/entities.py +0 -0
  42. {adloop-0.29.0 → adloop-0.29.1}/src/adloop/gtm/read.py +0 -0
  43. {adloop-0.29.0 → adloop-0.29.1}/src/adloop/gtm/write.py +0 -0
  44. {adloop-0.29.0 → adloop-0.29.1}/src/adloop/merchant/__init__.py +0 -0
  45. {adloop-0.29.0 → adloop-0.29.1}/src/adloop/merchant/client.py +0 -0
  46. {adloop-0.29.0 → adloop-0.29.1}/src/adloop/merchant/read.py +0 -0
  47. {adloop-0.29.0 → adloop-0.29.1}/src/adloop/pagespeed.py +0 -0
  48. {adloop-0.29.0 → adloop-0.29.1}/src/adloop/reddit/__init__.py +0 -0
  49. {adloop-0.29.0 → adloop-0.29.1}/src/adloop/reddit/auth.py +0 -0
  50. {adloop-0.29.0 → adloop-0.29.1}/src/adloop/reddit/client.py +0 -0
  51. {adloop-0.29.0 → adloop-0.29.1}/src/adloop/reddit/read.py +0 -0
  52. {adloop-0.29.0 → adloop-0.29.1}/src/adloop/reddit/schedule.py +0 -0
  53. {adloop-0.29.0 → adloop-0.29.1}/src/adloop/reddit/write.py +0 -0
  54. {adloop-0.29.0 → adloop-0.29.1}/src/adloop/rules/__init__.py +0 -0
  55. {adloop-0.29.0 → adloop-0.29.1}/src/adloop/rules/adloop.md +0 -0
  56. {adloop-0.29.0 → adloop-0.29.1}/src/adloop/rules/commands/analyze-performance.md +0 -0
  57. {adloop-0.29.0 → adloop-0.29.1}/src/adloop/rules/commands/budget-plan.md +0 -0
  58. {adloop-0.29.0 → adloop-0.29.1}/src/adloop/rules/commands/create-ad.md +0 -0
  59. {adloop-0.29.0 → adloop-0.29.1}/src/adloop/rules/commands/create-campaign.md +0 -0
  60. {adloop-0.29.0 → adloop-0.29.1}/src/adloop/rules/commands/diagnose-tracking.md +0 -0
  61. {adloop-0.29.0 → adloop-0.29.1}/src/adloop/rules/commands/optimize-campaign.md +0 -0
  62. {adloop-0.29.0 → adloop-0.29.1}/src/adloop/rules_install.py +0 -0
  63. {adloop-0.29.0 → adloop-0.29.1}/src/adloop/runtime.py +0 -0
  64. {adloop-0.29.0 → adloop-0.29.1}/src/adloop/safety/__init__.py +0 -0
  65. {adloop-0.29.0 → adloop-0.29.1}/src/adloop/safety/approval.py +0 -0
  66. {adloop-0.29.0 → adloop-0.29.1}/src/adloop/safety/approval_card.html +0 -0
  67. {adloop-0.29.0 → adloop-0.29.1}/src/adloop/safety/audit.py +0 -0
  68. {adloop-0.29.0 → adloop-0.29.1}/src/adloop/safety/guards.py +0 -0
  69. {adloop-0.29.0 → adloop-0.29.1}/src/adloop/safety/preview.py +0 -0
  70. {adloop-0.29.0 → adloop-0.29.1}/src/adloop/tracking.py +0 -0
  71. {adloop-0.29.0 → adloop-0.29.1}/src/adloop/upload_card.html +0 -0
  72. {adloop-0.29.0 → adloop-0.29.1}/src/adloop/uploads.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: adloop
3
- Version: 0.29.0
3
+ Version: 0.29.1
4
4
  Summary: The AI command center for Google Ads, Reddit Ads, GA4, and tracking code.
5
5
  Keywords: mcp,google-ads,reddit-ads,google-analytics,ga4,cursor,marketing
6
6
  Author: Daniel Klose
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "adloop"
3
- version = "0.29.0"
3
+ version = "0.29.1"
4
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"
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "adloop"
3
- version = "0.29.0"
3
+ version = "0.29.1"
4
4
  description = "The AI command center for Google Ads, Reddit Ads, GA4, and tracking code."
5
5
  readme = "README.md"
6
6
  authors = [
@@ -252,11 +252,18 @@ _APP_ONLY_TOOLS = {
252
252
 
253
253
 
254
254
  class _AppOnlyToolsForCardClients(Middleware):
255
- """List and run app-only tools only for apps that render cards.
255
+ """List app-only tools only to apps that render cards.
256
256
 
257
257
  The MCP Apps spec makes a card-capable app hide app-only tools from its
258
258
  model. An app without the extension knows nothing about that rule and
259
259
  would hand them to its model, so they are not offered to it at all.
260
+
261
+ Calls are a different matter. Some apps send a card's own click without
262
+ the extension declaration (the Claude iOS app does), so refusing every
263
+ call from an "app without cards" breaks the card itself. approve_change
264
+ needs no such check: it only acts on the plan's one-time code, which
265
+ goes to the card and never into the model's context. The upload card's
266
+ tool has no code of its own and keeps the check.
260
267
  """
261
268
 
262
269
  async def on_list_tools(self, context, call_next):
@@ -267,7 +274,7 @@ class _AppOnlyToolsForCardClients(Middleware):
267
274
 
268
275
  async def on_call_tool(self, context, call_next):
269
276
  card = _APP_ONLY_TOOLS.get(context.message.name)
270
- if card and not client_shows_cards():
277
+ if card and context.message.name != APPROVE_TOOL and not client_shows_cards():
271
278
  from fastmcp.exceptions import ToolError
272
279
 
273
280
  raise ToolError(f"{context.message.name} can only be called from the {card}.")
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes