🎩 You're Invited:Meet the Socket team at Black Hat in Las Vegas, August 3-6.RSVP
Sign In

@cesteral/sa360-mcp

Package Overview
Dependencies
Maintainers
1
Versions
2
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@cesteral/sa360-mcp

Search Ads 360 MCP Server - Reporting and conversion upload via SA360 Reporting API v0 and legacy v2 API

latest
Source
npmnpm
Version
1.1.0
Version published
Maintainers
1
Created
Source

@cesteral/sa360-mcp

Search Ads 360 MCP Server — Cross-engine unified reporting and offline conversion upload via SA360 Reporting API v0 and legacy v2 API.

License TypeScript MCP

Overview

SA360 (Search Ads 360) sits above Google Ads, Microsoft Ads, Yahoo Japan, and Baidu, providing cross-engine unified reporting and automated bidding. This MCP server exposes SA360 reporting, conversion upload, audit, and query workflows:

  • 8 read-only tools for cross-engine reporting, entity browsing, field discovery, and custom columns
  • 3 async reporting tools for the submit → poll → download report workflow via the v2 API
  • 2 write tools for offline conversion upload and modification via the legacy v2 API
  • 1 validation tool for pre-flight conversion payload checks
  • 1 audit tool for entity change history tracking
  • 1 query tool for flexible cross-engine search

The SA360 API is read-only for campaign entities — there are no mutate/CRUD operations for campaigns, ad groups, or ads. Write capabilities are limited to offline conversion management and async reporting.

APIs Used

APIBase URLCapabilities
SA360 Reporting API v0https://searchads360.googleapis.com/v0Read-only queries (SQL-like, mirrors GAQL syntax)
SA360 v2 (DoubleClick Search)https://www.googleapis.com/doubleclicksearch/v2Conversion insert/update, async reporting

Quick Start

Prerequisites

  • Node.js >= 20.0.0
  • pnpm >= 8.0.0
  • Google OAuth2 credentials with https://www.googleapis.com/auth/doubleclicksearch scope

1. Install & Build

# From repository root
pnpm install
pnpm run build

2. Configure Environment

cp packages/sa360-mcp/.env.example packages/sa360-mcp/.env

Edit .env with your credentials:

SA360_MCP_PORT=3010
MCP_AUTH_MODE=sa360-headers

# For stdio mode (Claude Desktop, MCP Inspector)
SA360_CLIENT_ID=your-client-id
SA360_CLIENT_SECRET=your-client-secret
SA360_REFRESH_TOKEN=your-refresh-token
# SA360_LOGIN_CUSTOMER_ID=your-mcc-customer-id  # Optional, for manager accounts

3. Run Locally

# HTTP mode (port 3010)
./scripts/dev-server.sh sa360-mcp

# Or directly
cd packages/sa360-mcp && pnpm run dev:http

4. Verify

# Health check
curl http://localhost:3010/health

# List tools
curl -X POST http://localhost:3010/mcp \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","method":"tools/list","id":1}'

Authentication

SA360 uses OAuth2 refresh token authentication. Unlike Google Ads, no developer token is required.

HTTP Mode (sa360-headers)

Pass credentials via HTTP headers on each request:

HeaderRequiredDescription
X-SA360-Client-IdYesOAuth2 client ID
X-SA360-Client-SecretYesOAuth2 client secret
X-SA360-Refresh-TokenYesOAuth2 refresh token
X-SA360-Login-Customer-IdNoManager account ID (for MCC access)

Stdio Mode

Set environment variables for stdio transport (Claude Desktop, MCP Inspector):

SA360_CLIENT_ID=your-client-id
SA360_CLIENT_SECRET=your-client-secret
SA360_REFRESH_TOKEN=your-refresh-token
SA360_LOGIN_CUSTOMER_ID=your-mcc-customer-id  # Optional

JWT Mode

For managed deployments with centralized auth:

MCP_AUTH_MODE=jwt
MCP_AUTH_SECRET_KEY=your-jwt-secret

