aeo-scanner 2.2.0__tar.gz → 2.2.2__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.
Files changed (31) hide show
  1. {aeo_scanner-2.2.0 → aeo_scanner-2.2.2}/PKG-INFO +5 -8
  2. {aeo_scanner-2.2.0 → aeo_scanner-2.2.2}/README.md +4 -7
  3. {aeo_scanner-2.2.0 → aeo_scanner-2.2.2}/pyproject.toml +1 -1
  4. aeo_scanner-2.2.2/server.json +27 -0
  5. {aeo_scanner-2.2.0 → aeo_scanner-2.2.2}/src/server.py +52 -34
  6. {aeo_scanner-2.2.0 → aeo_scanner-2.2.2}/workers/package-lock.json +1117 -71
  7. {aeo_scanner-2.2.0 → aeo_scanner-2.2.2}/workers/package.json +4 -2
  8. aeo_scanner-2.2.2/workers/src/api-client.test.ts +197 -0
  9. aeo_scanner-2.2.2/workers/src/api-client.ts +198 -0
  10. {aeo_scanner-2.2.0 → aeo_scanner-2.2.2}/workers/src/index.ts +1 -1
  11. {aeo_scanner-2.2.0 → aeo_scanner-2.2.2}/workers/src/resources.ts +1 -1
  12. {aeo_scanner-2.2.0 → aeo_scanner-2.2.2}/workers/src/tools.ts +21 -23
  13. aeo_scanner-2.2.0/.github/workflows/publish.yml +0 -26
  14. aeo_scanner-2.2.0/server.json +0 -36
  15. aeo_scanner-2.2.0/workers/src/api-client.ts +0 -156
  16. {aeo_scanner-2.2.0 → aeo_scanner-2.2.2}/.gitignore +0 -0
  17. {aeo_scanner-2.2.0 → aeo_scanner-2.2.2}/.mcp.json +0 -0
  18. {aeo_scanner-2.2.0 → aeo_scanner-2.2.2}/LICENSE +0 -0
  19. {aeo_scanner-2.2.0 → aeo_scanner-2.2.2}/aeo-icon.svg +0 -0
  20. {aeo_scanner-2.2.0 → aeo_scanner-2.2.2}/scoring-methodology.md +0 -0
  21. {aeo_scanner-2.2.0 → aeo_scanner-2.2.2}/src/__init__.py +0 -0
  22. {aeo_scanner-2.2.0 → aeo_scanner-2.2.2}/uv.lock +0 -0
  23. {aeo_scanner-2.2.0 → aeo_scanner-2.2.2}/workers/.gitignore +0 -0
  24. {aeo_scanner-2.2.0 → aeo_scanner-2.2.2}/workers/.oxfmtrc.json +0 -0
  25. {aeo_scanner-2.2.0 → aeo_scanner-2.2.2}/workers/.oxlintrc.json +0 -0
  26. {aeo_scanner-2.2.0 → aeo_scanner-2.2.2}/workers/README.md +0 -0
  27. {aeo_scanner-2.2.0 → aeo_scanner-2.2.2}/workers/src/prompts.ts +0 -0
  28. {aeo_scanner-2.2.0 → aeo_scanner-2.2.2}/workers/src/scoring-methodology.ts +0 -0
  29. {aeo_scanner-2.2.0 → aeo_scanner-2.2.2}/workers/tsconfig.json +0 -0
  30. {aeo_scanner-2.2.0 → aeo_scanner-2.2.2}/workers/worker-configuration.d.ts +0 -0
  31. {aeo_scanner-2.2.0 → aeo_scanner-2.2.2}/workers/wrangler.jsonc +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: aeo-scanner
3
- Version: 2.2.0
3
+ Version: 2.2.2
4
4
  Summary: MCP server for AI search visibility auditing. Triple scoring: AEO (search findability), GEO (citation readiness), Agent Readiness (agent interaction). Plus AI Identity Card and business profile detection.
5
5
  Author-email: Convrgent <hello@convrgent.ai>
6
6
  License: MIT
@@ -56,7 +56,7 @@ claude mcp add aeo-scanner -- uvx aeo-scanner
56
56
  | Tool | What it does | Price |
57
57
  |------|-------------|-------|
58
58
  | `scan_site` | Quick triple-score scan + AI Identity Card + mention readiness + business profile + top issues | **Free** |
59
- | `audit_site` | Full 58+ check breakdown across 12 categories (4 AEO + 4 GEO + 4 Agent) | $1.00 |
59
+ | `audit_site` | Full 67+ check breakdown across 12 categories (4 AEO + 4 GEO + 4 Agent) | $1.00 |
60
60
  | `compare_sites` | Two-site gap analysis + category winners + overtake fix code | $3.00 |
61
61
  | `fix_site` | Generated fix code with two-tier score projections — apply directly with Claude Code | $5.00 |
