meta-ads-mcp 1.0.13__py3-none-any.whl → 1.0.18__py3-none-any.whl

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.
meta_ads_mcp/__init__.py CHANGED
@@ -6,7 +6,7 @@ This package provides a Meta Ads MCP integration
6
6
 
7
7
  from meta_ads_mcp.core.server import main
8
8
 
9
- __version__ = "1.0.13"
9
+ __version__ = "1.0.18"
10
10
 
11
11
  __all__ = [
12
12
  'get_ad_accounts',
meta_ads_mcp/core/ads.py CHANGED
@@ -831,32 +831,18 @@ async def create_ad_creative(
831
831
  if description and descriptions:
832
832
  return json.dumps({"error": "Cannot specify both 'description' and 'descriptions'. Use 'description' for single description or 'descriptions' for multiple."}, indent=2)
833
833
 
834
- # Convert simple parameters to complex format for internal processing
835
- final_headlines = None
836
- final_descriptions = None
837
-
838
- if headline:
839
- final_headlines = [headline]
840
- elif headlines:
841
- final_headlines = headlines
842
-
843
- if description:
844
- final_descriptions = [description]
845
- elif descriptions:
846
- final_descriptions = descriptions
847
-
848
- # Validate dynamic creative parameters
849
- if final_headlines:
850
- if len(final_headlines) > 5:
834
+ # Validate dynamic creative parameters (plural forms only)
835
+ if headlines:
836
+ if len(headlines) > 5:
851
837
  return json.dumps({"error": "Maximum 5 headlines allowed for dynamic creatives"}, indent=2)
852
- for i, h in enumerate(final_headlines):
838
+ for i, h in enumerate(headlines):
853
839
  if len(h) > 40:
854
840
  return json.dumps({"error": f"Headline {i+1} exceeds 40 character limit"}, indent=2)
855
841
 
856
- if final_descriptions:
857
- if len(final_descriptions) > 5:
842
+ if descriptions:
843
+ if len(descriptions) > 5:
858
844
  return json.dumps({"error": "Maximum 5 descriptions allowed for dynamic creatives"}, indent=2)
859
- for i, d in enumerate(final_descriptions):
845
+ for i, d in enumerate(descriptions):
860
846
  if len(d) > 125:
861
847
  return json.dumps({"error": f"Description {i+1} exceeds 125 character limit"}, indent=2)
862
848
 
@@ -866,25 +852,28 @@ async def create_ad_creative(
866
852
  }
867
853
 
868
854
  # Choose between asset_feed_spec (dynamic creative) or object_story_spec (traditional)
869
- if final_headlines or final_descriptions:
870
- # Use asset_feed_spec for dynamic creatives
855
+ # ONLY use asset_feed_spec when user explicitly provides plural parameters (headlines/descriptions)
856
+ if headlines or descriptions:
857
+ # Use asset_feed_spec for dynamic creatives with multiple variants
858
+ # Structure based on Meta API working example from documentation
859
+ # ad_formats must be specified with exactly one format
871
860
  asset_feed_spec = {
872
- "ad_formats": ["SINGLE_IMAGE"],
873
861
  "images": [{"hash": image_hash}],
874
- "link_urls": [{"website_url": link_url if link_url else "https://facebook.com"}]
862
+ "link_urls": [{"website_url": link_url if link_url else "https://facebook.com"}],
863
+ "ad_formats": ["SINGLE_IMAGE"]
875
864
  }
876
865
 
877
- # Handle headlines
878
- if final_headlines:
879
- asset_feed_spec["headlines"] = [{"text": headline_text} for headline_text in final_headlines]
866
+ # Handle headlines - Meta API uses "titles" not "headlines" in asset_feed_spec
867
+ if headlines:
868
+ asset_feed_spec["titles"] = [{"text": headline_text} for headline_text in headlines]
880
869
 
881
870
  # Handle descriptions
882
- if final_descriptions:
883
- asset_feed_spec["descriptions"] = [{"text": description_text} for description_text in final_descriptions]
871
+ if descriptions:
872
+ asset_feed_spec["descriptions"] = [{"text": description_text} for description_text in descriptions]
884
873
 
885
- # Add message as primary_texts if provided
874
+ # Add message as bodies - Meta API uses "bodies" not "primary_texts" in asset_feed_spec
886
875
  if message:
887
- asset_feed_spec["primary_texts"] = [{"text": message}]
876
+ asset_feed_spec["bodies"] = [{"text": message}]
888
877
 
889
878
  # Add call_to_action_types if provided
890
879
  if call_to_action_type:
@@ -892,12 +881,13 @@ async def create_ad_creative(
892
881
 
893
882
  creative_data["asset_feed_spec"] = asset_feed_spec
894
883
 
895
- # For dynamic creatives, we need a simplified object_story_spec
884
+ # For dynamic creatives with asset_feed_spec, object_story_spec only needs page_id
885
+ # Link information is already in asset_feed_spec.link_urls
896
886
  creative_data["object_story_spec"] = {
897
887
  "page_id": page_id
898
888
  }
899
889
  else:
900
- # Use traditional object_story_spec for single creative
890
+ # Use traditional object_story_spec with link_data for simple creatives
901
891
  creative_data["object_story_spec"] = {
902
892
  "page_id": page_id,
903
893
  "link_data": {
@@ -909,17 +899,25 @@ async def create_ad_creative(
909
899
  # Add optional parameters if provided
910
900
  if message:
911
901
  creative_data["object_story_spec"]["link_data"]["message"] = message
902
+
903
+ # Add headline (singular) to link_data
904
+ if headline:
905
+ creative_data["object_story_spec"]["link_data"]["name"] = headline
906
+
907
+ # Add description (singular) to link_data
908
+ if description:
909
+ creative_data["object_story_spec"]["link_data"]["description"] = description
910
+
911
+ # Add call_to_action to link_data for simple creatives
912
+ if call_to_action_type:
913
+ creative_data["object_story_spec"]["link_data"]["call_to_action"] = {
914
+ "type": call_to_action_type
915
+ }
912
916
 
913
917
  # Add dynamic creative spec if provided
914
918
  if dynamic_creative_spec:
915
919
  creative_data["dynamic_creative_spec"] = dynamic_creative_spec
916
920
 
917
- # Only add call_to_action to object_story_spec if we're not using asset_feed_spec
918
- if call_to_action_type and "asset_feed_spec" not in creative_data:
919
- creative_data["object_story_spec"]["link_data"]["call_to_action"] = {
920
- "type": call_to_action_type
921
- }
922
-
923
921
  if instagram_actor_id:
924
922
  creative_data["instagram_actor_id"] = instagram_actor_id
925
923
 
@@ -998,32 +996,18 @@ async def update_ad_creative(
998
996
  if description and descriptions:
999
997
  return json.dumps({"error": "Cannot specify both 'description' and 'descriptions'. Use 'description' for single description or 'descriptions' for multiple."}, indent=2)
1000
998
 
1001
- # Convert simple parameters to complex format for internal processing
1002
- final_headlines = None
1003
- final_descriptions = None
1004
-
1005
- if headline:
1006
- final_headlines = [headline]
1007
- elif headlines:
1008
- final_headlines = headlines
1009
-
1010
- if description:
1011
- final_descriptions = [description]
1012
- elif descriptions:
1013
- final_descriptions = descriptions
1014
-
1015
- # Validate dynamic creative parameters
1016
- if final_headlines:
1017
- if len(final_headlines) > 5:
999
+ # Validate dynamic creative parameters (plural forms only)
1000
+ if headlines:
1001
+ if len(headlines) > 5:
1018
1002
  return json.dumps({"error": "Maximum 5 headlines allowed for dynamic creatives"}, indent=2)
1019
- for i, h in enumerate(final_headlines):
1003
+ for i, h in enumerate(headlines):
1020
1004
  if len(h) > 40:
1021
1005
  return json.dumps({"error": f"Headline {i+1} exceeds 40 character limit"}, indent=2)
1022
1006
 
1023
- if final_descriptions:
1024
- if len(final_descriptions) > 5:
1007
+ if descriptions:
1008
+ if len(descriptions) > 5:
1025
1009
  return json.dumps({"error": "Maximum 5 descriptions allowed for dynamic creatives"}, indent=2)
1026
- for i, d in enumerate(final_descriptions):
1010
+ for i, d in enumerate(descriptions):
1027
1011
  if len(d) > 125:
1028
1012
  return json.dumps({"error": f"Description {i+1} exceeds 125 character limit"}, indent=2)
1029
1013
 
@@ -1033,45 +1017,58 @@ async def update_ad_creative(
1033
1017
  if name:
1034
1018
  update_data["name"] = name
1035
1019
 
1036
- if message:
1037
- update_data["object_story_spec"] = {"link_data": {"message": message}}
1038
-
1039
- # Handle dynamic creative assets via asset_feed_spec
1040
- if final_headlines or final_descriptions or dynamic_creative_spec:
1020
+ # Choose between asset_feed_spec (dynamic creative) or object_story_spec (traditional)
1021
+ # ONLY use asset_feed_spec when user explicitly provides plural parameters (headlines/descriptions)
1022
+ if headlines or descriptions or dynamic_creative_spec:
1023
+ # Handle dynamic creative assets via asset_feed_spec
1041
1024
  asset_feed_spec = {}
1042
1025
 
1043
1026
  # Add required ad_formats field for dynamic creatives
1044
1027
  asset_feed_spec["ad_formats"] = ["SINGLE_IMAGE"]
1045
1028
 
1046
- # Handle headlines
1047
- if final_headlines:
1048
- asset_feed_spec["headlines"] = [{"text": headline_text} for headline_text in final_headlines]
1029
+ # Handle headlines - Meta API uses "titles" not "headlines" in asset_feed_spec
1030
+ if headlines:
1031
+ asset_feed_spec["titles"] = [{"text": headline_text} for headline_text in headlines]
1049
1032
 
1050
1033
  # Handle descriptions
1051
- if final_descriptions:
1052
- asset_feed_spec["descriptions"] = [{"text": description_text} for description_text in final_descriptions]
1034
+ if descriptions:
1035
+ asset_feed_spec["descriptions"] = [{"text": description_text} for description_text in descriptions]
1053
1036
 
1054
- # Add message as primary_texts if provided
1037
+ # Add message as bodies - Meta API uses "bodies" not "primary_texts" in asset_feed_spec
1055
1038
  if message:
1056
- asset_feed_spec["primary_texts"] = [{"text": message}]
1039
+ asset_feed_spec["bodies"] = [{"text": message}]
1040
+
1041
+ # Add call_to_action_types if provided
1042
+ if call_to_action_type:
1043
+ asset_feed_spec["call_to_action_types"] = [call_to_action_type]
1057
1044
 
1058
1045
  update_data["asset_feed_spec"] = asset_feed_spec
1046
+ else:
1047
+ # Use traditional object_story_spec with link_data for simple creatives
1048
+ if message or headline or description or call_to_action_type:
1049
+ update_data["object_story_spec"] = {"link_data": {}}
1050
+
1051
+ if message:
1052
+ update_data["object_story_spec"]["link_data"]["message"] = message
1053
+
1054
+ # Add headline (singular) to link_data
1055
+ if headline:
1056
+ update_data["object_story_spec"]["link_data"]["name"] = headline
1057
+
1058
+ # Add description (singular) to link_data
1059
+ if description:
1060
+ update_data["object_story_spec"]["link_data"]["description"] = description
1061
+
1062
+ # Add call_to_action to link_data for simple creatives
1063
+ if call_to_action_type:
1064
+ update_data["object_story_spec"]["link_data"]["call_to_action"] = {
1065
+ "type": call_to_action_type
1066
+ }
1059
1067
 
1060
1068
  # Add dynamic creative spec if provided
1061
1069
  if dynamic_creative_spec:
1062
1070
  update_data["dynamic_creative_spec"] = dynamic_creative_spec
1063
1071
 
1064
- # Handle call_to_action - add to asset_feed_spec if using dynamic creative, otherwise to object_story_spec
1065
- if call_to_action_type:
1066
- if "asset_feed_spec" in update_data:
1067
- update_data["asset_feed_spec"]["call_to_action_types"] = [call_to_action_type]
1068
- else:
1069
- if "object_story_spec" not in update_data:
1070
- update_data["object_story_spec"] = {"link_data": {}}
1071
- update_data["object_story_spec"]["link_data"]["call_to_action"] = {
1072
- "type": call_to_action_type
1073
- }
1074
-
1075
1072
  # Prepare the API endpoint for updating the creative
1076
1073
  endpoint = f"{creative_id}"
1077
1074
 
meta_ads_mcp/core/api.py CHANGED
@@ -6,7 +6,8 @@ import httpx
6
6
  import asyncio
7
7
  import functools
8
8
  import os
9
- from .auth import needs_authentication, get_current_access_token, auth_manager, start_callback_server, shutdown_callback_server
9
+ from . import auth
10
+ from .auth import needs_authentication, auth_manager, start_callback_server, shutdown_callback_server
10
11
  from .utils import logger
11
12
 
12
13
  # Constants
@@ -203,7 +204,7 @@ def meta_api_tool(func):
203
204
  # If access_token is not in kwargs or not kwargs['access_token'], try to get it from auth_manager
204
205
  if 'access_token' not in kwargs or not kwargs['access_token']:
205
206
  try:
206
- access_token = await get_current_access_token()
207
+ access_token = await auth.get_current_access_token()
207
208
  if access_token:
208
209
  kwargs['access_token'] = access_token
209
210
  logger.debug("Using access token from auth_manager")
@@ -29,7 +29,8 @@ from typing import Optional
29
29
  import asyncio
30
30
  import os
31
31
  from .api import meta_api_tool
32
- from .auth import start_callback_server, shutdown_callback_server, auth_manager, get_current_access_token
32
+ from . import auth
33
+ from .auth import start_callback_server, shutdown_callback_server, auth_manager
33
34
  from .server import mcp_server
34
35
  from .utils import logger, META_APP_SECRET
35
36
  from .pipeboard_auth import pipeboard_auth_manager
@@ -9,7 +9,14 @@ from .server import mcp_server
9
9
 
10
10
  @mcp_server.tool()
11
11
  @meta_api_tool
12
- async def get_campaigns(account_id: str, access_token: Optional[str] = None, limit: int = 10, status_filter: str = "", after: str = "") -> str:
12
+ async def get_campaigns(
13
+ account_id: str,
14
+ access_token: Optional[str] = None,
15
+ limit: int = 10,
16
+ status_filter: str = "",
17
+ objective_filter: Union[str, List[str]] = "",
18
+ after: str = ""
19
+ ) -> str:
13
20
  """
14
21
  Get campaigns for a Meta Ads account with optional filtering.
15
22
 
@@ -26,6 +33,11 @@ async def get_campaigns(account_id: str, access_token: Optional[str] = None, lim
26
33
  status_filter: Filter by effective status (e.g., 'ACTIVE', 'PAUSED', 'ARCHIVED').
27
34
  Maps to the 'effective_status' API parameter, which expects an array
28
35
  (this function handles the required JSON formatting). Leave empty for all statuses.
36
+ objective_filter: Filter by campaign objective(s). Can be a single objective string or a list of objectives.
37
+ Valid objectives: 'OUTCOME_AWARENESS', 'OUTCOME_TRAFFIC', 'OUTCOME_ENGAGEMENT',
38
+ 'OUTCOME_LEADS', 'OUTCOME_SALES', 'OUTCOME_APP_PROMOTION'.
39
+ Examples: 'OUTCOME_LEADS' or ['OUTCOME_LEADS', 'OUTCOME_SALES'].
40
+ Leave empty for all objectives.
29
41
  after: Pagination cursor to get the next set of results
30
42
  """
31
43
  # Require explicit account_id
@@ -38,10 +50,32 @@ async def get_campaigns(account_id: str, access_token: Optional[str] = None, lim
38
50
  "limit": limit
39
51
  }
40
52
 
53
+ # Build filtering array for complex filtering
54
+ filters = []
55
+
41
56
  if status_filter:
42
57
  # API expects an array, encode it as a JSON string
43
58
  params["effective_status"] = json.dumps([status_filter])
44
59
 
60
+ # Handle objective filtering - supports both single string and list of objectives
61
+ if objective_filter:
62
+ # Convert single string to list for consistent handling
63
+ objectives = [objective_filter] if isinstance(objective_filter, str) else objective_filter
64
+
65
+ # Filter out empty strings
66
+ objectives = [obj for obj in objectives if obj]
67
+
68
+ if objectives:
69
+ filters.append({
70
+ "field": "objective",
71
+ "operator": "IN",
72
+ "value": objectives
73
+ })
74
+
75
+ # Add filtering parameter if we have filters
76
+ if filters:
77
+ params["filtering"] = json.dumps(filters)
78
+
45
79
  if after:
46
80
  params["after"] = after
47
81
 
@@ -6,7 +6,7 @@ import httpx
6
6
  from typing import Optional, Dict, Any, List, Union
7
7
  from .server import mcp_server
8
8
  from .api import meta_api_tool
9
- from .auth import get_current_access_token
9
+ from . import auth
10
10
  from .http_auth_integration import FastMCPAuthIntegration
11
11
 
12
12
 
@@ -204,7 +204,7 @@ async def _forward_duplication_request(resource_type: str, resource_id: str, acc
204
204
 
205
205
  # Use provided access_token parameter if no Facebook token found in context
206
206
  if not facebook_token:
207
- facebook_token = access_token if access_token else await get_current_access_token()
207
+ facebook_token = access_token if access_token else await auth.get_current_access_token()
208
208
 
209
209
  # Validate we have both required tokens
210
210
  if not pipeboard_token:
@@ -1,7 +1,7 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: meta-ads-mcp
3
- Version: 1.0.13
4
- Summary: Model Context Protocol (MCP) server for interacting with Meta Ads API
3
+ Version: 1.0.18
4
+ Summary: Model Context Protocol (MCP) server for Meta Ads - Use Remote MCP at pipeboard.co for easiest setup
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
  Author-email: Yves Junqueira <yves.junqueira@gmail.com>
@@ -25,12 +25,14 @@ Description-Content-Type: text/markdown
25
25
 
26
26
  # Meta Ads MCP
27
27
 
28
- A [Model Context Protocol (MCP)](https://modelcontextprotocol.io/) server for interacting with Meta Ads API. This tool enables AI models to access, analyze, and manage Meta advertising campaigns through a standardized interface, allowing LLMs to retrieve performance data, visualize ad creatives, and provide strategic insights for Facebook, Instagram, and other Meta platforms.
28
+ A [Model Context Protocol (MCP)](https://modelcontextprotocol.io/) server for interacting with Meta Ads. Analyze, manage and optimize Meta advertising campaigns through an AI interface. Use an LLM to retrieve performance data, visualize ad creatives, and provide strategic insights for your ads on Facebook, Instagram, and other Meta platforms.
29
29
 
30
30
  > **DISCLAIMER:** This is an unofficial third-party tool and is not associated with, endorsed by, or affiliated with Meta in any way. This project is maintained independently and uses Meta's public APIs according to their terms of service. Meta, Facebook, Instagram, and other Meta brand names are trademarks of their respective owners.
31
31
 
32
32
  [![Meta Ads MCP Server Demo](https://github.com/user-attachments/assets/3e605cee-d289-414b-814c-6299e7f3383e)](https://github.com/user-attachments/assets/3e605cee-d289-414b-814c-6299e7f3383e)
33
33
 
34
+ [![MCP Badge](https://lobehub.com/badge/mcp/nictuku-meta-ads-mcp)](https://lobehub.com/mcp/nictuku-meta-ads-mcp)
35
+
34
36
  mcp-name: co.pipeboard/meta-ads-mcp
35
37
 
36
38
  ## Community & Support
@@ -66,6 +68,16 @@ The fastest and most reliable way to get started is to **[🚀 Get started with
66
68
 
67
69
  That's it! You can now ask Claude to analyze your Meta ad campaigns, get performance insights, and manage your advertising.
68
70
 
71
+ #### Advanced: Direct Token Authentication (Claude)
72
+
73
+ For direct token-based authentication without the interactive flow, use this URL format when adding the integration:
74
+
75
+ ```
76
+ https://mcp.pipeboard.co/meta-ads-mcp?token=YOUR_PIPEBOARD_TOKEN
77
+ ```
78
+
79
+ Get your token at [pipeboard.co/api-tokens](https://pipeboard.co/api-tokens).
80
+
69
81
  ### For Cursor Users
70
82
 
71
83
  Add the following to your `~/.cursor/mcp.json`. Once you enable the remote MCP, click on "Needs login" to finish the login process.
@@ -81,31 +93,43 @@ Add the following to your `~/.cursor/mcp.json`. Once you enable the remote MCP,
81
93
  }
82
94
  ```
83
95
 
96
+ #### Advanced: Direct Token Authentication (Cursor)
97
+
98
+ If you prefer to authenticate without the interactive login flow, you can include your Pipeboard API token directly in the URL:
99
+
100
+ ```json
101
+ {
102
+ "mcpServers": {
103
+ "meta-ads-remote": {
104
+ "url": "https://mcp.pipeboard.co/meta-ads-mcp?token=YOUR_PIPEBOARD_TOKEN"
105
+ }
106
+ }
107
+ }
108
+ ```
109
+
110
+ Get your token at [pipeboard.co/api-tokens](https://pipeboard.co/api-tokens).
111
+
84
112
  ### For Other MCP Clients
85
113
 
86
114
  Use the Remote MCP URL: `https://mcp.pipeboard.co/meta-ads-mcp`
87
115
 
88
116
  **[📖 Get detailed setup instructions for your AI client here](https://pipeboard.co)**
89
117
 
90
- ## Local Installation (Technical Users Only)
91
-
92
- If you're a developer or need to customize the installation, you can run Meta Ads MCP locally. **Most marketers should use the Remote MCP above instead!** For complete technical setup instructions, see our **[Local Installation Guide](LOCAL_INSTALLATION.md)**.
118
+ #### Advanced: Direct Token Authentication (Other Clients)
93
119
 
94
- Meta Ads MCP also supports **streamable HTTP transport**, allowing you to run it as a standalone HTTP API for web applications and custom integrations. See **[Streamable HTTP Setup Guide](STREAMABLE_HTTP_SETUP.md)** for complete instructions.
120
+ For MCP clients that support token-based authentication, you can append your Pipeboard API token to the URL:
95
121
 
96
- ### Quick Local Setup
122
+ ```
123
+ https://mcp.pipeboard.co/meta-ads-mcp?token=YOUR_PIPEBOARD_TOKEN
124
+ ```
97
125
 
98
- ```bash
99
- # Install via uvx (recommended)
100
- uvx meta-ads-mcp
126
+ This bypasses the interactive login flow and authenticates immediately. Get your token at [pipeboard.co/api-tokens](https://pipeboard.co/api-tokens).
101
127
 
102
- # Set your Pipeboard token
103
- export PIPEBOARD_API_TOKEN=your_pipeboard_token
128
+ ## Local Installation (Advanced Technical Users Only)
104
129
 
105
- # Add to your MCP client configuration
106
- ```
130
+ 🚀 **We strongly recommend using [Remote MCP](https://pipeboard.co) instead** - it's faster, more reliable, and requires no technical setup.
107
131
 
108
- For detailed step-by-step instructions, authentication setup, debugging, and troubleshooting, visit **[LOCAL_INSTALLATION.md](LOCAL_INSTALLATION.md)**.
132
+ Meta Ads MCP also supports a local streamable HTTP transport, allowing you to run it as a standalone HTTP API for web applications and custom integrations. See **[Streamable HTTP Setup Guide](STREAMABLE_HTTP_SETUP.md)** for complete instructions.
109
133
 
110
134
  ## Features
111
135
 
@@ -128,9 +152,9 @@ For detailed step-by-step instructions, authentication setup, debugging, and tro
128
152
 
129
153
  **[✨ Get started with Remote MCP here](https://pipeboard.co)** - no technical setup required! Just connect your Facebook Ads account and start asking AI to analyze your campaigns.
130
154
 
131
- ### Local Installation (Technical Users)
155
+ ### Local Installation (Advanced Technical Users)
132
156
 
133
- For local installation configuration, authentication options, and advanced technical setup, see our **[Local Installation Guide](LOCAL_INSTALLATION.md)**.
157
+ For advanced users who need to self-host, the package can be installed from source. Local installations require creating your own Meta Developer App. **We recommend using [Remote MCP](https://pipeboard.co) for a simpler experience.**
134
158
 
135
159
  ### Available MCP Tools
136
160
 
@@ -456,7 +480,7 @@ The only restriction is that you cannot offer this as a competing hosted service
456
480
  Meta Ads MCP follows security best practices with secure token management and automatic authentication handling.
457
481
 
458
482
  - **Remote MCP**: All authentication is handled securely in the cloud - no local token storage required
459
- - **Local Installation**: Tokens are cached securely on your local machine - see [Local Installation Guide](LOCAL_INSTALLATION.md) for details
483
+ - **Local Installation**: Tokens are cached securely on your local machine
460
484
 
461
485
  ## Testing
462
486
 
@@ -468,7 +492,7 @@ Test your Meta Ads MCP connection with any MCP client:
468
492
  2. **Check Account Details**: Use `mcp_meta_ads_get_account_info` with your account ID
469
493
  3. **List Campaigns**: Try `mcp_meta_ads_get_campaigns` to see your ad campaigns
470
494
 
471
- For detailed local installation testing, see [Local Installation Guide](LOCAL_INSTALLATION.md).
495
+ For detailed local installation testing, see the source repository.
472
496
 
473
497
  ## Troubleshooting
474
498
 
@@ -478,10 +502,4 @@ The easiest way to avoid any setup issues is to **[🎯 use our Remote MCP inste
478
502
 
479
503
  ### Local Installation Issues
480
504
 
481
- For comprehensive troubleshooting, debugging, and local installation issues, see our **[Local Installation Guide](LOCAL_INSTALLATION.md)** which includes:
482
-
483
- - Authentication troubleshooting
484
- - Installation issues and solutions
485
- - API error resolution
486
- - Debug logs and diagnostic commands
487
- - Performance optimization tips
505
+ For local installation issues, refer to the source repository. **For the easiest experience, we recommend using [Remote MCP](https://pipeboard.co) instead.**
@@ -1,17 +1,17 @@
1
- meta_ads_mcp/__init__.py,sha256=T0td-KBlHfj2ZrwXw6KM7u__flP25vlUMUyy5Befuzs,1477
1
+ meta_ads_mcp/__init__.py,sha256=qVIccqA3rZtJUEMjPcFLKFUhyRlnAJyTyP4l29VklAU,1477
2
2
  meta_ads_mcp/__main__.py,sha256=XaQt3iXftG_7f0Zu7Wop9SeFgrD2WBn0EQOaPMc27d8,207
3
3
  meta_ads_mcp/core/__init__.py,sha256=IEJtqpyUo0CZSUWeQPljQ-D2vKorTFwXnpBQWSi1hIM,1819
4
4
  meta_ads_mcp/core/accounts.py,sha256=7Zoqq0zMIJi_Xsxe9-_b3EYx-UTeieJJvO7HxVRuUS0,4327
5
- meta_ads_mcp/core/ads.py,sha256=5ulQ4p3lLo1_sIiAoMdyeo0O2y7Yq2zSDuvqkNiqX1c,61376
5
+ meta_ads_mcp/core/ads.py,sha256=ED67n5kCcmqk5BDDTOA4zVYUPUsAJw8ZvlM2kVwNQlI,62007
6
6
  meta_ads_mcp/core/ads_library.py,sha256=smGz9FhM6RIUjlQT4Jv1BaZmXahGdK21eRCB7QMhK-4,3228
7
7
  meta_ads_mcp/core/adsets.py,sha256=3Ok3EwPTReKshtsVs4gRMlws6LMTUJTb4ZeGPPM8JR8,16570
8
- meta_ads_mcp/core/api.py,sha256=dR1h3sTnSmIdEz8OSttqELA0YxBkbjMnSflgM5LsJ1A,16858
8
+ meta_ads_mcp/core/api.py,sha256=RvEbXpVO_SxKJeuqsiQhpGYLZuhQlYKCd9hNv7AIZac,16856
9
9
  meta_ads_mcp/core/auth.py,sha256=l_IvejK2KYXg8yhBiP0ifE6mGwJ6ZujqYQbVw1KOUME,23649
10
- meta_ads_mcp/core/authentication.py,sha256=ftoKec1HpfYCCVYIVKUD3ezvVAk6n_CJlBuePn8fzpM,10547
10
+ meta_ads_mcp/core/authentication.py,sha256=bAdmlSxQpqFN1vup9Wijl-iCfPLPMyFfMhIPdoNOPYg,10540
11
11
  meta_ads_mcp/core/budget_schedules.py,sha256=FVyJuKbjUE4cmtlPJEbIwpN6JmU-1WQjc7io1y5JaHE,2911
12
12
  meta_ads_mcp/core/callback_server.py,sha256=LIAJv9DW--83kdZ7VWWZal8xEprYjRZ8iug4rMczYbQ,9372
13
- meta_ads_mcp/core/campaigns.py,sha256=m24epO1QmyBVBXfqHIFZAi6sRCTlOGLQckjy0azqkvo,14319
14
- meta_ads_mcp/core/duplication.py,sha256=ae9GisFg9MMXbgX8zqb6ekEFIv7DGNCMV-lwkDXSL-c,18928
13
+ meta_ads_mcp/core/campaigns.py,sha256=LKo5B8hNUUmfVQ1iu88o8HoU9ixOlGS9lwmPu6x9keA,15604
14
+ meta_ads_mcp/core/duplication.py,sha256=pJ41pI9bIxNf21TSy6KkpcUsc3aSr4KIiO__sunNoq0,18909
15
15
  meta_ads_mcp/core/http_auth_integration.py,sha256=lGpKhfzJcyWugBcYEvypY-qnlt-3UDBLqh7xAUH0DGw,12473
16
16
  meta_ads_mcp/core/insights.py,sha256=ogSGlC0ddh8RFzWydilfDc7GYnjtInFiEQS7cSoyTmw,5061
17
17
  meta_ads_mcp/core/openai_deep_research.py,sha256=68ayGopnBSPEYhN9R1sFvTXtyWtM0lji9aWS3uSXnLY,18649
@@ -21,8 +21,8 @@ meta_ads_mcp/core/resources.py,sha256=-zIIfZulpo76vcKv6jhAlQq91cR2SZ3cjYZt3ek3x0
21
21
  meta_ads_mcp/core/server.py,sha256=9SlgM_qvdlxo24ctnZzLgW1e1nfAspCSx3YyJQkKP64,17856
22
22
  meta_ads_mcp/core/targeting.py,sha256=d2uLWbIEtucRuTgwZEdtVKLDZJgaxQ1lDtZ0ZgkBJC4,25150
23
23
  meta_ads_mcp/core/utils.py,sha256=ytj41yC5SqduLrAiZYBSd6OUwlJRaIClTwnnYKpNFds,9387
24
- meta_ads_mcp-1.0.13.dist-info/METADATA,sha256=W4fdNhV4K_RuA1d2Er-2Xqz46dHn0AJm-wDkLcL-DIk,24289
25
- meta_ads_mcp-1.0.13.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
26
- meta_ads_mcp-1.0.13.dist-info/entry_points.txt,sha256=Dv2RkoBjRJBqj6CyhwqGIiwPCD-SCL1-7B9-zmVRuv0,57
27
- meta_ads_mcp-1.0.13.dist-info/licenses/LICENSE,sha256=E2d762fbhwKRYn8o7J6Szr6vyBPrHVDlK3jbHPx-d84,3851
28
- meta_ads_mcp-1.0.13.dist-info/RECORD,,
24
+ meta_ads_mcp-1.0.18.dist-info/METADATA,sha256=9Dyns9X9nMyMP-ZCMWpFuk6lckX7ApqIAJIfIiYY_vs,24903
25
+ meta_ads_mcp-1.0.18.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
26
+ meta_ads_mcp-1.0.18.dist-info/entry_points.txt,sha256=Dv2RkoBjRJBqj6CyhwqGIiwPCD-SCL1-7B9-zmVRuv0,57
27
+ meta_ads_mcp-1.0.18.dist-info/licenses/LICENSE,sha256=E2d762fbhwKRYn8o7J6Szr6vyBPrHVDlK3jbHPx-d84,3851
28
+ meta_ads_mcp-1.0.18.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: hatchling 1.27.0
2
+ Generator: hatchling 1.28.0
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any