Getting OAuth2 Credentials

  • Create a project in Google Cloud Console
  • Enable the Search Ads 360 API and DoubleClick Search API
  • Create OAuth2 credentials (Desktop application type)
  • Generate a refresh token with scope https://www.googleapis.com/auth/doubleclicksearch

Tools Reference

Reporting API v0 Tools (Read-Only)

Execute raw SA360 query language queries against any SA360 resource. Same syntax as GAQL (Google Ads Query Language).

ParameterTypeRequiredDescription
customerIdstringYesSA360 customer ID (no dashes)
querystringYesSA360 query (SELECT ... FROM ... WHERE ...)
pageSizenumberNoDeprecated. Use maxRows for the returned row count.
pageTokenstringNoCursor for the next upstream page (different from offset which slices the in-memory buffer)
modeenumNo"summary" (default) returns headers + counts + 10-row preview; "rows" returns one bounded page of rows
columnsstring[]NoProject returned rows to selected columns
offsetnumberNoZero-based row offset for pagination (default: 0)
maxRowsnumberNoPage size before the 200-row hard cap (default: 10 for summary, 50 for rows)
{
  "customerId": "1234567890",
  "query": "SELECT campaign.id, campaign.name, campaign.engine_id, metrics.impressions, metrics.clicks, metrics.cost_micros FROM campaign WHERE segments.date DURING LAST_30_DAYS ORDER BY metrics.impressions DESC LIMIT 50"
}

sa360_list_accounts

List all SA360 customer accounts accessible to the authenticated user.

No parameters required.

sa360_list_entities

List SA360 entities with optional query filters and pagination.

ParameterTypeRequiredDescription
entityTypeenumYesEntity type (see supported types below)
customerIdstringYesSA360 customer ID
filtersobjectNoField:value filter conditions
pageSizenumberNoResults per page (default 100)
pageTokenstringNoPagination token
orderBystringNoORDER BY clause

Supported entity types: customer, campaign, adGroup, adGroupAd, adGroupCriterion, campaignCriterion, biddingStrategy, conversionAction

sa360_get_entity

Get a single entity by type and ID.

ParameterTypeRequiredDescription
entityTypeenumYesEntity type
customerIdstringYesSA360 customer ID
entityIdstringYesEntity ID to retrieve

sa360_get_insights

Performance metrics with preset or custom date ranges. Convenience wrapper that builds queries from simple parameters.

ParameterTypeRequiredDescription
customerIdstringYesSA360 customer ID
entityTypeenumYescustomer, campaign, adGroup, adGroupAd, adGroupCriterion, or campaignCriterion
entityIdstringNoFilter to specific entity
dateRangeenumNo*TODAY, YESTERDAY, LAST_7_DAYS, LAST_30_DAYS, THIS_MONTH, LAST_MONTH, LAST_90_DAYS
startDatestringNo*Custom start date (YYYY-MM-DD)
endDatestringNo*Custom end date (YYYY-MM-DD)
metricsstring[]NoCustom metrics (defaults: impressions, clicks, cost_micros, conversions, ctr, average_cpc)
includeComputedMetricsbooleanNoAdd derived CPA, ROAS, CPM (default false)
limitnumberNoDeprecated. Use maxRows instead.
modeenumNo"summary" (default) returns headers + counts + 10-row preview; "rows" returns one bounded page of rows
columnsstring[]NoProject returned rows to selected columns
offsetnumberNoZero-based row offset for pagination (default: 0)
maxRowsnumberNoPage size before the 200-row hard cap (default: 10 for summary, 50 for rows)

*Provide either dateRange OR both startDate + endDate.

sa360_get_insights_breakdowns

Performance metrics with dimensional breakdowns (device, date, network, etc.).

