google-ads-intent-mcp 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (25) hide show
  1. google_ads_intent_mcp-0.1.0/.github/workflows/ci.yml +19 -0
  2. google_ads_intent_mcp-0.1.0/.github/workflows/pypi.yml +57 -0
  3. google_ads_intent_mcp-0.1.0/.gitignore +13 -0
  4. google_ads_intent_mcp-0.1.0/LICENSE +21 -0
  5. google_ads_intent_mcp-0.1.0/PKG-INFO +145 -0
  6. google_ads_intent_mcp-0.1.0/README.md +116 -0
  7. google_ads_intent_mcp-0.1.0/SECURITY.md +5 -0
  8. google_ads_intent_mcp-0.1.0/docs/pypi-publishing.md +22 -0
  9. google_ads_intent_mcp-0.1.0/examples/claude-desktop.json +8 -0
  10. google_ads_intent_mcp-0.1.0/examples/hermes.yaml +6 -0
  11. google_ads_intent_mcp-0.1.0/examples/search_terms.csv +4 -0
  12. google_ads_intent_mcp-0.1.0/llms.txt +20 -0
  13. google_ads_intent_mcp-0.1.0/pyproject.toml +41 -0
  14. google_ads_intent_mcp-0.1.0/server.json +60 -0
  15. google_ads_intent_mcp-0.1.0/src/google_ads_intent_mcp/__init__.py +14 -0
  16. google_ads_intent_mcp-0.1.0/src/google_ads_intent_mcp/__main__.py +3 -0
  17. google_ads_intent_mcp-0.1.0/src/google_ads_intent_mcp/agent.py +93 -0
  18. google_ads_intent_mcp-0.1.0/src/google_ads_intent_mcp/cli.py +67 -0
  19. google_ads_intent_mcp-0.1.0/src/google_ads_intent_mcp/csv_io.py +9 -0
  20. google_ads_intent_mcp-0.1.0/src/google_ads_intent_mcp/intent.py +126 -0
  21. google_ads_intent_mcp-0.1.0/src/google_ads_intent_mcp/mcp_server.py +50 -0
  22. google_ads_intent_mcp-0.1.0/src/google_ads_intent_mcp/negatives.py +27 -0
  23. google_ads_intent_mcp-0.1.0/tests/test_google_ads_intent_mcp.py +65 -0
  24. google_ads_intent_mcp-0.1.0/tests/test_metadata.py +24 -0
  25. google_ads_intent_mcp-0.1.0/uv.lock +1286 -0
