gmc-mcp 0.2.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.
- gmc_mcp-0.2.0/.gitignore +13 -0
- gmc_mcp-0.2.0/CHANGELOG.md +73 -0
- gmc_mcp-0.2.0/CONTRIBUTING.md +61 -0
- gmc_mcp-0.2.0/LICENSE +21 -0
- gmc_mcp-0.2.0/PKG-INFO +351 -0
- gmc_mcp-0.2.0/README.md +302 -0
- gmc_mcp-0.2.0/examples/README.md +18 -0
- gmc_mcp-0.2.0/examples/audit_disapproved.py +67 -0
- gmc_mcp-0.2.0/examples/bulk_price_update.py +78 -0
- gmc_mcp-0.2.0/examples/claude_desktop_config_snippet.json +14 -0
- gmc_mcp-0.2.0/examples/quickstart.py +50 -0
- gmc_mcp-0.2.0/pyproject.toml +120 -0
- gmc_mcp-0.2.0/src/gmc_mcp/__init__.py +1 -0
- gmc_mcp-0.2.0/src/gmc_mcp/_logging.py +52 -0
- gmc_mcp-0.2.0/src/gmc_mcp/audit.py +59 -0
- gmc_mcp-0.2.0/src/gmc_mcp/auth.py +117 -0
- gmc_mcp-0.2.0/src/gmc_mcp/cli.py +279 -0
- gmc_mcp-0.2.0/src/gmc_mcp/client.py +202 -0
- gmc_mcp-0.2.0/src/gmc_mcp/config.py +126 -0
- gmc_mcp-0.2.0/src/gmc_mcp/py.typed +0 -0
- gmc_mcp-0.2.0/src/gmc_mcp/server.py +106 -0
- gmc_mcp-0.2.0/src/gmc_mcp/tools/__init__.py +45 -0
- gmc_mcp-0.2.0/src/gmc_mcp/tools/account_config.py +289 -0
- gmc_mcp-0.2.0/src/gmc_mcp/tools/accounts.py +166 -0
- gmc_mcp-0.2.0/src/gmc_mcp/tools/bulk.py +124 -0
- gmc_mcp-0.2.0/src/gmc_mcp/tools/conversions.py +89 -0
- gmc_mcp-0.2.0/src/gmc_mcp/tools/diagnostics.py +222 -0
- gmc_mcp-0.2.0/src/gmc_mcp/tools/feeds.py +112 -0
- gmc_mcp-0.2.0/src/gmc_mcp/tools/homepage.py +48 -0
- gmc_mcp-0.2.0/src/gmc_mcp/tools/inventory.py +140 -0
- gmc_mcp-0.2.0/src/gmc_mcp/tools/issues.py +99 -0
- gmc_mcp-0.2.0/src/gmc_mcp/tools/lfp.py +114 -0
- gmc_mcp-0.2.0/src/gmc_mcp/tools/mca.py +132 -0
- gmc_mcp-0.2.0/src/gmc_mcp/tools/notifications.py +61 -0
- gmc_mcp-0.2.0/src/gmc_mcp/tools/omnichannel.py +119 -0
- gmc_mcp-0.2.0/src/gmc_mcp/tools/products.py +217 -0
- gmc_mcp-0.2.0/src/gmc_mcp/tools/promotions.py +45 -0
- gmc_mcp-0.2.0/src/gmc_mcp/tools/quotas.py +36 -0
- gmc_mcp-0.2.0/src/gmc_mcp/tools/regions.py +99 -0
- gmc_mcp-0.2.0/src/gmc_mcp/tools/reports.py +170 -0
- gmc_mcp-0.2.0/src/gmc_mcp/tools/return_policies.py +79 -0
- gmc_mcp-0.2.0/src/gmc_mcp/tools/reviews.py +99 -0
- gmc_mcp-0.2.0/tests/__init__.py +0 -0
- gmc_mcp-0.2.0/tests/conftest.py +62 -0
- gmc_mcp-0.2.0/tests/test_audit.py +47 -0
- gmc_mcp-0.2.0/tests/test_client.py +114 -0
- gmc_mcp-0.2.0/tests/test_config.py +106 -0
- gmc_mcp-0.2.0/tests/test_tools_issues.py +104 -0
- gmc_mcp-0.2.0/tests/test_tools_products.py +96 -0
- gmc_mcp-0.2.0/tests/test_tools_reports.py +47 -0
- gmc_mcp-0.2.0/tests/test_tools_v2.py +179 -0
gmc_mcp-0.2.0/.gitignore
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# Changelog — Google Merchant Center MCP (`gmc-mcp`)
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [Unreleased]
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
- `tools/regions.py`: regions CRUD (list / get / create / update / delete) —
|
|
12
|
+
required to set up regional inventory targeting.
|
|
13
|
+
- `tools/accounts.py`: `gmc_update_business_info` (PATCH businessInfo —
|
|
14
|
+
address, phone, customer service, KR business registration number).
|
|
15
|
+
- `tools/accounts.py`: `gmc_request_program_review` and `gmc_get_program_review`
|
|
16
|
+
for re-requesting Shopping Ads / Free Listings approval after fixing issues.
|
|
17
|
+
|
|
18
|
+
## [0.2.0] - 2026-05-01
|
|
19
|
+
|
|
20
|
+
### Added — full Merchant API v1 surface
|
|
21
|
+
- `tools/return_policies.py`: list / get / create / update / delete `onlineReturnPolicies` (Google now requires a return policy in US/EU).
|
|
22
|
+
- `tools/homepage.py`: get / update / `claim` / `unclaim` the registered homepage.
|
|
23
|
+
- `tools/account_config.py`: business identity, checkout settings (per program),
|
|
24
|
+
automatic improvements, autofeed settings, account tax, email preferences,
|
|
25
|
+
Terms of Service (latest / agreement states / accept).
|
|
26
|
+
- `tools/quotas.py`: list per-method quota usage and limits.
|
|
27
|
+
- `tools/reviews.py`: merchant + product reviews CRUD.
|
|
28
|
+
- `tools/conversions.py`: conversion sources CRUD + undelete.
|
|
29
|
+
- `tools/omnichannel.py`: omnichannel settings, GBP account linkage,
|
|
30
|
+
`requestInventoryVerification`.
|
|
31
|
+
- `tools/lfp.py`: full Local Feed Partnership API
|
|
32
|
+
(lfpStores / lfpInventories / lfpSales / lfpMerchantStates).
|
|
33
|
+
- `tools/mca.py`: relationships, account aggregation, account services delegation
|
|
34
|
+
(propose / approve / reject).
|
|
35
|
+
- `tools/bulk.py`: `gmc_bulk_update_regional_prices`,
|
|
36
|
+
`gmc_bulk_set_availability` — both gated by `confirm='APPLY'`.
|
|
37
|
+
- `tools/diagnostics.py`: `gmc_health_check`, `gmc_rollback(audit_id)`,
|
|
38
|
+
`gmc_export_all(output_dir)`, `gmc_diff_with_shopify(shopify_csv)`.
|
|
39
|
+
- `tools/products.py`: `gmc_bulk_delete_products` with `confirm='DELETE'` gate
|
|
40
|
+
and automatic `dataSource` extraction (works on orphan products).
|
|
41
|
+
- `tools/reports.py`: 6 new canned queries — revenue by brand, category
|
|
42
|
+
performance, competitive visibility, price insights, demoted products.
|
|
43
|
+
- CLI: `gmc-mcp webhook` — tiny HTTP receiver that decodes Pub/Sub push
|
|
44
|
+
notifications from `gmc_subscribe`. Logs to JSONL with `--out`.
|
|
45
|
+
|
|
46
|
+
### Fixed
|
|
47
|
+
- `gmc_summarize_product_issues` now reads the v1 `itemIssues` schema
|
|
48
|
+
(`type.code`, `type.canonicalAttribute`, `severity.aggregatedSeverity`,
|
|
49
|
+
`resolution`) instead of the v1beta flat shape.
|
|
50
|
+
- `gmc_list_disapproved_products` now includes the required `id` field in the
|
|
51
|
+
Reports SELECT (v1 requirement).
|
|
52
|
+
- `gmc_update_regional_inventory` / `gmc_update_local_inventory` build the
|
|
53
|
+
`regionalInventoryAttributes` / `localInventoryAttributes` envelope required
|
|
54
|
+
by v1 (v1beta flat fields are no longer accepted).
|
|
55
|
+
|
|
56
|
+
## [0.1.0] - 2026-04-30
|
|
57
|
+
|
|
58
|
+
### Added
|
|
59
|
+
- Initial release. Targets **Merchant API v1** (v1beta was shut down 2026-02-28).
|
|
60
|
+
- `gmc-mcp register-gcp` CLI: one-time link of GCP project to Merchant Center,
|
|
61
|
+
required before any v1 call works.
|
|
62
|
+
- 42 MCP tools across 8 modules covering products, inventory, issues, reports,
|
|
63
|
+
promotions, accounts, notifications, and data sources (feeds).
|
|
64
|
+
- Service-account authentication with auto-refresh.
|
|
65
|
+
- OAuth 2.0 user-credential authentication as an alternative.
|
|
66
|
+
- Append-only audit log for every write operation, with `gmc_audit_lookup`
|
|
67
|
+
and `gmc_audit_tail` for inspection.
|
|
68
|
+
- Dry-run mode (`GMC_DRY_RUN=true` or `gmc_set_dry_run`) for safe testing.
|
|
69
|
+
- Both stdio and HTTP/SSE transports.
|
|
70
|
+
- CLI entrypoint `gmc-mcp` with `--transport`, `--host`, `--port`, `--env`.
|
|
71
|
+
- Reports API helpers: raw SQL queries, top performers, price competitiveness,
|
|
72
|
+
best sellers, zero-click outliers.
|
|
73
|
+
- Issue summarization that aggregates problem codes across all products.
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# Contributing to gmc-mcp
|
|
2
|
+
|
|
3
|
+
Thanks for your interest! Contributions of all sizes are welcome.
|
|
4
|
+
|
|
5
|
+
## Dev setup
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
git clone https://github.com/<you>/gmc-mcp.git
|
|
9
|
+
cd gmc-mcp
|
|
10
|
+
python -m venv .venv
|
|
11
|
+
. .venv/Scripts/activate # Windows; use 'source .venv/bin/activate' on Unix
|
|
12
|
+
pip install -e ".[dev,test]"
|
|
13
|
+
pre-commit install
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## Running tests
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
pytest # all tests
|
|
20
|
+
pytest -k products # filter
|
|
21
|
+
pytest --cov=gmc_mcp # with coverage
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Tests run fully offline using `respx` to mock the Merchant API. They do **not**
|
|
25
|
+
hit Google's servers, so you don't need credentials to develop on this repo.
|
|
26
|
+
|
|
27
|
+
## Style
|
|
28
|
+
|
|
29
|
+
- `ruff format` + `ruff check --fix` (run automatically by pre-commit).
|
|
30
|
+
- `mypy src/gmc_mcp` should pass.
|
|
31
|
+
- Type-hint everything new.
|
|
32
|
+
- Public tool functions need a docstring; the first line becomes the MCP tool
|
|
33
|
+
description shown to the model.
|
|
34
|
+
|
|
35
|
+
## Adding a tool
|
|
36
|
+
|
|
37
|
+
1. Pick (or create) a module under `src/gmc_mcp/tools/`.
|
|
38
|
+
2. Define the function inside the module's `register(mcp, client)` and decorate
|
|
39
|
+
with `@mcp.tool()`.
|
|
40
|
+
3. Use `client.request(method, path, ...)` for everything — never call `httpx`
|
|
41
|
+
directly so audit and retries stay consistent.
|
|
42
|
+
4. For write operations, pass `op="..."` so the audit log has a readable label.
|
|
43
|
+
5. For tools that read the existing state before mutating, pass `before=...`
|
|
44
|
+
so the audit log can be used to roll back.
|
|
45
|
+
6. Add a unit test in `tests/test_tools_<module>.py`.
|
|
46
|
+
|
|
47
|
+
## Releasing
|
|
48
|
+
|
|
49
|
+
Maintainers only.
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
# 1. Bump the version in src/gmc_mcp/__init__.py and pyproject.toml
|
|
53
|
+
# 2. Update CHANGELOG.md (move Unreleased entries to a new dated section)
|
|
54
|
+
# 3. Commit + tag
|
|
55
|
+
git commit -am "release: 0.x.y"
|
|
56
|
+
git tag v0.x.y
|
|
57
|
+
git push origin main --tags
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
The `publish.yml` workflow then builds and uploads to PyPI via OIDC trusted
|
|
61
|
+
publishing (no API tokens stored in the repo).
|
gmc_mcp-0.2.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 eric.eom
|
|
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.
|
gmc_mcp-0.2.0/PKG-INFO
ADDED
|
@@ -0,0 +1,351 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: gmc-mcp
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: Google Merchant Center MCP — the first MCP server for Google Merchant Center (Merchant API v1). Drive your Google Shopping feed, products, inventory, reports, promotions, returns, and account in natural language from Claude.
|
|
5
|
+
Project-URL: Homepage, https://github.com/kiwoongeom/gmc-mcp
|
|
6
|
+
Project-URL: Documentation, https://github.com/kiwoongeom/gmc-mcp#readme
|
|
7
|
+
Project-URL: Repository, https://github.com/kiwoongeom/gmc-mcp
|
|
8
|
+
Project-URL: Issues, https://github.com/kiwoongeom/gmc-mcp/issues
|
|
9
|
+
Project-URL: Changelog, https://github.com/kiwoongeom/gmc-mcp/blob/main/CHANGELOG.md
|
|
10
|
+
Author-email: "eric.eom" <eric.eom@gmail.com>
|
|
11
|
+
License: MIT
|
|
12
|
+
License-File: LICENSE
|
|
13
|
+
Keywords: agent-tools,anthropic,claude,claude-desktop,ecommerce,free-listings,gmc,google-merchant-center,google-merchant-center-mcp,google-shopping,google-shopping-ads,llm-tools,mcp,merchant-api,merchant-center,model-context-protocol,shopify,shopping-ads
|
|
14
|
+
Classifier: Development Status :: 4 - Beta
|
|
15
|
+
Classifier: Environment :: Console
|
|
16
|
+
Classifier: Intended Audience :: Developers
|
|
17
|
+
Classifier: Intended Audience :: Information Technology
|
|
18
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
19
|
+
Classifier: Operating System :: OS Independent
|
|
20
|
+
Classifier: Programming Language :: Python :: 3
|
|
21
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
23
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
24
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
25
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
26
|
+
Classifier: Topic :: Internet :: WWW/HTTP
|
|
27
|
+
Classifier: Topic :: Office/Business
|
|
28
|
+
Classifier: Topic :: Software Development :: Libraries
|
|
29
|
+
Classifier: Typing :: Typed
|
|
30
|
+
Requires-Python: >=3.10
|
|
31
|
+
Requires-Dist: click>=8.1.0
|
|
32
|
+
Requires-Dist: google-auth-oauthlib>=1.2.0
|
|
33
|
+
Requires-Dist: google-auth>=2.30.0
|
|
34
|
+
Requires-Dist: httpx>=0.27.0
|
|
35
|
+
Requires-Dist: mcp>=1.2.0
|
|
36
|
+
Requires-Dist: pydantic>=2.7.0
|
|
37
|
+
Requires-Dist: python-dotenv>=1.0.1
|
|
38
|
+
Provides-Extra: dev
|
|
39
|
+
Requires-Dist: build>=1.2; extra == 'dev'
|
|
40
|
+
Requires-Dist: mypy>=1.10; extra == 'dev'
|
|
41
|
+
Requires-Dist: pre-commit>=3.7; extra == 'dev'
|
|
42
|
+
Requires-Dist: ruff>=0.8; extra == 'dev'
|
|
43
|
+
Provides-Extra: test
|
|
44
|
+
Requires-Dist: pytest-asyncio>=0.23; extra == 'test'
|
|
45
|
+
Requires-Dist: pytest-cov>=5.0; extra == 'test'
|
|
46
|
+
Requires-Dist: pytest>=8.0; extra == 'test'
|
|
47
|
+
Requires-Dist: respx>=0.21; extra == 'test'
|
|
48
|
+
Description-Content-Type: text/markdown
|
|
49
|
+
|
|
50
|
+
# Google Merchant Center MCP (`gmc-mcp`)
|
|
51
|
+
|
|
52
|
+
[](https://pypi.org/project/gmc-mcp/)
|
|
53
|
+
[](https://github.com/kiwoongeom/gmc-mcp/actions/workflows/ci.yml)
|
|
54
|
+
[](https://pypi.org/project/gmc-mcp/)
|
|
55
|
+
[](https://opensource.org/licenses/MIT)
|
|
56
|
+
[](https://github.com/astral-sh/ruff)
|
|
57
|
+
|
|
58
|
+
> **The first MCP server for Google Merchant Center (GMC).**
|
|
59
|
+
> Drive your Google Shopping feed, products, inventory, Reports, promotions,
|
|
60
|
+
> returns, and account configuration in natural language from Claude Desktop,
|
|
61
|
+
> Claude Code, or any MCP-compatible client.
|
|
62
|
+
|
|
63
|
+
Built on **Merchant API v1** (replaces Content API for Shopping; v1beta was
|
|
64
|
+
discontinued 2026-02-28). Safe by default: every write is recorded to an
|
|
65
|
+
append-only audit log with `before` snapshots, dry-run is one toggle away, and
|
|
66
|
+
destructive bulk operations require an explicit `confirm` parameter.
|
|
67
|
+
|
|
68
|
+
## Why this exists
|
|
69
|
+
|
|
70
|
+
Google Merchant Center (GMC) is what powers Google Shopping listings, Free
|
|
71
|
+
Listings, Shopping Ads, Buy on Google checkout, YouTube Shopping, and more.
|
|
72
|
+
Until now there was no MCP server for it — managing a feed of thousands of
|
|
73
|
+
products through the GMC web UI is tedious, and writing one-off Python scripts
|
|
74
|
+
against the Merchant API REST endpoints is slow.
|
|
75
|
+
|
|
76
|
+
This package gives Claude (or any MCP client) **126 tools** that map directly
|
|
77
|
+
onto the Merchant API v1 surface, so you can do things like:
|
|
78
|
+
|
|
79
|
+
- *"Show me every disapproved product, grouped by issue code."*
|
|
80
|
+
- *"Bump US prices 5% on these 40 SKUs."*
|
|
81
|
+
- *"Which products had impressions but zero clicks last week?"*
|
|
82
|
+
- *"Roll back audit ID 8fc8dc42… — that update broke something."*
|
|
83
|
+
- *"Compare this Shopify CSV against my GMC feed; what's missing?"*
|
|
84
|
+
|
|
85
|
+
## What's exposed
|
|
86
|
+
|
|
87
|
+
**126 tools across 19 modules + 4 meta tools.**
|
|
88
|
+
|
|
89
|
+
| Module | Tools |
|
|
90
|
+
|---|---|
|
|
91
|
+
| **products** | `gmc_list_products`, `gmc_get_product`, `gmc_insert_product`, `gmc_update_product`, `gmc_delete_product`, `gmc_bulk_delete_products`, `gmc_list_disapproved_products` |
|
|
92
|
+
| **inventory** | `gmc_update_regional_inventory`, `gmc_update_local_inventory`, `gmc_list_regional_inventories`, `gmc_list_local_inventories` |
|
|
93
|
+
| **issues** | `gmc_list_account_issues`, `gmc_get_product_status`, `gmc_summarize_product_issues` |
|
|
94
|
+
| **reports** | `gmc_query_report`, `gmc_product_performance`, `gmc_price_competitiveness`, `gmc_best_sellers`, `gmc_zero_click_products`, `gmc_revenue_by_brand`, `gmc_category_performance`, `gmc_competitive_visibility_top_merchants`, `gmc_price_insights`, `gmc_demoted_products` |
|
|
95
|
+
| **promotions** | `gmc_list_promotions`, `gmc_get_promotion`, `gmc_insert_promotion` |
|
|
96
|
+
| **accounts** | `gmc_get_account`, `gmc_get_business_info`, `gmc_update_business_info`, `gmc_list_users`, `gmc_add_user`, `gmc_remove_user`, `gmc_get_shipping_settings`, `gmc_update_shipping_settings`, `gmc_list_programs`, `gmc_request_program_review`, `gmc_get_program_review` |
|
|
97
|
+
| **regions** | `gmc_list_regions`, `gmc_get_region`, `gmc_create_region`, `gmc_update_region`, `gmc_delete_region` |
|
|
98
|
+
| **notifications** | `gmc_list_subscriptions`, `gmc_subscribe`, `gmc_unsubscribe` |
|
|
99
|
+
| **feeds** | `gmc_list_datasources`, `gmc_get_datasource`, `gmc_create_supplemental_feed`, `gmc_create_primary_feed`, `gmc_delete_datasource`, `gmc_fetch_datasource` |
|
|
100
|
+
| **return_policies** | `gmc_list_return_policies`, `gmc_get_return_policy`, `gmc_create_return_policy`, `gmc_update_return_policy`, `gmc_delete_return_policy` |
|
|
101
|
+
| **homepage** | `gmc_get_homepage`, `gmc_update_homepage`, `gmc_claim_homepage`, `gmc_unclaim_homepage` |
|
|
102
|
+
| **account_config** | `gmc_get_business_identity`, `gmc_update_business_identity`, `gmc_get_checkout_settings`, `gmc_create_checkout_settings`, `gmc_update_checkout_settings`, `gmc_delete_checkout_settings`, `gmc_get_automatic_improvements`, `gmc_update_automatic_improvements`, `gmc_get_autofeed_settings`, `gmc_update_autofeed_settings`, `gmc_get_account_tax`, `gmc_update_account_tax`, `gmc_get_email_preferences`, `gmc_update_email_preferences`, `gmc_get_latest_tos`, `gmc_list_tos_agreement_states`, `gmc_accept_tos` |
|
|
103
|
+
| **quotas** | `gmc_list_quotas` |
|
|
104
|
+
| **reviews** | `gmc_list_merchant_reviews`, `gmc_get_merchant_review`, `gmc_insert_merchant_review`, `gmc_delete_merchant_review`, `gmc_list_product_reviews`, `gmc_get_product_review`, `gmc_insert_product_review`, `gmc_delete_product_review` |
|
|
105
|
+
| **conversions** | `gmc_list_conversion_sources`, `gmc_get_conversion_source`, `gmc_create_conversion_source`, `gmc_update_conversion_source`, `gmc_delete_conversion_source`, `gmc_undelete_conversion_source` |
|
|
106
|
+
| **omnichannel** | `gmc_list_omnichannel_settings`, `gmc_get_omnichannel_settings`, `gmc_create_omnichannel_settings`, `gmc_update_omnichannel_settings`, `gmc_request_inventory_verification`, `gmc_link_gbp_account`, `gmc_list_gbp_accounts` |
|
|
107
|
+
| **lfp** | `gmc_lfp_list_stores`, `gmc_lfp_get_store`, `gmc_lfp_insert_store`, `gmc_lfp_delete_store`, `gmc_lfp_insert_inventory`, `gmc_lfp_insert_sale`, `gmc_lfp_get_merchant_state` |
|
|
108
|
+
| **mca** | `gmc_list_relationships`, `gmc_get_relationship`, `gmc_update_relationship`, `gmc_create_aggregation`, `gmc_delete_aggregation`, `gmc_list_account_services`, `gmc_propose_account_service`, `gmc_approve_account_service`, `gmc_reject_account_service` |
|
|
109
|
+
| **bulk** | `gmc_bulk_update_regional_prices`, `gmc_bulk_set_availability` |
|
|
110
|
+
| **diagnostics** | `gmc_health_check`, `gmc_rollback`, `gmc_export_all`, `gmc_diff_with_shopify` |
|
|
111
|
+
| **meta** | `gmc_describe_server`, `gmc_audit_lookup`, `gmc_audit_tail`, `gmc_set_dry_run` |
|
|
112
|
+
|
|
113
|
+
CLI also exposes: `gmc-mcp run`, `auth-init`, `register-gcp`, `webhook`, `describe`, `version`.
|
|
114
|
+
|
|
115
|
+
## Install
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
pip install gmc-mcp
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
For development:
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
git clone https://github.com/kiwoongeom/gmc-mcp
|
|
125
|
+
cd gmc-mcp
|
|
126
|
+
pip install -e ".[dev,test]"
|
|
127
|
+
pre-commit install
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
## Quick start
|
|
131
|
+
|
|
132
|
+
### 1. Enable the Merchant API and create a service account
|
|
133
|
+
|
|
134
|
+
1. [console.cloud.google.com](https://console.cloud.google.com) → create / pick a project.
|
|
135
|
+
2. **APIs & Services → Library** → enable **Merchant API**.
|
|
136
|
+
3. **IAM & Admin → Service Accounts → Create service account** named `gmc-mcp`.
|
|
137
|
+
4. Open the new service account → **Keys → Add key → Create new key → JSON**. Save it somewhere safe.
|
|
138
|
+
|
|
139
|
+
### 2. Add the service account to your Merchant Center
|
|
140
|
+
|
|
141
|
+
1. [merchants.google.com](https://merchants.google.com) → top-right gear → **Account access → People**.
|
|
142
|
+
2. **Add user** → enter the `gmc-mcp@PROJECT.iam.gserviceaccount.com` email → grant **Admin**.
|
|
143
|
+
3. Note the 10-digit Merchant Center ID in the top-right.
|
|
144
|
+
|
|
145
|
+
### 3. Configure
|
|
146
|
+
|
|
147
|
+
```bash
|
|
148
|
+
cp .env.example .env
|
|
149
|
+
# edit:
|
|
150
|
+
# GMC_ACCOUNT_ID=1234567890
|
|
151
|
+
# GMC_SERVICE_ACCOUNT_KEY=/abs/path/to/service-account.json
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### 4. One-time GCP registration
|
|
155
|
+
|
|
156
|
+
Required before any v1 Merchant API call works for a new project.
|
|
157
|
+
|
|
158
|
+
```bash
|
|
159
|
+
gmc-mcp register-gcp --developer-email you@example.com
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
### 5. Smoke-test
|
|
163
|
+
|
|
164
|
+
```bash
|
|
165
|
+
gmc-mcp describe # prints the resolved config
|
|
166
|
+
python examples/quickstart.py # makes one read against the Merchant API
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
### 6. Wire into Claude
|
|
170
|
+
|
|
171
|
+
Drop this into `%APPDATA%/Claude/claude_desktop_config.json` (Desktop) or `~/.claude/settings.json` (Code):
|
|
172
|
+
|
|
173
|
+
```json
|
|
174
|
+
{
|
|
175
|
+
"mcpServers": {
|
|
176
|
+
"gmc": {
|
|
177
|
+
"command": "gmc-mcp",
|
|
178
|
+
"args": ["run"],
|
|
179
|
+
"env": {
|
|
180
|
+
"GMC_ACCOUNT_ID": "1234567890",
|
|
181
|
+
"GMC_SERVICE_ACCOUNT_KEY": "/abs/path/to/service-account.json"
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
Restart Claude. Ask: *"What account am I connected to?"* — it should call `gmc_describe_server`.
|
|
189
|
+
|
|
190
|
+
## OAuth instead of a service account
|
|
191
|
+
|
|
192
|
+
For acting on behalf of an end user (e.g. multi-tenant SaaS):
|
|
193
|
+
|
|
194
|
+
```bash
|
|
195
|
+
# 1. In GCP, create OAuth client credentials (type: Desktop), download client_secret.json.
|
|
196
|
+
gmc-mcp auth-init --client-secrets ./client_secret.json
|
|
197
|
+
# follow the browser flow; a token JSON is saved to secrets/oauth-token.json.
|
|
198
|
+
|
|
199
|
+
# 2. Use it
|
|
200
|
+
export GMC_OAUTH_TOKEN=./secrets/oauth-token.json
|
|
201
|
+
gmc-mcp run
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
## Transports
|
|
205
|
+
|
|
206
|
+
```bash
|
|
207
|
+
gmc-mcp run # stdio (Claude Desktop default)
|
|
208
|
+
gmc-mcp run --transport sse --port 8000 # SSE / HTTP (remote, Docker, hosted)
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
Or via Docker:
|
|
212
|
+
|
|
213
|
+
```bash
|
|
214
|
+
docker build -t gmc-mcp .
|
|
215
|
+
docker run --rm -p 8000:8000 \
|
|
216
|
+
-e GMC_ACCOUNT_ID=1234567890 \
|
|
217
|
+
-v $PWD/secrets:/secrets \
|
|
218
|
+
-e GMC_SERVICE_ACCOUNT_KEY=/secrets/service-account.json \
|
|
219
|
+
gmc-mcp
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
## Audit log + rollback
|
|
223
|
+
|
|
224
|
+
Every write logs a JSONL entry to `GMC_AUDIT_LOG` (default: `./logs/audit.jsonl`). Each entry contains:
|
|
225
|
+
|
|
226
|
+
- `audit_id` — UUID for lookup
|
|
227
|
+
- `op`, `method`, `url`, `request_body`, `response_status`, `response_body`
|
|
228
|
+
- `before` — pre-write snapshot when the tool fetched it (used by `update_*` and `delete_*`)
|
|
229
|
+
- `dry_run` — whether the request was actually sent
|
|
230
|
+
|
|
231
|
+
Inspect from inside Claude:
|
|
232
|
+
|
|
233
|
+
```
|
|
234
|
+
> Show me my last 5 GMC writes.
|
|
235
|
+
[gmc_audit_tail(limit=5) → ...]
|
|
236
|
+
|
|
237
|
+
> Look up audit ID abc123.
|
|
238
|
+
[gmc_audit_lookup(audit_id="abc123") → ...]
|
|
239
|
+
|
|
240
|
+
> Roll back audit ID abc123, that update was wrong.
|
|
241
|
+
[gmc_rollback(audit_id="abc123", confirm="ROLLBACK") → ...]
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
## Dry-run
|
|
245
|
+
|
|
246
|
+
Two ways to enable:
|
|
247
|
+
|
|
248
|
+
```bash
|
|
249
|
+
GMC_DRY_RUN=true gmc-mcp run
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
```
|
|
253
|
+
> Set dry-run on and update the price of SKU1 to $19.99.
|
|
254
|
+
[gmc_set_dry_run(enabled=True) → ok]
|
|
255
|
+
[gmc_update_regional_inventory(...) → {"_dry_run": true, ...}]
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
Reads always go through; only writes are skipped.
|
|
259
|
+
|
|
260
|
+
## Reports query examples
|
|
261
|
+
|
|
262
|
+
Paste into `gmc_query_report`:
|
|
263
|
+
|
|
264
|
+
```sql
|
|
265
|
+
-- Top 50 by clicks last 7 days
|
|
266
|
+
SELECT offer_id, title, clicks, impressions, ctr
|
|
267
|
+
FROM product_performance_view
|
|
268
|
+
WHERE date BETWEEN '2026-04-23' AND '2026-04-30'
|
|
269
|
+
ORDER BY clicks DESC LIMIT 50
|
|
270
|
+
|
|
271
|
+
-- Disapproved products with reason codes
|
|
272
|
+
SELECT id, offer_id, title, item_issues
|
|
273
|
+
FROM product_view
|
|
274
|
+
WHERE aggregated_reporting_context_status = 'NOT_ELIGIBLE_OR_DISAPPROVED'
|
|
275
|
+
|
|
276
|
+
-- You're priced higher than the benchmark
|
|
277
|
+
SELECT offer_id, title, price, benchmark_price
|
|
278
|
+
FROM price_competitiveness_product_view
|
|
279
|
+
WHERE price > benchmark_price LIMIT 100
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
## Configuration reference
|
|
283
|
+
|
|
284
|
+
All config is via env vars (or `.env`). CLI flags `--transport`, `--host`, `--port`, `--env` override.
|
|
285
|
+
|
|
286
|
+
| Var | Required | Default | Notes |
|
|
287
|
+
|---|---|---|---|
|
|
288
|
+
| `GMC_ACCOUNT_ID` | yes | — | 10-digit Merchant Center ID |
|
|
289
|
+
| `GMC_SERVICE_ACCOUNT_KEY` | one of | — | Path to service-account JSON |
|
|
290
|
+
| `GMC_OAUTH_TOKEN` | one of | — | Path to OAuth token JSON |
|
|
291
|
+
| `GMC_SUBACCOUNT_ID` | no | — | When using an MCA |
|
|
292
|
+
| `GMC_AUDIT_LOG` | no | `./logs/audit.jsonl` | Append-only JSONL |
|
|
293
|
+
| `GMC_PAGE_SIZE` | no | `100` | Default list page size |
|
|
294
|
+
| `GMC_TIMEOUT` | no | `30` | Per-request seconds |
|
|
295
|
+
| `GMC_DRY_RUN` | no | `false` | Writes go to audit only |
|
|
296
|
+
| `GMC_LOG_LEVEL` | no | `INFO` | DEBUG/INFO/WARNING/ERROR |
|
|
297
|
+
| `GMC_TRANSPORT` | no | `stdio` | `stdio` or `sse` |
|
|
298
|
+
| `GMC_HOST` | no | `127.0.0.1` | SSE only |
|
|
299
|
+
| `GMC_PORT` | no | `8000` | SSE only |
|
|
300
|
+
|
|
301
|
+
## Architecture
|
|
302
|
+
|
|
303
|
+
```
|
|
304
|
+
Claude (any MCP client)
|
|
305
|
+
│ JSON-RPC over stdio or SSE
|
|
306
|
+
▼
|
|
307
|
+
gmc-mcp server ──► audit.jsonl
|
|
308
|
+
│
|
|
309
|
+
│ HTTP + Bearer token
|
|
310
|
+
▼
|
|
311
|
+
merchantapi.googleapis.com ──► Google Merchant Center
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
- `auth.py` — `ServiceAccountAuth` and `OAuthUserAuth` share an `Auth` protocol.
|
|
315
|
+
- `client.py` — single `MerchantClient` with retries (5x w/ jitter), pagination helper, and write-audit hook.
|
|
316
|
+
- `tools/*.py` — each module exposes a `register(mcp, client)` that registers `@mcp.tool()` functions.
|
|
317
|
+
- `audit.py` — append-only JSONL, lookup by ID, supports `before` snapshots.
|
|
318
|
+
- `cli.py` — `gmc-mcp run | auth-init | register-gcp | webhook | describe | version`.
|
|
319
|
+
|
|
320
|
+
## Testing
|
|
321
|
+
|
|
322
|
+
```bash
|
|
323
|
+
pytest # 100% offline; uses respx to mock HTTP
|
|
324
|
+
pytest --cov=gmc_mcp # with coverage
|
|
325
|
+
ruff check src tests
|
|
326
|
+
mypy src/gmc_mcp
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
## Roadmap
|
|
330
|
+
|
|
331
|
+
- v0.3: webhook handler scaffolding (auto-respond to `gmc_subscribe` callbacks)
|
|
332
|
+
- v0.3: native Merchant API v1 GA migration when Google releases it
|
|
333
|
+
- v0.4: BigQuery export of Reports queries
|
|
334
|
+
- v0.4: rule-based auto-fixers ("on disapproval, retry with corrected attribute")
|
|
335
|
+
|
|
336
|
+
## Contributing
|
|
337
|
+
|
|
338
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md). PRs and issues welcome — this is the
|
|
339
|
+
first MCP for Google Merchant Center, so there's a lot of room for community
|
|
340
|
+
input on which workflows deserve dedicated tools.
|
|
341
|
+
|
|
342
|
+
## License
|
|
343
|
+
|
|
344
|
+
MIT — see [LICENSE](LICENSE).
|
|
345
|
+
|
|
346
|
+
---
|
|
347
|
+
|
|
348
|
+
*Search keywords: Google Merchant Center MCP, GMC MCP, Merchant API MCP,
|
|
349
|
+
Google Shopping MCP, Shopping Ads MCP, free listings MCP, Claude Desktop
|
|
350
|
+
Google Merchant Center, MCP for ecommerce, Shopify Google Merchant Center
|
|
351
|
+
automation.*
|