62
62
 
@@ -68,12 +68,9 @@ Rate limits: 20 scans/hour per IP, 5 per URL per day.
68
68
 
69
69
  ## Paid tools
70
70
 
71
- `audit_site`, `compare_sites`, and `fix_site` require an API key:
71
+ `audit_site`, `compare_sites`, and `fix_site` are pay-per-call via the [x402 protocol](https://www.x402.org/) — USDC on Base or Solana. No API key, no account.
72
72
 
73
- 1. Get your key at [scan.convrgent.ai](https://scan.convrgent.ai)
74
- 2. Set `AEO_API_KEY` in your MCP config
75
-
76
- Or pay per call with USDC via [x402 protocol](https://www.x402.org/) (Base network).
73
+ Without payment, the tool returns a structured `payment_required` error containing the full x402 payload (payTo address, amount, asset). x402-capable clients retry automatically with a signed `X-PAYMENT` header; other agents can relay the payment details to their operator.
77
74
 
78
75
  ## Workflow
79
76
 
@@ -87,7 +84,7 @@ The included `optimize_site` prompt guides the full workflow:
87
84
 
88
85
  ## Scoring
89
86
 
90
- 58+ checks across 12 categories. See the built-in `aeo://reference/scoring-methodology` resource for full details.
87
+ 67+ checks across 12 categories. See the built-in `aeo://reference/scoring-methodology` resource for full details.
91
88
 
92
89
  **AEO categories:** Structured Data (30%), Meta & Technical (20%), AI Accessibility (25%), Content Quality (25%)
93
90
 
@@ -39,7 +39,7 @@ claude mcp add aeo-scanner -- uvx aeo-scanner
39
39
  | Tool | What it does | Price |
40
40
  |------|-------------|-------|
41
41
  | `scan_site` | Quick triple-score scan + AI Identity Card + mention readiness + business profile + top issues | **Free** |
42
- | `audit_site` | Full 58+ check breakdown across 12 categories (4 AEO + 4 GEO + 4 Agent) | $1.00 |
42
+ | `audit_site` | Full 67+ check breakdown across 12 categories (4 AEO + 4 GEO + 4 Agent) | $1.00 |
43
43
  | `compare_sites` | Two-site gap analysis + category winners + overtake fix code | $3.00 |
44
44
  | `fix_site` | Generated fix code with two-tier score projections — apply directly with Claude Code | $5.00 |
45
45
 
@@ -51,12 +51,9 @@ Rate limits: 20 scans/hour per IP, 5 per URL per day.
51
51
 
52
52
  ## Paid tools
53
53
 
54
- `audit_site`, `compare_sites`, and `fix_site` require an API key:
54
+ `audit_site`, `compare_sites`, and `fix_site` are pay-per-call via the [x402 protocol](https://www.x402.org/) — USDC on Base or Solana. No API key, no account.
55
55
 
56
- 1. Get your key at [scan.convrgent.ai](https://scan.convrgent.ai)
57
- 2. Set `AEO_API_KEY` in your MCP config
58
-
59
- Or pay per call with USDC via [x402 protocol](https://www.x402.org/) (Base network).
56
+ Without payment, the tool returns a structured `payment_required` error containing the full x402 payload (payTo address, amount, asset). x402-capable clients retry automatically with a signed `X-PAYMENT` header; other agents can relay the payment details to their operator.
60
57
 
61
58
  ## Workflow
62
59
 
@@ -70,7 +67,7 @@ The included `optimize_site` prompt guides the full workflow:
70
67
 
71
68
  ## Scoring
72
69
 
73
- 58+ checks across 12 categories. See the built-in `aeo://reference/scoring-methodology` resource for full details.
70
+ 67+ checks across 12 categories. See the built-in `aeo://reference/scoring-methodology` resource for full details.
74
71
 
75
72
  **AEO categories:** Structured Data (30%), Meta & Technical (20%), AI Accessibility (25%), Content Quality (25%)
76
73
 
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "aeo-scanner"
3
- version = "2.2.0"
3
+ version = "2.2.2"
4
4
  description = "MCP server for AI search visibility auditing. Triple scoring: AEO (search findability), GEO (citation readiness), Agent Readiness (agent interaction). Plus AI Identity Card and business profile detection."
5
5
  readme = "README.md"
6
6
  license = {text = "MIT"}
@@ -0,0 +1,27 @@
1
+ {
2
+ "$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
3
+ "name": "io.github.Convrgent/aeo-scanner",
4
+ "title": "AEO Scanner",
5
+ "description": "AI visibility for ChatGPT/Perplexity/Claude — triple score (AEO+GEO+Agent) with fix code. Free.",
6
+ "repository": {
7
+ "url": "https://github.com/Convrgent/aeo-saas",
8
+ "source": "github"
9
+ },
10
+ "version": "2.2.2",
11
+ "remotes": [
12
+ {
13
+ "type": "streamable-http",
14
+ "url": "https://aeo-mcp.convrgent.ai/mcp"
15
+ }
16
+ ],
17
+ "packages": [
18
+ {
19
+ "registryType": "pypi",
20
+ "identifier": "aeo-scanner",
21
+ "version": "2.2.2",
22
+ "transport": {
23
+ "type": "stdio"
24
+ }
25
+ }
26
+ ]
27
+ }
@@ -9,42 +9,59 @@ mcp = FastMCP(
9
9
  )
10
10
 
11
11
  API_BASE = os.environ.get("AEO_API_URL", "https://scan.convrgent.ai")
12
- AEO_API_KEY = os.environ.get("AEO_API_KEY")
13
12
 
14
-
15
- def _get_paid_headers() -> dict:
16
- """Build headers for paid API calls."""
17
- headers = {"Content-Type": "application/json"}
18
- if AEO_API_KEY:
19
- headers["Authorization"] = f"Bearer {AEO_API_KEY}"
20
- return headers
21
-
22
-
23
- def _payment_required_response() -> str:
24
- """Structured 402 response that agents can relay to their operators."""
13
+ # Single source of truth for tool name + price per endpoint — mirrors
14
+ # TOOL_PRICING in mcp/workers/src/api-client.ts. Keep the two in sync.
15
+ TOOL_PRICING = {
16
+ "/api/aeo/audit": ("audit_site", "$1.00"),
17
+ "/api/aeo/compare": ("compare_sites", "$3.00"),
18
+ "/api/aeo/fix": ("fix_site", "$5.00"),
19
+ }
20
+
21
+
22
+ def _payment_required_response(resp: httpx.Response, tool: str, price: str) -> str:
23
+ """Pass the backend's x402 v2 payload through verbatim so x402-capable
24
+ agents can auto-pay, and agents without a wallet can relay payTo/amount
25
+ to their operator. Never swallow the payload behind a static message —
26
+ that was the exact bug fixed in the worker (PR #3, 2026-04-17). The old
27
+ AEO_API_KEY / Bearer flow was dead config: the backend only ever checked
28
+ x402 payment headers."""
29
+ try:
30
+ x402_payload = resp.json()
31
+ except Exception:
32
+ x402_payload = {"raw": resp.text[:500]}
25
33
  return json.dumps(
26
34
  {
27
35
  "error": "payment_required",
28
- "message": "This tool requires a paid API key.",
29
- "how_to_pay": {
30
- "stripe": "Get your API key at https://scan.convrgent.ai",
31
- "crypto": "Pay per call via x402 (USDC on Base). See https://scan.convrgent.ai",
32
- },
33
- "setup": "Set AEO_API_KEY in your MCP server config env vars.",
34
- "pricing": {"audit_site": "$1.00", "compare_sites": "$3.00", "fix_site": "$5.00"},
35
- "tip": "scan_site is free try it first to see your scores.",
36
+ "status": 402,
37
+ "tool": tool,
38
+ "price": price,
39
+ "message": (
40
+ f"{tool} is pay-per-call ({price}) via the x402 protocol — USDC on "
41
+ "Base or Solana. Retry with a signed X-PAYMENT header from an "
42
+ "x402-capable client, or relay the payment details below to your "
43
+ "operator. The x402 payload has the payTo address, amount, and asset."
44
+ ),
45
+ "x402": x402_payload,
46
+ "docs": "https://www.x402.org/",
47
+ "free_alternative": "scan_site is free — try it to see the three scores before paying for the full audit.",
36
48
  },
37
49
  indent=2,
38
50
  )
39
51
 
40
52
 
41
53
  async def _handle_paid_request(endpoint: str, payload: dict) -> str:
42
- """Call a paid endpoint with proper 402 handling."""
43
- headers = _get_paid_headers()
54
+ """Call a paid endpoint with proper 402 handling.
55
+
56
+ X-MCP-Tool tags the request as MCP-originated so the backend can measure
57
+ discovery->tool-call conversion (mirrors mcp/workers/src/api-client.ts).
58
+ """
59
+ tool, price = TOOL_PRICING[endpoint]
60
+ headers = {"Content-Type": "application/json", "X-MCP-Tool": tool}
44
61
  async with httpx.AsyncClient(timeout=180) as client:
45
62
  resp = await client.post(f"{API_BASE}{endpoint}", json=payload, headers=headers)
46
63
  if resp.status_code == 402:
47
- return _payment_required_response()
64
+ return _payment_required_response(resp, tool, price)
48
65
  if resp.status_code >= 400:
49
66
  try:
50
67
  error_data = resp.json()
@@ -68,13 +85,13 @@ async def scan_site(url: str, pages: int = 5) -> str:
68
85
  and Agent Readiness Score (0-100, AI agent interaction). Also returns
69
86
  AI Identity Card with mention readiness (0-100, predicts how likely AI
70
87
  will mention the brand), detected competitors, business profile
71
- (commerce/saas/media/general), and top issues. 58+ checks across
72
- 12 categories. Free — no API key needed."""
88
+ (commerce/saas/media/general), and top issues. 67+ checks across
89
+ 12 categories. Free — no payment or setup needed."""
73
90
  async with httpx.AsyncClient(timeout=120) as client:
74
91
  resp = await client.post(
75
92
  f"{API_BASE}/api/aeo/scan",
76
93
  json={"url": url, "pages": min(max(1, pages), 5)},
77
- headers={"Content-Type": "application/json"},
94
+ headers={"Content-Type": "application/json", "X-MCP-Tool": "scan_site"},
78
95
  )
79
96
  if resp.status_code >= 400:
80
97
  try:
@@ -96,13 +113,13 @@ async def scan_site(url: str, pages: int = 5) -> str:
96
113
  async def audit_site(
97
114
  url: str, pages: int = 5, categories: list[str] | None = None
98
115
  ) -> str:
99
- """Full AI visibility audit across 58+ checks in 12 categories:
116
+ """Full AI visibility audit across 67+ checks in 12 categories:
100
117
  AEO (structured data, meta & technical, AI accessibility, content quality),
101
118
  GEO (brand narrative, citation readiness with 3 research-backed checks,
102
119
  authority signals, entity definition), and Agent Readiness (machine
103
120
  identity, API discoverability, structured actions, programmatic access).
104
121
  Returns AI Identity Card with mention readiness and detected competitors.
105
- Requires API key (set AEO_API_KEY env var). $1.00 per call."""
122
+ Pay per call ($1.00) via x402 — USDC on Base or Solana."""
106
123
  payload: dict = {"url": url, "pages": min(max(1, pages), 5)}
107
124
  if categories:
108
125
  payload["categories"] = categories
@@ -117,7 +134,7 @@ async def compare_sites(url: str, competitor_url: str, pages: int = 5) -> str:
117
134
  fix code with projected scores after closing gaps. Use when the user
118
135
  wants to benchmark against a competitor or when scan_site detects
119
136
  competitors in the AI Identity Card.
120
- Requires API key (set AEO_API_KEY env var). $3.00 per call."""
137
+ Pay per call ($3.00) via x402 — USDC on Base or Solana."""
121
138
  return await _handle_paid_request(
122
139
  "/api/aeo/compare",
123
140
  {"url": url, "competitorUrl": competitor_url, "maxPages": min(max(1, pages), 5)},
@@ -132,7 +149,7 @@ async def fix_site(url: str, pages: int = 5, format: str = "generic") -> str:
132
149
  quick wins (critical + high fixes only) and full implementation
133
150
  ceiling (all fixes). Content recommendations include research citations.
134
151
  Set format to 'claude_code' for Claude Code optimized output.
135
- Requires API key (set AEO_API_KEY env var). $5.00 per call."""
152
+ Pay per call ($5.00) via x402 — USDC on Base or Solana."""
136
153
  return await _handle_paid_request(
137
154
  "/api/aeo/fix",
138
155
  {"url": url, "pages": min(max(1, pages), 5), "format": format},
@@ -141,7 +158,7 @@ async def fix_site(url: str, pages: int = 5, format: str = "generic") -> str:
141
158
 
142
159
  @mcp.resource("aeo://reference/scoring-methodology")
143
160
  async def scoring_methodology() -> str:
144
- """How AEO, GEO, and Agent Readiness scores are calculated across 58+ checks in 12 categories. Includes mention readiness, business profiles, and research sources."""
161
+ """How AEO, GEO, and Agent Readiness scores are calculated across 67+ checks in 12 categories. Includes mention readiness, business profiles, and research sources."""
145
162
  path = os.path.join(os.path.dirname(__file__), "..", "scoring-methodology.md")
146
163
  with open(path) as f:
147
164
  return f.read()
@@ -184,9 +201,10 @@ Priority focus: {priority}
184
201
  If priority is "auto", use the detected business profile to decide emphasis.
185
202
 
186
203
  If any paid tool returns a payment_required error, tell the user:
187
- - Get an API key at https://scan.convrgent.ai
188
- - Set it as AEO_API_KEY in your MCP config
189
- - Or pay per call with USDC via x402 protocol
204
+ - The tools are pay-per-call via the x402 protocol (USDC on Base or Solana)
205
+ - The error includes the full x402 payload (payTo address, amount, asset)
206
+ - An x402-capable client can retry with a signed X-PAYMENT header
207
+ - Details: https://www.x402.org/ and https://scan.convrgent.ai
190
208
  """
191
209
 
192
210