meta-ads-mcp 0.7.0__tar.gz → 0.7.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 (59) hide show
  1. {meta_ads_mcp-0.7.0 → meta_ads_mcp-0.7.1}/PKG-INFO +1 -1
  2. {meta_ads_mcp-0.7.0 → meta_ads_mcp-0.7.1}/meta_ads_mcp/__init__.py +1 -1
  3. {meta_ads_mcp-0.7.0 → meta_ads_mcp-0.7.1}/meta_ads_mcp/core/authentication.py +77 -32
  4. {meta_ads_mcp-0.7.0 → meta_ads_mcp-0.7.1}/pyproject.toml +1 -1
  5. {meta_ads_mcp-0.7.0 → meta_ads_mcp-0.7.1}/.github/workflows/publish.yml +0 -0
  6. {meta_ads_mcp-0.7.0 → meta_ads_mcp-0.7.1}/.github/workflows/test.yml +0 -0
  7. {meta_ads_mcp-0.7.0 → meta_ads_mcp-0.7.1}/.gitignore +0 -0
  8. {meta_ads_mcp-0.7.0 → meta_ads_mcp-0.7.1}/CUSTOM_META_APP.md +0 -0
  9. {meta_ads_mcp-0.7.0 → meta_ads_mcp-0.7.1}/Dockerfile +0 -0
  10. {meta_ads_mcp-0.7.0 → meta_ads_mcp-0.7.1}/LICENSE +0 -0
  11. {meta_ads_mcp-0.7.0 → meta_ads_mcp-0.7.1}/LOCAL_INSTALLATION.md +0 -0
  12. {meta_ads_mcp-0.7.0 → meta_ads_mcp-0.7.1}/META_API_NOTES.md +0 -0
  13. {meta_ads_mcp-0.7.0 → meta_ads_mcp-0.7.1}/README.md +0 -0
  14. {meta_ads_mcp-0.7.0 → meta_ads_mcp-0.7.1}/RELEASE.md +0 -0
  15. {meta_ads_mcp-0.7.0 → meta_ads_mcp-0.7.1}/STREAMABLE_HTTP_SETUP.md +0 -0
  16. {meta_ads_mcp-0.7.0 → meta_ads_mcp-0.7.1}/examples/README.md +0 -0
  17. {meta_ads_mcp-0.7.0 → meta_ads_mcp-0.7.1}/examples/example_http_client.py +0 -0
  18. {meta_ads_mcp-0.7.0 → meta_ads_mcp-0.7.1}/future_improvements.md +0 -0
  19. {meta_ads_mcp-0.7.0 → meta_ads_mcp-0.7.1}/images/meta-ads-example.png +0 -0
  20. {meta_ads_mcp-0.7.0 → meta_ads_mcp-0.7.1}/meta_ads_auth.sh +0 -0
  21. {meta_ads_mcp-0.7.0 → meta_ads_mcp-0.7.1}/meta_ads_mcp/__main__.py +0 -0
  22. {meta_ads_mcp-0.7.0 → meta_ads_mcp-0.7.1}/meta_ads_mcp/core/__init__.py +0 -0
  23. {meta_ads_mcp-0.7.0 → meta_ads_mcp-0.7.1}/meta_ads_mcp/core/accounts.py +0 -0
  24. {meta_ads_mcp-0.7.0 → meta_ads_mcp-0.7.1}/meta_ads_mcp/core/ads.py +0 -0
  25. {meta_ads_mcp-0.7.0 → meta_ads_mcp-0.7.1}/meta_ads_mcp/core/ads_library.py +0 -0
  26. {meta_ads_mcp-0.7.0 → meta_ads_mcp-0.7.1}/meta_ads_mcp/core/adsets.py +0 -0
  27. {meta_ads_mcp-0.7.0 → meta_ads_mcp-0.7.1}/meta_ads_mcp/core/api.py +0 -0
  28. {meta_ads_mcp-0.7.0 → meta_ads_mcp-0.7.1}/meta_ads_mcp/core/auth.py +0 -0
  29. {meta_ads_mcp-0.7.0 → meta_ads_mcp-0.7.1}/meta_ads_mcp/core/budget_schedules.py +0 -0
  30. {meta_ads_mcp-0.7.0 → meta_ads_mcp-0.7.1}/meta_ads_mcp/core/callback_server.py +0 -0
  31. {meta_ads_mcp-0.7.0 → meta_ads_mcp-0.7.1}/meta_ads_mcp/core/campaigns.py +0 -0
  32. {meta_ads_mcp-0.7.0 → meta_ads_mcp-0.7.1}/meta_ads_mcp/core/duplication.py +0 -0
  33. {meta_ads_mcp-0.7.0 → meta_ads_mcp-0.7.1}/meta_ads_mcp/core/http_auth_integration.py +0 -0
  34. {meta_ads_mcp-0.7.0 → meta_ads_mcp-0.7.1}/meta_ads_mcp/core/insights.py +0 -0
  35. {meta_ads_mcp-0.7.0 → meta_ads_mcp-0.7.1}/meta_ads_mcp/core/openai_deep_research.py +0 -0
  36. {meta_ads_mcp-0.7.0 → meta_ads_mcp-0.7.1}/meta_ads_mcp/core/pipeboard_auth.py +0 -0
  37. {meta_ads_mcp-0.7.0 → meta_ads_mcp-0.7.1}/meta_ads_mcp/core/reports.py +0 -0
  38. {meta_ads_mcp-0.7.0 → meta_ads_mcp-0.7.1}/meta_ads_mcp/core/resources.py +0 -0
  39. {meta_ads_mcp-0.7.0 → meta_ads_mcp-0.7.1}/meta_ads_mcp/core/server.py +0 -0
  40. {meta_ads_mcp-0.7.0 → meta_ads_mcp-0.7.1}/meta_ads_mcp/core/targeting.py +0 -0
  41. {meta_ads_mcp-0.7.0 → meta_ads_mcp-0.7.1}/meta_ads_mcp/core/utils.py +0 -0
  42. {meta_ads_mcp-0.7.0 → meta_ads_mcp-0.7.1}/requirements.txt +0 -0
  43. {meta_ads_mcp-0.7.0 → meta_ads_mcp-0.7.1}/setup.py +0 -0
  44. {meta_ads_mcp-0.7.0 → meta_ads_mcp-0.7.1}/smithery.yaml +0 -0
  45. {meta_ads_mcp-0.7.0 → meta_ads_mcp-0.7.1}/tests/README.md +0 -0
  46. {meta_ads_mcp-0.7.0 → meta_ads_mcp-0.7.1}/tests/README_REGRESSION_TESTS.md +0 -0
  47. {meta_ads_mcp-0.7.0 → meta_ads_mcp-0.7.1}/tests/__init__.py +0 -0
  48. {meta_ads_mcp-0.7.0 → meta_ads_mcp-0.7.1}/tests/conftest.py +0 -0
  49. {meta_ads_mcp-0.7.0 → meta_ads_mcp-0.7.1}/tests/test_account_search.py +0 -0
  50. {meta_ads_mcp-0.7.0 → meta_ads_mcp-0.7.1}/tests/test_duplication.py +0 -0
  51. {meta_ads_mcp-0.7.0 → meta_ads_mcp-0.7.1}/tests/test_duplication_regression.py +0 -0
  52. {meta_ads_mcp-0.7.0 → meta_ads_mcp-0.7.1}/tests/test_get_ad_creatives_fix.py +0 -0
  53. {meta_ads_mcp-0.7.0 → meta_ads_mcp-0.7.1}/tests/test_get_ad_image_regression.py +0 -0
  54. {meta_ads_mcp-0.7.0 → meta_ads_mcp-0.7.1}/tests/test_http_transport.py +0 -0
  55. {meta_ads_mcp-0.7.0 → meta_ads_mcp-0.7.1}/tests/test_integration_openai_mcp.py +0 -0
  56. {meta_ads_mcp-0.7.0 → meta_ads_mcp-0.7.1}/tests/test_openai.py +0 -0
  57. {meta_ads_mcp-0.7.0 → meta_ads_mcp-0.7.1}/tests/test_openai_mcp_deep_research.py +0 -0
  58. {meta_ads_mcp-0.7.0 → meta_ads_mcp-0.7.1}/tests/test_targeting.py +0 -0
  59. {meta_ads_mcp-0.7.0 → meta_ads_mcp-0.7.1}/tests/test_targeting_search_e2e.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: meta-ads-mcp
