<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: dror bengal</title>
    <description>The latest articles on DEV Community by dror bengal (@dror_bengal_4d4388774752d).</description>
    <link>https://dev.to/dror_bengal_4d4388774752d</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4088825%2Fbc6b3fbd-9407-442d-bd44-27da6969df98.png</url>
      <title>DEV Community: dror bengal</title>
      <link>https://dev.to/dror_bengal_4d4388774752d</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/dror_bengal_4d4388774752d"/>
    <language>en</language>
    <item>
      <title>MCP has a discovery problem. I built a meta-server that searches all 75,000 servers.</title>
      <dc:creator>dror bengal</dc:creator>
      <pubDate>Fri, 21 Aug 2026 20:40:29 +0000</pubDate>
      <link>https://dev.to/dror_bengal_4d4388774752d/mcp-has-a-discovery-problem-i-built-a-meta-server-that-searches-all-75000-servers-30gm</link>
      <guid>https://dev.to/dror_bengal_4d4388774752d/mcp-has-a-discovery-problem-i-built-a-meta-server-that-searches-all-75000-servers-30gm</guid>
      <description>&lt;p&gt;There are now tens of thousands of MCP servers. Glama indexes ~75,000. PulseMCP lists ~22,000. npm has thousands of packages tagged mcp-server. And yet the way we all use MCP is: find a server somewhere, paste it into a config file, restart the client, repeat.&lt;br&gt;
Two things are broken about this.&lt;/p&gt;

&lt;h2&gt;
  
  
  Discovery is manual
&lt;/h2&gt;

&lt;p&gt;Your agent can't answer "is there a tool that queries Postgres?" — you have to know the answer, find the server, and wire it up before the conversation even starts.&lt;br&gt;
Every server you add costs context, forever. Each configured server loads its tool schemas into every request. Ten servers with a dozen tools each, and you've burned thousands of tokens before saying hello. This is why most people cap out at a handful of servers — not because they don't want more capabilities, but because context is expensive.&lt;/p&gt;

&lt;h2&gt;
  
  
  Inverting the model
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/Dror-Bengal/mcp-anything" rel="noopener noreferrer"&gt;mcp-anything&lt;/a&gt; is a single MCP server that inverts this. Instead of you configuring N servers, the model gets exactly five meta-tools:&lt;/p&gt;

&lt;p&gt;search_mcp_servers   → BM25 search over the indexed ecosystem&lt;br&gt;
describe_mcp_server  → transports, env vars, security verdict&lt;br&gt;
list_mcp_tools       → live connect, real schemas for ONE server&lt;br&gt;
call_mcp_tool        → execute (sessions pooled and reused)&lt;br&gt;
sync_registry        → refresh the index&lt;/p&gt;

&lt;p&gt;​&lt;br&gt;
The index is built by syncing four catalogs — the official MCP registry, PulseMCP, npm search, and Glama — deduplicating across them by normalized repository URL and package identity, and merging popularity signals (GitHub stars, npm downloads). Ask for a capability, get the best server for it, pull its real schemas, execute. Context cost stays constant no matter how big the ecosystem grows.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;claude mcp add anything -- npx -y mcp-anything serve&lt;/code&gt;&lt;br&gt;
​&lt;/p&gt;

&lt;h2&gt;
  
  
  Design decisions worth arguing about
&lt;/h2&gt;

&lt;p&gt;Lexical search, not embeddings. Everyone's first instinct (mine included) is a vector database. I went with BM25 (MiniSearch) plus a log-scaled popularity boost instead: fully local, zero API cost, no index build step — and for tool discovery it performs comparably. Anthropic made the same call for Claude's native Tool Search. With 75k servers, the real ranking problem isn't semantic nuance; it's keeping the hundredth abandoned "gdrive-upload" clone out of the top 5. Stars and download counts solve that better than cosine similarity does.&lt;br&gt;
Sessions, not stateless proxying. MCP is not stateless RPC — there's an initialize handshake and capability negotiation. Treating downstream calls as one-shot requests breaks real servers. mcp-anything pools live client sessions with LRU eviction, so repeated calls to the same server reuse the connection.&lt;/p&gt;

&lt;p&gt;Security is the actual product. Pointing an LLM at a public catalog of arbitrary servers is a genuinely scary idea, and I think any aggregator that doesn't lead with this is being irresponsible. The defaults:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;SSRF guard: a registry entry whose endpoint points at loopback, private ranges, or a cloud metadata address (169.254.169.254 — yes, there's a test fixture with a fake "metadata-stealer" server) is refused.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;No arbitrary code execution: spawning stdio servers via npx/uvx is off by default, and enabling it requires an explicit per-package allowlist, version-pinned.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Secrets never indexed: API keys live only in your local config, injected at connect time, never cached or shown to the model.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Untrusted output, labeled: tool descriptions and results from downstream servers are marked as third-party data. This mitigates tool-poisoning; it does not solve it. Nobody has solved it. The SECURITY.md says so out loud.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Public hosting must be neutered. There's a hosted instance at mcp-anything.onrender.com you can point any MCP client at to try discovery right now — but it runs in a discovery-only mode that exposes just search/describe. A public instance with call_mcp_tool enabled would be an open proxy that executes anything against anyone. The Dockerfile defaults to discovery-only for exactly this reason.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I learned shipping it
&lt;/h2&gt;

&lt;p&gt;The unglamorous parts were the real work. npm rate-limits fast pagination (429s) — the sync needed retry-with-backoff and politeness delays before a full index run survived. The official registry rejects descriptions over 100 chars and enforces case-sensitive namespace ownership down to the mcpName field inside the published npm package. Cross-source dedupe sounds trivial until the same server appears as io.github.acme/weather, pulse/weather-mcp, and npm/&lt;a class="mentioned-user" href="https://dev.to/acme"&gt;@acme&lt;/a&gt;/weather-mcp with three different metadata shapes.&lt;br&gt;
And the honest positioning question everyone should ask: gateways like MetaMCP aggregate servers you already configured; Composio's Rube routes to its own hosted catalog; native tool search in clients searches tools already connected. The open combination — public registries as the catalog, local-first single binary, explicit security policy, works against a private registry — was the gap. Whether it stays a gap is a fair question; it's MIT-licensed either way.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's next
&lt;/h2&gt;

&lt;p&gt;Per-tool indexing (search actual tool names/schemas of popular servers, not just server descriptions), live health signals in ranking, and container sandboxing for stdio as an alternative to allowlisting. The repo has good-first-issues if any of that sounds fun.&lt;/p&gt;

&lt;p&gt;Repo: &lt;a href="https://github.com/Dror-Bengal/mcp-anything" rel="noopener noreferrer"&gt;https://github.com/Dror-Bengal/mcp-anything&lt;/a&gt; · &lt;br&gt;
Try discovery now: &lt;a href="https://mcp-anything.onrender.com" rel="noopener noreferrer"&gt;https://mcp-anything.onrender.com&lt;/a&gt; · 49 tests, CI green, no telemetry, no cloud account.&lt;/p&gt;

&lt;p&gt;Disclosure: built in the open with heavy AI pair-programming — every design decision reviewed, every line tested.&lt;/p&gt;

</description>
      <category>mcp</category>
      <category>ai</category>
      <category>opensource</category>
      <category>typescript</category>
    </item>
  </channel>
</rss>
