A production MCP server exposing structured research and live-data analysis as callable tools inside Claude.
Built by Mason Wu (writing as Max online) — researcher and AE selling complex technical platforms to founder/CTO buyers. MaxBrain is what happens when a specialist with a Substack ships their own MCP server.
Status: Production · Beta · Sole engineer · 130 paid subscribers ($24K ARR at $20/mo or $159/yr), converted from a 5K-person free newsletter
Live endpoint: brain.maxcrypto.space (MCP server — connected via Claude Desktop or the claude.ai connector, not opened in a browser)
Access: Paid subscribers of maxcrypto.space get an MCP token automatically
Source: Private. This repo is a README-only showcase of the architecture and engineering choices.
MaxBrain is a Model Context Protocol server I designed, built, and operate. It exposes a private knowledge base — structured research entries, deterministic valuation analysis on live external data, and semantic search over an embedded article corpus — as callable tools inside any MCP-compatible client. Claude Desktop, Claude Code, and claude.ai connectors all speak to the same server.
The domain is crypto project research, because that is the field I write about. The engineering question is more general: what does it look like to expose a specialist's private knowledge as a first-class tool surface for AI assistants? MaxBrain is my working answer.
MCP reshapes what AI assistants can do for specialist knowledge work. Rather than explore that on a toy, I built the tool I actually needed and put it in front of real users — ~130 readers of my research newsletter. Shipping it forced the architecture questions that matter: transport, auth, state persistence, observability, cost. Crypto research is the testbed. The pattern — structured views plus deterministic compute plus semantic search, with zero LLM at runtime — generalizes to any specialist knowledge workflow.
Real outputs from the live brain.maxcrypto.space server, captured against live DeFiLlama and CoinGecko data inside Claude Desktop.
Asking Claude to analyze AAVE pulls Max's view, fetches the live valuation snapshot, and renders a peer benchmark against Morpho and Compound — all in a single prompt:
Status cards on top, peer comparison charts below. Generated by tool_analyze_project("aave") plus tool_compare_projects for the peer benchmarking — one Claude prompt, ~3 MaxBrain calls under the hood.
When asked "find the 3 cheapest DeFi protocols by P/F, deep-dive the top result, and tell me whether it passes Max's framework", Claude orchestrates several MaxBrain tools and synthesizes a buy/hold/avoid call:
Claude chains tool_screen_protocols → tool_analyze_project → tool_search_max_views, surfaces the 3 candidates as summary cards, deep-dives the top result with the full framework scorecard, and renders the 90-day fee-trend chart. This is the MCP-as-agent pattern — Claude using tools to reason and decide, not just look things up.
Three layers, cleanly separated:
┌────────────────────────────────────────────────────┐
│ Views Layer 55 structured research entries │
│ (thesis, confidence, │
│ invalidation conditions) │
├────────────────────────────────────────────────────┤
│ Framework Layer Deterministic compute: │
│ P/F, P/S, holder yield, MC/FDV, │
│ sector benchmarks — pure │
│ functions over cached data │
├────────────────────────────────────────────────────┤
│ Data Layer Async DeFiLlama + CoinGecko │
│ clients, SQLite TTL cache, │
│ swappable PriceProvider │
└────────────────────────────────────────────────────┘
Zero LLM at runtime. Every tool output is either pre-authored content or deterministic compute over cached data. No model call in the hot path. Latency stays low, per-call cost stays near zero, and outputs are reproducible — you can diff them across deploys. Claude is the LLM layer; MaxBrain is the data-and-tools layer. This is the decision I'd defend hardest.
Views are authored in an Obsidian vault and synced to the server by a custom Python script (scripts/sync_views.py). Each entry encodes a thesis, a confidence level, key risks, and explicit conditions under which the thesis would be invalidated. The moat is the structure, not the opinions.
Semantic search runs on OpenAI text-embedding-3-small vectors in ChromaDB. 86 long-form articles → 722 chunks. Query cost is below $0.001 per call.
One FastMCP server, two transports: stdio locally for Claude Desktop, SSE on Railway for remote clients, wrapped in a Starlette app that adds a /health route.
| Tool | Purpose |
|---|---|
tool_analyze_project |
Full analysis — merges view, valuation, and live data snapshot |
tool_check_valuation |
Compute P/F, P/S, holder yield, MC/FDV on current data |
tool_compare_projects |
Side-by-side comparison across multiple projects |
tool_screen_protocols |
Filter the universe by valuation and revenue criteria |
tool_search_max_views |
Semantic search over the views corpus |
tool_generate_report |
Render a structured seven-section report |
tool_get_revenue_status |
Revenue quality and value-capture classification |
tool_get_sector |
Sector metadata and constituents |
Seven REST endpoints under /v1 cover the same surface for non-MCP clients. Per-user auth via UUID tokens. Rate limits: 100/hour, 500/day.
| Category | Components |
|---|---|
| Language | Python 3.12 (uv-managed venv) |
| Framework | FastAPI, FastMCP, Starlette |
| Data & compute | httpx, pydantic / pydantic-settings, aiosqlite, ChromaDB, OpenAI embeddings API |
| Deployment | Docker, Railway, uvicorn, Let's Encrypt TLS via Railway custom domain |
MCP SDK v1.26 + Railway reverse proxy → HTTP 421. The SDK's default DNS rebinding protection rejected Railway's reverse-proxied Host header with 421 Misdirected Request. Fixed by passing TransportSecuritySettings(enable_dns_rebinding_protection=False) into the SSE transport. A failure mode that only surfaces in a real deployment — local stdio tests pass cleanly.
Claude Desktop GUI ignores fnm/nvm node paths. Bridging remote MCP via npx mcp-remote failed because Claude Desktop launches without the shell's PATH modifications and couldn't find node. Symlinked node and npx into /usr/local/bin/ so the GUI-launched process could resolve them.
Railway state loss on redeploy. The first deployment stored auth tokens and rate-limit counters on the container filesystem. Every redeploy wiped them. Migrated to a Railway instance with a persistent volume for the SQLite files.
- Structured logging from day one. I started with
printand retrofitted structured logging with trace IDs only when the first cross-transport bug (stdio vs SSE) forced me to correlate events. The retrofit was cheap; the week of flying blind was not. - An in-process cache in front of ChromaDB. Every
tool_search_max_viewscall currently pays the collection's cold-start cost. A small LRU would cut p50 latency meaningfully on repeat queries. - Observability before beta, not after. No metrics in the first month of beta meant I had no view into tool-call distribution, cache hit rate, or failure modes. An events table (or Prometheus) from the first commit would have paid for itself.
Beta. ~130 paid subscribers via maxcrypto.space. Solo-maintained. Source code private. Architecture discussions welcome — open an issue or reach out via LinkedIn.
Contact: linkedin.com/in/mason-wu

