Phase 4 distribution audit: server-card.json + auth-wall findings

- Add /.well-known/mcp/server-card.json (Smithery auto-scan endpoint)
- Sitemap.xml now lists both well-known endpoints
- JOURNAL.md: full audit of marketplace auth walls (mcpservers.org=$39, mcp.so/smithery/glama=login)
- JAOUAD_TODO.md: updated with concrete copy-paste instructions for the 3 directories
- STATE.md: phase 4 marked blocked by auth walls until human steps in
- deploy/inspect_*.py + submit_mcpservers.py: playwright probes (kept for re-runs)
This commit is contained in:
Kaouani Jaouad
2026-04-13 11:57:32 +02:00
parent c08339e547
commit a12081e536
9 changed files with 262 additions and 15 deletions
+28
View File
@@ -0,0 +1,28 @@
"""Inspect glama.ai Add Server flow."""
from playwright.sync_api import sync_playwright
from pathlib import Path
with sync_playwright() as p:
b = p.chromium.launch(headless=True)
ctx = b.new_context(user_agent="Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0 Safari/537.36")
page = ctx.new_page()
page.goto("https://glama.ai/mcp/servers", wait_until="domcontentloaded", timeout=30000)
# find Add Server link
link = page.query_selector('a:has-text("Add Server")')
if link:
href = link.get_attribute("href")
print("ADD SERVER HREF:", href)
if href.startswith("/"):
href = "https://glama.ai" + href
page.goto(href, wait_until="domcontentloaded", timeout=30000)
print("--- ADD PAGE ---")
print("URL:", page.url)
print("TITLE:", page.title())
print(page.inner_text("body")[:1500])
Path("data/glama_add.html").write_text(page.content())
# any forms?
for inp in page.query_selector_all("input"):
print(" INPUT:", inp.get_attribute("name"), inp.get_attribute("type"), inp.get_attribute("placeholder"))
else:
print("No Add Server link found")
b.close()
+21
View File
@@ -0,0 +1,21 @@
"""Inspect mcp.so submission flow."""
from playwright.sync_api import sync_playwright
from pathlib import Path
OUT = Path(__file__).resolve().parent.parent / "data" / "mcpso.html"
with sync_playwright() as p:
b = p.chromium.launch(headless=True)
ctx = b.new_context(user_agent="Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0 Safari/537.36")
page = ctx.new_page()
for url in ("https://mcp.so/submit", "https://mcp.so/", "https://glama.ai/mcp/servers"):
try:
page.goto(url, wait_until="domcontentloaded", timeout=30000)
print(f"--- {url} -> {page.url}")
print("TITLE:", page.title())
txt = page.inner_text("body")[:600]
print(txt)
print()
except Exception as e:
print(f"FAIL {url}: {e}")
b.close()
+29
View File
@@ -0,0 +1,29 @@
"""Inspect smithery.ai/new submission form."""
from playwright.sync_api import sync_playwright
from pathlib import Path
OUT = Path(__file__).resolve().parent.parent / "data" / "smithery_new.html"
with sync_playwright() as p:
b = p.chromium.launch(headless=True)
ctx = b.new_context(user_agent="Mozilla/5.0 Aegis402-bot/0.1")
page = ctx.new_page()
page.goto("https://smithery.ai/new", wait_until="networkidle", timeout=45000)
OUT.write_text(page.content())
print("URL:", page.url)
print("TITLE:", page.title())
# capture all forms / inputs
inputs = page.query_selector_all("input")
print(f"INPUTS: {len(inputs)}")
for i in inputs:
print(" -", i.get_attribute("name"), i.get_attribute("type"), i.get_attribute("placeholder"))
btns = page.query_selector_all("button")
print(f"BUTTONS: {len(btns)}")
for bt in btns:
t = bt.inner_text().strip()
if t:
print(" -", t)
# body text first 1500 chars
print("---BODY---")
print(page.inner_text("body")[:1500])
b.close()
+102
View File
@@ -0,0 +1,102 @@
"""Submit Aegis402 to mcpservers.org via Playwright headless chromium.
Form spec (inspected previously):
GET https://mcpservers.org/submit
fields: name, description, url, category(select), email, terms(checkbox)
"""
import sys
from pathlib import Path
from playwright.sync_api import sync_playwright
OUT = Path(__file__).resolve().parent.parent / "data" / "mcpservers_submit.html"
OUT.parent.mkdir(exist_ok=True)
PAYLOAD = {
"name": "Aegis402",
"description": "Pay-per-call CVE intel for AI agent dependencies — scans GHSA + CISA KEV, x402 native, USDC on Base, no signup.",
"url": "https://aegis402.vmaxbadge.ch/",
"email": "contact@vmaxbadge.ch",
}
def main() -> int:
with sync_playwright() as p:
browser = p.chromium.launch(headless=True)
ctx = browser.new_context(user_agent="Mozilla/5.0 Aegis402-bot/0.1 (+https://aegis402.vmaxbadge.ch/)")
page = ctx.new_page()
try:
page.goto("https://mcpservers.org/submit", wait_until="networkidle", timeout=30000)
except Exception as e:
print(f"FAIL goto: {e}")
return 2
try:
page.fill('input[name="name"]', PAYLOAD["name"])
page.fill('input[name="description"], textarea[name="description"]', PAYLOAD["description"])
page.fill('input[name="url"]', PAYLOAD["url"])
page.fill('input[name="email"]', PAYLOAD["email"])
except Exception as e:
print(f"FAIL fill: {e}")
OUT.write_text(page.content())
return 3
# category select — try Security first, fallback Development
try:
sel = page.query_selector('select[name="category"]')
if sel:
opts = [o.inner_text().strip() for o in sel.query_selector_all("option")]
print("CATEGORY OPTIONS:", opts)
pick = None
for cand in ("Security", "Developer Tools", "Development", "Tools"):
for o in opts:
if cand.lower() in o.lower():
pick = o
break
if pick:
break
if pick:
page.select_option('select[name="category"]', label=pick)
print("PICKED:", pick)
except Exception as e:
print(f"WARN category: {e}")
# checkbox(es)
try:
for cb in page.query_selector_all('input[type="checkbox"]'):
if not cb.is_checked():
cb.check()
except Exception as e:
print(f"WARN checkbox: {e}")
OUT.write_text(page.content())
print(f"PRE-SUBMIT html saved to {OUT}")
# find submit button
try:
btn = page.query_selector('button[type="submit"], input[type="submit"]')
if not btn:
print("FAIL: no submit button found")
return 4
btn.click()
page.wait_for_load_state("networkidle", timeout=20000)
except Exception as e:
print(f"FAIL submit: {e}")
OUT.write_text(page.content())
return 5
post = Path(__file__).resolve().parent.parent / "data" / "mcpservers_response.html"
post.write_text(page.content())
print(f"POST-SUBMIT html: {post}")
print(f"FINAL URL: {page.url}")
# quick success heuristic
text = page.inner_text("body").lower()
for kw in ("thank", "received", "submitted", "success", "review"):
if kw in text:
print(f"SUCCESS keyword found: {kw}")
return 0
print("NO success keyword — inspect HTML manually")
return 1
if __name__ == "__main__":
sys.exit(main())