Claude Code Advanced
40 minutes
linux
macos
windows

Advanced MCP Integration

Connect Claude Code to external tools, databases, and custom functionality using Model Context Protocol.

What you'll accomplish

Set up and use MCP servers to extend Claude Code's capabilities.

Prerequisites

  • Claude Code working environment
  • Understanding of APIs and JSON
  • Node.js for custom servers

What is MCP?

MCP (Model Context Protocol) is a standard for connecting AI assistants to external tools and data sources. It allows Claude Code to:

  • Query databases directly
  • Access APIs and external services
  • Use specialized tools you create
  • Integrate with existing systems

Your browser can have extensions that add features (ad blockers, password managers). MCP works similarly for Claude Code:

  • Without MCP: Claude can only read/write files and run commands
  • With MCP: Claude can access databases, APIs, and custom tools

You "install" MCP servers that give Claude new abilities.

MCP Architecture

┌─────────────────┐
│   Claude Code   │
│   (Client)      │
└────────┬────────┘
         │ MCP Protocol (JSON-RPC)
         ▼
┌─────────────────┐     ┌─────────────────┐
│  MCP Server 1   │     │  MCP Server 2   │
│  (Database)     │     │  (Custom API)   │
└─────────────────┘     └─────────────────┘
         │                       │
         ▼                       ▼
    PostgreSQL              Your API

Client: Claude Code requests data/actions Servers: Programs that fulfill those requests

Configuring MCP Servers

Settings Location

MCP servers are configured in your settings:

json
// ~/.claude/settings.json or .claude/settings.json
{
  "mcpServers": {
    "database": {
      "command": "npx",
      "args": ["@modelcontextprotocol/server-postgres"],
      "env": {
        "DATABASE_URL": "postgresql://user:pass@localhost/db"
      }
    },
    "filesystem": {
      "command": "npx",
      "args": ["@modelcontextprotocol/server-filesystem", "/data"]
    }
  }
}

Server Configuration Options

OptionDescriptionRequired
commandExecutable to runYes
argsCommand argumentsNo
envEnvironment variablesNo
cwdWorking directoryNo

Built-in MCP Servers

Anthropic provides several pre-built MCP servers:

Filesystem Server

Access files beyond the project directory:

json
{
  "mcpServers": {
    "docs": {
      "command": "npx",
      "args": ["@modelcontextprotocol/server-filesystem", "/path/to/docs"]
    }
  }
}

Now Claude can access: Read the file at /path/to/docs/readme.md

PostgreSQL Server

Query PostgreSQL databases:

json
{
  "mcpServers": {
    "postgres": {
      "command": "npx",
      "args": ["@modelcontextprotocol/server-postgres"],
      "env": {
        "POSTGRES_HOST": "localhost",
        "POSTGRES_PORT": "5432",
        "POSTGRES_USER": "myuser",
        "POSTGRES_PASSWORD": "mypass",
        "POSTGRES_DATABASE": "mydb"
      }
    }
  }
}

Now Claude can: Query the users table to find inactive accounts

SQLite Server

For local SQLite databases:

json
{
  "mcpServers": {
    "sqlite": {
      "command": "npx",
      "args": ["@modelcontextprotocol/server-sqlite", "--db", "/path/to/database.db"]
    }
  }
}

GitHub Server

Access GitHub repositories and issues:

json
{
  "mcpServers": {
    "github": {
      "command": "npx",
      "args": ["@modelcontextprotocol/server-github"],
      "env": {
        "GITHUB_TOKEN": "ghp_xxxxxxxxxxxx"
      }
    }
  }
}

Now Claude can: List open issues in the anthropics/claude-code repo

Slack Server

Read and send Slack messages:

json
{
  "mcpServers": {
    "slack": {
      "command": "npx",
      "args": ["@modelcontextprotocol/server-slack"],
      "env": {
        "SLACK_TOKEN": "xoxb-xxxxx"
      }
    }
  }
}

Creating Custom MCP Servers

You can build your own MCP servers for custom functionality.

Basic Structure (TypeScript)

typescript
// custom-server.ts
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";

const server = new Server({
  name: "my-custom-server",
  version: "1.0.0",
});

// Define available tools
server.setRequestHandler("tools/list", async () => ({
  tools: [
    {
      name: "get_weather",
      description: "Get current weather for a location",
      inputSchema: {
        type: "object",
        properties: {
          location: {
            type: "string",
            description: "City name or coordinates",
          },
        },
        required: ["location"],
      },
    },
  ],
}));

// Handle tool calls
server.setRequestHandler("tools/call", async (request) => {
  if (request.params.name === "get_weather") {
    const location = request.params.arguments.location;
    // Your implementation here
    const weather = await fetchWeather(location);
    return {
      content: [{ type: "text", text: JSON.stringify(weather) }],
    };
  }
  throw new Error("Unknown tool");
});

// Start the server
const transport = new StdioServerTransport();
await server.connect(transport);

Package Setup

json
// package.json
{
  "name": "my-mcp-server",
  "version": "1.0.0",
  "type": "module",
  "bin": {
    "my-mcp-server": "./dist/server.js"
  },
  "dependencies": {
    "@modelcontextprotocol/sdk": "^0.5.0"
  }
}

