Claude Code MCP Servers: How to Extend Your AI Agent with Custom Tools
I kept getting hallucinated package names. Claude would suggest imports that didn’t exist, reference APIs that were deprecated, and recommend tools that weren’t even real. The worst part? I couldn’t blame the model—it just didn’t have access to the right context.
Then I discovered MCP servers in Claude Code.
The Problem: AI Coding Assistants Lie
Not intentionally. They hallucinate because they lack real-time access to package registries, internal documentation, and tool catalogs.
I asked Claude to add a caching layer to my Node.js API. It suggested using node-cache-manager-redis-store. Sounded reasonable. I installed it, wrote the code, ran my tests… and got a wall of errors.
The package was deprecated. Had been for two years.
This isn’t unique to Claude. Every LLM-based coding assistant has this problem:
- Hallucinated dependencies: Packages that don’t exist or are deprecated
- Outdated API usage: Methods removed in newer versions
- Missing context: No access to your internal tools or documentation
- Generic suggestions: One-size-fits-all advice that misses your ecosystem
MCP: Model Context Protocol
MCP (Model Context Protocol) is the solution. It’s an open protocol that lets you connect external tools and data sources directly to Claude Code.
Think of it as giving Claude access to a library of real, verified information instead of relying on its training data alone.
┌─────────────────────────────────────────────────────────────────┐│ Claude Code ││ (AI Coding Agent) │└─────────────────────────────────────────────────────────────────┘ │ │ MCP Protocol ▼┌─────────────────────────────────────────────────────────────────┐│ MCP Server Layer ││ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ││ │ Package │ │ Context7 │ │ Custom │ ││ │ Registry │ │ Docs │ │ APIs │ ││ │ (npm/pypi) │ │ Database │ │ (Internal) │ ││ └──────────────┘ └──────────────┘ └──────────────┘ │└─────────────────────────────────────────────────────────────────┘ │ ▼┌─────────────────────────────────────────────────────────────────┐│ Verified Data Sources ││ • Real package metadata ││ • Official documentation ││ • Internal company APIs ││ • Tool catalogs (8000+ tools) │└─────────────────────────────────────────────────────────────────┘Why MCP Reduces Hallucinations
Traditional AI assistants work like this:
User Question → LLM Training Data → Best Guess Answer (may be outdated/wrong)With MCP servers:
User Question → MCP Server Query → Real Data → Verified Answer (from live source)The key difference: MCP servers provide ground truth data. When Claude needs to know if a package exists, it queries the actual package registry. When it needs to understand an API, it reads the actual documentation.
How to Configure MCP Servers in Claude Code
MCP servers are configured in your Claude Code settings. Here’s a practical configuration example:
{ "mcpServers": { "context7": { "command": "mcp-server-context7", "args": ["--docs-path", "/path/to/your/docs"] }, "fetch": { "command": "mcp-server-fetch", "args": [] }, "postgres": { "command": "mcp-server-postgres", "args": ["--connection-string", "${DATABASE_URL}"] } }}Each MCP server exposes specific capabilities:
| Server | Purpose | Hallucination Reduction |
|---|---|---|
| context7 | Official documentation lookup | No outdated API usage |
| fetch | Web content retrieval | Real-time data access |
| postgres | Database schema awareness | Correct table/column names |
| npm-search | Package registry queries | No fake packages |
A Real Example: Before and After MCP
Before MCP - I asked Claude to implement rate limiting:
Claude: "Use the `express-rate-limit-middleware` package..."
Me: *installs package*npm ERR! 404 Not Found - GET https://registry.npmjs.org/express-rate-limit-middlewareThe package didn’t exist. Claude hallucinated a plausible-sounding name.
After MCP - With package registry access:
Claude: "Searching npm registry... Found `express-rate-limit` with 2M weekly downloads,last updated 2 weeks ago. Here's the implementation..."The difference? Claude verified the package exists before recommending it.
Agent Teams: The Killer Feature
MCP also enables something even more powerful: agent teams.
Instead of one Claude doing everything, you can have specialized agents coordinated through MCP:
┌────────────────────────────────────────────────────────────┐│ Your Project │└────────────────────────────────────────────────────────────┘ │ │ │ ▼ ▼ ▼┌──────────────┐ ┌──────────────┐ ┌──────────────┐│ Planner │ │ Builder │ │ Reviewer ││ Agent │───▶│ Agent │───▶│ Agent ││ │ │ │ │ ││ Uses: docs │ │ Uses: npm │ │ Uses: tests ││ MCP server │ │ MCP server │ │ MCP server │└──────────────┘ └──────────────┘ └──────────────┘Each agent has access to specific MCP servers relevant to its task:
- Planner agent: Reads documentation, searches web context
- Builder agent: Queries package registries, accesses code templates
- Reviewer agent: Runs tests, checks security databases
What Can You Connect via MCP?
The ecosystem is growing rapidly. Here are the most useful MCP servers I’ve configured:
Documentation & Context
context7- Search official documentation databasesfetch- Retrieve web content and APIsgithub- Access repositories, issues, and PRs
Package Management
npm-search- Query npm registry directlypypi- Python package information
Data Sources
postgres/sqlite- Database schema awarenessfilesystem- Local file operationsgoogle-drive- Document access
Development Tools
puppeteer- Browser automationdocker- Container management
Setting Up Your First MCP Server
Let’s walk through adding a package registry MCP server:
{ "mcpServers": { "npm-search": { "command": "npx", "args": ["-y", "@anthropic-ai/mcp-server-npm-search"] } }}Now when you ask Claude about a package:
You: "Add a Redis caching layer to my Express app"
Claude: *queries npm-search MCP server*"Found `connect-redis` (express-session store) and `redis` (node-redis client).The `redis` package has 4M weekly downloads and was updated 3 days ago.Here's the implementation..."The Architecture Deep Dive
Understanding how MCP works under the hood helps you debug issues:
┌─────────────────────────────────────────────────────────────┐│ Claude Code Process ││ ┌─────────────────┐ ┌─────────────────────────────┐ ││ │ Your Request │───▶│ MCP Client (built-in) │ ││ └─────────────────┘ └─────────────────────────────┘ ││ │ │└────────────────────────────────────│─────────────────────────┘ │ JSON-RPC over stdio ▼┌─────────────────────────────────────────────────────────────┐│ MCP Server Process ││ ┌─────────────────────────────────────────────────────┐ ││ │ Tools ──────▶ Functions Claude can call │ ││ │ Resources ──▶ Data Claude can read │ ││ │ Prompts ────▶ Pre-defined templates │ ││ └─────────────────────────────────────────────────────┘ │└─────────────────────────────────────────────────────────────┘ │ ▼┌─────────────────────────────────────────────────────────────┐│ External Data Source ││ (npm registry, docs database, etc.) │└─────────────────────────────────────────────────────────────┘The protocol is simple: JSON-RPC messages over stdin/stdout. This means any language can implement an MCP server—Python, Node.js, Go, Rust, even shell scripts.
Common MCP Pitfalls
I’ve made these mistakes so you don’t have to:
-
Not exploring MCP after switching to Claude Code: The default setup works fine, but you’re missing the real power.
-
Assuming hallucinations are unavoidable: They’re not. MCP servers provide ground truth data that eliminates many hallucination sources.
-
Using generic prompts when custom MCP would help: If you work with internal APIs or specialized tools, build a custom MCP server.
-
Ignoring the agent teams feature: Coordinated agents with specialized MCP access are far more powerful than a single general-purpose agent.
When to Build a Custom MCP Server
Consider building your own MCP server when:
- You have internal APIs that Claude should know about
- Your team uses proprietary tools or libraries
- You work with private documentation databases
- You need real-time access to company-specific data
The MCP SDK makes this straightforward. Here’s the skeleton of a custom server:
from mcp.server import Serverfrom mcp.server.stdio import stdio_server
app = Server("my-custom-server")
@app.list_tools()async def list_tools(): return [ Tool(name="query_internal_api", description="Query our internal API") ]
@app.call_tool()async def call_tool(name: str, arguments: dict): if name == "query_internal_api": # Your custom logic here return await query_internal_api(**arguments)
async def main(): async with stdio_server() as (read_stream, write_stream): await app.run(read_stream, write_stream)Related Knowledge
- Model Context Protocol Specification: The open standard that MCP implements
- Function Calling: The underlying mechanism MCP uses to expose tools
- RAG (Retrieval Augmented Generation): Similar concept, but MCP is more structured
- LangChain Tools: Comparable ecosystem, but MCP is language-agnostic
Final Words + More Resources
My intention with this article was to help others share my knowledge and experience. If you want to contact me, you can contact by email: Email me
Here are also the most important links from this article along with some further resources that will help you in this scope:
Oh, and if you found these resources useful, don’t forget to support me by starring the repo on GitHub!
Comments