A production-ready remote MCP server that gives Claude full access to your Google Search Console data. Deployed as a serverless AWS Lambda container, managed entirely with Terraform.
Edit the diagram: open
images/architecture.drawioin draw.io.
Claude.ai ──HTTPS/MCP──▶ Lambda Function URL
│
Lambda Web Adapter (TCP :8080)
│
FastMCP Server (streamable-http)
├── PropertyService
├── AnalyticsService
├── InspectionService
├── IndexingService
└── SitemapService
│
CredentialProvider ──▶ AWS Secrets Manager
GoogleServiceFactory ──▶ Google APIs
| Category | Tool | Description |
|---|---|---|
| Properties | list_properties |
List all GSC properties |
get_property |
Details for a specific property | |
add_property |
Add a new property | |
delete_property |
Remove a property | |
| Analytics | get_search_performance |
Full analytics query (any dimension/filter) |
get_top_queries |
Top queries by clicks | |
get_top_pages |
Top pages by clicks | |
get_performance_by_country |
Country breakdown | |
get_performance_by_device |
Device breakdown | |
get_daily_trend |
Daily click/impression trend | |
get_page_queries |
All queries driving traffic to a page | |
get_search_appearance_breakdown |
Rich results, AMP, Discover breakdown | |
compare_periods |
Compare two date ranges | |
| Inspection | inspect_url |
Full URL inspection (indexing, mobile, rich results) |
batch_inspect_urls |
Inspect up to 10 URLs at once | |
| Indexing | request_indexing |
Submit a URL for indexing |
batch_request_indexing |
Submit multiple URLs for indexing | |
notify_url_deleted |
Notify Google a URL was deleted | |
get_indexing_status |
Check indexing notification status | |
| Sitemaps | list_sitemaps |
List all submitted sitemaps |
get_sitemap |
Detailed sitemap info including errors | |
submit_sitemap |
Submit a sitemap | |
delete_sitemap |
Remove a sitemap | |
refresh_sitemap |
Force re-submission (delete + resubmit) |
- AWS CLI configured (
aws sts get-caller-identityshould succeed) - Terraform ≥ 1.6
- Docker with
buildxsupport - Python 3.12+ (local dev/tests only)
cd google-search-console
# 1. Copy and fill in credentials
cp .env.example .env
# Edit .env with your GOOGLE_CLIENT_SECRET and GOOGLE_REFRESH_TOKEN
# 2. Install dependencies
pip install -r app/requirements.txt
# 3. Run the server locally
cd app
source ../.env
python main.py
# Server starts at http://localhost:8080/mcp# From project root
pip install pytest
pytest tests/ -v# From project root
./deploy.shThe script will:
- Load credentials from
.env terraform init+plan+apply- Build the Docker image and push to ECR
- Create the Lambda function with a public Function URL
- Print the MCP endpoint URL
After deploy, copy the printed URL (e.g. https://xxx.lambda-url.eu-central-1.on.aws/mcp) and add it as a custom connector:
- Go to Claude → Customize → Connectors
- Click + → Add custom connector
- Paste the URL
- Click Add
google-search-console/
├── app/
│ ├── main.py # Entry point
│ ├── server.py # Composition root
│ ├── auth/
│ │ └── credentials.py # CredentialProvider (Strategy pattern)
│ ├── gsc/
│ │ ├── factory.py # GoogleServiceFactory
│ │ ├── properties.py
│ │ ├── analytics.py
│ │ ├── inspection.py
│ │ ├── indexing.py
│ │ └── sitemaps.py
│ ├── tools/ # MCP tool registrations
│ ├── requirements.txt
│ └── Dockerfile
├── terraform/
│ ├── main.tf # Provider + backend
│ ├── ecr.tf # ECR + Docker build
│ ├── lambda.tf # Lambda + Function URL
│ ├── iam.tf # IAM roles (least privilege)
│ ├── secrets.tf # Secrets Manager
│ ├── variables.tf
│ └── outputs.tf
├── tests/
├── images/
│ └── architecture.drawio
├── deploy.sh
├── .env.example
└── .gitignore
- Google credentials are stored in AWS Secrets Manager, never in environment variables in production
- Lambda IAM role has least-privilege access (reads only its specific secret)
- Credentials are auto-refreshed and cached (thread-safe)
- Error messages never expose credential values
.gitignoreprevents committing.env,token.json, orclient_secrets.json- ECR has image scanning enabled on push
- CloudWatch logs retained for 14 days
