DEV Community

Cover image for How I built a directory of 28,577 MCP servers
Tanvith Reddy
Tanvith Reddy

Posted on

How I built a directory of 28,577 MCP servers

The problem

mcp server discovery is a mess. you find a server on some github awesome-list, open the repo, realize it hasnt been touched in 8 months. the aggregator sites show a fraction of whats actually out there and most of them filter their listings down to whatever they can hand-curate. and there's no way to browse by what a server actually does, so you end up with 12 tabs open trying to figure out which postgres-mcp-wrapper actually works.

i wanted a flat searchable index of every MCP server that exists publicly, sorted by what they do. so i built one.

The scanner

scanner pulls candidates from github code search + the github api, plus a few aggregator sites that publish their listings. dedupes by owner/name. each candidate gets run through a classifier that confirms the repo actually implements MCP and isnt just mentioning it in the readme, then assigns a category and pulls a description.

went with gemini via openrouter for the classifier. tried claude and gpt for spot checks, agreement rate was high enough that flash was fine for the bulk pass and way cheaper at this volume. total classifier spend ended up around $8 for the full 30k+ candidate pool.

scanner reruns continuously so newly released servers show up in the index within a few days.

The frontend choice

three options here:

  1. pure static: prerender all 28k server pages at build time. dead on arrival because cloudflare workers free tier has a 20,000 static asset limit. id be over the cap before i even shipped.
  2. pure SSR: every page hit goes through the worker. fine for small sites but every visit pays a worker invocation, and i wanted infra cost to stay at $0.
  3. hybrid (what i picked): prerender the ~100 pages that matter (home, browse, search, about, 95 category pages) into static html. the 28k per-server pages are dynamic, query cloudflare D1 (free SQLite at the edge) on first request, then cloudflare's CDN caches the rendered html for 24h. after the first hit, popular server pages are as fast as static.

astro hybrid mode + @astrojs/cloudflare adapter handles this cleanly. one template, one route file, scales to as many servers as D1 can hold.

Two gotchas that bit me

D1's 100KB statement limit

initial export script batched INSERTs at 500 rows per statement. wrangler immediately threw SQLITE_TOOBIG. turns out D1 caps a single statement at 100KB. dropped the batch size to 50 rows per INSERT and the generated sql file grew to ~570 statements. fine, just have to know the limit exists, its not in the obvious place in their docs.

.assetsignore for _worker.js

astro's cloudflare adapter outputs both _worker.js (the SSR entrypoint) and your prerendered html into the same dist/ directory. wrangler then tries to upload _worker.js as a static asset, which (a) eats one of your 20k asset slots and (b) usually fails the size check. fix is a single .assetsignore file in public/ listing _worker.js and _routes.json. took an hour to find because the error messages dont point at it.

The numbers

  • 28,577 verified MCP servers indexed
  • 95 categories
  • 30k+ views on the launch post, #1 in r/mcp on day 1

What's not great

about 20% of servers land in an "other" bucket. MCP itself is new enough that a lot of servers are too niche to slot into the 95 categories i defined, and too different from each other to spin up their own category. i show that openly on the home page instead of hiding it.

the 0-100 score on each server is metadata based (popularity + description quality + multi-source presence). its a discovery signal, not a security audit, so review code before connecting anything that touches your data.

solo project, no SLA. if it breaks i fix it when i see the email.

Try it

site is at safemcp.info. free, no signup, no rate limit. if you've published an MCP server and its categorized weird or theres one i missed, email hello@safemcp.info, i read everything.

Top comments (0)