Commercial launch: Postgres auth, BTCPay payments, premium UI

- Postgres: users, api_keys, usage_log, payments tables
- Auth: API key system with rate limiting (402 when out of calls)
- BTCPay:  Bitcoin = 5 API calls, webhook for auto-credit
- Admin: sk-admin-unlimited-2026 with unlimited calls
- UI: Landing, Pricing (/5calls), Signup (no KYC), Dashboard with usage stats
- Footer: Created by drjones + Buy Me a Coffee link
- All endpoints auth-gated except signup, status, pages
This commit is contained in:
drjones
2026-08-04 06:38:51 -07:00
parent 966b0e8d59
commit da98397c3f
3 changed files with 447 additions and 506 deletions

View File

@@ -1,110 +1,81 @@
#!/usr/bin/env python3
"""
AI Research Engine — Thin MCP Proxy
Runs on MacBook. Forwards all tool calls to the CT 145 backend.
Minimal resource usage — all heavy lifting on Proxmox.
"""
"""AI Research Engine — Thin MCP Proxy. Admin key for backend auth."""
import json
import httpx
from mcp.server import FastMCP
BACKEND_URL = "http://10.30.20.249:8000"
ADMIN_KEY = "sk-admin-unlimited-2026"
client = httpx.Client(timeout=120.0)
mcp = FastMCP(
"ai-research-engine",
instructions="""
AI Research Engine — private knowledge acquisition system.
search_web(query) — Full-text search across indexed documents
semantic_search(query) — Find documents by meaning (vector search)
crawl_url(url) — Crawl a URL into the index
crawl_topic(topic) — Discover and crawl sources for a topic
research_topic(topic) — Full pipeline: discover → crawl → summarize
retrieve_document(url) — Get full content of an indexed document
summarize_sources(urls, instruction) — AI summary of multiple sources
extract_information(url, schema) — Structured data extraction
create_report(topic, sources) — Generate comprehensive research report
index_status() — System health and stats
""",
)
def _get(path: str) -> dict:
r = client.get(f"{BACKEND_URL}{path}")
sep = "&" if "?" in path else "?"
r = client.get(f"{BACKEND_URL}{path}{sep}api_key={ADMIN_KEY}")
r.raise_for_status()
return r.json()
mcp = FastMCP("ai-research-engine", instructions="AI Research Engine — private knowledge acquisition. 10 tools.")
@mcp.tool()
def search_web(query: str, category: str = "", limit: int = 10) -> str:
"""Full-text search across indexed documents. Find by keywords, titles, content."""
"""Full-text search across indexed documents."""
r = _get(f"/api/search?q={query}&category={category}&limit={limit}")
return json.dumps(r, indent=2)
@mcp.tool()
def semantic_search(query: str, limit: int = 10) -> str:
"""Search by meaning using vector embeddings. Finds conceptually related docs."""
"""Search by meaning using vector embeddings."""
r = _get(f"/api/semantic-search?q={query}&limit={limit}")
return json.dumps(r, indent=2)
@mcp.tool()
def crawl_url(url: str, depth: int = 1) -> str:
"""Crawl a URL. depth: 0=just this page, 1=+linked pages."""
"""Crawl a URL and index it."""
r = _get(f"/api/crawl?url={url}&depth={depth}")
return json.dumps(r, indent=2)
@mcp.tool()
def crawl_topic(topic: str, max_urls: int = 20) -> str:
"""Discover and crawl sources for a topic using YaCy."""
"""Discover and crawl sources for a topic."""
r = _get(f"/api/crawl-topic?topic={topic}&max_urls={max_urls}")
return json.dumps(r, indent=2)
@mcp.tool()
def research_topic(topic: str) -> str:
"""Full research pipeline: keyword search → semantic search → crawl new sources → AI summary."""
"""Full pipeline: search → crawl → AI summary."""
r = _get(f"/api/research?topic={topic}")
return json.dumps(r, indent=2)
@mcp.tool()
def retrieve_document(url: str) -> str:
"""Get full indexed content of a document by URL."""
"""Get full indexed content of a document."""
r = _get(f"/api/document?url={url}")
return json.dumps(r, indent=2)
@mcp.tool()
def summarize_sources(urls: str, instruction: str = "Summarize key points") -> str:
"""Summarize multiple URLs using local LLM. urls: comma-separated."""
"""AI summary of multiple URLs. urls: comma-separated."""
r = _get(f"/api/summarize?urls={urls}&instruction={instruction}")
return json.dumps(r, indent=2)
@mcp.tool()
def extract_information(url: str, schema: str = "company names, products, prices, specifications") -> str:
"""Extract structured information from a document using LLM."""
def extract_information(url: str, schema: str = "company names, products, prices") -> str:
"""Extract structured data from a document using LLM."""
r = _get(f"/api/extract?url={url}&schema={schema}")
return json.dumps(r, indent=2)
@mcp.tool()
def create_report(topic: str, sources: str = "") -> str:
"""Generate a comprehensive research report. sources: optional comma-separated URLs."""
"""Generate comprehensive research report."""
r = _get(f"/api/report?topic={topic}&sources={sources}")
return json.dumps(r, indent=2)
@mcp.tool()
def index_status() -> str:
"""Check health of all backend services: OpenSearch, Qdrant, YaCy, Ollama."""
"""System health + business stats."""
r = _get("/api/status")
return json.dumps(r, indent=2)
if __name__ == "__main__":
mcp.run(transport="stdio")