@@ -0,0 +1,19 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ pull_request:
6
+
7
+ jobs:
8
+ test:
9
+ runs-on: ubuntu-latest
10
+ steps:
11
+ - uses: actions/checkout@v4
12
+ - uses: actions/setup-python@v5
13
+ with:
14
+ python-version: "3.11"
15
+ cache: pip
16
+ - run: python -m pip install --upgrade pip
17
+ - run: pip install -e ".[dev]"
18
+ - run: python -m compileall -q src
19
+ - run: pytest
@@ -0,0 +1,57 @@
1
+ name: Publish to PyPI
2
+
3
+ on:
4
+ workflow_dispatch:
5
+ release:
6
+ types: [published]
7
+
8
+ concurrency:
9
+ group: pypi-${{ github.ref }}
10
+ cancel-in-progress: false
11
+
12
+ jobs:
13
+ build:
14
+ name: Build distributions
15
+ runs-on: ubuntu-latest
16
+ permissions:
17
+ contents: read
18
+ steps:
19
+ - name: Check out repository
20
+ uses: actions/checkout@v4
21
+
22
+ - name: Set up Python
23
+ uses: actions/setup-python@v5
24
+ with:
25
+ python-version: "3.12"
26
+
27
+ - name: Install build tooling
28
+ run: python -m pip install --upgrade pip build twine
29
+
30
+ - name: Build package
31
+ run: python -m build
32
+
33
+ - name: Check distributions
34
+ run: python -m twine check dist/*
35
+
36
+ - name: Upload distributions
37
+ uses: actions/upload-artifact@v4
38
+ with:
39
+ name: python-package-distributions
40
+ path: dist/
41
+
42
+ publish:
43
+ name: Publish package
44
+ needs: build
45
+ runs-on: ubuntu-latest
46
+ environment: pypi
47
+ permissions:
48
+ id-token: write
49
+ steps:
50
+ - name: Download distributions
51
+ uses: actions/download-artifact@v4
52
+ with:
53
+ name: python-package-distributions
54
+ path: dist/
55
+
56
+ - name: Publish to PyPI
57
+ uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,13 @@
1
+ .venv/
2
+ __pycache__/
3
+ *.py[cod]
4
+ .pytest_cache/
5
+ .mypy_cache/
6
+ .env
7
+ credentials/
8
+ google-ads.yaml
9
+ token.json
10
+ dist/
11
+ build/
12
+ *.egg-info/
13
+ .DS_Store
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 David Mosiah
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,145 @@
1
+ Metadata-Version: 2.4
2
+ Name: google-ads-intent-mcp
3
+ Version: 0.1.0
4
+ Summary: Dry-run-first Google Ads search-term intent analyzer with CLI and optional MCP server.
5
+ Project-URL: Homepage, https://github.com/davidmosiah/google-ads-intent-mcp
6
+ Project-URL: Repository, https://github.com/davidmosiah/google-ads-intent-mcp
7
+ Project-URL: Issues, https://github.com/davidmosiah/google-ads-intent-mcp/issues
8
+ Author: David Mosiah
9
+ License-Expression: MIT
10
+ License-File: LICENSE
11
+ Keywords: agent-tools,agentic-workflows,ai-agents,google-ads,local-first,mcp,mcp-server,negative-keywords,ppc,search-terms
12
+ Classifier: Development Status :: 3 - Alpha
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3 :: Only
17
+ Classifier: Topic :: Office/Business
18
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
19
+ Requires-Python: >=3.10
20
+ Provides-Extra: dev
21
+ Requires-Dist: pytest>=8.0; extra == 'dev'
22
+ Provides-Extra: google-ads
23
+ Requires-Dist: google-ads>=29.0.0; extra == 'google-ads'
24
+ Requires-Dist: google-auth-oauthlib>=1.0.0; extra == 'google-ads'
25
+ Requires-Dist: pyyaml>=6.0; extra == 'google-ads'
26
+ Provides-Extra: mcp
27
+ Requires-Dist: mcp>=1.13.0; extra == 'mcp'
28
+ Description-Content-Type: text/markdown
29
+
30
+ # Google Ads Intent MCP
31
+
32
+ [![GitHub stars](https://img.shields.io/github/stars/davidmosiah/google-ads-intent-mcp?style=flat-square&logo=github)](https://github.com/davidmosiah/google-ads-intent-mcp/stargazers)
33
+ [![CI](https://github.com/davidmosiah/google-ads-intent-mcp/actions/workflows/ci.yml/badge.svg)](https://github.com/davidmosiah/google-ads-intent-mcp/actions/workflows/ci.yml)
34
+ [![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)
35
+ [![Agent-first](https://img.shields.io/badge/agent--first-MCP-0ea5a3?style=flat-square)](https://github.com/davidmosiah/google-ads-intent-mcp)
36
+
37
+ > If this agent-first tool helps your workflow, please star the repo. Stars make this agent-first tooling easier for other builders to discover and help Delx keep shipping open infrastructure.
38
+
39
+ Dry-run-first Google Ads search-term intent analyzer for agents. It helps Codex, Claude, Cursor, Hermes, OpenClaw and other MCP clients classify search terms, protect buyer intent and draft negative-keyword plans from CSV exports before any live account change.
40
+
41
+ Use it when an agent needs to reduce wasted spend without accidentally excluding buyer-intent queries.
42
+
43
+ ## Why It Exists
44
+
45
+ Google Ads cleanup is risky when agents act directly on accounts. This package makes the safe path the default:
46
+
47
+ - analyze exported search-term CSVs locally
48
+ - classify waste, buyer, research and competitor intent
49
+ - draft negative-keyword plans without applying them
50
+ - expose `manifest`, `connection_status` and `privacy_audit` before action tools
51
+ - keep live mutation out of v0.1
52
+
53
+ ## Install
54
+
55
+ ```bash
56
+ pipx install "git+https://github.com/davidmosiah/google-ads-intent-mcp.git"
57
+ ```
58
+
59
+ With MCP support:
60
+
61
+ ```bash
62
+ pipx install "git+https://github.com/davidmosiah/google-ads-intent-mcp.git#egg=google-ads-intent-mcp[mcp]"
63
+ ```
64
+
65
+ PyPI release automation is configured with Trusted Publishing. See [docs/pypi-publishing.md](docs/pypi-publishing.md) for the one-time PyPI pending-publisher setup.
66
+
67
+ ## CLI
68
+
69
+ ```bash
70
+ google-ads-intent manifest --client codex
71
+ google-ads-intent doctor
72
+ google-ads-intent privacy-audit
73
+ google-ads-intent classify "free robux generator no verification"
74
+ google-ads-intent analyze-csv --csv examples/search_terms.csv
75
+ google-ads-intent plan-negatives --csv examples/search_terms.csv
76
+ ```
77
+
78
+ ## MCP
79
+
80
+ ```bash
81
+ google-ads-intent-mcp
82
+ ```
83
+
84
+ Hermes-style config:
85
+
86
+ ```yaml
87
+ mcp_servers:
88
+ google_ads_intent:
89
+ command: google-ads-intent-mcp
90
+ args: []
91
+ sampling:
92
+ enabled: false
93
+ ```
94
+
95
+ Recommended first calls:
96
+
97
+ 1. `google_ads_connection_status`
98
+ 2. `google_ads_privacy_audit`
99
+ 3. `google_ads_analyze_search_terms`
100
+ 4. `google_ads_build_negative_plan`
101
+
102
+ ## Agent Surfaces
103
+
104
+ | Tool | Purpose |
105
+ |---|---|
106
+ | `google_ads_agent_manifest` | Install/runtime guidance for agent clients |
107
+ | `google_ads_connection_status` | CSV/API readiness without credentials |
108
+ | `google_ads_privacy_audit` | Dry-run, account and export boundaries |
109
+ | `google_ads_classify_search_term` | Single-query intent classification |
110
+ | `google_ads_analyze_search_terms` | Batch CSV-style analysis |
111
+ | `google_ads_build_negative_plan` | Dry-run negative keyword plan |
112
+
113
+ ## Copy-Paste Agent Prompt
114
+
115
+ ```text
116
+ Use google-ads-intent-mcp. First call google_ads_connection_status and google_ads_privacy_audit.
117
+ Analyze the search terms, protect buyer/conversion queries, and return a dry-run negative plan only.
118
+ ```
119
+
120
+ ## CSV Format
121
+
122
+ The parser accepts common exported columns such as:
123
+
124
+ - `search_term`, `Search term`, `Query`
125
+ - `cost`, `Cost`, `cost_micros`
126
+ - `clicks`, `Clicks`
127
+ - `conversions`, `Conversions`, `Conv.`
128
+ - `impressions`, `Impr.`, `Impressions`
129
+
130
+ ## Safety Model
131
+
132
+ - CSV analysis is local.
133
+ - Negative plans are dry-run only.
134
+ - Buyer/conversion terms are protected from automatic exclusion.
135
+ - OAuth tokens, developer tokens and account identifiers should stay in local environment/config files.
136
+
137
+ ## Development
138
+
139
+ ```bash
140
+ python3 -m venv .venv
141
+ . .venv/bin/activate
142
+ pip install -e ".[dev]"
143
+ pytest
144
+ python -m compileall -q src
145
+ ```
@@ -0,0 +1,116 @@
1
+ # Google Ads Intent MCP
2
+
3
+ [![GitHub stars](https://img.shields.io/github/stars/davidmosiah/google-ads-intent-mcp?style=flat-square&logo=github)](https://github.com/davidmosiah/google-ads-intent-mcp/stargazers)
4
+ [![CI](https://github.com/davidmosiah/google-ads-intent-mcp/actions/workflows/ci.yml/badge.svg)](https://github.com/davidmosiah/google-ads-intent-mcp/actions/workflows/ci.yml)
5
+ [![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)
6
+ [![Agent-first](https://img.shields.io/badge/agent--first-MCP-0ea5a3?style=flat-square)](https://github.com/davidmosiah/google-ads-intent-mcp)
7
+
8
+ > If this agent-first tool helps your workflow, please star the repo. Stars make this agent-first tooling easier for other builders to discover and help Delx keep shipping open infrastructure.
9
+
10
+ Dry-run-first Google Ads search-term intent analyzer for agents. It helps Codex, Claude, Cursor, Hermes, OpenClaw and other MCP clients classify search terms, protect buyer intent and draft negative-keyword plans from CSV exports before any live account change.
11
+
12
+ Use it when an agent needs to reduce wasted spend without accidentally excluding buyer-intent queries.
13
+
14
+ ## Why It Exists
15
+
16
+ Google Ads cleanup is risky when agents act directly on accounts. This package makes the safe path the default:
17
+
18
+ - analyze exported search-term CSVs locally
19
+ - classify waste, buyer, research and competitor intent
20
+ - draft negative-keyword plans without applying them
21
+ - expose `manifest`, `connection_status` and `privacy_audit` before action tools
22
+ - keep live mutation out of v0.1
23
+
24
+ ## Install
25
+
26
+ ```bash
27
+ pipx install "git+https://github.com/davidmosiah/google-ads-intent-mcp.git"
28
+ ```
29
+
30
+ With MCP support:
31
+
32
+ ```bash
33
+ pipx install "git+https://github.com/davidmosiah/google-ads-intent-mcp.git#egg=google-ads-intent-mcp[mcp]"
34
+ ```
35
+
36
+ PyPI release automation is configured with Trusted Publishing. See [docs/pypi-publishing.md](docs/pypi-publishing.md) for the one-time PyPI pending-publisher setup.
37
+
38
+ ## CLI
39
+
40
+ ```bash
41
+ google-ads-intent manifest --client codex
42
+ google-ads-intent doctor
43
+ google-ads-intent privacy-audit
44
+ google-ads-intent classify "free robux generator no verification"
45
+ google-ads-intent analyze-csv --csv examples/search_terms.csv
46
+ google-ads-intent plan-negatives --csv examples/search_terms.csv
47
+ ```
48
+
49
+ ## MCP
50
+
51
+ ```bash
52
+ google-ads-intent-mcp
53
+ ```
54
+
55
+ Hermes-style config:
56
+
57
+ ```yaml
58
+ mcp_servers:
59
+ google_ads_intent:
60
+ command: google-ads-intent-mcp
61
+ args: []
62
+ sampling:
63
+ enabled: false
64
+ ```
65
+
66
+ Recommended first calls:
67
+
68
+ 1. `google_ads_connection_status`
69
+ 2. `google_ads_privacy_audit`
70
+ 3. `google_ads_analyze_search_terms`
71
+ 4. `google_ads_build_negative_plan`
72
+
73
+ ## Agent Surfaces
74
+
75
+ | Tool | Purpose |
76
+ |---|---|
77
+ | `google_ads_agent_manifest` | Install/runtime guidance for agent clients |
78
+ | `google_ads_connection_status` | CSV/API readiness without credentials |
79
+ | `google_ads_privacy_audit` | Dry-run, account and export boundaries |
80
+ | `google_ads_classify_search_term` | Single-query intent classification |
81
+ | `google_ads_analyze_search_terms` | Batch CSV-style analysis |
82
+ | `google_ads_build_negative_plan` | Dry-run negative keyword plan |
83
+
84
+ ## Copy-Paste Agent Prompt
85
+
86
+ ```text
87
+ Use google-ads-intent-mcp. First call google_ads_connection_status and google_ads_privacy_audit.
88
+ Analyze the search terms, protect buyer/conversion queries, and return a dry-run negative plan only.
89
+ ```
90
+
91
+ ## CSV Format
92
+
93
+ The parser accepts common exported columns such as:
94
+
95
+ - `search_term`, `Search term`, `Query`
96
+ - `cost`, `Cost`, `cost_micros`
97
+ - `clicks`, `Clicks`
98
+ - `conversions`, `Conversions`, `Conv.`
99
+ - `impressions`, `Impr.`, `Impressions`
100
+
101
+ ## Safety Model
102
+
103
+ - CSV analysis is local.
104
+ - Negative plans are dry-run only.
105
+ - Buyer/conversion terms are protected from automatic exclusion.
106
+ - OAuth tokens, developer tokens and account identifiers should stay in local environment/config files.
107
+
108
+ ## Development
109
+
110
+ ```bash
111
+ python3 -m venv .venv
112
+ . .venv/bin/activate
113
+ pip install -e ".[dev]"
114
+ pytest
115
+ python -m compileall -q src
116
+ ```
@@ -0,0 +1,5 @@
1
+ # Security Policy
2
+
3
+ Do not include OAuth tokens, developer tokens, account identifiers or raw private campaign exports in issues. Redact sensitive account details before sharing logs.
4
+
5
+ The package is dry-run-first. Live Google Ads mutation is intentionally not automatic in v0.1.
@@ -0,0 +1,22 @@
1
+ # PyPI publishing
2
+
3
+ This package is configured for PyPI Trusted Publishing through GitHub Actions.
4
+ No long-lived PyPI token is required in GitHub secrets or local config.
5
+
6
+ ## One-time PyPI setup
7
+
8
+ Create a pending GitHub publisher in PyPI account settings:
9
+
10
+ - PyPI project name: `google-ads-intent-mcp`
11
+ - Owner: `davidmosiah`
12
+ - Repository name: `google-ads-intent-mcp`
13
+ - Workflow name: `pypi.yml`
14
+ - Environment name: `pypi`
15
+
16
+ PyPI docs:
17
+
18
+ - Pending publishers: https://docs.pypi.org/trusted-publishers/creating-a-project-through-oidc/
19
+ - Publishing workflow: https://docs.pypi.org/trusted-publishers/using-a-publisher/
20
+
21
+ After the pending publisher exists, run the `Publish to PyPI` GitHub Actions
22
+ workflow manually or publish a GitHub release.
@@ -0,0 +1,8 @@
1
+ {
2
+ "mcpServers": {
3
+ "google_ads_intent": {
4
+ "command": "google-ads-intent-mcp",
5
+ "args": []
6
+ }
7
+ }
8
+ }
@@ -0,0 +1,6 @@
1
+ mcp_servers:
2
+ google_ads_intent:
3
+ command: google-ads-intent-mcp
4
+ args: []
5
+ sampling:
6
+ enabled: false
@@ -0,0 +1,4 @@
1
+ search_term,cost,clicks,conversions,impressions
2
+ free robux generator,12.50,8,0,120
3
+ ai automation agency pricing,20.00,2,1,24
4
+ best workflow automation platform,8.25,3,0,80
@@ -0,0 +1,20 @@
1
+ # Google Ads Intent MCP
2
+
3
+ Dry-run-first Google Ads search-term intent analyzer with CLI and optional MCP server.
4
+
5
+ Repository: https://github.com/davidmosiah/google-ads-intent-mcp
6
+ Install: pipx install "git+https://github.com/davidmosiah/google-ads-intent-mcp.git"
7
+ MCP command: google-ads-intent-mcp
8
+
9
+ Core tools:
10
+ - google_ads_agent_manifest
11
+ - google_ads_connection_status
12
+ - google_ads_privacy_audit
13
+ - google_ads_classify_search_term
14
+ - google_ads_analyze_search_terms
15
+ - google_ads_build_negative_plan
16
+
17
+ Safety:
18
+ - CSV analysis is local.
19
+ - Negative plans are dry-run only.
20
+ - Live Google Ads mutation is intentionally not automatic in v0.1.
@@ -0,0 +1,41 @@
1
+ [build-system]
2
+ requires = ["hatchling>=1.26"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "google-ads-intent-mcp"
7
+ version = "0.1.0"
8
+ description = "Dry-run-first Google Ads search-term intent analyzer with CLI and optional MCP server."
9
+ readme = "README.md"
10
+ requires-python = ">=3.10"
11
+ license = "MIT"
12
+ authors = [{ name = "David Mosiah" }]
13
+ keywords = ["ai-agents", "agent-tools", "agentic-workflows", "mcp", "mcp-server", "google-ads", "search-terms", "negative-keywords", "ppc", "local-first"]
14
+ dependencies = []
15
+ classifiers = [
16
+ "Development Status :: 3 - Alpha",
17
+ "Intended Audience :: Developers",
18
+ "License :: OSI Approved :: MIT License",
19
+ "Programming Language :: Python :: 3",
20
+ "Programming Language :: Python :: 3 :: Only",
21
+ "Topic :: Office/Business",
22
+ "Topic :: Software Development :: Libraries :: Python Modules",
23
+ ]
24
+
25
+ [project.optional-dependencies]
26
+ mcp = ["mcp>=1.13.0"]
27
+ google-ads = ["google-ads>=29.0.0", "google-auth-oauthlib>=1.0.0", "pyyaml>=6.0"]
28
+ dev = ["pytest>=8.0"]
29
+
30
+ [project.scripts]
31
+ google-ads-intent = "google_ads_intent_mcp.cli:main"
32
+ google-ads-intent-mcp = "google_ads_intent_mcp.mcp_server:main"
33
+
34
+ [project.urls]
35
+ Homepage = "https://github.com/davidmosiah/google-ads-intent-mcp"
36
+ Repository = "https://github.com/davidmosiah/google-ads-intent-mcp"
37
+ Issues = "https://github.com/davidmosiah/google-ads-intent-mcp/issues"
38
+
39
+ [tool.pytest.ini_options]
40
+ pythonpath = ["src"]
41
+ testpaths = ["tests"]
@@ -0,0 +1,60 @@
1
+ {
2
+ "$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
3
+ "name": "io.github.davidmosiah/google-ads-intent-mcp",
4
+ "description": "Dry-run-first Google Ads search-term intent analyzer and negative-keyword MCP for agents.",
5
+ "status": "active",
6
+ "repository": {
7
+ "url": "https://github.com/davidmosiah/google-ads-intent-mcp",
8
+ "source": "github"
9
+ },
10
+ "version": "0.1.0",
11
+ "packages": [
12
+ {
13
+ "registryType": "pypi",
14
+ "identifier": "google-ads-intent-mcp",
15
+ "version": "0.1.0",
16
+ "transport": {
17
+ "type": "stdio"
18
+ },
19
+ "environmentVariables": [
20
+ {
21
+ "name": "GOOGLE_ADS_DEVELOPER_TOKEN",
22
+ "description": "Google Ads developer token used only when live Google Ads access is configured.",
23
+ "isRequired": false,
24
+ "format": "string",
25
+ "isSecret": true
26
+ },
27
+ {
28
+ "name": "GOOGLE_ADS_CLIENT_ID",
29
+ "description": "OAuth client ID used only when live Google Ads access is configured.",
30
+ "isRequired": false,
31
+ "format": "string",
32
+ "isSecret": false
33
+ },
34
+ {
35
+ "name": "GOOGLE_ADS_CLIENT_SECRET",
36
+ "description": "OAuth client secret used only when live Google Ads access is configured.",
37
+ "isRequired": false,
38
+ "format": "string",
39
+ "isSecret": true
40
+ },
41
+ {
42
+ "name": "GOOGLE_ADS_REFRESH_TOKEN",
43
+ "description": "OAuth refresh token used only when live Google Ads access is configured.",
44
+ "isRequired": false,
45
+ "format": "string",
46
+ "isSecret": true
47
+ },
48
+ {
49
+ "name": "GOOGLE_ADS_CUSTOMER_ID",
50
+ "description": "Google Ads customer ID for live account queries.",
51
+ "isRequired": false,
52
+ "format": "string",
53
+ "isSecret": false
54
+ }
55
+ ]
56
+ }
57
+ ],
58
+ "remotes": [],
59
+ "websiteUrl": "https://github.com/davidmosiah/google-ads-intent-mcp"
60
+ }
@@ -0,0 +1,14 @@
1
+ """Agent-first Google Ads intent analysis toolkit."""
2
+
3
+ from .agent import build_agent_manifest, build_connection_status, build_privacy_audit
4
+ from .intent import analyze_search_terms, classify_search_term
5
+ from .negatives import build_negative_plan
6
+
7
+ __all__ = [
8
+ "analyze_search_terms",
9
+ "build_agent_manifest",
10
+ "build_connection_status",
11
+ "build_negative_plan",
12
+ "build_privacy_audit",
13
+ "classify_search_term",
14
+ ]
@@ -0,0 +1,3 @@
1
+ from .cli import main
2
+
3
+ raise SystemExit(main())
@@ -0,0 +1,93 @@
1
+ from __future__ import annotations
2
+
3
+ from collections.abc import Mapping
4
+
5
+ SUPPORTED_CLIENTS = ["generic", "claude", "codex", "cursor", "windsurf", "hermes", "openclaw"]
6
+
7
+
8
+ def _safe_client(client: str = "generic") -> str:
9
+ return client if client in SUPPORTED_CLIENTS else "generic"
10
+
11
+
12
+ def _present(env: Mapping[str, str], key: str) -> bool:
13
+ return bool(str(env.get(key, "")).strip())
14
+
15
+
16
+ def build_agent_manifest(client: str = "generic") -> dict:
17
+ return {
18
+ "project": "google-ads-intent-mcp",
19
+ "mcp_name": "io.github.davidmosiah/google-ads-intent-mcp",
20
+ "client": _safe_client(client),
21
+ "default_mode": "dry_run",
22
+ "package": {
23
+ "pip": "pipx install google-ads-intent-mcp[mcp]",
24
+ "cli": "google-ads-intent",
25
+ "mcp": "google-ads-intent-mcp",
26
+ },
27
+ "supported_clients": SUPPORTED_CLIENTS,
28
+ "standard_tools": [
29
+ "google_ads_agent_manifest",
30
+ "google_ads_connection_status",
31
+ "google_ads_privacy_audit",
32
+ "google_ads_classify_search_term",
33
+ "google_ads_analyze_search_terms",
34
+ "google_ads_build_negative_plan",
35
+ ],
36
+ "recommended_first_calls": ["google_ads_connection_status", "google_ads_privacy_audit"],
37
+ "hermes": {
38
+ "config_path": "~/.hermes/config.yaml",
39
+ "tool_name_prefix": "mcp_google_ads_",
40
+ "recommended_config": (
41
+ "mcp_servers:\n"
42
+ " google_ads_intent:\n"
43
+ " command: google-ads-intent-mcp\n"
44
+ " args: []\n"
45
+ " sampling:\n"
46
+ " enabled: false"
47
+ ),
48
+ },
49
+ "agent_rules": [
50
+ "Analyze exported search-term CSVs before live Google Ads API work.",
51
+ "Never apply negatives automatically; build a plan and ask for confirmation.",
52
+ "Protect buyer-intent terms even when they have low clicks.",
53
+ "Prioritize wasted cost, zero-conversion spend and obvious junk traffic.",
54
+ ],
55
+ }
56
+
57
+
58
+ def build_connection_status(env: Mapping[str, str] | None = None) -> dict:
59
+ env = env or {}
60
+ configured = {
61
+ "developer_token": _present(env, "GOOGLE_ADS_DEVELOPER_TOKEN"),
62
+ "customer_id": _present(env, "GOOGLE_ADS_CUSTOMER_ID"),
63
+ "oauth_refresh": _present(env, "GOOGLE_ADS_REFRESH_TOKEN"),
64
+ "oauth_client": _present(env, "GOOGLE_ADS_CLIENT_ID") and _present(env, "GOOGLE_ADS_CLIENT_SECRET"),
65
+ }
66
+ ready_live = all(configured.values()) and str(env.get("GOOGLE_ADS_DRY_RUN", "true")).lower() in {"0", "false", "no"}
67
+ return {
68
+ "ok": True,
69
+ "mode": "api_ready" if ready_live else "csv_dry_run",
70
+ "configured": configured,
71
+ "ready_for_csv_analysis": True,
72
+ "ready_for_live_apply": ready_live,
73
+ "next_steps": [
74
+ "Export Google Ads search terms as CSV and run analyze-csv.",
75
+ "Review the negative plan manually before applying changes in Google Ads.",
76
+ ],
77
+ }
78
+
79
+
80
+ def build_privacy_audit() -> dict:
81
+ return {
82
+ "project": "google-ads-intent-mcp",
83
+ "secrets_returned_to_agent": False,
84
+ "local_files_ignored": [".env", "credentials/", "google-ads.yaml", "token.json", "node_modules/", "coverage/"],
85
+ "external_services": ["optional: Google Ads API"],
86
+ "data_boundary": "CSV analysis is local. API apply flows should stay dry-run until explicit user approval.",
87
+ "safety_rules": [
88
+ "Dry-run is the default.",
89
+ "Never add negative keywords without human confirmation.",
90
+ "Do not print OAuth tokens, developer tokens or customer account identifiers in logs.",
91
+ "Keep raw search-term exports local unless the user asks to share them.",
92
+ ],
93
+ }