Installing an MCP server means registering a server process or remote endpoint with an MCP host so the host can discover its tools, resources, and prompts. The work splits into four stages: pick the transport, install runtime prerequisites, write a client configuration entry, and verify discovery with a controlled test call. This guide walks through each stage with runnable configuration and diagnostic commands, then covers the failure modes that most often block a first connection.
What Installing an MCP Server Actually Means
An MCP server is not installed into your application the way a library is. It is a separate process or remote service that speaks JSON-RPC with an MCP host such as a desktop assistant, an IDE extension, or a coding agent. "Installing" therefore means two things: making the server executable on your machine (or reachable over the network), and adding a configuration entry that tells the host how to launch or connect to it.
This distinction matters because most first-run failures are configuration failures, not code failures. A server that works perfectly from a terminal can still fail inside a host if the host's working directory, environment variables, or command path differ from your shell. The workflow below treats the host configuration as the primary artifact and verifies it end to end.
- Local servers use the stdio transport and are launched by the host as a child process.
- Remote servers use an HTTP-based transport and are reached by URL, usually with authentication headers.
- The host owns discovery: it lists tools, resources, and prompts after the connection is established.
Prerequisites and Assumptions
Before writing any configuration, confirm the runtime that the server package expects. Node-based servers typically need a current Node.js LTS release and are launched with npx. Python-based servers typically need a Python 3 environment and are launched with uv or python. Remote servers need only network access and, where required, a token.
You should also know where your host stores its MCP configuration. Desktop clients commonly use a JSON file in an application-support directory, while IDE integrations often expose a settings panel. Consult your host's documentation for the exact path; the structure of the entry is what this guide standardizes.
- Node.js LTS and npm/npx for JavaScript servers.
- Python 3.10 or newer plus uv for Python servers.
- A host that supports MCP and a known configuration file location.
- For remote servers: a URL and any required bearer token or OAuth client registration.
Choosing Between stdio and HTTP Transports
The transport determines almost everything about how you install and debug the server. stdio servers are simple to distribute because the host manages the process lifecycle, but they are tied to one machine and one host session. HTTP servers can be shared across users and hosts, but they introduce authentication, session management, and network failure modes.
A useful rule: use stdio for local file access, local databases, and developer tooling that should not leave the machine. Use HTTP when the server fronts a shared API, requires centralized credentials, or must serve multiple clients. If you are still deciding which remote endpoint or provider fits your stack, the RPC Assistant can shortlist concrete options while this page focuses on the installation mechanics.
- stdio: host launches the process; logs must go to stderr, never stdout.
- HTTP: server runs independently; the host connects by URL and manages sessions.
- Mixing the two in one config is fine, but debug them separately.
Installing and Registering a stdio Server
The following configuration registers a filesystem server over stdio. Replace the workspace path with a directory you actually want the server to expose. The command and arguments are passed as an array so the host does not rely on shell parsing.
After saving the file, restart the host completely. Many hosts read MCP configuration only at startup, so a reload of the chat window is not sufficient.
{
"mcpServers": {
"filesystem": {
"command": "npx",
"args": [
"-y",
"@modelcontextprotocol/server-filesystem",
"/absolute/path/to/workspace"
],
"env": {
"LOG_LEVEL": "info"
}
}
}
}Registering a Remote HTTP Server
Remote servers are registered by URL rather than command. The example below uses a placeholder endpoint and a bearer token read from the environment. Never commit real tokens to a shared configuration file; prefer host-managed secrets or environment interpolation where the host supports it.
Some hosts require an explicit transport field, while others infer HTTP from the presence of a url key. Check your host's schema before adding fields it does not recognize, because strict parsers may reject the entire entry.
{
"mcpServers": {
"remote-api": {
"url": "https://mcp.example.com/mcp",
"headers": {
"Authorization": "Bearer ${MCP_API_TOKEN}"
}
}
}
}Verifying Tool Discovery from the Command Line
Before blaming the host, verify the server independently. For a remote HTTP server, send an initialize request and confirm a JSON-RPC response. This isolates network and authentication problems from host configuration problems.
A successful response contains a protocol version, server capabilities, and server info. If you receive an HTML error page or a 401, the problem is at the HTTP layer and no amount of host configuration will fix it.
curl -sS -X POST "$MCP_URL" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-H "Authorization: Bearer $MCP_API_TOKEN" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "initialize",
"params": {
"protocolVersion": "2025-06-18",
"capabilities": {},
"clientInfo": { "name": "install-check", "version": "0.1.0" }
}
}'Verifying a stdio Server with a Python Harness
For stdio servers, the host is the client, so a standalone check requires a small harness that spawns the process and exchanges JSON-RPC messages over stdin and stdout. The script below performs an initialize handshake and then lists tools. It prints raw responses so you can see exactly what the server returns.
Run it with the same command and arguments from your host configuration. If the harness succeeds but the host fails, the difference is almost always environment, working directory, or PATH.
import json, subprocess, sys
cmd = ["npx", "-y", "@modelcontextprotocol/server-filesystem", "/absolute/path/to/workspace"]
p = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
def send(msg):
p.stdin.write(json.dumps(msg) + "\n")
p.stdin.flush()
send({"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"harness","version":"0.1.0"}}})
print("init:", p.stdout.readline())
send({"jsonrpc":"2.0","method":"notifications/initialized"})
send({"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}})
print("tools:", p.stdout.readline())
p.terminate()
print("stderr:", p.stderr.read()[:500])Recording Verification Results
Keep a short results table for each server you install so that later failures can be compared against a known-good baseline. The table below is a template; fill it with your own observed values rather than assumed ones.
| Server | Transport | Init OK | Tools listed | Latency (ms) | Notes |
|---|---|---|---|---|---|
| filesystem | stdio | ||||
| remote-api | http | ||||
| database | stdio |
Measure latency by timing the initialize round trip several times and recording the median. Do not publish or rely on numbers you have not measured on your own machine, because host startup, package downloads, and network conditions dominate first-run timings.
Troubleshooting Common Installation Failures
Most failures fall into a small number of categories. Work through them in order, because a later symptom often masks an earlier cause.
If the server starts but the host shows no tools, confirm that the host completed the initialized notification before listing tools. If the server exits immediately, run the exact command from the config in a terminal and read stderr. If a remote server returns 401 or 403, verify the token scope and header format before changing anything else.
- Command not found: the host's PATH differs from your shell; use an absolute path to the runtime.
- Corrupted JSON-RPC: a stdio server wrote logs to stdout; move all logging to stderr.
- Empty tool list: initialization handshake incomplete or server crashed after connecting.
- 401/403 on HTTP: expired token, wrong header name, or missing OAuth registration.
- Works locally, fails in host: different working directory or missing environment variables.
Limitations and Operational Tradeoffs
Installing a server is the easy part; operating it is where tradeoffs appear. stdio servers inherit the host's lifecycle, so a crash takes the tool offline until the host restarts it. HTTP servers survive host restarts but require you to manage deployment, TLS, authentication, and session state yourself.
There is also a trust dimension. Every MCP server you register can expose data and execute actions on your behalf. Prefer pinned package versions over floating tags, review the tools a server advertises before granting it access to sensitive directories, and scope tokens to the minimum permissions the server needs. For infrastructure that must stay available across teams, a dedicated node or managed endpoint removes the single-laptop failure mode.
Next Steps for a Repeatable Setup
Once a single server is verified, standardize the pattern: keep configuration in version control with secrets excluded, document the exact command and arguments, and record a baseline results table for each environment. When you add remote servers, apply the same initialize-and-list check before wiring them into agent workflows.
If your MCP servers call blockchain data or RPC endpoints, treat endpoint reliability as part of the installation. Review the available networks, compare RPC pricing and limits, and consider a dedicated node when shared endpoints introduce variable latency. The RPC Assistant can help you choose a concrete endpoint once your transport and configuration are settled.
- Pin server package versions and record them alongside the config.
- Store tokens outside the config file and rotate them on a schedule.
- Re-run the verification harness after every host or server upgrade.