How to Self-Host an MCP Server (Two Real Ways)
There are two things people mean by "self-host an MCP server," and picking the wrong one costs you a weekend.

To self-host an MCP server you have two real options: run it locally over stdio (your client spawns the process on your own machine), or stand up a self-hosted remote endpoint that your client reaches over HTTP. Most people asking how to self-host an MCP server actually want the first one — it needs zero infrastructure — and reach for the second only when a team has to share one running instance.
The distinction matters because the word "host" is doing two jobs. About 90% of servers run locally over stdio, which is already "self-hosted" in every sense that counts: the code runs on your hardware, sees your files, and phones nothing home. If that's all you need, you're 20 minutes from done. Below is how to do both, and how to tell which one you're actually asking for.
Local stdio: the self-host that needs no server
The fastest way to self-host an MCP server is to not run a server at all — you let your client launch the process on demand over stdio. There's no port, no daemon, no TLS, no uptime to babysit. Your client spawns the command, talks to it over stdin/stdout, and kills it when you close the app.
The canonical example is the official Filesystem reference server, which reads and writes only inside directories you explicitly allow. A minimal config looks like this:
{
"mcpServers": {
"filesystem": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/Users/you/projects"]
}
}
}
That last argument is the allow-list — the server refuses anything outside it. This is the model to prefer. It's private by default, uses your already-authenticated local CLIs, and has no attack surface exposed to the network. That's the whole "self-host" story for solo work: point a command at a package and you're running your own server, on your own box, under your own account.
Self-hosted remote: when you actually need a running endpoint
Self-host a remote MCP server only when the thing has to outlive your editor session or be shared. Concretely: a team wants one instance with one set of credentials, or the server needs a long-lived connection to a database or internal API that shouldn't live on every laptop.
This is a real server now — it listens on a port, speaks HTTP (the current transport; older builds use SSE), and needs the usual operational care: a process manager, TLS, and auth in front of it. The trade you're making is convenience for surface area. Don't make it by default.
The GitHub MCP Server is a clean case study because it ships both modes: a local Docker container you run yourself, and a hosted remote GitHub operates for you. Self-hosting its Docker build gives you one endpoint your whole team hits, with a single GitHub token scoped once instead of per-developer.
Local vs. self-hosted remote: pick by who needs it
Choose by audience, not by which sounds more serious. If it's just you, stdio wins on every axis that matters. If it's a team sharing state or credentials, the remote endpoint earns its keep.
| Local (stdio) | Self-hosted remote (HTTP) | |
|---|---|---|
| Infra needed | None | Host, port, TLS, process manager |
| Who it's for | You, one machine | A team, shared instance |
| Auth | Uses your local CLIs/keys | Set up once, centrally |
| Network surface | Zero | A real endpoint to secure |
| Runs when | Client spawns it on demand | Always on |
| Setup time | Minutes | An afternoon, plus upkeep |
The honest default is: start local, go remote only when a specific sharing or connectivity problem forces you to. Most "we should host this" instincts are premature.
What to skip
Skip the remote endpoint for anything single-user. The most common mistake I see is developers standing up an HTTP server with Docker and a reverse proxy for a tool only they will ever call — that's a database, a TLS cert, and a security review you signed up for to save yourself a command line. It's strictly worse than stdio for solo use.
Skip re-hosting servers that already offer a good hosted remote unless you have a concrete reason (compliance, network isolation, a self-hosted GitHub Enterprise). If a vendor runs it well, let them.
And skip hosting your own documentation-fetching or web-lookup layer. A server like Context7, which injects version-specific library docs into your agent, is the kind of read-only, no-secrets tool where self-hosting buys you nothing. Reach for it as-is.
Mind the tool budget when you self-host several
Self-hosting one server is easy; self-hosting five quietly breaks your client. Every server you run adds its tools to the same context window, and most clients start degrading past roughly a 40-tool budget — the model gets worse at picking the right tool as the list grows.
This is a portfolio problem, not a per-server one. Five average servers at ~10 tools each already put you near the ceiling, and a single heavy server can blow it alone. When you self-host, prefer focused servers and turn off tools you don't use. The cursor tool-limit math spells out exactly where it bites, and the config generator will build a clean config so you don't hand-edit JSON into a broken state. If something won't connect after you deploy it, the usual culprit is a stdio-vs-HTTP transport mismatch — our troubleshooting guide covers the rest.