Skip to main content
Glama
CFP-102

cfp-seo-agent

README.md
# CFP SEO Agent (Agent Data API)

Pay-per-call SEO-Daten-APIs für KI-Agenten: DataForSEO als Datenquelle, Bezahlung per **x402 v2** in USDC auf Base.
Ein Node.js-Service (Express + TypeScript) hinter Caddy, SQLite für Request-Ledger, kein LLM, keine GPU.

## Projektstatus

| Phase | Inhalt | Status |
|---|---|---|
| 1 | Grundgerüst, DataForSEO-Client, Keyword-Metrics mit Sandbox | ✅ fertig, Sandbox-Abnahme erfolgreich (2026-10-20) |
| 2 | x402 Testnet-Zahlung, Settlement, E2E-Test | ✅ fertig, echte Base-Sepolia-Zahlung erfolgreich (2026-10-20) |
| 3 | Restliche fünf Endpunkte | ✅ fertig, alle sechs per echter Base-Sepolia-Zahlung bestätigt (2026-10-21) |
| 4 | MCP, OpenAPI, Discovery, Landingpage | ✅ fertig, MCP-Zahlung auf Base Sepolia für alle sechs Tools bestätigt (2026-10-21) |
| 5 | Admin, Docker/Caddy, Sicherheitsprüfung, Mainnet-Vorbereitung, Marktplätze | ✅ Server mit HTTPS läuft im Testbetrieb (Testnet + Sandbox); Mainnet wartet auf deine Freigabe |

## Schnellstart (Mac)

```bash
brew install node@24
echo 'export PATH="/opt/homebrew/opt/node@24/bin:$PATH"' >> ~/.zshrc && source ~/.zshrc
npm install
cp .env.example .env && chmod 600 .env   # DATAFORSEO_LOGIN / DATAFORSEO_PASSWORD eintragen
npm test
npm run dev                               # http://localhost:3000
npm run smoke:sandbox                     # zweites Terminal
```

## API

| Methode | Pfad | Preis (USDC) | Inhalt |
|---|---|---|---|
| GET | `/health` | frei | Status |
| GET | `/api/v1/services` | frei | Katalog mit Preisen, Limits, Beispiel-Requests |
| POST | `/api/v1/preflight/:serviceId` | frei | Validierung + Kosten-/Budgetprüfung, kein DataForSEO-Call |
| POST | `/api/v1/keyword-metrics` | 0.12 | Suchvolumen, CPC, Wettbewerb, 12 Monate; bis 1000 Keywords |
| POST | `/api/v1/keyword-ideas` | 0.025 | bis 25 Wortvarianten zu einem Startbegriff (Keyword Suggestions) |
| POST | `/api/v1/google-serp` | 0.025 | Top-10 organische Treffer |
| POST | `/api/v1/competitors` | 0.04 | bis 10 Wettbewerber-Domains mit Überschneidung und Kennzahlen |
| POST | `/api/v1/search-intent` | 0.04 | Suchintention + Wahrscheinlichkeit, bis 10 Keywords |
| POST | `/api/v1/ranked-keywords` | 0.04 | Top 25 Keywords, für die eine Domain rankt |
| POST | `/api/v1/keyword-difficulty` | 0.04 | Keyword-Difficulty 0–100, bis 100 Keywords |
| POST | `/api/v1/domain-overview` | 0.04 | Traffic, Keyword-Anzahl und Ranking-Verteilung einer Domain |
| POST | `/api/v1/keyword-gap` | 0.045 | Keywords, für die ein Konkurrent rankt und du nicht (Top 25) |
| POST | `/api/v1/google-trends` | 0.025 | Google-Trends-Verlauf, bis 5 Keywords, 12 Monate |
| POST | `/api/v1/local-business` | 0.03 | Google-Maps-Firmen (20) zu einer Suche: Adresse, Telefon, Bewertung |
| POST | `/api/v1/bing-serp` | 0.02 | Top 10 organische Bing-Ergebnisse |
| POST | `/api/v1/page-audit` | 0.02 | Technischer SEO-Schnellcheck einer Seite (ohne JavaScript) |
| POST | `/api/v1/domain-technologies` | 0.03 | Technologien einer Website (CMS, Analytics, Server …) |
| POST | `/api/v1/keywords-for-site` | 0.04 | Relevante Keywords einer Website (25) |
| POST | `/api/v1/traffic-estimate` | 0.04 | Geschätzter Traffic für bis zu 10 Domains |
| POST | `/api/v1/news-search` | 0.02 | Google-News-Ergebnisse (10) |
| POST | `/api/v1/image-search` | 0.02 | Google-Bilder-Ergebnisse (20) |
| POST | `/api/v1/local-market-check` | 0.1 | **Paket**: Google-Treffer + Maps-Betriebe + Wettbewerber-Domains + Beobachtungen für eine lokale Suche (2 Datenabrufe, keine Gratis-Probe) |
| POST | `/api/v1/wishlist` | gratis | Wunsch für ein neues Werkzeug (nur schreibend) |
| POST | `/api/v1/free-sample/{service-id}` | gratis | 1 Probe pro Dienst und Tag (Dienste bis 0,05 USDC, keine Pakete) |

