<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Kanwar Kohli</title>
    <description>The latest articles on DEV Community by Kanwar Kohli (@kanwar_kohli).</description>
    <link>https://dev.to/kanwar_kohli</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3929700%2F52519bac-2d85-4f66-af47-5306edcca82c.png</url>
      <title>DEV Community: Kanwar Kohli</title>
      <link>https://dev.to/kanwar_kohli</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/kanwar_kohli"/>
    <language>en</language>
    <item>
      <title>I built a Google Ads MCP because AI could read my data but couldn't fix it</title>
      <dc:creator>Kanwar Kohli</dc:creator>
      <pubDate>Sat, 23 May 2026 21:32:45 +0000</pubDate>
      <link>https://dev.to/kanwar_kohli/i-built-a-google-ads-mcp-because-ai-could-read-my-data-but-couldnt-fix-it-4dik</link>
      <guid>https://dev.to/kanwar_kohli/i-built-a-google-ads-mcp-because-ai-could-read-my-data-but-couldnt-fix-it-4dik</guid>
      <description>&lt;p&gt;I own a wood-fired pizza restaurant in Iowa.&lt;/p&gt;

&lt;p&gt;Last month I noticed my Google Ads were burning money. Low conversions, weird CPC spikes on Fridays, one campaign doing everything. I asked Claude to help me fix it. Claude could read the data. It could tell me what was wrong. But it couldn't actually change anything.&lt;/p&gt;

&lt;p&gt;So I built GadsChain.&lt;/p&gt;




&lt;h2&gt;
  
  
  The problem with existing tools
&lt;/h2&gt;

&lt;p&gt;Windsor.ai and Supermetrics connect AI to Google Ads data. They're great for analytics. But they can only read — pause a campaign, update a budget, add negative keywords? Not possible.&lt;/p&gt;

&lt;p&gt;I needed AI that could act, not just report.&lt;/p&gt;




&lt;h2&gt;
  
  
  What I found in the data
&lt;/h2&gt;

&lt;p&gt;Before building anything, I pulled 28 days of my restaurant's Google Ads data and had Claude analyze it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Total spend:       $51.41 over 28 days
Clicks:            163
Impressions:       3,389
CTR:               4.81% (above average)
Conversions:       3
Cost/conversion:   $17.14
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The CTR was actually good. The problem was elsewhere.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Finding 1 — Friday anomaly.&lt;/strong&gt; Friday CPC was $0.11 vs $0.44 average. That's Display Network traffic mixing in — low intent, low quality clicks burning budget.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Finding 2 — Conversion tracking broken.&lt;/strong&gt; Only 3 conversions in 28 days from 163 clicks. Most days showed zero. The tracking wasn't firing correctly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Finding 3 — Destination URL broken.&lt;/strong&gt; The campaign was pointing to a subdomain I'd deleted months ago during a DNS cleanup. Google had been trying to crawl a dead URL since May 3. Zero impressions for three weeks because of one broken link.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Finding 4 — Wrong campaign type.&lt;/strong&gt; Running Performance Max instead of Search. PMax is opaque and needs 30+ conversions to optimize. With 3 conversions it was flying blind.&lt;/p&gt;

&lt;p&gt;Claude identified all of this. But I had to fix it manually — clicking through Google Ads UI one setting at a time.&lt;/p&gt;

&lt;p&gt;That's the gap GadsChain fills.&lt;/p&gt;




&lt;h2&gt;
  
  
  What GadsChain does
&lt;/h2&gt;

&lt;p&gt;GadsChain is an open-source MCP server that gives AI assistants direct write access to Google Ads.&lt;/p&gt;

&lt;p&gt;Three layers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Google Ads API → [Fetch] → [Transform] → [Act] → AI Agent
                  GAQL      micros→$      mutate
                  queries   CTR norm      campaigns
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Fetch&lt;/strong&gt; — GAQL queries for campaigns, search terms, budget data.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Transform&lt;/strong&gt; — Converts raw protobuf responses. Micros to dollars, decimal CTR to percentage, enum names extracted, None values handled gracefully. The AI gets clean data, not raw API output.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Act&lt;/strong&gt; — Six tools that actually change things:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nf"&gt;get_campaigns&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;customer_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;get_search_terms&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;customer_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;campaign_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;days&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;update_budget&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;customer_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;campaign_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;daily_budget_usd&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;pause_campaign&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;customer_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;campaign_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;enable_campaign&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;customer_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;campaign_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;add_negative_keywords&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;customer_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;campaign_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;keywords&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Safety controls built in:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;REMOVED&lt;/code&gt; status blocked — irreversible, hard error&lt;/li&gt;
&lt;li&gt;Shared budgets refused — explicit error instead of silent mutation affecting multiple campaigns&lt;/li&gt;
&lt;li&gt;Missing credentials raise on first tool call, not import&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  The stack
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Language:     Python 3.11
MCP layer:    FastMCP
Google Ads:   google-ads &amp;gt;= 24.0.0
Validation:   Pydantic v2
Config:       python-dotenv
Container:    Docker
Registry:     PyPI
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Same stack as ThinChain, our first server (options chain data, 95% token reduction). The pattern works — FastMCP handles the MCP protocol, you focus on the domain logic.&lt;/p&gt;




