Two ways to deploy a Model Context Protocol server: install via npx/npm, or run an official Docker image. Docker wins for almost everyone. It avoids Node version drift, skips the global-install permission mess, and matches what GitHub, Anthropic, and most vendors actually ship. The npx path works fine for quick local experiments – but if you plan to keep the server running past tomorrow, use Docker.
This guide deploys the official GitHub MCP Server against the latest spec revision, 2025-11-25. The release is backward compatible – existing implementations keep working, per the MCP one-year anniversary post – so you can adopt new pieces as you need them rather than rewriting everything at once.
What MCP actually is (30 seconds)
MCP is an open standard Anthropic introduced in November 2024 to standardize how AI systems talk to external tools and data sources. The wire format is JSON-RPC over stdio or HTTP, with a defined handshake for capabilities, tools, and resources. In December 2025, Anthropic donated the protocol to the Agentic AI Foundation – a directed fund under the Linux Foundation, co-founded with Block and OpenAI. So it’s no longer a single-vendor project, which matters if you’re betting infrastructure on it.
Think of MCP like a shipping container standard for AI integrations. Before containers, every port had its own loading system. After: one format, any ship. MCP is trying to do the same thing for the “AI model talks to your tools” layer – one protocol, any client. Whether that analogy holds in three years depends on adoption, but the Linux Foundation backing makes it harder to abandon quietly.
Download and install
Pull the official image from GitHub Container Registry – no account needed, it’s public:
docker pull ghcr.io/github/github-mcp-server:latest
Generate a GitHub Personal Access Token at github.com/settings/tokens with the scopes you need (start with repo and read:org if unsure). Store it somewhere safe – you’ll inject it as an env var, not paste it into a config file.
Wire it to your MCP client. For Claude Desktop, edit ~/Library/Application Support/Claude/claude_desktop_config.json on macOS or %APPDATA%Claudeclaude_desktop_config.json on Windows:
{
"mcpServers": {
"github": {
"command": "docker",
"args": [
"run", "-i", "--rm",
"-e", "GITHUB_PERSONAL_ACCESS_TOKEN",
"-e", "GITHUB_TOOLSETS=repos,issues,pull_requests",
"ghcr.io/github/github-mcp-server"
],
"env": {
"GITHUB_PERSONAL_ACCESS_TOKEN": "ghp_yourTokenHere"
}
}
}
}
The GITHUB_TOOLSETS env var scopes which tools the LLM can call, per the server’s README. Leaving it unset means giving the model your entire GitHub surface area. Don’t do that.
In VS Code, MCP servers can be installed per-user-profile or per-workspace. The workspace option writes to .vscode/mcp.json, per the VS Code Copilot docs. The Extensions view supports @mcp as a search prefix for browsing the gallery.
Three config settings worth getting right the first time
Toolset scoping. Default toolsets expose more than you usually need. Pick the smallest set that covers your actual use case – you can always add scopes later.
Read-only mode. Pass --read-only if the agent only needs to inspect, not modify. Per the server’s README, when read-only is set, write tools are skipped even if explicitly requested via --tools. Useful guardrail for review-only workflows.
The protocol version header. If you’re calling an HTTP MCP server directly, every HTTP request must include MCP-Protocol-Version. Miss it, and servers fall back silently to 2025-03-26, per ForgeCode’s spec analysis. You’ll get old auth behavior and won’t see batching errors until something breaks in production. Set the header explicitly.
Security note: Never paste a real PAT into a config file you might commit. Use OS-level secret managers (macOS Keychain via
security, Linuxsecret-tool, Windows Credential Manager) and reference them in your launcher script. Tokens in committed JSON are the most common way MCP setups leak credentials.
Verify it works
Restart your client. In Claude Desktop, look for the hammer/plug icon – it should list tools prefixed with github_. Ask the model something concrete: “List the open issues on owner/repo.” Real data back? You’re done.
For a non-UI check, send a handshake directly:
echo '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-11-25","capabilities":{},"clientInfo":{"name":"test","version":"0.1"}}}'
| docker run -i --rm -e GITHUB_PERSONAL_ACCESS_TOKEN=$TOKEN ghcr.io/github/github-mcp-server
A valid initialize response means transport, image, and token are all good. The 2025-11-25 spec standardized tool names into a canonical format (SEP-986, per WorkOS) – so what you see in tools/list should be consistent across SDKs.
Common install errors (the ones tutorials skip)
1. EACCES: permission denied after global npm install. Running sudo npm install -g creates files owned by root, which breaks future installs – the MCPcat installation guide documents this exact trap. The fix isn’t more sudo. Uninstall, then set a user-writable prefix (npm config set prefix ~/.npm-global), or just use Docker and skip this entirely.
2. Server disconnected immediately on Claude Desktop startup. Almost always a wrong path to docker on macOS – Claude Desktop doesn’t inherit your shell’s PATH. Use the absolute path: /usr/local/bin/docker, or wherever which docker reports.
3. Old tutorial, broken package. As of April 2025, the npm package @modelcontextprotocol/server-github is no longer supported, per the official GitHub MCP server repo. If a guide tells you to run npx -y @modelcontextprotocol/server-github, the guide is stale. Use the Docker image or the remote server at https://api.githubcopilot.com/mcp/.
4. Tool calls return data that doesn’t match the spec you expect. Check the negotiated protocolVersion in the initialize response. Getting 2025-03-26 when you wanted something newer usually means the client downgraded – most often because the host hasn’t updated its SDK.
Upgrading across spec revisions
Batching is gone in 2025-06-18. Speakeasy’s release notes confirm it was a deliberate breaking change – JSON-RPC batching was added in 2025-03-26 and pulled in 2025-06-18 with no automated migration. If your implementation batched multiple requests in a single JSON-RPC call, you’ll need to refactor before upgrading the SDK. Search your code for arrays of request objects before touching the version.
For Docker users, the upgrade itself is trivial: docker pull ghcr.io/github/github-mcp-server:latest then restart your client. The spec-revision jump is the only real risk.
To uninstall: remove the server entry from your client’s config, then docker rmi ghcr.io/github/github-mcp-server to reclaim disk. Nothing leaks outside the container – no system-level installer, no leftover files in unexpected places. For npm-installed servers, npm uninstall -g [package] handles it, but also check ~/.npm-global if you previously fought permission errors.
Two things most guides don’t cover yet
Turns out the MCP Registry launched quietly in September 2025 as an open catalog and discovery API for MCP servers – both public and private sub-registries are supported, per the modelcontextprotocol.info blog. If you’re deploying internally, the private sub-registry pattern is the better fit for internal deployments long-term rather than hard-coding server locations into every client config.
The .mcpb bundle format is the other one. As of late 2025, client support is still patchy – it’s one file that packages server code, manifest, and dependencies together. Drop it into a host, done. Plan for it as the eventual default for shipping local servers, but don’t depend on it yet unless your specific client explicitly advertises bundle support. Where .mcpb actually lands in 12 months is an open question; adoption speed depends entirely on how fast client maintainers ship support.
FAQ
Do I need to redeploy when the spec updates?
Usually no. The 2025-11-25 release is backward compatible. The one real exception was 2025-06-18 dropping batching – that required code changes.
Can I run multiple MCP servers in the same client?
Yes – it’s the normal setup. Each entry in mcpServers runs as its own process with its own tool namespace, so there’s no collision between, say, a filesystem server and a GitHub server. The catch: every declared server starts on every client launch. Anecdotally, once you’re past about 8-10 servers, startup gets noticeably slower. If you hit that, the MCP Registry’s on-demand loading pattern is worth investigating instead of pre-declaring everything upfront.
Is MCP only for Claude?
A common assumption, but no. OpenAI officially adopted MCP in March 2025 and added support to ChatGPT apps in September 2025. VS Code, Cursor, Windsurf, JetBrains IDEs, and Visual Studio all ship MCP clients now. The Linux Foundation donation in December 2025 was specifically designed to prevent any single vendor – including Anthropic – from controlling the direction of the spec.
Before closing: check your claude_desktop_config.json for any @modelcontextprotocol/server-github entries and swap them for the Docker image. The old npm package is already unsupported – it’s not a matter of if it breaks again, but when.