Weitere Seiten: `/de/` (deutsche Startseite), `/status` und `/de/status` (Verfügbarkeit, Zusagen), `/status.json`, `/.well-known/agent.json`, `/.well-known/mcp/server-card.json`.
| POST | `/api/v1/ai-keyword-demand` | 0.04 | **geschätzte** AI-Search-Nachfrage, bis 10 Keywords |
| POST | `/mcp` | frei/bezahlt | MCP (Streamable HTTP): 4 kostenlose + 6 Bezahl-Tools (x402-fähiger Client nötig) |
| GET | `/openapi.json` | frei | OpenAPI 3.1 inkl. x402-Preisangaben |
| GET | `/`, `/llms.txt`, `/legal.html`, `/.well-known/x402` | frei | Website, Kurzbeschreibung für LLMs, Impressum-Platzhalter, Kompatibilitätsdatei |
| GET | `/api/v1/results/:requestId` | frei | Ergebnis/Status mit `Authorization: Bearer <result_token>` |
| POST | `/api/v1/results/:requestId/retry` | frei | ein kostenloser Wiederholungsversuch nach Upstream-Fehler (bezahlte Anfragen) |

`location_code` = Länder-Code von DataForSEO (Standard 2840 = USA; 2276 Deutschland; 2826 Großbritannien),
`language_code` z. B. `en`/`de` (Standard je nach Land). Nicht unterstützte Kombinationen werden **vor** der Zahlung mit 422 abgelehnt.
Bezahlt wird per x402 (USDC); ohne `PAYMENT-SIGNATURE` antwortet jede Service-Route mit HTTP 402 und dem Preis.

Beispiel:

```bash
curl -s -X POST http://localhost:3000/api/v1/keyword-metrics \
  -H 'content-type: application/json' \
  -d '{"keywords":["seo tools","keyword research"],"location_code":2276,"language_code":"de"}'
```

Antwort (Struktur):

```json
{
  "request_id": "…uuid…",
  "service": "keyword-metrics",
  "data_source": "sandbox",
  "cached": false,
  "result": { "location_code": 2276, "language_code": "de",
    "keywords": [{ "keyword": "seo tools", "search_volume": 0, "competition": "…", "competition_index": 0,
                   "cpc": 0, "low_top_of_page_bid": 0, "high_top_of_page_bid": 0,
                   "monthly_searches": [{ "year": 2026, "month": 9, "search_volume": 0 }] }] },
  "result_token": "…"
}
```

`data_source: "sandbox"` kennzeichnet Dummy-Daten der DataForSEO-Sandbox.

## Struktur