3
- Version: 0.7.0
3
+ Version: 0.7.1
4
4
  Summary: Model Context Protocol (MCP) plugin for interacting with Meta Ads API
5
5
  Project-URL: Homepage, https://github.com/pipeboard-co/meta-ads-mcp
6
6
  Project-URL: Bug Tracker, https://github.com/pipeboard-co/meta-ads-mcp/issues
@@ -7,7 +7,7 @@ with the Claude LLM.
7
7
 
8
8
  from meta_ads_mcp.core.server import main
9
9
 
10
- __version__ = "0.7.0"
10
+ __version__ = "0.7.1"
11
11
 
12
12
  __all__ = [
13
13
  'get_ad_accounts',
@@ -1,4 +1,27 @@
1
- """Authentication-specific functionality for Meta Ads API."""
1
+ """Authentication-specific functionality for Meta Ads API.
2
+
3
+ The Meta Ads MCP server supports three authentication modes:
4
+
5
+ 1. **Development/Local Mode** (default)
6
+ - Uses local callback server on localhost:8080+ for OAuth redirect
7
+ - Requires META_ADS_DISABLE_CALLBACK_SERVER to NOT be set
8
+ - Best for local development and testing
9
+
10
+ 2. **Production with API Token**
11
+ - Uses PIPEBOARD_API_TOKEN for server-to-server authentication
12
+ - Bypasses OAuth flow entirely
13
+ - Best for server deployments with pre-configured tokens
14
+
15
+ 3. **Production OAuth Flow** (NEW)
16
+ - Uses Pipeboard OAuth endpoints for dynamic client registration
17
+ - Triggered when META_ADS_DISABLE_CALLBACK_SERVER is set but no PIPEBOARD_API_TOKEN
18
+ - Supports MCP clients that implement OAuth 2.0 discovery
19
+
20
+ Environment Variables:
21
+ - PIPEBOARD_API_TOKEN: Enables mode 2 (token-based auth)
22
+ - META_ADS_DISABLE_CALLBACK_SERVER: Disables local server, enables mode 3
23
+ - META_ACCESS_TOKEN: Direct Meta token (fallback)
24
+ """
2
25
 
3
26
  import json
4
27
  import asyncio
@@ -27,41 +50,49 @@ async def get_login_link(access_token: str = None) -> str:
27
50
  """
28
51
  # Check if we're using pipeboard authentication
29
52
  using_pipeboard = bool(os.environ.get("PIPEBOARD_API_TOKEN", ""))
53
+ callback_server_disabled = bool(os.environ.get("META_ADS_DISABLE_CALLBACK_SERVER", ""))
30
54
 
31
55
  if using_pipeboard:
32
- # Handle Pipeboard authentication
33
- # Check if we have a cached token
34
- cached_token = pipeboard_auth_manager.get_access_token()
35
- token_status = "No token" if not cached_token else "Valid token"
36
-
37
- # If we already have a valid token and none was provided, just return success
38
- if cached_token and not access_token:
39
- logger.info("get_login_link called with existing valid Pipeboard token")
40
- return json.dumps({
41
- "message": "Already authenticated with Pipeboard",
42
- "token_status": token_status,
43
- "token_preview": cached_token[:10] + "..." if cached_token else None,
44
- "authentication_method": "pipeboard"
45
- }, indent=2)
46
-
47
- # Initiate the auth flow via Pipeboard
56
+ # Pipeboard token-based authentication
48
57
  try:
49
- auth_data = pipeboard_auth_manager.initiate_auth_flow()
50
- login_url = auth_data.get("loginUrl")
58
+ logger.info("Using Pipeboard token-based authentication")
51
59
 
52
- # Return a special format that helps the LLM format the response properly
53
- response = {
54
- "login_url": login_url,
55
- "token_status": token_status,
56
- "markdown_link": f"[Click here to authenticate with Meta Ads via Pipeboard]({login_url})",
57
- "message": "IMPORTANT: Please use the Markdown link format in your response to allow the user to click it.",
58
- "instructions_for_llm": "You must present this link as clickable Markdown to the user using the markdown_link format provided.",
59
- "authentication_method": "pipeboard",
60
- "token_duration": "Approximately 60 days",
61
- "note": "After authenticating, the token will be automatically saved."
62
- }
60
+ # If an access token was provided, this is likely a test - return success
61
+ if access_token:
62
+ return json.dumps({
63
+ "message": "Manual token provided",
64
+ "token_status": "Provided token",
65
+ "authentication_method": "manual_token"
66
+ }, indent=2)
67
+
68
+ # Check if Pipeboard token is working
69
+ token = pipeboard_auth_manager.get_access_token()
70
+ if token:
71
+ return json.dumps({
72
+ "message": "Already authenticated via Pipeboard",
73
+ "token_status": "Valid Pipeboard token",
74
+ "authentication_method": "pipeboard_token"
75
+ }, indent=2)
63
76
 
64
- return json.dumps(response, indent=2)
77
+ # Start Pipeboard auth flow
78
+ auth_data = pipeboard_auth_manager.initiate_auth_flow()
79
+ login_url = auth_data.get('loginUrl')
80
+
81
+ if login_url:
82
+ return json.dumps({
83
+ "login_url": login_url,
84
+ "markdown_link": f"[Click here to authenticate with Meta Ads via Pipeboard]({login_url})",
85
+ "message": "IMPORTANT: Please use the Markdown link format in your response to allow the user to click it.",
86
+ "instructions_for_llm": "You must present this link as clickable Markdown to the user using the markdown_link format provided.",
87
+ "authentication_method": "pipeboard_oauth",
88
+ "note": "After authenticating, the token will be automatically retrieved from Pipeboard."
89
+ }, indent=2)
90
+ else:
91
+ return json.dumps({
92
+ "error": "No login URL received from Pipeboard",
93
+ "authentication_method": "pipeboard_oauth_failed"
94
+ }, indent=2)
95
+
65
96
  except Exception as e:
66
97
  logger.error(f"Error initiating Pipeboard auth flow: {e}")
67
98
  return json.dumps({
@@ -69,8 +100,22 @@ async def get_login_link(access_token: str = None) -> str:
69
100
  "message": "Please check your PIPEBOARD_API_TOKEN environment variable.",
70
101
  "authentication_method": "pipeboard"
71
102
  }, indent=2)
103
+ elif callback_server_disabled:
104
+ # Production OAuth flow - use Pipeboard OAuth endpoints directly
105
+ logger.info("Production OAuth flow - using Pipeboard OAuth endpoints")
106
+
107
+ return json.dumps({
108
+ "authorization_endpoint": "https://pipeboard.co/oauth/authorize",
109
+ "token_endpoint": "https://pipeboard.co/oauth/token",
110
+ "registration_endpoint": "https://pipeboard.co/oauth/register",
111
+ "discovery_endpoint": "/.well-known/oauth-authorization-server",
112
+ "message": "Production OAuth flow - use dynamic client registration",
113
+ "instructions": "MCP clients should use the OAuth discovery endpoint to get authorization URLs",
114
+ "authentication_method": "production_oauth",
115
+ "note": "For manual authentication, clients need to register with Pipeboard OAuth service first"
116
+ }, indent=2)
72
117
  else:
73
- # Original Meta authentication flow
118
+ # Original Meta authentication flow (development/local)
74
119
  # Check if we have a cached token
75
120
  cached_token = auth_manager.get_access_token()
76
121
  token_status = "No token" if not cached_token else "Valid token"
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "meta-ads-mcp"
7
- version = "0.7.0"
7
+ version = "0.7.1"
8
8
  description = "Model Context Protocol (MCP) plugin for interacting with Meta Ads API"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes