App SEO AI
app-seo-ai is a Node.js SEO automation server with Google Ads Keyword Planner integration and MCP tool definitions.
Before You Start
- Confirm the server is running —
GET http://localhost:3000/healthshould return{ "status": "ok" }. - Keyword data is live —
/api/keywords/*calls the real Google Ads API. - SERP and competitor endpoints return mock data — treat them as structural placeholders until a SERP API is wired up. Do not present mock metrics as real rankings or DA scores.
If the server is not running, guide setup (see Setup) or call the REST API yourself via curl once it is up.
Setup
git clone https://github.com/ayushsinghvi92/app-seo-ai.git
cd app-seo-ai
npm install
cp .env.example .env
Required .env variables:
| Variable | Purpose |
|---|---|
GOOGLE_ADS_DEVELOPER_TOKEN |
Google Ads API developer token |
GOOGLE_ADS_CLIENT_ID |
OAuth client ID |
GOOGLE_ADS_CLIENT_SECRET |
OAuth client secret |
GOOGLE_ADS_REFRESH_TOKEN |
OAuth refresh token (npm run get-token) |
GOOGLE_ADS_LOGIN_CUSTOMER_ID |
Ads customer ID, no dashes |
SERP_API_KEY |
Optional; not used by current SERP routes |
npm run get-token # OAuth flow, saves refresh token to .env
npm run dev # development (port 3000)
# or: docker compose up
API docs: http://localhost:3000/api-docs
Cursor Integration
Option A — Local REST API (recommended for local dev)
Start the server, then use curl or shell fetch against http://localhost:3000. No MCP config required.
Option B — Smithery MCP
Deploy via Smithery using the repo's mcp.json tool definitions. Smithery maps MCP tools to the HTTP endpoints below.
Option C — Cursor MCP config
Add to ~/.cursor/mcp.json only after the server is running locally. The repo exposes HTTP endpoints, not a stdio MCP process — prefer Option A unless Smithery is deployed.
SEO Workflow
Copy this checklist and track progress:
Task Progress:
- [ ] Step 1: Health check
- [ ] Step 2: Seed keyword research
- [ ] Step 3: Metrics on shortlisted keywords
- [ ] Step 4: SERP / competitor context (note mock data)
- [ ] Step 5: Deliver recommendations
Step 1 — Health check
curl -s http://localhost:3000/health
Step 2 — Keyword ideas (primary tool)
curl -s "http://localhost:3000/api/keywords/ideas?keyword=SEED&language=de&locations=[2276]&limit=30"
locationsis a JSON array in the query string, e.g.[2276]for Germany,[2250]for US.- Default language:
en. Default location: US (2250).
Step 3 — Metrics on a keyword list
curl -s -X POST http://localhost:3000/api/keywords/metrics \
-H "Content-Type: application/json" \
-d '{"keywords":["kw1","kw2"],"language":"de","locations":[2276]}'
Step 4 — SERP and competitors (mock responses today)
curl -s "http://localhost:3000/api/serp/analyze?query=QUERY&location=Germany&language=de"
curl -s "http://localhost:3000/api/competitors/analyze?keyword=QUERY&limit=10"
Step 5 — Recommendations
Synthesize findings into:
- Primary keyword — highest relevance + workable volume/competition
- Secondary keywords — 3–5 supporting terms
- Content angles — H1, meta title/description drafts, FAQ topics
- Gaps — what top results cover that the target page should address
For WordPress/landing pages in this workspace, map keywords to on-page elements (title, H1, schema, FAQ) and note Rank Math / Yoast fields to fill.
MCP Tool Mapping
| MCP tool | HTTP endpoint | Notes |
|---|---|---|
research_keywords |
GET /api/keywords/ideas |
Live Google Ads data |
analyze_serp |
GET /api/serp/analyze |
Mock data |
analyze_competitors |
GET /api/competitors/analyze |
Mock data |
_health |
GET /health |
Server status |
Keyword Response Fields
| Field | Meaning |
|---|---|
keyword |
Suggested search term |
avgMonthlySearches |
Average monthly search volume |
competition |
LOW, MEDIUM, HIGH, or UNKNOWN |
competitionIndex |
0–100 competition score |
lowTopOfPageBidMicros / highTopOfPageBidMicros |
Estimated top-of-page bid range (USD) |
Error Handling
| Symptom | Action |
|---|---|
| Connection refused on :3000 | Start server: npm run dev in app-seo-ai directory |
| 500 on keyword endpoints | Check .env credentials; re-run npm run get-token |
| Empty keyword ideas | Try broader seed keyword or different locations |
Invalid locations |
Pass valid JSON array, e.g. locations=[2276] |
Additional Resources
- Geo target location IDs: reference.md
- Full API list and examples: reference.md