ParameterTypeRequiredDescription
customerIdstringYesSA360 customer ID
entityTypeenumYescustomer, campaign, adGroup, adGroupAd, adGroupCriterion, or campaignCriterion
entityIdstringNoFilter to specific entity
dateRangeenumNo*Date range preset
startDatestringNo*Custom start date (YYYY-MM-DD)
endDatestringNo*Custom end date (YYYY-MM-DD)
breakdownsstring[]YesSegment dimensions (e.g., segments.date, segments.device)
metricsstring[]NoCustom metrics
includeComputedMetricsbooleanNoAdd derived CPA, ROAS, CPM (default false)
limitnumberNoDeprecated. Use maxRows instead.
modeenumNo"summary" (default) returns headers + counts + 10-row preview; "rows" returns one bounded page of rows
columnsstring[]NoProject returned rows to selected columns
offsetnumberNoZero-based row offset for pagination (default: 0)
maxRowsnumberNoPage size before the 200-row hard cap (default: 10 for summary, 50 for rows)

*Provide either dateRange OR both startDate + endDate.

Supported breakdowns: segments.date, segments.device, segments.ad_network_type, segments.conversion_action, segments.day_of_week, segments.month, segments.quarter, segments.week, segments.year

sa360_list_custom_columns

List custom columns defined for an SA360 customer account.

ParameterTypeRequiredDescription
customerIdstringYesSA360 customer ID

sa360_search_fields

Discover available fields, resources, and metrics in the SA360 API schema.

ParameterTypeRequiredDescription
querystringYesField discovery query
pageSizenumberNoMax results (default 100)
{
  "query": "SELECT name, category, data_type, selectable, filterable, sortable FROM searchAds360Fields WHERE name LIKE 'campaign.%'"
}

sa360_get_change_history

Get change history for SA360 entities using the change_event resource.

ParameterTypeRequiredDescription
customerIdstringYesSA360 customer ID
startDatestringYesStart date (YYYY-MM-DD)
endDatestringYesEnd date (YYYY-MM-DD)
resourceTypeenumNoFilter: CAMPAIGN, AD_GROUP, AD, KEYWORD, CRITERION
limitnumberNoMax results (default 100)

Async Reporting Tools (v2 API)

sa360_submit_report

Submit an asynchronous report request. Returns a report ID for polling.

ParameterTypeRequiredDescription
agencyIdstringYesSA360 agency ID
advertiserIdstringNoSA360 advertiser ID
reportTypeenumYescampaign, adGroup, keyword, ad, advertiser, etc.
columnsarrayYesColumns to include (min 1)
startDatestringYesReport start date (YYYY-MM-DD)
endDatestringYesReport end date (YYYY-MM-DD)
filtersarrayNoFilter conditions
includeRemovedEntitiesbooleanNoInclude deleted entities

sa360_check_report_status

Poll a submitted report until ready.

ParameterTypeRequiredDescription
reportIdstringYesReport ID from submit_report

sa360_download_report

Download a completed report file as parsed CSV.

ParameterTypeRequiredDescription
downloadUrlstringYesFile URL from check_report_status
modeenumNo"summary" (default) returns headers + counts + 10-row preview; "rows" returns one bounded page of rows
columnsstring[]NoProject returned rows to selected columns
offsetnumberNoZero-based row offset for pagination (default: 0)
maxRowsnumberNoPage size before the 200-row hard cap (default: 10 for summary, 50 for rows)

Conversion API v2 Tools (Write)

sa360_insert_conversions

Insert offline conversions via the legacy v2 API.

ParameterTypeRequiredDescription
agencyIdstringYesSA360 agency ID
advertiserIdstringYesSA360 advertiser ID
conversionsarrayYesConversion rows (max 200)

Each conversion row:

FieldTypeRequiredDescription
clickIdstringNoSA360 click ID
gclidstringNoGoogle click ID
conversionTimestampstringYesEpoch milliseconds
revenueMicrosstringNoRevenue (1,000,000 = 1 currency unit)
currencyCodestringNoISO 4217 currency code
segmentationTypestringYesSegment type (default: FLOODLIGHT)
floodlightActivityIdstringNoFloodlight activity ID
typestringNoACTION or TRANSACTION

sa360_update_conversions

Update existing conversions via the legacy v2 API.

Same parameters as sa360_insert_conversions, but each conversion row must include conversionId (returned from the original insert). Set state: "REMOVED" to delete a conversion.

Validation

sa360_validate_conversion

