Retour aux articles
10 MIN READ

Model Context Protocol (MCP) for Claude Code: Complete Guide

By Learnia Team

Model Context Protocol (MCP) for Claude Code: Complete Guide

This article is written in English. Our training modules are available in French.

Model Context Protocol (MCP) is the bridge between Claude Code and the outside world. It connects Claude to databases, APIs, SaaS platforms, and custom tools—transforming a smart coding assistant into an integrated development hub that understands your entire ecosystem.


What is MCP?

MCP is an open protocol that standardizes how AI assistants communicate with external data sources and tools. Think of it as USB for AI—a universal connector that works with anything.

Without MCP

> What's the status of issue #432?

I don't have access to your issue tracker. 
Please check GitHub directly.

With MCP + GitHub Server

> What's the status of issue #432?

Issue #432: "Fix authentication redirect loop"
Status: Open
Assignee: @developer
Labels: bug, high-priority
Last updated: 2 hours ago
Related PR: #445 (in review)

Claude can now query, create, and update GitHub issues directly.


How MCP Works

MCP Data Flow:

Claude CodeMCP ServerExternal Service

  1. Claude Code sends requests through the MCP protocol
  2. MCP Server translates requests to the external service's API
  3. External Service returns data through the same chain

MCP servers can run:

  • Locally (stdio transport) — Scripts on your machine
  • Remotely (HTTP transport) — Hosted services with OAuth

Built-in MCP Servers

Claude Code includes several MCP servers out of the box:

ServerPurpose
filesystem
File operations beyond current directory
postgres
PostgreSQL database access
sqlite
SQLite database access
memory
Persistent key-value storage
fetch
HTTP requests to external APIs

Managing MCP Connections

View Current Servers

claude mcp list

Output:

Configured MCP Servers:
  github (http) - https://api.github.com/mcp/ [authenticated]
  sentry (http) - https://mcp.sentry.dev/mcp [authenticated]
  filesystem (stdio) - local

Interactive Management

> /mcp

Opens interactive menu:

MCP Servers

[1] github (http) - authenticated
    Tools: get_issue, create_issue, list_repos...
    
[2] sentry (http) - authenticated
    Tools: get_issues, search_errors...
    
[3] filesystem (stdio) - connected
    Tools: read_file, write_file, list_directory...

[a] Add server  [r] Remove server  [s] Server status
[o] Re-authenticate  [Esc] Exit

Adding MCP Servers

HTTP Servers (Remote)

Most SaaS integrations use HTTP transport with OAuth:

# GitHub integration
claude mcp add github --transport http https://api.github.com/mcp/

# Sentry error tracking
claude mcp add sentry --transport http https://mcp.sentry.dev/mcp

# Linear project management
claude mcp add linear --transport http https://mcp.linear.app/mcp

# Notion (with header auth)
claude mcp add notion --transport http-stream https://mcp.notion.so/mcp

After adding, Claude Code opens a browser for OAuth authentication.

Stdio Servers (Local)

Local servers run as scripts:

# Using npx
claude mcp add my-server npx -y @modelcontextprotocol/server-filesystem /path/to/dir

# Using Python
claude mcp add my-db-server python /path/to/mcp_server.py

# Using Node.js
claude mcp add custom-tools node /path/to/server.js

With Environment Variables

claude mcp add my-server -e API_KEY=secret -e DB_URL=postgres://... npx my-mcp-server

Popular MCP Integrations

GitHub

claude mcp add github --transport http https://api.github.com/mcp/

Available tools:

  • get_issue
    /
    create_issue
    /
    update_issue
  • get_pull_request
    /
    create_pull_request
  • list_repos
    /
    search_code
  • get_file_contents
    /
    create_or_update_file

Usage:

> Create an issue for the login bug we discussed

Created issue #543: "Login fails when session expires"
Labels: bug
Assignee: @me

Sentry

claude mcp add sentry --transport http https://mcp.sentry.dev/mcp

Available tools:

  • get_sentry_issues
    - Fetch error issues
  • search_sentry_errors
    - Search by query
  • get_issue_details
    - Detailed error info

Usage:

> Show me the most frequent errors this week

Top Sentry Issues (last 7 days):
1. TypeError: Cannot read 'map' of undefined
   - 342 events, 89 users affected
   - File: src/components/List.tsx:45
   
2. NetworkError: Failed to fetch
   - 156 events, 45 users affected
   - File: src/api/client.ts:23