```
src/
  config/env.ts        Umgebungsvariablen (Zod) inkl. Sicherheits-Kombinationsregeln
  config/services.ts   zentrale Preise, Limits, Kostendeckel, Cache-TTL, an/aus
  dataforseo/client.ts DataForSEO-Client (Sandbox/Live, kein Retry, Timeout, Kosten)
  services/            ein Adapter pro Service + Pipeline (prepare → [Zahlung] → execute)
  lib/                 Cache, Kostenschutz, SQLite-Store, Rate-Limit, Logger mit Redaction
test/                  Vitest (Fixtures sind als Testdaten markiert)
docs/                  DATAFORSEO.md, PAYMENTS.md, AGENTS.md, DISCOVERY.md, TESTING.md (weitere folgen in Phase 5)
public/                Website (Vorlagen mit {{Platzhaltern}}), llms.txt, Impressum-Platzhalter
src/mcp/, src/discovery/, src/web/   MCP-Server, OpenAPI-Erzeugung, Website-Auslieferung
```

## Service hinzufügen

1. Eintrag in `src/config/services.ts` (Preis, Limits, Endpoint, Kostendeckel, TTL).
2. Adapter `src/services/<name>.ts` nach Vorbild `keywordMetrics.ts` (Zod-Schema, `estimateCostUsd`, `buildRequest`, `mapResult`).
3. In `src/services/index.ts` registrieren, Fixture + Tests ergänzen.

## Betrieb und Deployment

```bash
./scripts/deploy.sh          # Mac -> Server: hochladen, bauen, starten, HTTPS-Check
```

- Server, Befehle, Update und Fehlersuche: [docs/DEPLOYMENT.md](docs/DEPLOYMENT.md)
- Tägliche Kontrolle (`/admin`), Erstattung, Backups, Notfälle: [docs/OPERATIONS.md](docs/OPERATIONS.md)
- Mainnet-Umstieg: Checkliste in [docs/PAYMENTS.md](docs/PAYMENTS.md)
- Eintrag in Verzeichnisse (alles manuelle Schritte): [docs/MARKETPLACES.md](docs/MARKETPLACES.md)
- Sicherheit, Prüfung, Restrisiken: [docs/SECURITY.md](docs/SECURITY.md)
- Rechtlicher Abgleich (Datenschutz, Nutzungsbedingungen, offene Punkte): [docs/LEGAL-CHECK.md](docs/LEGAL-CHECK.md)

## Lizenz
MIT, siehe [LICENSE](LICENSE). Die Datenlizenz von DataForSEO und die Nutzungsbedingungen des Dienstes (`public/legal.html`) bleiben davon unberührt.

TDQS

A3.6/5.0

Scored across 26 tools

Disambiguation4/5

Most tools target a distinct resource+action, and descriptions clearly separate lookalikes such as keyword_ideas (seed-phrase suggestions), keywords_for_site (keywords for a URL), ranked_keywords (keywords a domain already ranks for) and keyword_gap (competitor-only keywords). The closest overlaps are domain_overview vs traffic_estimate (both return traffic estimates, differentiated mainly by bulk vs single-domain) and local_business vs local_market_check (the latter is a bundle containing the former), which could still cause occasional misselection.

Naming Consistency4/5

All names are snake_case and readable, with a coherent two-tier convention: free plumbing helpers use verb_noun (list_services, find_location, get_result, retry_request) while paid data endpoints use noun phrases (keyword_metrics, google_serp, domain_overview). That split is sensible but not strictly a single predictable pattern, and the noun-phrase data tools mix 'google/bing' prefixes with bare domain nouns.

Tool Count3/5

At 26 tools the surface is heavy and sits at the top of the practical range for an agent to scan reliably. The breadth is defensible since each tool maps to a distinct DataForSEO endpoint for a different SEO question, but some consolidation (e.g. merging traffic_estimate/domain_overview, or serp variants) would reduce selection cost.

Completeness3/5

Keyword research, SERP retrieval, competitor analysis, local/Maps, trends, tech detection, traffic estimation and basic on-page auditing are all covered, so core discovery workflows have no dead ends. However, backlink/link-profile data (referring domains, anchors) is entirely absent, and there is no crawl, sitemap, or historical rank-tracking capability, which are notable gaps for an SEO agent.

Maintenance

ActivityMaintained
ResponsivenessNo issues