Validate a conversion payload before uploading (no API call).

Key Gotchas

IssueDetails
SA360 is read-only for entitiesNo create/update/delete for campaigns, ad groups, or ads. Only conversions and reports are writable.
cost_micros conventionAll monetary values are in micros (1,000,000 = 1 currency unit). Divide by 1M for display.
Dual APIReporting API v0 for reads, legacy v2 API for conversions and async reports. Different auth headers.
login-customer-idRequired for MCC (manager) accounts to access sub-accounts. Set via SA360_LOGIN_CUSTOMER_ID.
No developer tokenUnlike Google Ads, SA360 does not require a developer token — just OAuth2 credentials.
90-day conversion windowConversions older than 90 days are rejected by the v2 API.

Rate Limiting

  • Default: 100 requests/minute per customer ID
  • Separate rate limit pools for reporting API v0 and v2 API
  • Automatic exponential backoff on 429/5xx responses (max 3 retries)
  • Configurable via SA360_RATE_LIMIT_PER_MINUTE environment variable

Entity Types

SA360 supports 8 entity types for read-only access:

Entity TypeQuery ResourceID FieldHas Status
customercustomercustomer.idNo
campaigncampaigncampaign.idYes
adGroupad_groupad_group.idYes
adGroupAdad_group_adad_group_ad.ad.idYes
adGroupCriterionad_group_criterionad_group_criterion.criterion_idYes
campaignCriterioncampaign_criterioncampaign_criterion.criterion_idNo
biddingStrategybidding_strategybidding_strategy.idYes
conversionActionconversion_actionconversion_action.idYes

SA360 entities include an engine_id field that maps back to the source engine (Google Ads, Microsoft Ads, etc.), enabling cross-engine correlation.

Example Workflows

Cross-Engine Performance Analysis

User: "Compare campaign performance across all search engines for last month"

AI Agent:
1. sa360_list_accounts → discover accessible accounts
2. sa360_get_insights → campaign performance with LAST_MONTH date range
3. sa360_get_insights_breakdowns → break down by segments.ad_network_type
4. Synthesize cross-engine comparison report

Async Report for Large Datasets

User: "Pull keyword-level performance for Q1 across all advertisers"

AI Agent:
1. sa360_submit_report → submit async keyword report with Q1 date range
2. sa360_check_report_status → poll until isReportReady is true
3. sa360_download_report → download and parse CSV results
4. Analyze keyword performance across engines

Offline Conversion Upload

User: "Upload these CRM conversions to SA360 for bid optimization"

AI Agent:
1. sa360_list_entities (conversionAction) → find the right floodlight activity
2. sa360_insert_conversions → upload conversion data with gclids
3. Confirm upload with count and any errors

Field Discovery

User: "What metrics are available for SA360 campaign reporting?"

AI Agent:
1. sa360_search_fields → query for metrics.* fields
2. Present available metrics with data types and descriptions

Configuration Reference

VariableDefaultDescription
SA360_MCP_PORT3010HTTP server port
SA360_MCP_HOST127.0.0.1HTTP server bind address
MCP_AUTH_MODEsa360-headersAuth mode: sa360-headers, jwt, none
MCP_AUTH_SECRET_KEYJWT secret (jwt mode only)
SA360_API_BASE_URLhttps://searchads360.googleapis.com/v0Reporting API base URL
SA360_V2_API_BASE_URLhttps://www.googleapis.com/doubleclicksearch/v2Legacy v2 API base URL
SA360_RATE_LIMIT_PER_MINUTE100Rate limit per customer ID
SA360_CLIENT_IDOAuth2 client ID (stdio mode)
SA360_CLIENT_SECRETOAuth2 client secret (stdio mode)
SA360_REFRESH_TOKENOAuth2 refresh token (stdio mode)
SA360_LOGIN_CUSTOMER_IDManager account ID (optional)
LOG_LEVELinfoLogging level
OTEL_ENABLEDfalseEnable OpenTelemetry
OTEL_SERVICE_NAMEsa360-mcpOTEL service name

Architecture

