TL;DR
Everything you need to know about Model Context Protocol - what it is, how it works, how to install servers, how to build your own, and the best servers by category.
Every AI agent needs to interact with the outside world. Read a file. Query a database. Search the web. Call an API. Before Model Context Protocol existed, every one of these integrations was custom glue code. You wrote a different adapter for every tool, every model, every framework. Then you maintained all of it.
MCP is the standard that replaced that mess. Created by Anthropic and adopted across the industry, Model Context Protocol defines a universal interface between AI agents and external tools. One protocol. Any client. Any server. Configure a server once, and every MCP-compatible tool can use it - Claude Code, Cursor, Windsurf, the Claude desktop app, and a growing list of others.
Think of it as USB-C for AI integrations. Before USB-C, every device had its own charger. MCP does the same thing for AI tool connections - it standardizes the plug so you never write custom integration code again.
This guide covers everything: how the protocol works under the hood, how to install and configure servers, how to build your own, and which servers solve real problems in real workflows.
MCP uses a client-server model with three actors:
The host starts the client. The client connects to one or more servers. Each server exposes capabilities. The AI model sees those capabilities as available tools and decides when to use them.
User prompt: "What queries are causing slow performance?"
|
v
Host (Claude Code)
|
v
MCP Client
|
v
┌──────────────┬──────────────┬──────────────┐
│ Postgres MCP │ GitHub MCP │ Datadog MCP │
│ - query() │ - search() │ - metrics() │
│ - explain() │ - issues() │ - logs() │
│ - tables() │ - prs() │ - traces() │
└──────────────┴──────────────┴──────────────┘
The model decides which servers and tools to call based on the user's request. You did not write any routing logic. The protocol handles discovery, and the model handles selection.
Every MCP server can expose three types of capabilities:
Tools - functions the AI can call. "Run this SQL query." "Create a GitHub issue." "Send a Slack message." Tools have typed parameters, descriptions the model reads, and execute functions that perform the action.
Resources - data the AI can read. File contents, database schemas, API documentation. Resources provide context without requiring the model to call a function.
Prompts - reusable templates for common interactions. "Summarize this PR" or "Review this SQL query" - pre-built prompt structures that users can invoke by name.
Most servers focus on tools. Resources and prompts are useful but less commonly implemented.
MCP supports two communication transports:
stdio - the server runs as a local child process. The client spawns it, sends JSON-RPC messages over stdin, and reads responses from stdout. This is the most common setup. It is fast, secure (the server runs on your machine with your permissions), and requires no network configuration.
Streamable HTTP - the server runs as an HTTP endpoint. The client connects over the network using HTTP with optional Server-Sent Events for streaming. Used for shared servers, remote deployments, and multi-user setups.
Most development tools use stdio because it is simpler and keeps everything local. Remote servers over HTTP are becoming more common for team-shared integrations.
When your AI tool starts up, here is what happens:
initialize request with its capabilitiestools/call request to the appropriate serverThis handshake happens once at startup. After that, tool calls are fast - just JSON-RPC messages between processes.
Claude Code reads MCP configuration from two locations:
.claude/settings.json in your project root~/.claude/settings.json for servers available in every projectThe format uses a mcpServers key with named server entries:
{
"mcpServers": {
"filesystem": {
"command": "npx",
"args": [
"-y",
"@anthropic-ai/mcp-server-filesystem",
"/Users/you/projects"
]
},
"github": {
"command": "npx",
"args": ["-y", "@anthropic-ai/mcp-server-github"],
"env": {
"GITHUB_TOKEN": "ghp_your_token"
}
}
}
}
Each entry specifies the command to run, arguments, and optional environment variables. Claude Code spawns these processes on startup and discovers their tools automatically.
After adding or changing servers, restart Claude Code for the changes to take effect.
Cursor reads MCP configuration from .cursor/mcp.json in your project root:
{
"mcpServers": {
"filesystem": {
"command": "npx",
"args": [
"-y",
"@anthropic-ai/mcp-server-filesystem",
"/Users/you/projects"
]
}
}
}
The format is nearly identical to Claude Code. Most servers work with both tools without modification.
Most MCP servers are published to npm. The npx -y pattern in the configurations above handles installation automatically - it downloads and runs the package without requiring a global install.
For servers you use frequently, you can install them globally for faster startup:
npm install -g @anthropic-ai/mcp-server-filesystem
npm install -g @anthropic-ai/mcp-server-githubThen reference the command directly instead of using npx:
{
"filesystem": {
"command": "mcp-server-filesystem",
"args": ["/Users/you/projects"]
}
}
Some servers are not on npm. Clone the repo and build:
git clone https://github.com/example/custom-mcp-server.git
cd custom-mcp-server
npm install && npm run build
Then point your configuration at the built entry point:
{
"custom": {
"command": "node",
"args": ["/path/to/custom-mcp-server/dist/index.js"]
}
}
For servers that need specific system dependencies or isolation:
{
"postgres": {
"command": "docker",
"args": [
"run", "-i", "--rm",
"-e", "DATABASE_URL=postgresql://user:pass@host:5432/db",
"mcp/postgres-server"
]
}
}
The -i flag is critical - it keeps stdin open for the JSON-RPC protocol. Without it, the container exits immediately.
Get the weekly deep dive
Tutorials on Claude Code, AI agents, and dev tools - delivered free every week.
When no existing server fits your use case, you build your own. The TypeScript SDK makes this straightforward.
mkdir my-mcp-server
cd my-mcp-server
npm init -y
npm install @modelcontextprotocol/sdk zod
npm install -D typescript @types/node
Create a tsconfig.json:
{
"compilerOptions": {
"target": "ES2022",
"module": "Node16",
"moduleResolution": "Node16",
"outDir": "dist",
"strict": true
},
"include": ["src"]
}
Here is a complete MCP server that exposes tools for interacting with a project management system:
// src/index.ts
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: "project-manager",
version: "1.0.0",
});
// Define a tool for listing tasks
server.tool(
"list_tasks",
"List all tasks, optionally filtered by status",
{
status: z.enum(["open", "in_progress", "done"]).optional()
.describe("Filter by task status"),
limit: z.number().default(20)
.describe("Maximum number of tasks to return"),
},
async ({ status, limit }) => {
const tasks = await fetchTasks({ status, limit });
return {
content: [
{
type: "text",
text: JSON.stringify(tasks, null, 2),
},
],
};
}
);
// Define a tool for creating tasks
server.tool(
"create_task",
"Create a new task with a title and optional description",
{
title: z.string().describe("Task title"),
description: z.string().optional().describe("Task description"),
priority: z.enum(["low", "medium", "high"]).default("medium")
.describe("Task priority level"),
assignee: z.string().optional().describe("Email of the assignee"),
},
async ({ title, description, priority, assignee }) => {
const task = await createTask({ title, description, priority, assignee });
return {
content: [
{
type: "text",
text: `Created task ${task.id}: ${task.title}`,
},
],
};
}
);
// Define a tool for updating task status
server.tool(
"update_task_status",
"Update the status of an existing task",
{
taskId: z.string().describe("The task ID"),
status: z.enum(["open", "in_progress", "done"])
.describe("New status"),
},
async ({ taskId, status }) => {
const task = await updateTask(taskId, { status });
return {
content: [
{
type: "text",
text: `Updated task ${task.id} to ${status}`,
},
],
};
}
);
// Start the server
const transport = new StdioServerTransport();
await server.connect(transport);
Build and test:
npx tsc
echo '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{},"clientInfo":{"name":"test","version":"1.0.0"}}}' | node dist/index.js
If you see a JSON response with the server's capabilities, it is working.
Resources let you expose read-only data that the model can access without calling a tool:
server.resource(
"project-readme",
"file:///project/README.md",
async (uri) => {
const content = await readFile("./README.md", "utf-8");
return {
contents: [
{
uri: uri.href,
mimeType: "text/markdown",
text: content,
},
],
};
}
);
Tools should return errors as content, not throw exceptions. This gives the model information it can reason about:
server.tool(
"query_database",
"Execute a read-only SQL query",
{ sql: z.string() },
async ({ sql }) => {
try {
if (!sql.trim().toUpperCase().startsWith("SELECT")) {
return {
content: [{
type: "text",
text: "Error: Only SELECT queries are allowed.",
}],
isError: true,
};
}
const result = await pool.query(sql);
return {
content: [{
type: "text",
text: JSON.stringify(result.rows, null, 2),
}],
};
} catch (err) {
return {
content: [{
type: "text",
text: `Query failed: ${(err as Error).message}`,
}],
isError: true,
};
}
}
);
The isError: true flag tells the client that this response represents a failure, which helps the model decide whether to retry or take a different approach.
Package it for npm:
{
"name": "mcp-server-project-manager",
"version": "1.0.0",
"bin": {
"mcp-server-project-manager": "dist/index.js"
},
"files": ["dist"]
}
Add a shebang to your entry point:
#!/usr/bin/env node
// src/index.ts
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
// ...
Publish:
npm publish
Users can now configure it with:
{
"project-manager": {
"command": "npx",
"args": ["-y", "mcp-server-project-manager"]
}
}
The ecosystem has hundreds of servers. These are the ones that solve real problems. For the full searchable directory with working configurations, visit mcp.developersdigest.tech.
Postgres (@anthropic-ai/mcp-server-postgres) - the gold standard. Read-only by default, which is exactly right for AI agents writing SQL against your data. Supports query execution, schema inspection, and EXPLAIN ANALYZE.
SQLite (@anthropic-ai/mcp-server-sqlite) - same capabilities as Postgres, for SQLite databases. Good for local development and embedded applications.
Redis (mcp-server-redis) - key-value operations, pub/sub inspection, and cache management. Useful for debugging caching issues without switching to a Redis CLI.
GitHub (@anthropic-ai/mcp-server-github) - the second server most developers install. Search repos, read and create issues, open PRs, comment on code reviews. Scope your token to minimum required permissions.
Git (mcp-server-git) - local git operations. Diff inspection, log browsing, branch management. Useful when your agent needs git context without shelling out to the CLI.
Firecrawl (firecrawl-mcp) - scrape web pages, extract structured data, crawl entire sites. The best web scraping server in the ecosystem. Handles JavaScript-rendered pages that simpler scrapers miss.
Brave Search (@anthropic-ai/mcp-server-brave-search) - web search with clean, structured results. Requires a Brave Search API key (free tier available).
Slack (mcp-server-slack) - read channels, send messages, search history. Useful for agents that need to pull context from team conversations.
Linear (mcp-server-linear) - issue tracking integration. Create, update, and search issues. Good for agents that manage engineering workflows.
Notion (mcp-server-notion) - read and write Notion pages and databases. Useful for agents that need to reference documentation or update project wikis.
Docker (mcp-server-docker) - list containers, read logs, manage images. Useful for debugging deployment issues without switching to a terminal.
Kubernetes (mcp-server-kubernetes) - pod management, log access, resource inspection. Read-only by default - do not give an AI agent write access to production clusters.
AWS (mcp-server-aws) - S3, Lambda, CloudWatch, and other AWS service interactions. Scope your IAM credentials tightly.
Filesystem (@anthropic-ai/mcp-server-filesystem) - the most fundamental server. Read, write, search, and manage files. Restrict access to specific directories. This is the first server you should install.
Google Drive (mcp-server-google-drive) - read and search files in Google Drive. Useful for agents that need to reference documents, spreadsheets, or presentations.
MCP servers run with the permissions of the user who starts them. This means they can potentially access anything on your machine. Follow these practices:
Principle of least privilege. Give each server only the access it needs. The filesystem server takes directory paths as arguments - pass only the directories the agent should read. GitHub tokens should use minimum required scopes.
Read-only defaults. When possible, configure servers for read-only access. The Postgres server is read-only by default. If your server supports write operations, make them opt-in rather than default.
No secrets in server configs. Use environment variables for API keys and tokens, not hardcoded values in configuration files. If your config is checked into version control, anyone with repo access can see your secrets.
{
"github": {
"command": "npx",
"args": ["-y", "@anthropic-ai/mcp-server-github"],
"env": {
"GITHUB_TOKEN": "${GITHUB_TOKEN}"
}
}
}
Audit tool calls. Monitor what your agent is doing with MCP tools. Most hosts provide logging of tool calls and their results. Review these logs regularly, especially when first deploying a new server.
Sandbox destructive operations. If an MCP server can modify data (write files, update databases, create issues), add confirmation mechanisms. The agent should preview what it intends to do before executing destructive actions.
When a server is not working, the issue is usually in one of three places.
Check that the command and arguments are correct. Test by running the command manually:
npx -y @anthropic-ai/mcp-server-filesystem /Users/you/projects
If it fails, the error message usually tells you what is wrong - missing dependency, invalid arguments, or permissions issue.
The client and server might have a protocol version mismatch. Check the server's package version and update if needed:
npm info @anthropic-ai/mcp-server-filesystem version
Add logging to your custom servers:
server.tool("my_tool", "description", { param: z.string() }, async ({ param }) => {
console.error(`[my_tool] Called with param: ${param}`);
try {
const result = await doSomething(param);
console.error(`[my_tool] Success: ${JSON.stringify(result)}`);
return { content: [{ type: "text", text: JSON.stringify(result) }] };
} catch (err) {
console.error(`[my_tool] Error: ${err}`);
return { content: [{ type: "text", text: `Error: ${err}` }], isError: true };
}
});
Logs go to stderr (not stdout, which is reserved for the JSON-RPC protocol). In Claude Code, check the MCP server logs with /mcp to see server status and recent errors.
Model Context Protocol (MCP) is an open standard created by Anthropic that defines how AI agents connect to external tools and data sources. It provides a universal interface so that any MCP client (like Claude Code or Cursor) can work with any MCP server (like a database connector or GitHub integration) without custom code.
No. Claude Code works without any MCP servers configured. MCP extends what the agent can access beyond the local filesystem and shell. Without MCP, Claude Code reads files and runs commands. With MCP, it can also query databases, search the web, manage GitHub issues, and interact with any service that has an MCP server.
There is no hard limit, but each server is a running process that consumes memory. Most developers run 3-8 servers. Start with filesystem and one or two domain-specific servers, then add more as needed.
MCP servers run with your user permissions. They are as secure as you configure them to be. Follow the principle of least privilege - restrict filesystem access to specific directories, use read-only database connections, and scope API tokens to minimum required permissions. The protocol itself does not add security vulnerabilities, but misconfigured servers can expose sensitive data.
Yes. MCP is model-agnostic. Any AI tool that implements the MCP client protocol can use MCP servers. Cursor (which uses multiple models), the Claude desktop app, and several open-source tools all support MCP. The protocol does not care which model is making the tool calls.
Tools are functions the model can call - they perform actions and return results. Resources are data the model can read - they provide context passively. Use tools for operations (query a database, create an issue) and resources for reference data (project documentation, configuration files).
The MCP Server Directory catalogs 184+ servers with working configurations and category-based browsing. You can also search npm for mcp-server-* packages or browse the community repositories on GitHub.
If you are new to MCP, start with two servers: filesystem and one that connects to a service you use daily (GitHub, Postgres, Slack). Configure them, restart your AI tool, and try prompts that require cross-service context.
If you have hit the limits of existing servers, build your own. The TypeScript SDK gets you from zero to a working server in under an hour. Start with a single tool, verify it works, and add more capabilities incrementally.
For the quick-start conceptual overview, see What Is MCP. For configuration details specific to Claude Code and Cursor, see How to Use MCP Servers. For a ranked list of the best servers, see Best MCP Servers 2026. And for the full searchable directory, visit mcp.developersdigest.tech.
Technical content at the intersection of AI and development. Building with AI agents, Claude Code, and modern dev tools - then showing you exactly how it works.
New tutorials, open-source projects, and deep dives on coding agents - delivered weekly.
Install Claude Code, configure your first project, and start shipping code with AI in under 5 minutes.
MCP servers connect AI agents to databases, APIs, and tools through a standard protocol. Here is how to configure and us...

A step-by-step guide to building Model Context Protocol servers in TypeScript. Project setup, tool registration, resourc...
A searchable directory of 184+ MCP servers organized by category. Find the right server for databases, browsers, APIs, D...