How to Set Up an MCP Server from Scratch (2026)
MCP (Model Context Protocol) gives Claude Code the ability to call external tools—read from your database, search GitHub issues, run Playwright browser tests—without those tools having to be built into Claude Code itself. If you've seen references to MCP servers and haven't set one up yet, this guide goes from zero to a working server in under 20 minutes.
This is a different angle from the Tutorial de servidor MCP 2026 post, which covers intermediate configuration and multi-server setups. This post starts earlier: what MCP actually is, how the config file works, and the exact error messages you'll see on the first attempt.
What MCP is in one paragraph
MCP is a JSON-RPC protocol that lets Claude Code communicate with external processes during a session. Each MCP server is a separate process that exposes "tools"—named functions Claude can call. When you configure a server, Claude Code starts it as a subprocess, maintains a persistent connection, and can invoke its tools the same way it invokes built-in tools like file reading or bash execution. The model doesn't know the difference between a built-in tool and an MCP tool. From Claude's perspective, it's just a function it can call.
This means: anything you can wrap in a function that takes parameters and returns text or structured data can become an MCP tool. Database queries, API calls, file system operations on a remote server, browser automation—all of it is in scope.
Before you start: the three things you need
- Claude Code installed and authenticated. You need
claudein your PATH and a working API key. If you don't have this yet, runnpm install -g @anthropic-ai/claude-codeand thenclaude auth. - Node.js 18+ or Python 3.10+, depending on which server you're installing. Most popular MCP servers are Node packages. A few (including the official filesystem server) also have Python versions.
- The server package name. MCP servers are distributed as npm packages or Python packages. The Anthropic-maintained ones live in the
@modelcontextprotocolnpm scope.
If you're on Windows and encounter path errors with MCP servers, the most common fix is using WSL2 rather than native Windows paths. The MCP server process spawner has historically had issues with Windows path separators in certain server implementations.
Step-by-step: installing your first MCP server
We'll use the GitHub MCP server as the example. It's maintained by Anthropic, well-documented, and immediately useful for most developers.
Install the server package globally
The GitHub MCP server requires a personal access token. First, install the package:
npm install -g @modelcontextprotocol/server-github
Verify the install by running mcp-server-github --version. If you see a version number, the binary is in your PATH.
Create or edit your MCP config file
Claude Code reads MCP server configuration from ~/.claude/claude_desktop_config.json (global, applies to all projects) or .claude/claude_desktop_config.json inside your project directory (project-scoped).
Create the file if it doesn't exist:
{
"mcpServers": {
"github": {
"command": "mcp-server-github",
"env": {
"GITHUB_PERSONAL_ACCESS_TOKEN": "ghp_your_token_here"
}
}
}
}
Replace ghp_your_token_here with a GitHub PAT that has repo and read:org scope. Generate one at github.com/settings/tokens.
Restart Claude Code
Claude Code loads the MCP config at startup. If Claude Code is already running, you need to quit and relaunch. In a terminal session, press Ctrl+C to exit and then claude to restart.
There's no hot-reload for MCP server config. This is the most common mistake beginners make—editing the config while Claude Code is running and wondering why nothing changed.
Verify the server is connected
Inside a Claude Code session, run the slash command:
/mcp
You should see output listing github under "Connected servers" with a list of available tools like list_repositories, search_code, create_issue, and others. If the server isn't listed, jump to the troubleshooting section below.
Test a tool call
Ask Claude to use the server:
> List the open issues in the anthropics/claude-code repository
Claude will call the list_issues tool, retrieve the data from GitHub, and return it in the session. If you see a real list of issues, the server is working.
Adding a second server: Filesystem
The filesystem server gives Claude Code access to files outside your current working directory. It's scoped to specific paths you configure—Claude can't read /etc/passwd unless you've added /etc to the allowed paths.
Add it to the same config file:
{
"mcpServers": {
"github": {
"command": "mcp-server-github",
"env": {
"GITHUB_PERSONAL_ACCESS_TOKEN": "ghp_your_token_here"
}
},
"filesystem": {
"command": "npx",
"args": [
"-y",
"@modelcontextprotocol/server-filesystem",
"/Users/yourname/Projects",
"/Users/yourname/Documents"
]
}
}
}
The paths after the package name are the allowed directories. Add as many as you need. Restart Claude Code and run /mcp again to confirm both servers appear.
Five servers worth installing in your first week
The Anthropic-maintained registry has 20+ servers. These five cover the use cases that come up most often for developers:
@modelcontextprotocol/server-github— issues, PRs, code search, file reading from repos. Daily use.@modelcontextprotocol/server-filesystem— read/write files outside the CWD. Required for multi-project work.@modelcontextprotocol/server-memory— persistent key-value store Claude can write to across sessions. Useful for projects where you want Claude to "remember" decisions between runs.@modelcontextprotocol/server-fetch— HTTP fetch with optional browser-like rendering. Lets Claude read documentation URLs you paste in.@modelcontextprotocol/server-postgres(orserver-sqlite) — read-only database access. Useful for debugging and writing queries against your actual schema.
Troubleshooting: the errors you'll actually see
| Error | What it means | Fix |
|---|---|---|
| Server "github" failed to start | The binary isn't in PATH, or the command is wrong. | Run which mcp-server-github. If nothing returns, the global install failed. Try sudo npm install -g or add --prefix ~/.npm-global and update PATH. |
| Authentication failed | Your PAT is invalid, expired, or missing the required scope. | Generate a new token at github.com/settings/tokens with repo scope. Check that the token starts with ghp_ (fine-grained tokens may not work with all MCP servers). |
| Server not listed in /mcp | Claude Code didn't pick up the config change. | Confirm the config file path is exactly ~/.claude/claude_desktop_config.json. JSON must be valid—run it through a linter. Restart Claude Code completely. |
| Tool call returned empty result | The server connected but the tool returned nothing. | Check the server's stderr. In Claude Code, server logs appear in the session output with a [MCP] prefix. Usually a scoping issue (wrong repo name, no matching results). |
| EACCES permission denied | The filesystem server is trying to read a path outside its allowed list. | Add the path to the args list in your config. The filesystem server only reads paths you explicitly allow. |
Project-scoped vs global MCP config
The global config at ~/.claude/claude_desktop_config.json applies to every Claude Code session. If you work on multiple projects and some need different servers (e.g., a Supabase server for one project, a PostgreSQL server for another), use project-scoped config files.
Create .claude/claude_desktop_config.json in your project root. Claude Code merges project config with global config, with project config taking precedence on conflicts. This means you can have GitHub and Filesystem globally, and add a project-specific database server only to the projects that need it.
Project-scoped config files containing API keys or database connection strings will be committed to version control if you're not careful. Add .claude/claude_desktop_config.json to your .gitignore. Use environment variables for secrets, not hardcoded values in the config. See the credentials leak prevention post for the full pattern.
Writing your own MCP server
If you need a tool that doesn't exist in the registry, writing a minimal MCP server is about 60 lines of TypeScript. The pattern:
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
const server = new Server(
{ name: "my-custom-server", version: "0.1.0" },
{ capabilities: { tools: {} } }
);
server.setRequestHandler("tools/list", async () => ({
tools: [{
name: "my_tool",
description: "Does the thing",
inputSchema: {
type: "object",
properties: { query: { type: "string" } },
required: ["query"]
}
}]
}));
server.setRequestHandler("tools/call", async (req) => {
const { query } = req.params.arguments;
// your logic here
return { content: [{ type: "text", text: `Result for: ${query}` }] };
});
const transport = new StdioServerTransport();
await server.connect(transport);
Build this with tsc, point your config at the compiled JS file, and Claude Code will call my_tool the same way it calls any built-in tool. The MCP SDK handles all the protocol boilerplate.
What to do after your first server is working
Once you have one server running, the next step is understanding the security surface you've opened up. MCP servers run as subprocesses with the same system privileges as your Claude Code session. A malicious or compromised MCP server can read anything in your allowed paths and make outbound network calls. Read the Lista de verificación de vulnerabilidades en servidores MCP before you add servers to production workflows.
Septim Tether: session state that persists
If you're setting up MCP specifically to give Claude persistent memory across sessions, Septim Tether is a pre-built context-management toolkit for Claude Code workflows. It handles session state, cross-project context, and the CLAUDE.md patterns that keep long sessions on track. Paga una vez, sin suscripción.