google_ads_add_shared_negative_keywords
Add negative keywords to an account-level shared list to exclude unwanted search terms across multiple campaigns.
Instructions
Add negative keywords to a shared negative keyword list (account-level).
This adds keywords to an existing shared negative keyword list that can be applied across multiple campaigns for account-level negative keyword management.
Args: customer_id: Customer ID (without hyphens) shared_set_id: The ID of the shared negative keyword list keywords: List of keyword dicts with 'text' and 'match_type'
Returns: Success message with count of keywords added
Example: keywords = [ {"text": "cheap", "match_type": "BROAD"}, {"text": "free", "match_type": "BROAD"}, {"text": "jobs", "match_type": "BROAD"} ]
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| customer_id | Yes | ||
| shared_set_id | Yes | ||
| keywords | Yes |
Output Schema
| Name | Required | Description | Default |
|---|---|---|---|
| result | Yes |
Implementation Reference
- The MCP tool handler for 'google_ads_add_shared_negative_keywords'. This is the function decorated with @mcp.tool() that defines the tool, accepts customer_id, shared_set_id, and keywords params, validates input, calls the KeywordManager's add_keywords_to_shared_set method, logs the operation via audit_logger, invalidates cache, and returns a formatted success message.
@mcp.tool() def google_ads_add_shared_negative_keywords( customer_id: str, shared_set_id: str, keywords: List[Dict[str, str]] ) -> str: """ Add negative keywords to a shared negative keyword list (account-level). This adds keywords to an existing shared negative keyword list that can be applied across multiple campaigns for account-level negative keyword management. Args: customer_id: Customer ID (without hyphens) shared_set_id: The ID of the shared negative keyword list keywords: List of keyword dicts with 'text' and 'match_type' Returns: Success message with count of keywords added Example: keywords = [ {"text": "cheap", "match_type": "BROAD"}, {"text": "free", "match_type": "BROAD"}, {"text": "jobs", "match_type": "BROAD"} ] """ with performance_logger.track_operation('add_shared_negative_keywords', customer_id=customer_id): try: client = get_auth_manager().get_client() keyword_manager = KeywordManager(client) result = keyword_manager.add_keywords_to_shared_set( customer_id, shared_set_id, keywords ) # Audit log audit_logger.log_api_call( customer_id=customer_id, operation="add_shared_negative_keywords", resource_type="shared_criterion", action="create", result="success", details={ 'shared_set_id': shared_set_id, 'keyword_count': len(keywords) } ) # Invalidate cache get_cache_manager().invalidate(customer_id, ResourceType.KEYWORD) output = f"✅ Keywords added to shared negative keyword list!\n\n" output += f"**Shared Set ID**: {shared_set_id}\n" output += f"**Keywords Added**: {result['keywords_added']}\n\n" output += "**Added Keywords**:\n" for kw in keywords[:20]: output += f"- {kw['text']} ({kw['match_type']})\n" if len(keywords) > 20: output += f"... and {len(keywords) - 20} more\n" output += "\nThese negative keywords will apply to all campaigns linked to this shared list." return output except Exception as e: error_msg = ErrorHandler.handle_error(e, context="add_shared_negative_keywords") return f"❌ Failed to add shared negative keywords: {error_msg}" - managers/keyword_manager.py:198-247 (helper)The 'add_keywords_to_shared_set' method in KeywordManager. This is the core business logic: it builds SharedCriterionOperations using the Google Ads API, setting the shared_set resource name and keyword text/match_type for each keyword, then calls shared_criterion_service.mutate_shared_criteria() to add negative keywords to the shared list.
def add_keywords_to_shared_set( self, customer_id: str, shared_set_id: str, keywords: List[Dict[str, str]] ) -> Dict[str, Any]: """ Add negative keywords to a shared negative keyword list. Args: customer_id: Customer ID shared_set_id: Shared set ID (the negative keyword list ID) keywords: List of dicts with 'text' and 'match_type' Returns: Operation result with count of keywords added """ shared_criterion_service = self.client.get_service("SharedCriterionService") operations = [] for kw in keywords: operation = self.client.get_type("SharedCriterionOperation") criterion = operation.create # Set the shared set resource name criterion.shared_set = f"customers/{customer_id}/sharedSets/{shared_set_id}" # Set keyword criterion.keyword.text = kw['text'] criterion.keyword.match_type = self.client.enums.KeywordMatchTypeEnum[ kw['match_type'].upper() ] operations.append(operation) # Add keywords to shared set response = shared_criterion_service.mutate_shared_criteria( customer_id=customer_id, operations=operations ) added_count = len(response.results) logger.info(f"Added {added_count} keywords to shared set {shared_set_id}") return { "keywords_added": added_count, "shared_set_id": shared_set_id, "message": f"Successfully added {added_count} negative keywords to shared list" } - tools/keywords/mcp_tools_keywords.py:24-27 (registration)The 'register_keyword_tools' function that registers all keyword tools (including this one) with the MCP server via the @mcp.tool() decorator pattern.
def register_keyword_tools(mcp: FastMCP): """Register keyword management tools with MCP server.""" # ============================================================================ - google_ads_mcp.py:498-513 (registration)The '_register_all_modular_tools' function that dynamically imports and calls register_keyword_tools (among others) via the _TOOL_MODULES list, which includes the keywords module at line 483.
def _register_all_modular_tools(): """Import and register every modular tool module.""" import importlib registered = 0 for label, module_path, func_name in _TOOL_MODULES: try: mod = importlib.import_module(module_path) register_fn = getattr(mod, func_name) register_fn(mcp) logger.info(f" ✓ {label}") registered += 1 except Exception as exc: logger.error(f" ✗ {label}: {exc}") logger.info(f"Registered {registered}/{len(_TOOL_MODULES)} modular tool modules") - tools/keywords/__init__.py:1-19 (helper)Package init that exports register_keyword_tools from the keyword tools module, allowing the main server to discover and register this tool.
""" Google Ads MCP Tools - Keyword Management Tools for keyword research, management, and optimization. Includes tools for: - Adding and removing keywords - Managing negative keywords - Updating keyword bids and match types - Keyword quality score analysis - Search term mining and analysis - Keyword idea generation Total: 14 tools """ from .mcp_tools_keywords import register_keyword_tools __all__ = ['register_keyword_tools']