Skip to main content
Glama
johnoconnor0

Google Ads MCP Server

by johnoconnor0

google_ads_create_ad_group

Create a new ad group in a Google Ads campaign by specifying campaign ID, ad group name, and optional cost-per-click bid. Ad group is created paused for safety.

Instructions

Create a new ad group within a campaign.

Args: customer_id: Customer ID (without hyphens) campaign_id: Campaign ID to create ad group in ad_group_name: Name for the ad group cpc_bid: Cost-per-click bid in currency units (e.g., 1.50 for $1.50) status: Initial status (ENABLED or PAUSED, default: PAUSED) ad_group_type: Optional ad group type (SEARCH_STANDARD, DISPLAY_STANDARD, etc.)

Returns: Success message with ad group details

Note: Ad groups are created PAUSED by default for safety.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
customer_idYes
campaign_idYes
ad_group_nameYes
cpc_bidNo
statusNoPAUSED
ad_group_typeNo

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
resultYes

Implementation Reference

  • The MCP tool handler that creates an ad group. Validates inputs, builds an AdGroupConfig, delegates to AdGroupManager.create_ad_group(), logs the operation, invalidates cache, and returns a formatted success/error message.
    @mcp.tool()
    def google_ads_create_ad_group(
        customer_id: str,
        campaign_id: str,
        ad_group_name: str,
        cpc_bid: Optional[float] = None,
        status: str = "PAUSED",
        ad_group_type: Optional[str] = None
    ) -> str:
        """
        Create a new ad group within a campaign.
    
        Args:
            customer_id: Customer ID (without hyphens)
            campaign_id: Campaign ID to create ad group in
            ad_group_name: Name for the ad group
            cpc_bid: Cost-per-click bid in currency units (e.g., 1.50 for $1.50)
            status: Initial status (ENABLED or PAUSED, default: PAUSED)
            ad_group_type: Optional ad group type (SEARCH_STANDARD, DISPLAY_STANDARD, etc.)
    
        Returns:
            Success message with ad group details
    
        Note: Ad groups are created PAUSED by default for safety.
        """
        with performance_logger.track_operation('create_ad_group', customer_id=customer_id):
            try:
                client = get_auth_manager().get_client()
                ad_group_manager = AdGroupManager(client)
    
                # Convert bid to micros
                cpc_bid_micros = int(cpc_bid * 1_000_000) if cpc_bid else None
    
                # Create config
                config = AdGroupConfig(
                    name=ad_group_name,
                    campaign_id=campaign_id,
                    status=AdGroupStatus[status.upper()],
                    cpc_bid_micros=cpc_bid_micros,
                    ad_group_type=AdGroupType[ad_group_type.upper()] if ad_group_type else None
                )
    
                # Create ad group
                result = ad_group_manager.create_ad_group(customer_id, config)
    
                # Audit log
                audit_logger.log_api_call(
                    customer_id=customer_id,
                    operation="create_ad_group",
                    resource_type="ad_group",
                    resource_id=result['ad_group_id'],
                    action="create",
                    result="success",
                    details={
                        'name': ad_group_name,
                        'campaign_id': campaign_id,
                        'cpc_bid': cpc_bid
                    }
                )
    
                # Invalidate cache
                get_cache_manager().invalidate(customer_id, ResourceType.AD_GROUP)
    
                output = f"✅ Ad group created successfully!\n\n"
                output += f"**Ad Group ID**: {result['ad_group_id']}\n"
                output += f"**Name**: {ad_group_name}\n"
                output += f"**Campaign ID**: {campaign_id}\n"
                output += f"**Status**: {status}\n"
    
                if cpc_bid:
                    output += f"**CPC Bid**: ${cpc_bid:.2f}\n"
    
                output += f"\n"
                output += f"Ad group is now {status.lower()}. "
                output += f"Next steps:\n"
                output += f"1. Add keywords to the ad group\n"
                output += f"2. Create ads\n"
                output += f"3. Enable the ad group when ready"
    
                return output
    
            except Exception as e:
                error_msg = ErrorHandler.handle_error(e, context="create_ad_group")
                return f"❌ Failed to create ad group: {error_msg}"
  • The @mcp.tool() decorator on line 31 registers google_ads_create_ad_group as an MCP tool. This registration is triggered by register_ad_group_tools() which is called from google_ads_mcp.py via _register_all_modular_tools().
    def register_ad_group_tools(mcp: FastMCP):
        """Register ad group management tools with MCP server."""
  • Data class schema for ad group configuration, including name, campaign_id, status, CPC bid (in micros), ad_group_type, and other bid types.
    @dataclass
    class AdGroupConfig:
        """Configuration for creating an ad group."""
        name: str
        campaign_id: str
        status: AdGroupStatus = AdGroupStatus.PAUSED
        cpc_bid_micros: Optional[int] = None  # Manual CPC bid
        cpm_bid_micros: Optional[int] = None  # CPM bid (display)
        cpv_bid_micros: Optional[int] = None  # CPV bid (video)
        target_cpa_micros: Optional[int] = None  # Target CPA
        percent_cpc_bid_micros: Optional[int] = None  # Enhanced CPC
        ad_group_type: Optional[AdGroupType] = None
  • The AdGroupManager.create_ad_group() helper that executes the Google Ads API call to mutate/create an ad group, including setting campaign path, status, type, and bid fields.
    def create_ad_group(
        self,
        customer_id: str,
        config: AdGroupConfig
    ) -> Dict[str, Any]:
        """
        Create a new ad group.
    
        Args:
            customer_id: Customer ID
            config: Ad group configuration
    
        Returns:
            Created ad group details
        """
        ad_group_service = self.client.get_service("AdGroupService")
        campaign_service = self.client.get_service("CampaignService")
    
        # Create operation
        ad_group_operation = self.client.get_type("AdGroupOperation")
        ad_group = ad_group_operation.create
    
        # Set basic fields
        ad_group.name = config.name
        ad_group.campaign = campaign_service.campaign_path(
            customer_id, config.campaign_id
        )
        ad_group.status = self.client.enums.AdGroupStatusEnum[config.status.value]
    
        # Set ad group type if specified
        if config.ad_group_type:
            ad_group.type_ = self.client.enums.AdGroupTypeEnum[config.ad_group_type.value]
    
        # Set bidding (only set the relevant bid type)
        if config.cpc_bid_micros is not None:
            ad_group.cpc_bid_micros = config.cpc_bid_micros
        elif config.cpm_bid_micros is not None:
            ad_group.cpm_bid_micros = config.cpm_bid_micros
        elif config.cpv_bid_micros is not None:
            ad_group.cpv_bid_micros = config.cpv_bid_micros
        elif config.target_cpa_micros is not None:
            ad_group.target_cpa_micros = config.target_cpa_micros
        elif config.percent_cpc_bid_micros is not None:
            ad_group.percent_cpc_bid_micros = config.percent_cpc_bid_micros
    
        # Create ad group
        response = ad_group_service.mutate_ad_groups(
            customer_id=customer_id,
            operations=[ad_group_operation]
        )
    
        ad_group_resource_name = response.results[0].resource_name
        ad_group_id = ad_group_resource_name.split("/")[-1]
    
        logger.info(f"Created ad group: {ad_group_id} in campaign {config.campaign_id}")
    
        return {
            "ad_group_id": ad_group_id,
            "resource_name": ad_group_resource_name,
            "name": config.name,
            "campaign_id": config.campaign_id,
            "status": config.status.value
        }
  • Top-level registration entry: google_ads_mcp.py lists ad_groups module with register_ad_group_tools, which is imported and called by _register_all_modular_tools() to register all tools including google_ads_create_ad_group.
    _TOOL_MODULES = [
        ("campaigns",     "tools.campaigns.mcp_tools_campaigns",         "register_campaign_tools"),
        ("ad_groups",     "tools.ad_groups.mcp_tools_ad_groups",         "register_ad_group_tools"),
        ("keywords",      "tools.keywords.mcp_tools_keywords",           "register_keyword_tools"),
        ("ads",           "tools.ads.mcp_tools_ads",                     "register_ad_tools"),
        ("bidding",       "tools.bidding.mcp_tools_bidding",             "register_bidding_tools"),
        ("automation",    "tools.automation.mcp_tools_automation",       "register_automation_tools"),
        ("audiences",     "tools.audiences.mcp_tools_audiences",         "register_audience_tools"),
        ("conversions",   "tools.conversions.mcp_tools_conversions",     "register_conversion_tools"),
        ("reporting",     "tools.reporting.mcp_tools_reporting",         "register_reporting_tools"),
        ("insights",      "tools.insights.mcp_tools_insights",           "register_insights_tools"),
        ("batch",         "tools.batch.mcp_tools_batch",                 "register_batch_tools"),
        ("shopping_pmax", "tools.shopping_pmax.mcp_tools_shopping_pmax", "register_shopping_pmax_tools"),
        ("extensions",    "tools.extensions.mcp_tools_extensions",       "register_extension_tools"),
        ("local_app",     "tools.local_app.mcp_tools_local_app",         "register_local_app_tools"),
    ]
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations provided, so the description carries full burden. It adds a useful safety note about ad groups being created PAUSED by default, but does not disclose authentication needs, rate limits, or exact side effects.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is concise and front-loaded with the purpose. The Args block is clear but slightly informal; no wasted words, though it could be more structured.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Covers key parameters and the safety default, but lacks mention of prerequisites (e.g., existing campaign) or how to interpret the return value beyond 'Success message with ad group details'. Given the tool's complexity and lack of annotations, some gaps remain.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 0% schema description coverage, the description adds meaningful context for all 6 parameters: explains customer_id format, cpc_bid units with example, status options and default, and ad_group_type examples. This compensates fully for the schema gaps.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states 'Create a new ad group within a campaign,' specifying the verb (Create) and resource (ad group) and distinguishing it from update or batch creation siblings.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No guidance on when to use this tool versus alternatives like google_ads_batch_create_ad_groups or update_ad_group. The description does not mention any prerequisites or exclusions.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/johnoconnor0/google-ads-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server