Skip to main content
Claude Code Tutorial: From First Command to Custom Workflows

MCP Fundamentals: Architecture and Tool Invocation

The Model Context Protocol connects Claude Code to external tools. Learn the client-server model, how tools are discovered and named, and how results flow back into the agent loop.

Intermediate16 minBy ToolDix Editorial

Learning objectives

  • Understand MCP as a client-server protocol for tool integration
  • Recognize how Claude Code discovers MCP tools and uses `mcp__server__action` naming
  • Trace the flow of a tool call from Claude's decision through MCP to result
  • Distinguish stdio (local) vs. HTTP (remote) MCP transport modes

ToolDix original visual

Claude Code Tutorial practice loop
1

Frame

Name the outcome and constraints.

2

Build

Try one bounded workflow.

3

Review

Keep evidence, revise, and share.

Claude Code has built-in tools (Read, Edit, Bash, etc.), but the Model Context Protocol (MCP) lets you plug in external tools—GitHub APIs, Slack, databases, custom services—without modifying Claude Code itself. MCP is a client-server standard: Claude Code is the client, MCP servers provide the tools.

ToolDix original diagram
MCP: connecting tools via servers
Claude Code
Asks for tools via MCP
MCP Servers
Playwright (browser)
GitHub (git ops)
Slack (messaging)
Your custom APIs
Tools appear as: mcp__server_name__action

What MCP is and why it exists

Claude Code includes tools for filesystem and shell operations. But if you want Claude to:

  • Search a GitHub issue tracker and create PRs
  • Query a Postgres database
  • Control a web browser (Playwright)
  • Send Slack messages
  • Call your custom internal APIs

...you don't add these tools to Claude Code. Instead, you run an MCP server that exposes them, and Claude Code connects to it via MCP.

MCP benefits:

  • Decoupling: Tools live in separate processes, not in Claude Code.
  • Reusability: MCP servers work with Claude.ai, the Claude API, and other clients.
  • Security: Each server has its own sandbox and authentication.
  • Flexibility: Build servers in any language; Claude Code doesn't care.

The client-server architecture

When you start Claude Code with MCP servers configured:

Claude Code (client)
  ↓
  Establishes connection to MCP servers
  ├→ Server A (stdio): spawns process, connects via stdin/stdout
  ├→ Server B (HTTP): POST to URL
  └→ Server C (SSE): Server-Sent Events stream
  ↓
Claude Code asks each server: "What tools do you have?"
  ↓
Servers respond with tool list + schemas
  ↓
Claude Code merges all tools into its context
  ↓
In each turn, Claude Code can call any registered tool

The connection is established at session startup and stays open for the duration. If a server crashes or disconnects, Claude Code logs the error and disables that server's tools for the rest of the session.

How tools are discovered and named

When Claude Code connects to an MCP server, the server sends back a list of available tools, each with:

  • Name (string): The tool identifier (e.g., search_issues)
  • Description (string): What the tool does, when to use it
  • Input schema (JSON Schema): What arguments the tool accepts and their types
  • Output schema (optional): What the tool returns

Claude Code combines the server name and tool name into a single identifier:

mcp__<server_name>__<tool_name>

Example: If you add an MCP server named github with a tool called search_issues, Claude Code refers to it as:

mcp__github__search_issues

In Claude's output, you'll see:

Calling: mcp__github__search_issues with arguments:
  query: "authentication bug"
  repo: "my-org/my-repo"

This naming convention makes it clear which server and tool are being used, and allows permission rules and hooks to filter by server prefix.

Transport types: stdio vs. HTTP vs. SSE

MCP servers can communicate with Claude Code via three transports:

TransportTypeHow It WorksBest ForExample
StdioLocal processClaude Code spawns server process; communicates via stdin/stdout with JSON-RPC messagesLocal tools, browser automation, file accessnpx @playwright/mcp
HTTPRemote serverClaude Code POSTs tool calls and requests to server URL; server responds with JSONHosted services (GitHub, Sentry), APIs, cloud toolshttps://api.github.com/mcp
SSERemote serverClaude Code opens HTTP stream; server sends events. Less common than HTTP.Real-time data, channels, webhooksInternal streaming tools

Tool invocation flow: from decision to result

Here's the exact sequence when Claude Code calls an MCP tool:

Step 1: Claude decides to call a tool

After reading context and reasoning about the task, Claude decides: "I need to search GitHub for issues related to 'auth'."

Claude Code generates a tool call in its internal format:

{
  "type": "tool_use",
  "id": "tool_abc123",
  "name": "mcp__github__search_issues",
  "input": {
    "query": "authentication",
    "repo": "my-org/my-repo",
    "state": "open"
  }
}