PostgreSQL

claude mcp add postgres npx -y @modelcontextprotocol/server-postgres \
  "postgresql://user:pass@localhost:5432/mydb"

Available tools:

  • query
    - Execute read queries
  • list_tables
    - Show database schema
  • describe_table
    - Table structure

Usage:

> Show me users who signed up this month

Executing: SELECT * FROM users WHERE created_at >= '2026-01-01'

Results (23 rows):
id | email              | plan    | created_at
---+--------------------+---------+------------
 1 | alice@example.com  | pro     | 2026-01-02
 2 | bob@example.com    | free    | 2026-01-03
...

Filesystem

claude mcp add docs-fs npx -y @modelcontextprotocol/server-filesystem /path/to/docs

Access files outside your current working directory.

Memory (Persistent Storage)

claude mcp add memory npx -y @modelcontextprotocol/server-memory

Store and retrieve data across sessions:

> Remember that the API key rotates every 30 days

Stored: api_key_rotation -> "30 days"

# Later session:
> When does the API key rotate?

Retrieved: The API key rotates every 30 days.

Configuring MCP in Settings

User Settings

Global MCP configuration in

~/.claude/settings.json
:

{
  "mcpServers": {
    "github": {
      "transport": "http",
      "url": "https://api.github.com/mcp/"
    },
    "filesystem": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-filesystem", "/home/user/docs"],
      "env": {}
    },
    "custom-db": {
      "command": "python",
      "args": ["/path/to/db_server.py"],
      "env": {
        "DATABASE_URL": "postgresql://localhost/mydb"
      }
    }
  }
}

Project Settings

Project-specific MCP in

.claude/settings.json
:

{
  "mcpServers": {
    "project-db": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-postgres"],
      "env": {
        "DATABASE_URL": "${DATABASE_URL}"
      }
    }
  }
}

Use

${VAR}
to reference environment variables.


MCP Permissions

Control which MCP tools Claude can use:

# Allow all tools from a server
claude config add permissions.allow "mcp__github__*"

# Allow specific tools
claude config add permissions.allow "mcp__github__get_issue"
claude config add permissions.allow "mcp__github__create_issue"

# Deny destructive operations
claude config add permissions.deny "mcp__github__delete_repo"
claude config add permissions.deny "mcp__postgres__query" # block all DB queries

See Claude Code Permissions: Deny, Allow & Ask Modes Explained.


Building Custom MCP Servers

When existing servers don't fit your needs, build your own.

Server Template (TypeScript)

// 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 tools
server.setRequestHandler("tools/list", async () => ({
  tools: [
    {
      name: "get_weather",
      description: "Get weather for a city",
      inputSchema: {
        type: "object",
        properties: {
          city: { type: "string", description: "City name" }
        },
        required: ["city"]
      }
    }
  ]
}));

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

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

Server Template (Python)

# server.py
import json
import sys
from mcp.server import Server, stdio_transport

server = Server("my-python-server")

@server.list_tools()
async def list_tools():
    return [
        {
            "name": "analyze_logs",
            "description": "Analyze application logs",
            "inputSchema": {
                "type": "object",
                "properties": {
                    "path": {"type": "string", "description": "Log file path"},
                    "pattern": {"type": "string", "description": "Search pattern"}
                },
                "required": ["path"]
            }
        }
    ]

@server.call_tool()
async def call_tool(name: str, arguments: dict):
    if name == "analyze_logs":
        result = analyze_logs(arguments["path"], arguments.get("pattern"))
        return {"content": [{"type": "text", "text": json.dumps(result)}]}
    
    raise ValueError(f"Unknown tool: {name}")

if __name__ == "__main__":
    stdio_transport.run(server)

Register Your Server

claude mcp add my-server node /path/to/server.js
# or
claude mcp add my-server python /path/to/server.py

MCP Server Registry

Find community-built servers at the MCP Registry:

Official Servers:

  • @modelcontextprotocol/server-filesystem
  • @modelcontextprotocol/server-postgres
  • @modelcontextprotocol/server-sqlite
  • @modelcontextprotocol/server-memory
  • @modelcontextprotocol/server-fetch

Community Servers:

  • Slack integration
  • Jira integration
  • AWS services
  • Docker management
  • Kubernetes operations

Install from npm:

claude mcp add slack npx -y mcp-server-slack

Authentication

OAuth Flow (HTTP Servers)

HTTP servers typically use OAuth:

  1. Add the server:

    claude mcp add github --transport http https://api.github.com/mcp/
    
  2. Claude Code opens browser for authentication

  3. After authorizing, tokens are stored securely

  4. Re-authenticate if needed:

    > /mcp
    Select server > [o] Re-authenticate
    

API Keys (Stdio Servers)

Pass API keys via environment:

claude mcp add weather -e WEATHER_API_KEY=abc123 npx weather-mcp-server

Or in settings:

{
  "mcpServers": {
    "weather": {
      "command": "npx",
      "args": ["weather-mcp-server"],
      "env": {
        "WEATHER_API_KEY": "${WEATHER_API_KEY}"
      }
    }
  }
}

Set the environment variable:

export WEATHER_API_KEY=abc123

Debugging MCP

Check Server Status

claude mcp list

Shows connection status for each server.

View Server Logs

claude --verbose

Shows MCP communications:

[MCP] Connecting to github...
[MCP] github: authenticated
[MCP] Calling tool: get_issue(number=432)
[MCP] Response received (245 bytes)

Test Server Locally

# Test stdio server directly
echo '{"method":"tools/list"}' | node /path/to/server.js

Common Issues

Server won't connect:

  • Check the command path is correct
  • Verify dependencies are installed
  • Check environment variables

Authentication expired:

  • Use
    /mcp
    > Re-authenticate
  • Or remove and re-add the server

Tool calls failing:

  • Check server logs for errors
  • Verify input schema matches
  • Check API rate limits

MCP in Practice

Workflow: Automated Bug Fixing

Combine Sentry + GitHub + your codebase:

> Find the most critical Sentry error and create a fix

[Querying Sentry...]
Found: TypeError in src/components/UserList.tsx:45
"Cannot read property 'map' of undefined"

[Analyzing code...]
Issue: `users` can be null when API fails

[Creating fix...]
Added null check and loading state

[Creating GitHub issue...]
Created #234: "Fix UserList crash on API failure"

[Creating PR...]
Created PR #235 with the fix

Workflow: Database-Aware Development

> Add a "last_login" field to the users table

[Querying schema via MCP...]
Current users table: id, email, name, created_at

[Generating migration...]
Created: migrations/20260112_add_last_login.sql

[Updating models...]
Modified: src/models/User.ts
Modified: src/types/user.ts

[Updating tests...]
Modified: tests/user.test.ts

Ready to run: npm run migrate

Workflow: Cross-Platform Sync

> Update all platforms with the new release

[Checking GitHub...]
Latest tag: v2.3.0

[Updating Linear...]
Marked related issues as completed

[Posting to Slack...]
Sent release announcement to #releases

[Updating Notion...]
Added release notes to documentation

Release v2.3.0 synchronized across all platforms.

MCP Security Best Practices

1. Principle of Least Privilege

Only enable servers you need:

# Good: specific integration
claude mcp add github --transport http ...

# Avoid: exposing entire filesystem
claude mcp add fs npx server-filesystem /

2. Use Environment Variables for Secrets

Never hardcode credentials:

{
  "mcpServers": {
    "db": {
      "env": {
        "DATABASE_URL": "${DATABASE_URL}"  // Good
        // "DATABASE_URL": "postgres://user:pass@..." // Bad
      }
    }
  }
}

3. Restrict Tool Permissions

Block destructive operations:

claude config add permissions.deny "mcp__github__delete_*"
claude config add permissions.deny "mcp__postgres__query" # if read-only needed

4. Audit MCP Usage

Review what Claude accesses:

claude --verbose 2>&1 | grep "\[MCP\]"

See Claude Code Best Practices: Security, Performance & Teams.


Key Takeaways

  1. MCP extends Claude's reach: Connect to any external service or data source.

  2. Two transport types: HTTP for SaaS with OAuth, stdio for local scripts.

  3. Easy to add:

    claude mcp add
    handles configuration.

  4. Build your own: TypeScript and Python SDKs make custom servers simple.

  5. Security matters: Use permissions to control which tools Claude can access.


Master API Interactions

MCP opens the door to API integrations. Learn to work with APIs effectively in your prompts.

In our Module 5 — Working with APIs, you'll learn:

  • Prompting for API interactions
  • Handling authentication in prompts
  • Error handling patterns
  • Building API-powered workflows

Explore Module 5: Working with APIs

GO DEEPER

Module 5 — RAG (Retrieval-Augmented Generation)

Ground AI responses in your own documents and data sources.