MCP Servers Explained: What the Model Context Protocol Actually Does
Every AI coding tool in 2026 has the same problem: it can read your code, but it can't read your Jira board, query your staging database, or check why Sentry is on fire. The model is smart. The model is also isolated.
MCP -- the Model Context Protocol -- fixes that. It's an open standard created by Anthropic that gives AI tools a universal way to connect to external data sources, APIs, and services. Think of it as USB-C for AI assistants: one protocol, hundreds of integrations, no custom wiring for each connection.
Before MCP, connecting Claude to your Postgres database required a different approach than connecting it to GitHub, which required a different approach than connecting it to Notion. You had an N-times-M integration problem -- N tools times M data sources, each with its own glue code. MCP collapses that into a single protocol that any client can speak and any server can implement.
This guide covers what MCP actually is under the hood, how to configure it across the tools you're likely already using, and which servers are worth setting up first.
🧰 What You'll Need
- An AI coding tool that supports MCP -- Claude Code, Claude Desktop, Cursor, VS Code with Copilot, or Windsurf
- Node.js 18+ -- Most MCP servers ship as npm packages and run via
npx - A terminal -- You'll be editing JSON config files and running CLI commands
- 10-15 minutes -- That's genuinely all it takes to get your first server connected
🔍 What MCP Actually Is (And Isn't)
MCP is a client-server protocol that runs alongside your AI tool. The AI tool (Claude Code, Cursor, etc.) is the MCP client. The services it connects to (a database, GitHub, a filesystem) are MCP servers.
Here's the architecture in plain terms:
┌──────────────────┐ ┌──────────────────┐
│ │ │ │
│ AI Tool │ MCP │ MCP Server │
│ (Client) │◄───────►│ (e.g. GitHub) │
│ │ │ │
│ Claude Code │ │ Exposes tools, │
│ Cursor │ │ resources, and │
│ VS Code │ │ prompts │
│ │ │ │
└──────────────────┘ └──────────────────┘
│ │
│ JSON-RPC │
└────────────────────────────┘
The protocol uses JSON-RPC 2.0 for message exchange. When you ask Claude "check the latest Sentry errors," Claude sees that a Sentry MCP server is available, calls the appropriate tool through the protocol, and gets structured data back.
What MCP Servers Expose
Every MCP server can provide three types of capabilities:
| Primitive | What It Does | Example |
|---|---|---|
| Tools | Functions the AI can call | run_query, create_issue, search_files |
| Resources | Data the AI can read | Database schemas, file contents, API docs |
| Prompts | Pre-built instruction templates | "Summarize this PR," "Explain this error" |
Tools are the most common. When you connect a PostgreSQL MCP server, it exposes tools like run_sql_query that Claude can invoke. When you connect GitHub, it exposes tools like create_pull_request and list_issues.
Resources are read-only data that the AI can pull into its context. A database server might expose table schemas as resources so the AI understands your data model without running queries.
Prompts are the least used but occasionally handy -- pre-written templates that standardize how the AI approaches specific tasks through that server.
What MCP Is NOT
Let's clear up a few common misconceptions:
- MCP is not an AI model. It's a protocol. It doesn't generate text or make decisions -- it connects things.
- MCP is not an API wrapper. It's a standardized interface that any tool can implement. The protocol itself is open source and vendor-neutral.
- MCP is not cloud-only. Most MCP servers run locally on your machine as subprocesses. Your data doesn't leave your laptop unless you explicitly connect to a remote server.
🚀 Transport: How Clients Talk to Servers
MCP supports two transport mechanisms. Understanding the difference matters because it determines how you configure each server.
stdio (Standard I/O)
The client launches the MCP server as a local subprocess. Communication happens over stdin/stdout using JSON-RPC messages. This is the most common transport -- it's what you use for local tools like filesystem access, database connections, and Git operations.
┌─────────────┐ stdin/stdout ┌─────────────┐
│ Client │◄─────────────────►│ Server │
│ (AI Tool) │ (JSON-RPC) │ (subprocess)│
└─────────────┘ └─────────────┘
When to use: Local servers, databases, filesystem access, anything that runs on your machine.
Streamable HTTP
The server runs as an independent HTTP service (either locally or remotely). The client connects via HTTP POST/GET requests, with optional Server-Sent Events for streaming. This replaced the older SSE transport in the March 2025 spec update.
┌─────────────┐ HTTP POST/GET ┌─────────────┐
│ Client │◄─────────────────►│ Server │
│ (AI Tool) │ (+ optional SSE)│ (HTTP svc) │
└─────────────┘ └─────────────┘
When to use: Cloud-hosted servers, shared team services, SaaS integrations like Sentry or Notion that expose their own MCP endpoints.
| Transport | Runs Where | Setup | Best For |
|---|---|---|---|
| stdio | Local subprocess | command + args in config |
Local tools, DBs, files |
| Streamable HTTP | Local or remote HTTP | URL endpoint | Cloud services, shared servers |
| SSE (deprecated) | Remote HTTP | URL endpoint | Legacy servers only ⚠️ |
⚙️ Setting Up MCP Servers Across Your Tools
The configuration format is nearly identical across tools -- a JSON object with an mcpServers key. The differences are mostly about where that JSON lives.
Claude Code
Claude Code is the most flexible MCP client. You can add servers via CLI or config file, at project or global scope.
Add via CLI (recommended):
# Add a GitHub MCP server (HTTP transport)
claude mcp add --transport http github https://api.githubcopilot.com/mcp/
# Add a PostgreSQL server (stdio transport)
claude mcp add --transport stdio db -- npx -y @bytebase/dbhub \
--dsn "postgresql://readonly:pass@localhost:5432/myapp"
# Add a filesystem server with specific directory access
claude mcp add --transport stdio files -- npx -y @modelcontextprotocol/server-filesystem \
/path/to/allowed/directory
Add via config file:
For project-level config (shared with your team), create .mcp.json in your project root:
{
"mcpServers": {
"db": {
"command": "npx",
"args": ["-y", "@bytebase/dbhub", "--dsn", "postgresql://readonly:pass@localhost:5432/myapp"]
},
"files": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/Users/you/projects"]
}
}
}
For global config (personal, all projects), servers are stored in ~/.claude.json.
Manage servers:
claude mcp list # See all configured servers
claude mcp get github # Details on a specific server
claude mcp remove github # Remove a server
Claude Desktop
Edit the config file directly. On macOS:
# Open (or create) the config file
open ~/Library/Application\ Support/Claude/claude_desktop_config.json
{
"mcpServers": {
"filesystem": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/Users/you/projects"]
},
"github": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-github"],
"env": {
"GITHUB_PERSONAL_ACCESS_TOKEN": "ghp_your_token_here"
}
}
}
}
| Platform | Config File Location |
|---|---|
| macOS | ~/Library/Application Support/Claude/claude_desktop_config.json |
| Windows | %APPDATA%/Claude/claude_desktop_config.json |
| Linux | ~/.config/Claude/claude_desktop_config.json |
Cursor
Cursor supports MCP through its settings UI or a config file:
- Open Settings > MCP
- Click Add new global MCP server
- This opens
~/.cursor/mcp.jsonfor editing
{
"mcpServers": {
"postgres": {
"command": "npx",
"args": ["-y", "@bytebase/dbhub", "--dsn", "postgresql://readonly:pass@localhost:5432/myapp"]
}
}
}
Once connected, MCP tools appear in Cursor's Composer Agent mode. There's a hard limit of 40 tools across all connected servers -- keep that in mind if you're connecting multiple servers.
VS Code (GitHub Copilot)
VS Code added MCP support for GitHub Copilot in 2025. Configuration lives in .vscode/mcp.json at the workspace level:
{
"servers": {
"db": {
"command": "npx",
"args": ["-y", "@bytebase/dbhub", "--dsn", "postgresql://readonly:pass@localhost:5432/myapp"]
}
}
}
VS Code also has an MCP Server Gallery in the Extensions view -- search for @mcp to browse and install servers directly.
env field in MCP config can reference variables from your shell environment.
Quick Comparison: MCP Client Support
| Feature | Claude Code | Claude Desktop | Cursor | VS Code (Copilot) |
|---|---|---|---|---|
| stdio transport | ✅ | ✅ | ✅ | ✅ |
| HTTP transport | ✅ | ✅ | ✅ | ✅ |
| CLI management | ✅ | ❌ | ❌ | ❌ |
| Project-level config | ✅ (.mcp.json) | ❌ | ❌ | ✅ (.vscode/mcp.json) |
| Global config | ✅ (~/.claude.json) | ✅ | ✅ (~/.cursor/mcp.json) | ✅ (user settings) |
| Tool limit | None | None | 40 tools ⚠️ | None |
| Server gallery/UI | ❌ | ❌ | ✅ | ✅ |
🏆 MCP Servers Worth Setting Up First
There are hundreds of MCP servers available. Here are the ones that deliver the most immediate value for day-to-day development.
Tier 1: Set These Up Today
| Server | What It Does | Install Command |
|---|---|---|
| Filesystem | Read/write files with access controls | npx -y @modelcontextprotocol/server-filesystem /path |
| GitHub | Issues, PRs, repos, code search | npx -y @modelcontextprotocol/server-github |
| PostgreSQL (via dbhub) | Query databases, inspect schemas | npx -y @bytebase/dbhub --dsn "postgresql://..." |
| Memory | Persistent knowledge graph across sessions | npx -y @modelcontextprotocol/server-memory |
Tier 2: High Value for Specific Workflows
| Server | What It Does | Best For |
|---|---|---|
| Sentry | Error monitoring, stack traces | Debugging production issues |
| Notion | Read/search workspace docs | Teams using Notion for docs |
| Slack | Search messages, channels | Finding context in conversations |
| Puppeteer/Browser | Browser automation, screenshots | Frontend testing, scraping |
| ESLint | Lint analysis and fixes | JavaScript/TypeScript projects |
Tier 3: Specialized
| Server | What It Does |
|---|---|
| Figma | Read design files, extract component specs |
| Linear | Issue tracking, project management |
| Cloudflare | Workers, KV, D1 database management |
| Prisma | ORM-aware database operations |
Example: Connecting GitHub + Postgres in One Session
Here's what a real workflow looks like once you have MCP servers connected:
# Set up both servers
claude mcp add --transport http github https://api.githubcopilot.com/mcp/
claude mcp add --transport stdio db -- npx -y @bytebase/dbhub \
--dsn "postgresql://readonly:pass@localhost:5432/myapp"
Now in Claude Code:
> Look at GitHub issue #87. It reports that users with special characters in
their username can't log in. Query the users table to find affected accounts,
then implement a fix.
Claude reads the issue from GitHub, queries your database to understand the data, and writes the fix -- all without you manually copying information between tools.
🔒 Security: What You Need to Know
MCP servers run code on your machine and can access external services. That power comes with real security considerations.
The Risks
- Arbitrary code execution -- A malicious MCP server from an untrusted source can execute any command with your user privileges
- Credential exposure -- Hardcoding tokens in config files that get committed to git is a common mistake
- Tool poisoning -- A compromised server could manipulate tool descriptions to trick the AI into executing unintended actions
- Over-permissioned database access -- Connecting a production database with write access is asking for trouble
Best Practices
1. Use read-only credentials for databases.
# Good: read-only user
claude mcp add --transport stdio db -- npx -y @bytebase/dbhub \
--dsn "postgresql://readonly:pass@localhost:5432/myapp"
# Bad: connecting as the superuser
claude mcp add --transport stdio db -- npx -y @bytebase/dbhub \
--dsn "postgresql://admin:pass@prod.db:5432/myapp"
2. Only install MCP servers from trusted sources. Stick to the official @modelcontextprotocol npm scope, verified publisher packages, and servers from the tools you already trust (Sentry, Notion, GitHub).
3. Keep credentials out of committed config files. Use the env field to reference environment variables:
{
"mcpServers": {
"github": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-github"],
"env": {
"GITHUB_PERSONAL_ACCESS_TOKEN": "${GITHUB_TOKEN}"
}
}
}
}
4. Use HTTPS for remote servers. If you're connecting to a Streamable HTTP server, always use https://, never http://.
5. Audit your connected servers periodically.
claude mcp list # What's connected?
🛠️ Building Your Own MCP Server
If the existing servers don't cover your use case, building a custom one is straightforward. The official SDK supports Python and TypeScript.
Python Example: A Simple Weather Server
from mcp.server.fastmcp import FastMCP
import httpx
mcp = FastMCP("weather")
@mcp.tool()
async def get_forecast(city: str) -> str:
"""Get the current weather forecast for a city."""
async with httpx.AsyncClient() as client:
response = await client.get(
f"https://wttr.in/{city}?format=3"
)
return response.text
@mcp.resource("weather://cities")
async def list_cities() -> str:
"""List supported cities."""
return "New York, London, Tokyo, Sydney, Mumbai"
if __name__ == "__main__":
mcp.run(transport="stdio")
Save this as weather_server.py, then connect it:
claude mcp add --transport stdio weather -- python3 weather_server.py
TypeScript Example: A TODO Server
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";
const server = new McpServer({
name: "todo-server",
version: "1.0.0",
});
const todos: { id: number; text: string; done: boolean }[] = [];
let nextId = 1;
server.tool("add_todo", { text: z.string() }, async ({ text }) => {
const todo = { id: nextId++, text, done: false };
todos.push(todo);
return { content: [{ type: "text", text: `Added: ${todo.text} (id: ${todo.id})` }] };
});
server.tool("list_todos", {}, async () => {
const list = todos
.map((t) => `${t.done ? "✅" : "⬜"} [${t.id}] ${t.text}`)
.join("\n");
return { content: [{ type: "text", text: list || "No todos yet." }] };
});
server.tool("complete_todo", { id: z.number() }, async ({ id }) => {
const todo = todos.find((t) => t.id === id);
if (!todo) return { content: [{ type: "text", text: `Todo ${id} not found.` }] };
todo.done = true;
return { content: [{ type: "text", text: `Completed: ${todo.text}` }] };
});
const transport = new StdioServerTransport();
await server.connect(transport);
The pattern is always the same: define tools with typed parameters, implement the logic, and expose it over a transport. The SDK handles all the JSON-RPC plumbing.
🔧 Troubleshooting
Server not showing up after configuration
Problem: You added a server to your config but the AI tool doesn't see it.
Fix: Restart the AI tool completely. Claude Desktop and Cursor need a full restart (not just reload) to pick up config changes. For Claude Code, start a new session.
"Command not found" errors
Problem: The server fails to start with an error about the command not being found.
Fix: Make sure Node.js 18+ is installed and npx is on your PATH. Test by running the command manually:
npx -y @modelcontextprotocol/server-filesystem /tmp
If that fails, reinstall Node.js or check your PATH configuration.
Server connects but tools aren't available
Problem: The server shows as connected, but the AI doesn't seem to use its tools.
Fix: Some clients need a specific prompt to discover tools. Try asking explicitly: "Use the database MCP server to query the users table." Also verify the server is correctly exposing tools -- check the server's documentation for required environment variables or configuration.
Timeout errors on database queries
Problem: Database queries through MCP time out on large tables.
Fix: MCP servers have default timeouts (usually 30-60 seconds). For large queries, add LIMIT clauses. Some database MCP servers support a --timeout flag:
claude mcp add --transport stdio db -- npx -y @bytebase/dbhub \
--dsn "postgresql://readonly:pass@localhost:5432/myapp" \
--timeout 120
Cursor hitting the 40-tool limit
Problem: Cursor stops recognizing tools from newly added servers.
Fix: Cursor has a hard limit of 40 tools across all connected servers. Disconnect servers you're not actively using, or switch to Claude Code which has no tool limit.
🚀 What's Next
- Connect your first MCP server -- Start with the filesystem or GitHub server, they're the quickest wins
- Set up a project-level
.mcp.jsonso your whole team gets the same MCP connections automatically - Build a custom MCP server for your team's internal tools or APIs -- the Python SDK makes it a 30-minute project
- Explore the official server registry at modelcontextprotocol.io/examples and github.com/modelcontextprotocol/servers for community-built servers
- Combine MCP with CLAUDE.md -- reference your MCP-connected tools in your project instructions so Claude knows what's available
MCP is the infrastructure layer that turns AI coding tools from smart autocomplete into genuine development partners. The protocol is still young, the server ecosystem is growing fast, and the tools that support it today will only get deeper integrations tomorrow. The best time to learn it is now, while the ecosystem is manageable enough to understand end-to-end.
Want to see MCP in action within Claude Code? Read our Claude Code Workflow Guide for practical workflows that use MCP daily. Comparing AI coding tools? Check out our AI Coding Agents Compared breakdown, or see how Cursor and GitHub Copilot handle MCP in their own environments.