Lesson 06: MCP Servers (Model Context Protocol)
What Is MCP?
MCP (Model Context Protocol) is an open standard that lets you give Claude access to external tools, data sources, and services. Think of MCP servers as plugins that extend what Claude can do.
Without MCP, Claude can:
- Read/write files
- Run shell commands
- Search the web
With MCP, Claude can also:
- Query your actual database
- Create GitHub issues and PRs
- Browse the web with a real browser
- Read your Slack messages
- Query your Jira tickets
- Access your Google Drive
- Control your computer's GUI
How MCP Works
Claude ←→ MCP Client (Claude Code) ←→ MCP Server ←→ External Service
An MCP server is a small program that:
- Exposes a set of tools (functions Claude can call)
- Exposes optional resources (data Claude can read)
- Communicates with Claude Code via stdio or HTTP
Claude sees MCP tools just like its built-in tools. It decides when to use them based on context.
Configuring MCP Servers
MCP servers are configured in ~/.claude/settings.json:
{
"mcpServers": {
"github": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-github"],
"env": {
"GITHUB_PERSONAL_ACCESS_TOKEN": "ghp_..."
}
},
"postgres": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-postgres", "postgresql://localhost/mydb"]
},
"brave-search": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-brave-search"],
"env": {
"BRAVE_API_KEY": "..."
}
}
}
}
High-Value MCP Servers
Database Access
Gives Claude direct SQL query capability:
"postgres": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-postgres", "postgresql://localhost/mydb"]
}
Claude can now answer "show me all users who signed up this week" by actually querying your database.
GitHub
Full GitHub API access:
- Create issues, PRs, comments
- Search code across repos
- Manage branches
- Read PR reviews
"github": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-github"],
"env": { "GITHUB_PERSONAL_ACCESS_TOKEN": "..." }
}
Puppeteer / Browser
Real browser control for scraping, testing, automation:
"puppeteer": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-puppeteer"]
}
Claude can take screenshots, fill forms, click buttons.
Filesystem (Extended)
More powerful file access than default:
"filesystem": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/path/to/allow"]
}
Brave Search
Real web search without API key limits:
"brave-search": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-brave-search"],
"env": { "BRAVE_API_KEY": "..." }
}
Building a Custom MCP Server
If no existing server does what you need, build your own. It's surprisingly simple.
Minimal MCP Server (Node.js)
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
const server = new Server(
{ name: "my-custom-tools", version: "1.0.0" },
{ capabilities: { tools: {} } }
);
// Define a tool
server.setRequestHandler("tools/list", async () => ({
tools: [
{
name: "get_deployment_status",
description: "Get the current deployment status from our internal API",
inputSchema: {
type: "object",
properties: {
environment: { type: "string", enum: ["staging", "production"] }
},
required: ["environment"]
}
}
]
}));
// Handle tool calls
server.setRequestHandler("tools/call", async (request) => {
if (request.params.name === "get_deployment_status") {
const { environment } = request.params.arguments;
// Your actual logic here
const status = await fetchDeploymentStatus(environment);
return {
content: [{ type: "text", text: JSON.stringify(status) }]
};
}
});
const transport = new StdioServerTransport();
await server.connect(transport);
Then in settings.json:
"my-tools": {
"command": "node",
"args": ["/path/to/my-server.js"]
}
What to Build Custom MCP Servers For
- Internal APIs and dashboards
- Company-specific tooling
- Database schemas Claude should understand
- Custom search over internal documentation
- Integration with proprietary systems
Security Considerations
MCP servers have real access to real systems. Be careful:
- Never put credentials in settings.json if it's shared — use env vars
- Scope database access — create read-only DB users for Claude
- Review what tools expose — a
runArbitrarySQLtool is dangerous - Don't expose prod systems to development Claude sessions
Practical Exercise
- Install the GitHub MCP server
- Add your GitHub token to settings
- Ask Claude: "List my open GitHub issues and summarize the most urgent ones"
- Ask Claude: "Create a GitHub issue for [something in your current project]"
Notice how Claude can now interact with GitHub without you copy-pasting URLs or issue numbers.