&lt;h2&gt;
  
  
  Real numbers after fixes
&lt;/h2&gt;

&lt;p&gt;Within 24 hours of fixing the destination URL and requesting review:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ads back in Google's review queue&lt;/li&gt;
&lt;li&gt;Budget raised from $7 to $20/day&lt;/li&gt;
&lt;li&gt;Display Network waste identified and addressable&lt;/li&gt;
&lt;li&gt;Conversion tracking being rebuilt&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Before GadsChain: AI reads your ad data, you fix it manually.&lt;br&gt;&lt;br&gt;
After GadsChain: AI reads your ad data, AI fixes it.&lt;/p&gt;




&lt;h2&gt;
  
  
  This is the SnipMCP pattern
&lt;/h2&gt;

&lt;p&gt;GadsChain is the second server under SnipMCP. The thesis:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Every domain has the same problem — raw API data is too noisy, too large, and too complex for AI agents to act on reliably. SnipMCP builds domain-aware MCP servers that sanitize, compress, and structure that data before it reaches the model.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;ThinChain:&lt;/strong&gt; 482 option strikes → 25 relevant ones (95% token reduction)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;GadsChain:&lt;/strong&gt; thousands of ad metrics → actionable signals&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Same pattern. Different domain. We're building more.&lt;/p&gt;




&lt;h2&gt;
  
  
  Get started
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;gadschain
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You'll need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Google Ads Manager Account (MCC)&lt;/li&gt;
&lt;li&gt;Developer token (apply at Google Ads API Center)&lt;/li&gt;
&lt;li&gt;OAuth2 credentials from Google Cloud Console&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Full setup guide in the README.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GitHub:&lt;/strong&gt; &lt;a href="https://github.com/SnipMCP/gadschain" rel="noopener noreferrer"&gt;github.com/SnipMCP/gadschain&lt;/a&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;ThinChain:&lt;/strong&gt; &lt;a href="https://github.com/SnipMCP/thinchain" rel="noopener noreferrer"&gt;github.com/SnipMCP/thinchain&lt;/a&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Platform:&lt;/strong&gt; &lt;a href="https://snipmcp.com" rel="noopener noreferrer"&gt;snipmcp.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;PRs welcome. If you're building MCP servers for other domains, we'd like to talk.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>mcp</category>
      <category>python</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Built a small tool that tells you why your AWS bill changed each week</title>
      <dc:creator>Kanwar Kohli</dc:creator>
      <pubDate>Wed, 13 May 2026 16:03:47 +0000</pubDate>
      <link>https://dev.to/kanwar_kohli/built-a-small-tool-that-tells-you-why-your-aws-bill-changed-each-week-3klo</link>
      <guid>https://dev.to/kanwar_kohli/built-a-small-tool-that-tells-you-why-your-aws-bill-changed-each-week-3klo</guid>
      <description>&lt;p&gt;Over the past year I kept seeing the same AWS problem across founders and small engineering teams: the bill changes faster than people can explain it.&lt;br&gt;
Usually nobody notices until month-end, and by then they're digging through Cost Explorer trying to figure out which service changed, what deployment caused it, and whether it's real growth or waste.&lt;br&gt;
So I built a lightweight tool called ThinCost.&lt;br&gt;
It connects to AWS using a read-only IAM role and sends a weekly email explaining what changed, which services drove the increase, potential waste, and concrete actions to reduce spend.&lt;br&gt;
The goal wasn't another dashboard. It was: "Tell me in plain English why my AWS bill changed."&lt;br&gt;
Setup is about 60 seconds: email + AWS account ID → deploy a CloudFormation stack → done. No stored credentials. No write access. Read-only permissions only.&lt;br&gt;
Looking for a handful of beta testers running real AWS workloads. Happy to give free access for a few months in exchange for honest feedback.&lt;br&gt;
→ thincost.com&lt;/p&gt;

</description>
      <category>aws</category>
      <category>monitoring</category>
      <category>showdev</category>
      <category>tooling</category>
    </item>
  </channel>
</rss>
