The MCP Ecosystem: What's Worth Using
A guided tour of the servers, registries, and patterns that survived the hype.
The MCP (Model Context Protocol) ecosystem is large enough now to be dangerous. Thousands of servers exist. Most will waste your time. The ones worth using fall into three categories: infrastructure servers that every assistant needs (filesystem, web search, shell execution), domain-specific servers with active maintenance and clean permission models (GitHub, databases, cloud APIs), and servers you build yourself for internal systems. The signal is in the implementation quality, not the README.
Here is the uncomfortable truth: a server with 2,000 GitHub stars and a flashy demo video can still be a security disaster. Many popular MCP servers execute arbitrary commands, lack permission scoping, or leak credentials through environment variables. The protocol gives you a standard interface. It does not give you a standard for safety. The servers that survived the hype are the ones whose authors understood this distinction.
What makes an MCP server worth using in production?
Two things: a clear threat model and a narrow scope. A good server does one category of work, does it with explicit permission boundaries, and ships with documentation that tells you exactly what it can touch and what it cannot. If you cannot answer "what happens if the model goes rogue with this server's tools" after reading the README, the server is not ready for production.
The protocol itself gives you a framework for evaluating this. Every MCP server exposes tools, resources, and prompts. Tools are the dangerous ones. They execute code, mutate state, and call external APIs. Resources are read-only context providers, safer by design. Prompts are templates, harmless on their own. When you evaluate a server, count its tools. Each tool is an attack surface. A server with 47 tools and no documentation about which ones require user confirmation is a red flag.
The infrastructure tier: servers every assistant needs
These are the servers that wire your assistant into the machine itself. They are the most powerful and the most dangerous. Use them. Just understand what you are granting.
Filesystem access is the most common MCP server category. The official @modelcontextprotocol/server-filesystem lets the model read, write, and list files within configured directories. It uses the stdio transport, runs as a subprocess of the host, and scopes access to paths you specify at startup. This is the pattern to emulate. The server does not have access to your entire disk. You tell it which directories are fair game. The model cannot escape those boundaries because the server enforces them at the OS level, not through prompt engineering.
The filesystem server exposes resources for every file and directory in its scope. The model can read files as context without invoking a tool. It exposes tools for writing and editing files. The distinction matters: reading is safe and automatic. Writing requires an explicit tool call that the host can intercept, confirm, or reject. If you are building your own server, steal this pattern. Separate read-only context from mutating operations at the protocol level.
Web search servers bridge the model's knowledge cutoff. The Brave Search MCP server is the reference implementation here. It exposes a single tool, brave_web_search, that takes a query and returns structured results. It uses the streamable HTTP transport, which means it runs as a remote service. Your API (application programming interface) key travels over TLS. The server does not have access to your local machine. This is the right architecture for API-backed tools: run them remotely, authenticate them explicitly, and keep them stateless.
Shell execution servers are the most controversial. They let the model run arbitrary commands on your machine. The @anthropic/mcp-server-commands server does this with a configurable allowlist. You specify which commands the model can run. The server rejects anything not on the list. This is not perfect. An allowlisted curl command can still exfiltrate data. But it is better than unrestricted shell access. If you need shell execution, use a server with an allowlist. Better yet, build a narrow tool that does exactly what you need instead of exposing a general-purpose shell.
The domain tier: servers that connect to real systems
These servers bridge your assistant to specific services. The good ones are thin wrappers around well-known APIs. They do not invent new abstractions. They translate MCP tool calls into API requests and API responses into MCP results.
GitHub is the canonical example. The @modelcontextprotocol/server-github server exposes tools for creating issues, managing pull requests, and reading repository contents. It uses a personal access token for authentication. Each tool maps to a specific GitHub API endpoint. The server does not have its own database or state. It is a pure translation layer. This makes it auditable. You can read the source and trace every tool call to a specific API operation. If you know the GitHub API, you already know what this server can do.
The GitHub server also exposes resources for repository files. The model can read code as context without making API calls. This is the right design. Resources for reading, tools for writing. The server's README documents exactly which scopes the token needs. If you grant repo scope, the server can touch private repositories. If you grant public_repo, it cannot. The permission model is inherited from GitHub's own OAuth scopes. The server does not add its own layer.
Database servers are where things get interesting. A PostgreSQL MCP server typically exposes tools for running queries and resources for inspecting schemas. The dangerous pattern is a server that exposes a single run_query tool with no restrictions. This gives the model the ability to run DROP TABLE or SELECT * FROM users. The safer pattern is what the @anthropic/mcp-server-postgres server does: it exposes separate tools for read-only queries and write queries, and it lets you configure which tables are accessible.
When evaluating a database MCP server, check whether it uses prepared statements. If it concatenates user input into SQL strings, walk away. The model is not the user, but prompt injection through tool arguments is a real attack vector. A malicious prompt could craft a tool call that performs SQL injection. Prepared statements prevent this. If the server's source code shows string interpolation for query building, it is not production-ready.
Cloud API servers follow the same pattern as GitHub. They wrap AWS, GCP, or Azure SDKs behind MCP tools. The good ones scope permissions through IAM roles, not hardcoded credentials. They expose narrow tools like list_s3_buckets or describe_ec2_instances instead of a generic run_aws_command. They document which API calls each tool makes. The bad ones expose the entire SDK (software development kit) surface and tell you to "be careful with the prompt."
The registry landscape: where to find servers
The MCP ecosystem has no official package registry. This is a feature, not a bug. It means you are responsible for vetting servers before you install them. Several community directories have emerged to fill the gap.
mcp.directory is the largest curated listing. It categorizes servers by function and includes basic metadata: transport type, authentication requirements, and a link to the source repository. It does not perform security reviews. Treat it as a discovery tool, not an endorsement.
The awesome-mcp-servers repository on GitHub is a community-maintained list with more granular categorization. It distinguishes between official Anthropic servers, community servers, and experimental projects. This is useful for filtering. Official servers have undergone at least some review. Community servers vary wildly in quality. Experimental servers are prototypes. Know which category you are installing from.
npx is the de facto distribution mechanism for TypeScript MCP servers. Many servers are published as npm packages that you run via npx @scope/server-name. This is convenient. It is also a supply chain risk. Running npx executes code from the npm registry on your machine. Before you run an MCP server this way, read its source. Check its dependencies. Look at its publish history. A server that was first published three days ago with no prior versions is not something you should run on your production machine.
For Python servers, pipx serves a similar role. It installs servers in isolated environments and exposes their entry points. The same supply chain warnings apply. The Python MCP SDK is well-maintained and the FastMCP framework makes it easy to build servers quickly. This ease of development means there are many Python MCP servers. Most are weekend projects. Check the commit history before you trust one.
How does MCP handle server discovery at runtime?
The host does not magically find servers. You configure them. In Claude Desktop, you edit a JSON (JavaScript Object Notation) file at ~/Library/Application Support/Claude/claude_desktop_config.json on macOS. Each server entry specifies a command to launch the server and any arguments or environment variables. For stdio servers, this is typically an npx or pipx command. For HTTP servers, it is a URL and an authentication header.
When the host starts, it launches each configured server as a subprocess or opens an HTTP connection. It sends an initialize request. The server responds with its capabilities: which tools, resources, and prompts it exposes. The host caches this information for the session. If a server supports the tools/list_changed notification, it can tell the host when its tool list changes. Most servers do not implement this. Their tool lists are static.
This configuration model has implications. Servers are not discovered dynamically. You cannot install a server and have it automatically appear in every MCP host on your machine. Each host has its own configuration file. This is intentional. It prevents drive-by server injection. A malicious npm package cannot add itself to your Claude Desktop configuration without you noticing.
Why do some servers use stdio and others use HTTP?
The transport choice reflects the server's trust model. Stdio servers run on your machine as child processes. They have access to your filesystem, your environment variables, and your network. Use stdio for servers that need local access: filesystem, shell, local databases. The transport itself provides no authentication. Security comes from the OS process boundary and the permissions you grant when you launch the server.
HTTP servers run remotely. They are reachable over the network. They authenticate via headers, typically API keys or OAuth tokens. Use HTTP for servers that wrap cloud APIs or remote services. The transport provides TLS encryption. The server cannot access your local machine unless you explicitly send it data. This is the safer pattern for third-party services. A Brave Search server running remotely cannot read your home directory.
The MCP spec also defines an authorization framework for HTTP transports. It supports OAuth 2.0 flows where the server redirects the client to an authorization endpoint. Few community servers implement this yet. Most use static API keys in headers. This is fine for development. It is not fine for multi-user production deployments where you need to scope access per user.
What patterns separate maintained servers from abandoned ones?
Look at the commit history first. A server with no commits in six months is abandoned unless it is feature-complete and has no open security issues. A server with recent commits but no release tags or changelog is in active development and may break without warning. A server with tagged releases, a changelog, and a clear versioning scheme is maintained.
Look at the issue tracker. Are there open issues about security? About tool descriptions being inaccurate? About the server crashing on malformed input? How the maintainer responds tells you everything. A maintainer who closes security issues without comment is a red flag. A maintainer who acknowledges limitations and documents workarounds is a green flag.
Look at the dependency graph. A server with 200 dependencies, half of them unmaintained, is a supply chain risk. A server with a small, well-known dependency tree is easier to audit. This matters because MCP servers run with the permissions you grant them. A compromised dependency in a filesystem server can read your entire disk.
Quick Reference
| Property | Value |
|---|---|
| Protocol version (current) | 2024-11-05 |
| Transport options | stdio, streamable HTTP |
| Server primitives | Tools, Resources, Prompts |
| Client primitives | Sampling, Roots, Elicitation |
| Message format | JSON-RPC 2.0 |
| Official SDK languages | TypeScript, Python |
| Configuration location (Claude Desktop macOS) | ~/Library/Application Support/Claude/claude_desktop_config.json |
| Largest community registry | mcp.directory |
| Official specification repository | github.com/modelcontextprotocol/specification |
Test yourself
You are building an internal assistant for your engineering team. It needs to read documentation from a private GitHub wiki, query a read-only PostgreSQL replica for metrics, and post summaries to a Slack channel. You find three MCP servers: one for GitHub, one for PostgreSQL, and one for Slack. The GitHub server uses a personal access token with repo scope. The PostgreSQL server exposes a single run_query tool with no restrictions. The Slack server uses a bot token with chat:write scope and runs over HTTP. Which of these would you use as-is, which would you modify, and why?
Answer: The Slack server is the safest to use as-is. It runs remotely over HTTP, so it cannot touch your local machine. Its token has a narrow chat:write scope, limiting damage to posting messages in channels the bot can access. The GitHub server needs modification. repo scope grants read and write access to all repositories the token can see, including private ones. For a read-only documentation use case, create a fine-grained token with read-only access to the specific wiki repository. The PostgreSQL server is the most dangerous. A single run_query tool with no restrictions lets the model execute arbitrary SQL, including DROP TABLE or data exfiltration. Replace it with a server that separates read-only queries from writes, uses prepared statements, and restricts access to the specific tables and views your metrics queries need. Ideally, connect it with a read-only database user that has SELECT permissions only on the relevant schema.
Frequently Asked Questions
Q: Can I use MCP servers with models other than Claude? Yes. MCP is model-agnostic by design. OpenAI, Google DeepMind, and other providers have adopted MCP as a standard for tool integration. Any host that implements an MCP client can connect to any MCP server. The model itself never speaks MCP directly. The host translates between the model's tool-calling API and MCP's wire protocol. You can switch models without changing your servers.
Q: How do I audit what an MCP server is actually doing?
For stdio servers, start by reading the source code. Focus on the tool implementations. Trace each tool from the tools/call handler to the actual system call or API request. For HTTP servers, you can inspect the traffic with a proxy like mitmproxy. The MCP spec also defines a logging mechanism. Servers can send log messages to the client via notifications. Enable logging in your host's configuration and watch what the server reports during tool execution.
Q: What stops a malicious MCP server from exfiltrating data? Nothing, by default. The protocol does not enforce permission boundaries. A server with filesystem access can read any file in its configured scope and send it over the network. The protection comes from the transport and the execution environment. Run untrusted servers in sandboxes. Use HTTP servers for third-party services so they cannot access your local machine. Audit the source code of any stdio server before you run it. Treat every server as having the permissions you explicitly grant it plus the ability to make network requests.
Q: Are there MCP servers I should explicitly avoid? Avoid servers that expose a generic "run command" or "execute code" tool without an allowlist. Avoid servers that concatenate user input into SQL, shell commands, or eval statements. Avoid servers with no documentation about their permission model. Avoid servers whose source repository has no license file, no commit history, or dependencies that are themselves unmaintained. A server that was clearly built in a weekend and never updated is fine for experimentation. It is not fine for production.
Q: How do I build an MCP server that other people will actually trust?
Document your permission model first. State exactly what your server can access and what it cannot. Use the narrowest possible scope for each tool. Separate reads from writes. Use resources for context and tools for actions. Implement the tools/list_changed notification if your tool list is dynamic. Tag your releases. Write a changelog. Publish your server with a clear license. Respond to security issues in your issue tracker. The bar for trust in this ecosystem is not high. Most servers fail it. Being transparent about what your server does and what it cannot do puts you ahead of 90% of the ecosystem.
Where the ecosystem goes from here
This series walked you from the protocol's architecture through building your own server and securing it. The ecosystem is still young. The servers that will matter in two years are the ones being built right now with clear permission models, narrow scopes, and honest documentation. The hype cycle is fading. What remains is infrastructure. If you want breakdowns like this every week, how real systems work under the hood, which parts of the ecosystem are worth your time, and which are not, subscribe to Internals Decoded at internalsdecoded.com.
Sources
- MCP Server Features: Resources
- MCP Python SDK
- MCP TypeScript SDK
- mcp.directory Community Registry
- awesome-mcp-servers Curated List
- Claude Desktop MCP Configuration Guide
- npmjs.com · Npx
- github.com/modelcontextprotocol/specification
- internalsdecoded.com