The Complete Guide to MCP Servers in Claude Code: Extending Your CLI Agent
The Complete Guide to MCP Servers in Claude Code: Extending Your CLI Agent
Out of the box, Claude Code has access to bash execution, file reading, globbing, and text editing. That alone makes it formidable.
However, the real inflection point in agent productivity occurs when you plug Claude Code into the Model Context Protocol (MCP). MCP gives Claude direct, typed, authenticated access to databases, cloud infrastructure, issue trackers, and internal APIs without requiring hacky shell scripts or insecure copy-pasting.
In this guide, we break down how to configure MCP servers for Claude Code, how to scope them per project, and how to build a custom internal MCP server in TypeScript.
1. Project-Scoped vs Global MCP Configuration
Many developers install MCP servers into their global user profile (~/.claude.json). Avoid this pattern in team environments.
When you configure MCP servers globally, your teammates cannot run the same workflows when they clone your repository. Instead, check an mcp.json file into the root of your project:
{
"mcpServers": {
"postgres": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-postgres", "postgresql://user:secret@localhost:5432/app_db"]
},
"github": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-github"],
"env": {
"GITHUB_PERSONAL_ACCESS_TOKEN": "ghp_xxxxxxxxxxxxxxxxxxxx"
}
}
}
}
Whenever anyone on your team opens the project with claude, Claude Code immediately discovers these tools and prompts to activate them.
2. Essential MCP Servers for Daily Engineering
A. PostgreSQL / MySQL MCP Server
Stop asking Claude to guess database schemas or run unsafe raw bash queries. The official Postgres MCP server provides tools to inspect tables, examine foreign keys, and safely analyze query execution plans:
# Test connection via CLI
npx -y @modelcontextprotocol/server-postgres "postgresql://localhost:5432/production_replica"
In conversation, you can now prompt:
"Inspect the orders and line_items tables. Identify any missing indexes causing sequential table scans during customer search."
Claude queries the database metadata directly through MCP, returning exact index definitions.
B. Docker MCP Server
Allow Claude Code to inspect container logs, verify health checks, and restart microservice pods during local integration testing:
{
"mcpServers": {
"docker": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-docker"]
}
}
}
3. Building a Custom Internal MCP Server in TypeScript
If your company has proprietary APIs (e.g. an ERP, warehouse management system, or custom billing engine), you can write a bespoke MCP server in under 50 lines of TypeScript using @modelcontextprotocol/sdk.
// server.ts - Custom Internal Inventory MCP Server
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { CallToolRequestSchema, ListToolsRequestSchema } from "@modelcontextprotocol/sdk/types.js";
import { z } from "zod";
const server = new Server(
{ name: "inventory-mcp", version: "1.0.0" },
{ capabilities: { tools: {} } }
);
// Define tool catalog
server.setRequestHandler(ListToolsRequestSchema, async () => {
return {
tools: [
{
name: "get_stock_level",
description: "Fetch live warehouse inventory count by SKU",
inputSchema: {
type: "object",
properties: {
sku: { type: "string", description: "Product SKU identifier" }
},
required: ["sku"]
}
}
]
};
});
// Handle tool execution
server.setRequestHandler(CallToolRequestSchema, async (request) => {
if (request.params.name === "get_stock_level") {
const sku = String(request.params.arguments?.sku);
// Fetch from internal database or ERP
const stock = await fetch(`https://erp.internal/api/stock/${sku}`).then(r => r.json());
return {
content: [{ type: "text", text: JSON.stringify(stock) }]
};
}
throw new Error("Tool not found");
});
const transport = new StdioServerTransport();
await server.connect(transport);
Add your compiled server to mcp.json:
{
"mcpServers": {
"internal-inventory": {
"command": "node",
"args": ["./dist/server.js"]
}
}
}
4. Security & Access Boundaries
Giving an AI agent access to databases requires strict defense-in-depth:
- Read-Only Database Roles: Always connect the Postgres MCP server using a dedicated
claude_readonlydatabase role withSELECTpermissions only. - Never Commit Secrets: Use local environment variables (
process.env.DB_URL) or secret managers rather than plain-text credentials inmcp.json. - Audit Logging: All MCP tool calls are recorded in Claude Code session transcripts, providing a verifiable audit trail for compliance.
By standardizing MCP servers across your repositories, you convert Claude Code into an authenticated member of your engineering team.
READY TO IMPLEMENT THIS?
We specialize in turning these high-impact engineering concepts into production-grade systems.