Step 2: Route to the correct MCP server

Claude Code parses the tool name: mcp__github__search_issues

  • Server: github
  • Tool: search_issues

Claude Code looks up the github server connection and routes the call there.

Step 3: Send tool call to server (format depends on transport)

For stdio servers:

Claude Code writes JSON-RPC to the server's stdin:

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "search_issues",
    "arguments": {
      "query": "authentication",
      "repo": "my-org/my-repo",
      "state": "open"
    }
  }
}

The server process reads this, executes search_issues, and writes JSON-RPC response to stdout.

For HTTP servers:

Claude Code POSTs to the server URL:

POST https://api.github.com/mcp
Content-Type: application/json
Authorization: Bearer <token>

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "search_issues",
    "arguments": { ... }
  }
}

Step 4: Server executes and returns result

The github MCP server (which wraps GitHub's REST API):

  1. Calls GitHub's /search/issues endpoint
  2. Parses the response
  3. Formats it as JSON-RPC and returns to Claude Code:
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "Found 3 open issues:\n1. Issue #451: \"Login fails with OAuth\"\n2. Issue #502: \"Session timeout too short\"\n3. Issue #688: \"LDAP integration broken\""
      }
    ]
  }
}

Step 5: Result flows back into agent loop

Claude Code receives the result, extracts the text, and adds it to its context:

Claude's context:
  ...
  [Tool call result from mcp__github__search_issues]
  Found 3 open issues:
  1. Issue #451: "Login fails with OAuth"
  2. Issue #502: "Session timeout too short"
  3. Issue #688: "LDAP integration broken"

Claude now has information it didn't have before—real data from GitHub, not training data.

Step 6: Claude reasons and acts

Claude observes the results and decides the next step: "The most critical issue is #451. Let me read its details and create a fix."

Claude calls another tool (mcp__github__get_issue_details or similar), which goes through steps 1-5 again.

Permission model for MCP tools

MCP tools go through the same permission system as built-in tools:

  • Read-only tools (search, list, query, describe): Run without asking
  • Write tools (create, update, delete): Require permission approval

You can also fine-tune with permission rules in .claude/settings.json:

{
  "permissions": {
    "allow": ["mcp__github__.*"],
    "deny": ["mcp__github__delete_repo"]
  }
}

This allows any GitHub tool except deletion, which always requires approval.

Discovery and connection at session start

When you start Claude Code with MCP servers configured (in .mcp.json or ~/.claude.json), here's what happens:

  1. Parse config: Claude Code reads server addresses and startup commands
  2. Connect: For stdio, spawn process; for HTTP, test URL reachability
  3. Discover tools: Send initialize and tools/list requests to each server
  4. Merge schemas: Combine tool schemas from all servers
  5. Inject into context: Tool descriptions and schemas become part of Claude's system prompt
  6. Ready: Claude can now choose from the full tool set in its first turn

If a server is unreachable or fails to respond, Claude Code shows an error and disables that server's tools. The session continues with remaining servers.

Error handling and retry

If a tool call fails (timeout, server crash, malformed response):

  1. Timeout (default 30 seconds): Claude Code cancels the call and reports timeout to Claude
  2. Server error: Server returns JSON-RPC error; Claude Code logs and reports to Claude
  3. Malformed response: Claude Code logs and treats as error; Claude observes and can retry

Claude Code does not automatically retry. Claude must decide to retry based on the error. This puts control in Claude's hands: if an API rate-limit error occurs, Claude might wait and retry; if a permissions error occurs, Claude might ask the user instead.

MCP configuration hierarchy

Servers can be registered at different scopes, resolved in order of precedence:

  1. Managed (enterprise policy file): Exclusive control, users can't override
  2. Project (.mcp.json in repo root): Shared with team, requires approval first time
  3. User (~/.claude.json): Personal across all projects, no approval needed
  4. Local (.claude/settings.local.json per-project override): Personal, not shared

If the same server is defined in multiple scopes, the highest-priority one wins. This lets teams ship default servers in .mcp.json while users can add personal ones in ~/.claude.json.

Common mistake

Assuming all tool calls are safe or all return results of the same shape. MCP tools are arbitrary—they might be slow (take >30s), might fail partway, might return human-unreadable data, or might have side effects. Always validate tool schemas before relying on them, and use permission rules to restrict dangerous MCP tools. Just like built-in Bash, an MCP tool that calls an API can do anything that API allows, so choose which servers to trust carefully.

Sources and license context

These references informed the lesson. ToolDix adds its own explanation, workflow, and practice rather than reproducing source material. Every link below leaves ToolDix and opens the publisher's own site in a new tab.

Keep going

Read these next on ToolDix.

Original lessons that build on what you just read.