packages/sa360-mcp/
├── package.json
├── tsconfig.json
├── .env.example
├── README.md
├── src/
│   ├── index.ts                          # Entry point (bootstrap)
│   ├── config/
│   │   └── index.ts                      # Environment config (Zod schema)
│   ├── auth/
│   │   ├── sa360-auth-adapter.ts         # OAuth2 refresh token adapter
│   │   └── sa360-auth-strategy.ts        # HTTP headers auth strategy
│   ├── services/
│   │   ├── session-services.ts           # Per-session service factory
│   │   ├── sa360/
│   │   │   ├── sa360-http-client.ts      # Reporting API v0 HTTP client
│   │   │   └── sa360-service.ts          # Query, entity, field operations
│   │   └── sa360-v2/
│   │       ├── sa360-v2-http-client.ts   # Legacy v2 HTTP client
│   │       ├── conversion-service.ts     # Conversion insert/update
│   │       └── reporting-service.ts      # Async report submit/poll/download
│   ├── mcp-server/
│   │   ├── server.ts                     # MCP server setup
│   │   ├── tools/
│   │   │   ├── index.ts
│   │   │   ├── definitions/              # 16 tool files
│   │   │   │   ├── sa360-search.tool.ts
│   │   │   │   ├── list-accounts.tool.ts
│   │   │   │   ├── list-entities.tool.ts
│   │   │   │   ├── get-entity.tool.ts
│   │   │   │   ├── get-insights.tool.ts
│   │   │   │   ├── get-insights-breakdowns.tool.ts
│   │   │   │   ├── list-custom-columns.tool.ts
│   │   │   │   ├── search-fields.tool.ts
│   │   │   │   ├── submit-report.tool.ts
│   │   │   │   ├── check-report-status.tool.ts
│   │   │   │   ├── download-report.tool.ts
│   │   │   │   ├── insert-conversions.tool.ts
│   │   │   │   ├── update-conversions.tool.ts
│   │   │   │   ├── validate-conversion.tool.ts
│   │   │   │   ├── get-change-history.tool.ts
│   │   │   │   └── index.ts
│   │   │   └── utils/
│   │   │       ├── entity-mapping.ts     # 8 entity type configs
│   │   │       ├── query-helpers.ts      # Query builder functions
│   │   │       ├── computed-metrics.ts   # Derived CPA/ROAS/CPM
│   │   │       └── resolve-session.ts    # Session service resolver
│   │   ├── resources/
│   │   │   ├── types.ts
│   │   │   └── index.ts
│   │   ├── prompts/
│   │   │   └── index.ts
│   │   └── transports/
│   │       └── streamable-http-transport.ts
│   ├── types-global/
│   │   └── mcp.ts
│   └── utils/
│       ├── telemetry/
│       │   ├── tracing.ts
│       │   └── index.ts
│       └── security/
│           └── rate-limiter.ts
└── tests/                                # 30 test files, 459 tests

Key Design Decisions

  • Dual HTTP clients: Separate clients for Reporting API v0 and legacy v2, since they have different base URLs, error formats, and auth requirements
  • No mutate operations: SA360 is read-only for entities — the server intentionally omits create/update/delete entity tools
  • GAQL-compatible query language: SA360 uses the same query syntax as Google Ads (GAQL), making it familiar for users of gads-mcp
  • Session services pattern: Per-session SessionServices with 5 service instances (httpClient, v2HttpClient, sa360Service, conversionService, reportingService)

Development

# Build
cd packages/sa360-mcp && pnpm run build

# Type check
pnpm run typecheck

# Run tests (459 tests)
pnpm run test

# Dev mode with hot reload
pnpm run dev:http

Get Started

Self-host: Follow the deployment guide to run this server on your own infrastructure.

Cesteral Intelligence: Request access -- governed execution with credential brokering, approvals, audit, and multi-tenant access.

Book a workflow demo: See it in action with your own ad accounts.

Compare options: OSS connectors vs Cesteral Intelligence

License

Apache License 2.0

Keywords

mcp

FAQs

Package last updated on 10 Jun 2026

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts