Magic Tools
Claude GuidesBy CooconApril 13, 2026708 views2 min read

Claude Code MCP: Connect External Tools and Data Sources

What Is MCP

Model Context Protocol (MCP) is an open protocol by Anthropic that defines a standard communication layer between AI models and external tools. Through MCP, Claude Code can connect to databases, call APIs, and interact with third-party services, extending its capabilities far beyond code editing.

MCP uses a client-server architecture: Claude Code acts as the MCP client, communicating with MCP servers via the standard protocol. Each MCP server exposes a set of tools that Claude can invoke on demand.

Configuring MCP Servers

Add MCP server configurations to .claude/settings.json:

{
  "mcpServers": {
    "github": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-github"],
      "env": {
        "GITHUB_TOKEN": "ghp_your_token_here"
      }
    },
    "filesystem": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-filesystem", "/path/to/allowed/dir"]
    },
    "sqlite": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-sqlite", "--db-path", "./data.db"]
    }
  }
}

Restart Claude Code after adding configurations, and the external tools become available in your conversations.

Server Capabilities Package
GitHub Manage issues, PRs, repos @modelcontextprotocol/server-github
Filesystem Secure file system access @modelcontextprotocol/server-filesystem
SQLite Query SQLite databases @modelcontextprotocol/server-sqlite
PostgreSQL Query PostgreSQL databases @modelcontextprotocol/server-postgres
Slack Send messages, manage channels @modelcontextprotocol/server-slack
Memory Persistent cross-session memory @modelcontextprotocol/server-memory

Find more community-built MCP servers in the MCP Servers repository.

Writing a Simple MCP Server

Build a custom MCP server in TypeScript:

import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";

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

server.tool(
  "get_weather",
  "Get weather information for a city",
  { city: z.string().describe("City name") },
  async ({ city }) => {
    const data = await fetch(`https://api.weather.com/${city}`);
    return { content: [{ type: "text", text: JSON.stringify(await data.json()) }] };
  }
);

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

Security Considerations

  • Principle of least privilege: Only grant MCP servers the permissions they actually need
  • Protect secrets: Pass API keys via the env field; never hardcode them in configuration
  • Network isolation: For MCP servers accessing internal services, ensure proper network access controls
  • Audit third-party servers: Review source code of community MCP servers before using them

FAQ

Do MCP servers need to run continuously?

No. Claude Code automatically starts configured MCP server processes on launch and shuts them down when the session ends. You don't need to manage server lifecycles manually.

Can I use multiple MCP servers in one project?

Yes. Configure as many servers as needed in mcpServers. Claude automatically selects the appropriate tool for each task. Tools from all servers are merged into Claude's available tool list.

What programming languages can I use to write MCP servers?

The official MCP SDK is available in TypeScript and Python. Community implementations exist for Rust, Go, Java, and more. Any language can be used as long as it follows the MCP protocol specification.

Related Articles

Blocking rm -rf in Claude Code: A Deny Rule Stopped 14 Deletes in Two Weeks, 7 Other Spellings Still Get Through, and a Hook That Closes the Gap

To keep Claude Code from deleting things by accident, I added a deny rule, Bash(rm -rf *), to my global settings. Across my sessions from October 7 to 21 it blocked 14 deletes. After each denial the model picked a new directory name 8 times and dropped the delete 6 times. It never tried another spelling. Then I replayed 22 delete commands verbatim against Claude Code 2.1.285 through a stub. rm -fr, rm -r -f, rm -Rf and rm -r deleted the directory in manual, auto and bypass mode alike. /bin/rm, find -delete and bash -c deleted it in manual and bypass mode. In auto mode, rm -fr inside the working directory skips the classifier because it 'would be allowed in acceptEdits mode'. A second, built-in dangerous-rm check fires on targets like $D/*, even in bypass mode, but loses track of a variable assignment when a heredoc comes earlier in the same command. The post ends with a PreToolUse hook that blocks every recursive spelling in all three modes and tells the model what to do instead.

claude-codehooks+5
pitfallsOct 21, 20268 min
208

Claude Code Auto Mode with DeepSeek, GLM or Kimi: What Each "temporarily unavailable" Reason Means and When Retrying Is Pointless (Fault-Injection Test)

On a third-party model, Claude Code auto mode sends one extra classifier request per side-effecting action, from your session model to the same backend: a 132,470-character system prompt, about 29.7K input tokens per check. When it fails, you see "xxx is temporarily unavailable, so auto mode cannot determine the safety of Bash". We injected faults and recorded each message: 500 (server error), 429 (rate-limited), 529 (overloaded) and connection resets (connection failed) are retried 5 times; no reply in 60 s gives (timed out). **No parentheses means a 4xx rejection: tried once, and retrying never helps.** A reply with no verdict gives "could not evaluate"; three in a row bring back manual approval. CLAUDE_CODE_AUTO_MODE_MODEL has no effect. Claude Code 2.1.285, real DeepSeek v4-pro and MiMo v2.5 backends.

claude-codedeepseek+7
pitfallsOct 11, 202612 min
422

Claude Code "Prompt is too long" vs "maximum context length": Why Auto-Compact Works for One and Not the Other (Tested)

Claude Code decides a request was too long by matching the error text. If the backend says prompt is too long or input is too long for requested model, it auto-compacts the conversation and retries — invisible to you. DeepSeek and OpenAI-style gateways say This model's maximum context length is …, which it doesn't recognize: you get API Error: 400 on every turn. Manual /compact works; the better fix is to declare the real window with CLAUDE_CODE_MAX_CONTEXT_TOKENS (non-claude- model IDs) or CLAUDE_CODE_AUTO_COMPACT_WINDOW (claude- IDs) so it compacts before hitting the limit. Tested on Claude Code 2.1.285 against a local stub.

claude-codedeepseek+6
pitfallsOct 5, 20267 min
437

Claude Code Stuck on a Spinner With No Response: It Waits 6 Minutes per Attempt, and 10 Retries Can Hang It for Over an Hour (Tested)

When Claude Code spins without output or sits at Retrying in 0s, the backend is usually not sending anything. Tested on 2.1.285 (API key + ANTHROPIC_BASE_URL): with no response headers it waits 6 minutes (360 s) per attempt before timing out — setting API_TIMEOUT_MS to 600000 or 900000 doesn't change that; only lower values work. With the default 10 retries it can hang for over an hour. A gateway that buffers the reply until generation finishes will never deliver a reply that takes over 6 minutes. Press Esc to interrupt. All tested against a local stub.

claude-codetroubleshooting+5
pitfallsOct 5, 20269 min
377

Published by Magic Tools