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.
- google_ads_intent_mcp-0.1.0/.github/workflows/ci.yml +19 -0
- google_ads_intent_mcp-0.1.0/.github/workflows/pypi.yml +57 -0
- google_ads_intent_mcp-0.1.0/.gitignore +13 -0
- google_ads_intent_mcp-0.1.0/LICENSE +21 -0
- google_ads_intent_mcp-0.1.0/PKG-INFO +145 -0
- google_ads_intent_mcp-0.1.0/README.md +116 -0
- google_ads_intent_mcp-0.1.0/SECURITY.md +5 -0
- google_ads_intent_mcp-0.1.0/docs/pypi-publishing.md +22 -0
- google_ads_intent_mcp-0.1.0/examples/claude-desktop.json +8 -0
- google_ads_intent_mcp-0.1.0/examples/hermes.yaml +6 -0
- google_ads_intent_mcp-0.1.0/examples/search_terms.csv +4 -0
- google_ads_intent_mcp-0.1.0/llms.txt +20 -0
- google_ads_intent_mcp-0.1.0/pyproject.toml +41 -0
- google_ads_intent_mcp-0.1.0/server.json +60 -0
- google_ads_intent_mcp-0.1.0/src/google_ads_intent_mcp/__init__.py +14 -0
- google_ads_intent_mcp-0.1.0/src/google_ads_intent_mcp/__main__.py +3 -0
- google_ads_intent_mcp-0.1.0/src/google_ads_intent_mcp/agent.py +93 -0
- google_ads_intent_mcp-0.1.0/src/google_ads_intent_mcp/cli.py +67 -0
- google_ads_intent_mcp-0.1.0/src/google_ads_intent_mcp/csv_io.py +9 -0
- google_ads_intent_mcp-0.1.0/src/google_ads_intent_mcp/intent.py +126 -0
- google_ads_intent_mcp-0.1.0/src/google_ads_intent_mcp/mcp_server.py +50 -0
- google_ads_intent_mcp-0.1.0/src/google_ads_intent_mcp/negatives.py +27 -0
- google_ads_intent_mcp-0.1.0/tests/test_google_ads_intent_mcp.py +65 -0
- google_ads_intent_mcp-0.1.0/tests/test_metadata.py +24 -0
- 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,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
|
+
[](https://github.com/davidmosiah/google-ads-intent-mcp/stargazers)
|
|
33
|
+
[](https://github.com/davidmosiah/google-ads-intent-mcp/actions/workflows/ci.yml)
|
|
34
|
+
[](LICENSE)
|
|
35
|
+
[](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
|
+
[](https://github.com/davidmosiah/google-ads-intent-mcp/stargazers)
|
|
4
|
+
[](https://github.com/davidmosiah/google-ads-intent-mcp/actions/workflows/ci.yml)
|
|
5
|
+
[](LICENSE)
|
|
6
|
+
[](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,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,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
|
+
}
|