Camberstack
Server Configuration
Describes the environment variables required to run the server.
| Name | Required | Description | Default |
|---|---|---|---|
| BASE_URL | No | public origin, the OAuth issuer (default https://camberstack.io) | https://camberstack.io |
| DATA_DIR | No | SQLite location (default ./data) | ./data |
| PRO_EMAILS | No | billing gate for apply_changes (off during beta) | |
| ENCRYPTION_KEY | Yes | 32 bytes, hex or base64. Losing it only forces users to reconnect; leaking it exposes stored Google tokens | |
| GOOGLE_CLIENT_ID | Yes | OAuth client ID from a dedicated Google Cloud project with Google Ads API access. Redirect URI: <BASE_URL>/oauth/google/callback. Unset = pages only, sign-in reports "not open yet" | |
| APPLY_REQUIRES_PRO | No | billing gate for apply_changes (off during beta) | |
| GOOGLE_CLIENT_SECRET | Yes | OAuth client secret from a dedicated Google Cloud project with Google Ads API access. Redirect URI: <BASE_URL>/oauth/google/callback. Unset = pages only, sign-in reports "not open yet" | |
| GOOGLE_ADS_DEVELOPER_TOKEN | Yes | Google Ads API developer token, sent when set |
Instructions
Guidance the server publishes about itself, which clients place ahead of the tool catalog so the model reads it before choosing anything.
This server publishes no instructions, or was last inspected before Glama recorded them.
Capabilities
Features and capabilities supported by this server
Protocol revision2025-11-25
| Capability | Details |
|---|---|
| tools | {
"listChanged": true
} |
Tools
Functions exposed to the LLM to take actions
| Name | Description |
|---|---|
| list_accountsA | Lists every Google Ads account this login can reach, including client accounts under a manager (MCC). Start here. spentLast30Days says whether an account had ad spend in the last 30 days (show it when the user picks one). When the user's plan is at its limit, each account also says whether the plan covers it (plan_status: active, switch or locked). |
| account_overviewA | Spend, clicks, conversions and cost per conversion per campaign over a window, plus |
| run_gaqlA | Runs any read-only Google Ads Query Language SELECT for questions the other tools don't cover. Returns up to 500 rows. Google rejects queries that break these rules: selecting or segmenting by segments.date needs a finite range in WHERE (segments.date DURING LAST_30_DAYS, or BETWEEN 'YYYY-MM-DD' AND 'YYYY-MM-DD'); click_view needs a single day (segments.date = 'YYYY-MM-DD'); every field used in WHERE or ORDER BY must also be in SELECT. Maximize clicks is target_spend in the API: campaign.target_spend.cpc_bid_ceiling_micros (there is no campaign.maximize_clicks). Unsure of a field's name or whether it fits this FROM? Look it up first with a query that has no FROM, which reads Google's field catalog instead of the account (any customer_id): SELECT name, category, selectable WHERE name LIKE '%search_term%', or SELECT attribute_resources, metrics, segments WHERE name = 'campaign' for what can be used FROM campaign. |
| keyword_ideasA | Google Keyword Planner ideas from seed keywords and/or a landing-page URL: average monthly searches, competition and the top-of-page bid range in the account's currency, biggest first. Ideas the account already targets, or already blocks as negatives, are marked in_account. Changes nothing. |
| keyword_metricsA | Google Keyword Planner numbers for an exact list of keywords: average monthly searches, the last 12 months, competition and the top-of-page bid range in the account's currency. Use it to size keywords before adding them or to check a trend. Up to 100 keywords come back as one object each; over 100, as a compact table (columns, months, rows). Changes nothing. |
| search_console_sitesA | Lists the websites (Search Console properties) this Google login can read. Use a site_url from here in the other Search Console tools. |
| search_console_summaryA | A website's total organic Google Search clicks, impressions, CTR and average position over a window, next to the same number of days before it, with the change. Site-wide totals, more complete than adding up per-query rows. Changes nothing. |
| search_console_performanceA | Organic Google Search clicks, impressions, CTR and average position for a website, grouped by query, page, country, device or date, most clicks first. Search Console's last 2-3 days are incomplete, so the window ends 3 days ago unless fresh is set. Group by query and page together to see whether several pages compete for the same search; by page and date to see when a page's impressions or position changed. Changes nothing. |
| search_console_trendA | Compares a window with the same number of days right before it, query by query and page by page: rising, falling, new and lost queries, rising searches the site is losing position on, and rising and falling pages. Totals are the site's true totals. Changes nothing. |
| search_console_opportunitiesA | Finds where more organic clicks are within reach: queries on positions 4-20 with the clicks a realistic climb would add, top-5 queries with an unusually low click-through rate (a title or description to fix), and question-shaped queries. Changes nothing. |
| search_console_inspect_urlsA | Google's index record for each page: indexed or not and the reason (for example "Discovered - currently not indexed"), last crawl, robots.txt and fetch result, the canonical Google chose against the one the page declares, and structured-data items with their errors. Use it when a page gets no impressions, or seems to have dropped, before assuming a ranking problem. Changes nothing. |
| search_console_sitemapsA | The sitemaps submitted for a website: when Google last downloaded each one, how many URLs it lists, and its error and warning counts. Changes nothing: propose_search_console_changes submits one. |
| propose_search_console_changesA | Checks Search Console changes against the live property and stores them as a proposal with a plain-English summary; nothing is changed. Show the summary to the user and apply only after they approve, with apply_changes (undo_changes reverses it, except where a ⚠ line says it can't). Supported: submit_sitemap (also resubmits, so Google reads it again), delete_sitemap, add_site (unless the login already owns the domain, it stays unverified until the user verifies ownership in Search Console), remove_site. Requesting indexing isn't possible through Google's API. A connection made before editing existed answers with a link that adds it. Point out any ⚠ line before they approve. |
| paid_organic_overlapA | Joins a Google Ads account's search terms with a website's Search Console queries over the same days. Returns paid_and_ranking (searches you pay for where the site already ranks near the top organically, with ad spend) and organic_gaps (searches the site shows up for on page 2 or lower with no ad or keyword). Changes nothing; follow up with propose_changes. |
| analytics_propertiesA | Lists the Google Analytics 4 properties this Google login can read. Use a property_id from here in the other Google Analytics tools. If Google Analytics isn't part of the connection yet, says so and returns grant_url, a personal link the user opens to add it. |
| analytics_setupA | How a GA4 property is set up: its web streams with their measurement IDs (what the site's tag must use), which events are key events (GA4's conversions), and which Google Ads accounts it's linked to. Check this before proposing setup changes. Changes nothing. |
| propose_analytics_changesA | Checks Google Analytics setup changes against the live property and stores them as a proposal with a plain-English summary; nothing is changed. Show the summary to the user and apply only after they approve, with apply_changes (undo_changes reverses it). Supported: create_ga4_property (a property plus a web stream; the applied result gives the measurement ID and the tag the site needs), mark_key_event / unmark_key_event (GA4's conversions), set_key_event_counting (also recounts a Google Ads import of it), link_google_ads / unlink_google_ads. Point out any ⚠ line before they approve. |
| analytics_landing_pagesA | Where visitors land and whether it works: sessions, users, engagement rate, key events (GA4's conversions) and key event rate per landing page, most sessions first. Pass channel to see one source, e.g. "Paid Search" for Google Ads traffic or "Organic Search". Changes nothing. |
| analytics_reportA | Any GA4 report: dimensions and metrics by their GA4 API names, highest first. Common dimensions: date, landingPage, pagePath, sessionDefaultChannelGroup, sessionSourceMedium, sessionCampaignName, sessionGoogleAdsCampaignName, deviceCategory, country, eventName. Common metrics: sessions, totalUsers, engagedSessions, engagementRate, keyEvents, sessionKeyEventRate, screenPageViews, purchaseRevenue. Changes nothing. |
| merchant_accountsA | Lists the Google Merchant Center accounts this Google login can read, including sub-accounts of an advanced (multi-client) account. Use an account_id from here in the other Merchant Center tools. If Merchant Center isn't part of the connection yet, says so and returns grant_url, a personal link the user opens to add it. |
| merchant_product_issuesA | Why products aren't showing on Google (Shopping ads and free listings): the account's own issues, how many products are eligible, limited, pending or disapproved, and every product issue (such as a price mismatch or a missing GTIN) with how many products it affects, worst first, and a few example products. With offer_id, that one product's issues in full. Use it when Shopping or Performance Max spend or clicks drop, or products are missing. Changes nothing. |
| merchant_reportA | Runs a read-only Merchant Center Query Language (MCQL) query on one account and returns up to |
| merchant_ad_spendA | Which Merchant Center problems cost money: products that are disapproved, limited or pending, joined with what they earned in Shopping and Performance Max ads (cost, clicks, conversions, conversion value) over the window, most value first, and whether each has stopped spending in the last 7 days. Use it when Shopping or Performance Max results drop, before fixing issues one by one. Changes nothing. |
| propose_merchant_changesA | Checks Merchant Center product changes against the live account and stores them as a proposal with a plain-English summary; nothing is changed. Show the summary to the user and apply only after they approve, with apply_changes (undo_changes reverses it). Supported: set_product_attributes (override a product's price, sale price, GTIN, brand, title, availability, …, e.g. to fix a price mismatch or a missing GTIN), exclude_products / include_products (from Shopping ads or free listings), clear_product_overrides; and add_product / update_product / delete_product for products Camberstack creates in its own data source. Changes to products from the merchant's feed are overrides in Camberstack's own supplemental data source, layered on top: the feed itself is never edited. Point out any ⚠ line before they approve. A fix in the feed or the store (Shopify, …) lasts longer: suggest it too. |
| propose_changesA | Checks a set of changes against the live account and dry-runs them with Google, then stores them as a proposal and returns a plain-English summary. Nothing is changed. Show the summary to the user and apply only after they approve. Supported: add_negative_keywords, pause_campaign, enable_campaign, pause_keyword, enable_keyword, pause_ad_group, enable_ad_group, set_daily_budget, set_end_date, and building: create_campaign (Search), create_display_campaign, create_demand_gen_campaign (YouTube), create_performance_max_campaign, all created paused; add_ad_group, add_keywords, add_responsive_search_ad, add_sitelinks, set_conversion_goal; and tuning: set_keyword_bid, set_ad_group_bid, pause_ad, enable_ad (to replace an ad rather than edit it: add the new one and pause the old in one proposal), add_campaign_targeting, remove_campaign_targeting, set_location_mode, set_bidding_strategy, set_shared_bid_strategy, create_shared_bid_strategy, set_url_suffix, set_eu_political_advertising (Google refuses every change to an account until each campaign has declared this), create_conversion_action, set_conversion_counting, import_ga4_key_event, remove_conversion_action; and deleting: delete_keyword, delete_ad, delete_ad_group, delete_campaign (ads, ad groups and campaigns can't be undone), delete_negative_keywords, delete_sitelinks; and negatives: add_ad_group_negatives, delete_ad_group_negatives, create_negative_list, edit_negative_list, apply_negative_list, delete_negative_list; and edit_responsive_search_ad, which keeps the ad instead of replacing it; and set_ad_schedule, set_device_bid, add_campaign_assets, delete_campaign_assets, set_ai_max, set_conversion_settings; and create_remarketing_list, set_campaign_audience, act_on_recommendation; and link_merchant_center / unlink_merchant_center (Shopping and Performance Max need the link). Point out any ⚠ line in the summary to the user before they approve. At most 50 changes per proposal, counting each keyword in add_keywords and add_negative_keywords as one (a create_campaign or add_ad_group counts as one however much it holds); for more, split them into several proposals up front and show the user all the summaries together. |
| apply_changesA | Applies a proposal from propose_changes to the account. Only call this after the user has explicitly approved that proposal. All or nothing: every change is checked with Google first, and if one still fails the ones before it are rolled back. Each change is logged and, unless its summary says otherwise, can be reversed with undo_changes. If the account changed since the proposal, nothing is applied and the result (status "needs approval") is a new proposal with the updated summary: show it to the user and apply it only after they approve. |
| undo_changesA | Builds a new proposal that would reverse an applied one (removes the negatives it added, restores statuses and budgets). Changes nothing by itself: like any proposal, it must be approved and then applied with apply_changes. |
| discard_proposalA | Marks an open proposal as discarded so it can never be applied; this can't be reversed (propose again instead). Changes nothing in the Google Ads account. |
| change_historyB | Every proposal made through Camberstack, with what was applied, what failed, and what was undone. |
| switch_accountA | Spends the plan's one account switch per 30 days on customer_id: it becomes an active account, and the least recently used active account locks until the date the "Account switch:" notice gave, switching back included. Call it only after a tool answered "Account switch:" for this account and the user agreed, or answered "Account choice:" and the user picked this account (a first pick spends no switch). Called with neither, it answers with the "Account switch:" notice and spends nothing. Changes nothing in Google Ads; a no-op for an account that is already active. Merchant Center accounts are a separate allowance with their own switch: pass mc:<account_id>, as the notice gives it. |
| billingA | Shows the user's Camberstack plan: the Google Ads accounts used in the last 30 days against the number the plan covers (Free 1, Plus 1, Pro 5, Agency 25), and on Free which Google service it covers. Returns personal links to upgrade (Free to Plus or Pro, Plus to Pro, Pro to Agency) or to change card and cancel (paid plans). This is the Camberstack subscription only, not a Google Ads account's own billing, invoices or ad spend. |
| send_feedbackA | Sends the user's message to Camberstack's maintainer, who reads every one and can reply to the user's Google email. Use it when the user wants to report a bug or ask for something Camberstack doesn't do. Show them the exact message first and send it only after they agree. Put in only what they want said: no account IDs, campaign data or conversation history. |
| disconnectA | Revokes Camberstack's Google access and deletes the stored credentials. The user must confirm. |
Prompts
Interactive templates invoked by user choice
| Name | Description |
|---|---|
No prompts | |
Resources
Contextual data attached and managed by the client
| Name | Description |
|---|---|
No resources | |
TDQS
Scored across 33 tools
Tools are well-scoped by service and action (search_console_*, analytics_*, merchant_* are distinct resource families), so most are easy to tell apart. The four propose_* tools (propose_changes, propose_analytics_changes, propose_merchant_changes, propose_search_console_changes) overlap conceptually and rely on descriptions to separate them, and the multiple Search Console analysis tools (summary/performance/trend/opportunities) require reading descriptions to pick correctly.
Predominantly consistent snake_case with service-prefixed grouping (search_console_, analytics_, merchant_) and clear verb_noun action names (propose_*, apply_changes, undo_changes). Minor inconsistency: the generic Ads tool is 'propose_changes' while the others are 'propose_<service>_changes', and a few bare names (billing, disconnect) break the verb_noun pattern.
33 tools is heavy and pushes well past the typically-scoped range, requiring the agent to discriminate among many options. It is partly justified because the server spans four distinct Google services (Ads, Search Console, GA4, Merchant Center), but the count still feels borderline for smooth selection.
Coverage is broad across all four services: Ads full lifecycle (create/pause/edit/delete, bidding, negatives, conversions, audiences), Search Console read + sitemap/site changes, GA4 setup/reporting, and Merchant Center products/reports/ad spend, plus a generic GAQL escape hatch. Few obvious gaps, though some admin/edge operations depend on run_gaql and cross-service joins are limited to paid_organic_overlap.