MCP (Model Context Protocol) is an open standard that lets Claude Code connect to external tools and data sources. MCP servers give Claude Code new abilities like fetching web content, querying databases, or interacting with third-party APIs.
MCP follows a client-server architecture:
When you add an MCP server, its tools become available to Claude Code just like built-in tools.
Use the claude mcp add command:
# Add a filesystem MCP server claude mcp add filesystem -- npx -y @anthropic-ai/mcp-filesystem /path/to/dir # Add a PostgreSQL MCP server claude mcp add postgres -- npx -y @anthropic-ai/mcp-postgres "postgresql://localhost/mydb" # Add a web fetch MCP server claude mcp add fetch -- npx -y @anthropic-ai/mcp-fetch
# List all configured MCP servers claude mcp list # Remove an MCP server claude mcp remove postgres # Get details about a server claude mcp get filesystem
MCP servers can be configured at different scopes:
# Project-level (stored in .claude/settings.json) claude mcp add --scope project my-server -- command args # User-level (stored in ~/.claude/settings.json) claude mcp add --scope user my-server -- command args
| Server | Purpose | Example Use |
|---|---|---|
| mcp-filesystem | Access files outside project | Read config files from other directories |
| mcp-postgres | Query PostgreSQL | Check database schema and data |
| mcp-fetch | Fetch web URLs | Read API docs, check endpoints |
| mcp-github | GitHub integration | Manage issues, PRs, repos |
| mcp-slack | Slack integration | Send messages, read channels |
Once configured, MCP tools appear automatically. For example, with the postgres server:
> Show me all tables in the database # Claude uses the MCP postgres tool to query information_schema > What columns does the users table have? # Claude queries the table structure directly
You can create your own MCP servers for custom integrations. The MCP SDK is available in TypeScript and Python:
npm install @modelcontextprotocol/sdk
A minimal MCP server exposes tools that Claude Code can call:
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
const server = new McpServer({ name: "my-server", version: "1.0.0" });
server.tool("hello", "Say hello", { name: { type: "string" } },
async ({ name }) => ({
content: [{ type: "text", text: `Hello, ${name}!` }]
})
);
const transport = new StdioServerTransport();
await server.connect(transport);
MCP servers extend Claude Code’s capabilities by connecting it to external tools and data sources. From databases to APIs to custom integrations, MCP makes Claude Code infinitely extensible. Next, we’ll cover advanced tips and tricks to maximize your productivity.
Claude Code can be customized per-project using a CLAUDE.md file and has a memory system that persists information across sessions. These features make Claude Code smarter about your specific project over time.
CLAUDE.md is a markdown file you place in your project root. Claude Code reads it at the start of every session, using it as persistent instructions for how to work with your project.
Use the init command to create one interactively:
claude /init
Or create it manually. Here’s an example:
# CLAUDE.md ## Project Overview E-commerce API built with FastAPI and PostgreSQL. ## Tech Stack - Python 3.11, FastAPI, SQLAlchemy 2.0 - PostgreSQL 15, Redis for caching - pytest for testing ## Commands - Run tests: `pytest tests/` - Start dev server: `uvicorn app.main:app --reload` - Run migrations: `alembic upgrade head` ## Conventions - Use snake_case for Python, camelCase for JavaScript - All API endpoints must have input validation - Write tests for all new features ## Architecture - app/models/ - SQLAlchemy models - app/routes/ - API route handlers - app/services/ - Business logic - app/schemas/ - Pydantic schemas
Claude Code supports multiple CLAUDE.md files at different levels:
~/.claude/CLAUDE.md # Global (all projects) project-root/CLAUDE.md # Project-level project-root/src/CLAUDE.md # Directory-level (scoped)
Directory-level files are loaded when Claude reads files in that directory, giving you scoped instructions.
Claude Code has a persistent memory system that stores information across sessions. It automatically saves useful patterns it discovers about your project.
Memory is stored in ~/.claude/projects/<project-hash>/memory/.
# Ask Claude to remember something > Remember that we always use UTC timestamps in this project # Ask Claude to forget something > Forget the convention about UTC timestamps # Memory is automatically updated as Claude learns about your project
Claude Code also supports .claude/settings.json for configuration:
{
"permissions": {
"allow": [
"Bash(npm test)",
"Bash(npm run lint)",
"Read",
"Write"
]
}
}
This auto-approves specific tools and commands so you’re not prompted every time.
CLAUDE.md and memory make Claude Code smarter about your project over time. The more context you provide, the better Claude Code performs. Next, we’ll explore MCP servers and how they extend Claude Code’s capabilities.
Previous: Writing Tests with Claude Code
Writing tests is essential but often tedious. Claude Code can generate comprehensive test suites that cover your code’s behavior, edge cases, and error scenarios.
Point Claude Code at a function and ask for tests:
> Write unit tests for the validate_email function in src/utils/validators.py
Claude Code will generate tests covering:
Example generated test:
import pytest
from src.utils.validators import validate_email
class TestValidateEmail:
def test_valid_email(self):
assert validate_email("user@example.com") is True
def test_valid_email_with_subdomain(self):
assert validate_email("user@mail.example.com") is True
def test_invalid_email_no_at(self):
assert validate_email("userexample.com") is False
def test_invalid_email_no_domain(self):
assert validate_email("user@") is False
def test_empty_string(self):
assert validate_email("") is False
> Write integration tests for the /api/users endpoint. Test creating, reading, updating, and deleting users.
Ask Claude to analyze code and determine what needs testing:
> Look at the OrderService class and write tests for any untested business logic
Claude Code supports TDD workflows:
# Step 1: Write the test first > Write a failing test for a function that calculates shipping cost based on weight and destination # Step 2: Implement the code > Now implement the calculate_shipping function to make the tests pass # Step 3: Run and verify > Run the tests to confirm they pass
Ask Claude to run your test suite:
# Run all tests > Run the full test suite # Run specific tests > Run only the authentication tests # Run with coverage > Run tests with coverage report
When tests fail, Claude Code can diagnose and fix them:
> The test_create_user test is failing. Can you figure out why and fix it?
Claude Code can write unit tests, integration tests, and support TDD workflows. It generates comprehensive test coverage and helps fix failing tests. Next, we’ll learn about configuring Claude Code with CLAUDE.md and memory.
Previous: Working with Git using Claude Code
Claude Code integrates deeply with Git, making version control effortless. It can create commits, manage branches, review diffs, resolve merge conflicts, and even create pull requests.
Let Claude Code analyze your changes and write a commit message:
> Commit my current changes with a descriptive message
Claude Code will:
git status and git diff# Create a feature branch > Create a new branch called feature/user-authentication # Switch branches > Switch to the main branch # View branch info > Show me all branches and which one I'm on
Ask Claude Code to explain what changed:
# Review your uncommitted changes > What changes have I made since the last commit? # Review changes between branches > What's different between my branch and main? # Review a specific commit > Explain what commit abc1234 changed and why
Claude Code can handle merge conflicts for you:
> I have merge conflicts after rebasing on main. Can you resolve them?
Claude Code will read each conflicting file, understand both sides of the conflict, and make an intelligent resolution based on the intent of both changes.
Let Claude Code create a PR with a proper description:
> Create a pull request for my current branch against main
Claude Code will:
You can also ask Claude Code to review an existing PR:
# Review a specific PR > /review 42 # Or provide the URL > Review this PR: https://github.com/user/repo/pull/42
# Undo the last commit (keeping changes) > Undo my last commit but keep the file changes # Discard changes to a file > Revert all changes to src/config.js # Stash work in progress > Stash my current changes so I can switch branches
Claude Code makes Git workflows smooth — from smart commits to merge conflict resolution to PR creation. Next, we’ll explore how to use Claude Code for writing tests.
Previous: Refactoring Code with Claude Code
Refactoring — restructuring existing code without changing its behavior — is one of the most tedious parts of development. Claude Code makes it fast and safe by understanding your entire codebase and making consistent changes across multiple files.
Rename a function or variable across your entire project:
> Rename the function getUserData to fetchUserProfile everywhere it's used in the project
Claude Code will find all usages — definitions, calls, imports, and tests — and rename them consistently.
Pull complex logic into its own function:
> In src/handlers/order.py, the process_order function is too long. Extract the payment validation logic into its own function.
Modernize your code by converting between patterns:
# Convert callbacks to async/await > Convert all callback-based functions in src/services/ to use async/await # Convert class components to functional > Convert UserProfile.jsx from a class component to a functional component with hooks # Convert to TypeScript > Convert src/utils/helpers.js to TypeScript with proper type annotations
Reorganize your project’s directory structure:
> Move all API route handlers from routes/ into a new structure: controllers/ for business logic and routes/ for just route definitions. Update all imports accordingly.
Ask Claude to simplify overly complex code:
> This function in src/utils/parser.py has deeply nested if-else statements. Refactor it to be more readable using early returns and guard clauses.
Incrementally add types to a JavaScript project:
> Add JSDoc type annotations to all exported functions in src/services/auth.js
git diff to review all changesExample workflow:
> Run the tests first to make sure everything passes # Tests pass > Now refactor the UserService to use dependency injection # Claude makes the changes > Run the tests again to verify nothing broke # Tests still pass > Commit these changes with a descriptive message
Claude Code handles refactoring across your entire codebase — from simple renames to major architectural changes. It tracks all references and ensures consistency. Next, we’ll learn how Claude Code works with Git.
Previous: Debugging with Claude Code