Using Your Server

After building (npm run build):

json
{
  "mcpServers": {
    "weather": {
      "command": "node",
      "args": ["/path/to/my-mcp-server/dist/server.js"]
    }
  }
}

Advanced Examples

Database + AI Queries

json
{
  "mcpServers": {
    "business-data": {
      "command": "node",
      "args": ["./mcp/business-server.js"],
      "env": {
        "DB_URL": "postgresql://...",
        "ALLOW_WRITES": "false"
      }
    }
  }
}

Now you can ask Claude: What were our top 10 selling products last month?

Claude will:

  1. Use the MCP server to query the database
  2. Process the results
  3. Present them in a useful format

Multi-Service Integration

Connect multiple services:

json
{
  "mcpServers": {
    "database": {
      "command": "npx",
      "args": ["@modelcontextprotocol/server-postgres"],
      "env": { "DATABASE_URL": "..." }
    },
    "analytics": {
      "command": "node",
      "args": ["./mcp/analytics-server.js"],
      "env": { "ANALYTICS_KEY": "..." }
    },
    "notifications": {
      "command": "node",
      "args": ["./mcp/slack-notifier.js"],
      "env": { "SLACK_WEBHOOK": "..." }
    }
  }
}

Now Claude can: Check if any products are running low, and if so, notify the #inventory Slack channel

Read-Only Access

For safety, many MCP servers support read-only mode:

json
{
  "mcpServers": {
    "prod-db": {
      "command": "npx",
      "args": ["@modelcontextprotocol/server-postgres", "--read-only"],
      "env": {
        "DATABASE_URL": "postgresql://readonly_user:pass@prod-server/db"
      }
    }
  }
}
Warning

Production databases: Always use read-only credentials when connecting Claude to production data. Create a dedicated read-only database user.

MCP Tool Types

MCP servers can provide:

Tools

Functions Claude can call:

typescript
{
  tools: [
    {
      name: "create_ticket",
      description: "Create a support ticket",
      inputSchema: {
        type: "object",
        properties: {
          title: { type: "string" },
          priority: { type: "string", enum: ["low", "medium", "high"] }
        }
      }
    }
  ]
}

Resources

Data Claude can read:

typescript
{
  resources: [
    {
      uri: "config://app-settings",
      name: "Application Settings",
      mimeType: "application/json"
    }
  ]
}

Prompts

Reusable prompt templates:

typescript
{
  prompts: [
    {
      name: "code-review",
      description: "Standard code review template",
      arguments: [
        { name: "language", required: true }
      ]
    }
  ]
}

Debugging MCP Servers

Enable Verbose Logging

bash
claude --verbose

This shows MCP communication details.

Test Server Manually

Run your server directly and send test requests:

bash
echo '{"jsonrpc":"2.0","method":"tools/list","id":1}' | node ./my-server.js

Check Server Logs

Add logging to your server:

typescript
import { createWriteStream } from 'fs';
const log = createWriteStream('/tmp/mcp-server.log', { flags: 'a' });

function debug(msg: string) {
  log.write(`[${new Date().toISOString()}] ${msg}\n`);
}

debug('Server starting...');

Common Issues

Frequently Asked Questions

Check:

  1. Command path is correct (use absolute paths)
  2. Dependencies are installed (npm install)
  3. Server starts without errors when run manually
  4. Settings JSON is valid
  1. Restart Claude Code after settings changes
  2. Check tools/list returns your tool
  3. Verify tool name matches exactly
  4. Check for errors in server output
  1. Verify database credentials
  2. Check network connectivity from server
  3. Ensure user has SELECT permissions
  4. Test query manually first
  1. Use host.docker.internal instead of localhost
  2. Ensure network is configured correctly
  3. Mount MCP server files into container
  4. Pass environment variables to container

Security Best Practices

1. Use Read-Only Where Possible

json
{
  "env": {
    "MODE": "readonly",
    "ALLOW_WRITES": "false"
  }
}

2. Limit Data Access

Create database views instead of direct table access:

sql
CREATE VIEW safe_users AS
SELECT id, username, created_at
FROM users;
-- Excludes sensitive columns like password_hash, email

3. Rate Limiting

Implement rate limiting in your server:

typescript
const rateLimit = new Map<string, number>();

function checkRateLimit(tool: string): boolean {
  const count = rateLimit.get(tool) || 0;
  if (count > 100) return false;
  rateLimit.set(tool, count + 1);
  return true;
}

4. Audit Logging

Log all MCP operations:

typescript
function logOperation(tool: string, args: unknown) {
  console.error(JSON.stringify({
    timestamp: new Date().toISOString(),
    tool,
    args,
  }));
}

5. Separate Credentials

Use different credentials for different environments:

json
{
  "mcpServers": {
    "dev-db": {
      "env": { "DATABASE_URL": "${DEV_DATABASE_URL}" }
    },
    "prod-db": {
      "env": { "DATABASE_URL": "${PROD_DATABASE_URL}" }
    }
  }
}

Verify Your Understanding

You've completed this lesson if you can:

0/5

Next: Security best practices for Claude Code in professional environments.