AI Agents

What Is Model Context Protocol (MCP)? Complete Guide 2026

Model Context Protocol (MCP) explained - what it is, how it works, how MCP servers expose tools and resources, and why it replaces custom LLM integrations.

Every time you want to connect a large language model to an external tool - a database, a file system, a REST API, a code executor - you write a custom integration from scratch. You decide on the input format, parse the output, handle errors, and format everything for the model. Then you do it again for the next tool. Model Context Protocol (MCP) was designed to make this the last time anyone has to solve that problem. It defines a standard protocol so any AI client can connect to any tool server using the same interface, the same message format, and the same primitives - regardless of what the tool does or which model is running the agent.

Model Context Protocol (MCP)
Model Context Protocol (MCP) is a JSON-RPC 2.0 open protocol that standardises how AI applications connect to external tools, data sources, and services - defining a client-server architecture where an AI client (such as Claude Code or a custom agent) communicates with MCP servers that expose tools (callable actions), resources (readable content), and prompts (reusable instructions) through a transport-layer connection.

What Model Context Protocol is - the direct answer

MCP is a protocol specification, not a library or a framework. It defines three things: the message format (JSON-RPC 2.0 - request/response envelopes with method names and parameters), the transport options (stdio for local process communication, HTTP/SSE or Streamable HTTP for remote servers), and the three primitives each server can expose - tools, resources, and prompts. Any client that implements the MCP spec can connect to any server that implements it, without either side knowing implementation details about the other.

The analogy that makes this concrete: MCP is to AI tool integrations what USB is to hardware peripherals. Before USB, every device needed a custom port and a custom driver. USB defined a standard connector and protocol, and suddenly any device could plug into any computer. MCP does the same for AI agent integrations.

How MCP works - the request/response flow

An MCP session has two roles: the client (your AI agent or Claude Code) and the server (the process that exposes tools). The flow on every connection:

  1. Initialise - the client sends an initialize request with its protocol version; the server responds with its capabilities
  2. Discover - the client calls tools/list, resources/list, and prompts/list to learn what the server exposes
  3. Use - when the agent decides to use a tool, the client sends a tools/call request with the tool name and arguments; the server executes and returns the result
  4. Repeat - the result is passed back to the LLM as context; the loop continues

Here is a minimal MCP server using @modelcontextprotocol/sdk v1.0+ that exposes one tool:

import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';

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

// Register a tool
server.tool(
  'get_weather',
  'Get current weather for a city. Returns temperature and conditions.',
  {
    city: {
      type: 'string',
      description: 'City name, e.g. "Paris" or "Tokyo".',
    },
    units: {
      type: 'string',
      enum: ['celsius', 'fahrenheit'],
      description: 'Temperature unit. Defaults to celsius.',
    },
  },
  async ({ city, units = 'celsius' }) => {
    // Your implementation - call a weather API, query a database, anything
    const weather = await fetchWeatherData(city, units);
    return {
      content: [{
        type: 'text',
        text: JSON.stringify(weather),
      }],
    };
  }
);

// Connect via stdio - Claude Code spawns this as a child process
const transport = new StdioServerTransport();
await server.connect(transport);

Claude Code reads the tool list on startup, and from that point the agent can call get_weather as naturally as any built-in tool - no custom integration code in the agent, no model-specific formatting, no manual error handling at the agent layer.

The three primitives MCP servers expose

Every MCP server can expose up to three types of content. Understanding the distinction determines which one to reach for:

  • Tools - callable actions that the agent invokes. The agent sends arguments; the server does something and returns a result. Examples: execute a SQL query, send a Slack message, write a file, call an API. Tools are the most common MCP primitive.
  • Resources - URI-addressable read-only content the agent can embed in its context. Examples: a database schema, an API specification, a project's README. The agent reads the resource; the server does not perform an action.
  • Prompts - parameterised instruction templates that produce pre-constructed conversation messages. In Claude Code, these appear as slash commands the user can invoke with parameters.

MCP vs custom tool integrations - head to head

  • Custom integration - you write the tool definition, the executor, the error handler, and the output formatter specifically for your agent. Works for one agent. When you add a second agent or use a different model, you rewrite everything.
  • MCP server - you write the server once. Any MCP-compatible client (Claude Code, a custom agent, a future model you haven't chosen yet) can use it without changes. The protocol handles discovery, error propagation, and result formatting.

The trade-off: custom integrations are simpler for one-off, single-agent needs. MCP servers add a protocol layer that is worth the overhead when: multiple agents or users need the same tools, you want Claude Code's built-in MCP support, or you are building shared infrastructure for a team.

How to register an MCP server in Claude Code

Add the server to your project's .claude/mcp.json or to ~/.claude/mcp.json for user-level access:

{
  "mcpServers": {
    "my-first-server": {
      "command": "node",
      "args": ["./mcp-servers/weather.js"],
      "env": {
        "WEATHER_API_KEY": "${WEATHER_API_KEY}"
      }
    }
  }
}

Claude Code spawns the server as a child process on startup, reads its tool list, and makes those tools available to every agent in the session - including any subagents that inherit the session's tool access. For remote HTTP servers instead of local stdio processes, replace command/args with a url field pointing to your server's endpoint.

When to build an MCP server vs when not to

Build an MCP server when:

  • Multiple agents, users, or sessions need the same tools
  • You want to use Claude Code's built-in MCP client without writing a custom agent
  • Your tools need to be model-agnostic (usable with different LLMs over time)
  • You are building internal tooling infrastructure for a development team

Do not build an MCP server when:

  • You need one tool for one specific agent in one specific codebase - just write the tool inline
  • Your tool is a simple API call with no reuse requirements - the protocol overhead is not worth it
  • Latency is critical and sub-millisecond tool execution matters - the JSON-RPC round-trip adds 1-5ms per call

For a step-by-step tutorial building a complete MCP server with authentication and multiple tools, see building a custom MCP server. For adding OAuth and API key validation to an MCP server you plan to share across a team, see MCP server authentication.