---
title: "MCP: Protocol Fundamentals"
slug: "mcp-protocol"
category: "ai-agents"
tags: ["mcp", "ai-agents", "protocol", "json-rpc", "tools", "resources", "prompts"]
status: "stable"
last_updated: 2026-08-14
summary: "How the Model Context Protocol is framed over JSON-RPC 2.0, what capabilities a server can advertise, and how client and server roles divide responsibility."
related: ["[[ai-agents/mcp-servers]]", "[[ai-agents/mcp-tool-design]]", "[[ai-agents/mcp-resources]]", "[[ai-agents/mcp-transports]]", "[[ai-agents/mcp-elicitation]]", "[[ai-agents/mcp-security]]", "[[ai-agents/mcp-logging]]", "[[ai-agents/claude-code-mcp]]"]
---

## Overview

The Model Context Protocol (MCP) is a JSON-RPC 2.0 framing layer that lets an LLM client call external integrations through a stable, typed interface. The spec is published at [modelcontextprotocol.io](https://modelcontextprotocol.io); the current revision is 2026-07-28. Every MCP interaction is a JSON-RPC request-response pair or notification. The protocol defines three capability primitives: tools, resources, and prompts. Understanding the framing is the prerequisite for designing servers that work reliably across clients such as Claude Code and Claude Desktop.

## Speak JSON-RPC 2.0; every message has an id, method, and params

MCP is not a custom wire format. It reuses JSON-RPC 2.0 exactly: every request carries an `id`, a `method` string, and a `params` object. Every response carries the same `id` and either a `result` or an `error` object. Notifications omit `id` because they expect no response.

```json
{ "jsonrpc": "2.0", "id": 1, "method": "tools/call",
  "params": { "name": "search_issues", "arguments": { "q": "is:open label:bug" } } }

{ "jsonrpc": "2.0", "id": 1, "result": { "content": [{ "type": "text", "text": "..." }] } }
```

Reusing JSON-RPC means any JSON-RPC 2.0 library handles framing. The MCP-specific logic is entirely in the method names and payload shapes.

## Capabilities travel per-request, not through a session handshake

As of the 2026-07-28 spec, MCP is stateless at the protocol core: there is no connection-scoped `initialize`/`initialized` handshake to negotiate capabilities once. Every request carries its own protocol version and capabilities in `_meta.io.modelcontextprotocol/*` fields, so any request can land on any server instance behind a load balancer without shared session storage. Earlier revisions (2025-06-18 and before) used the connection-scoped handshake; clients and servers that must interoperate with those revisions detect the counterpart's era and fall back accordingly.

Server capabilities include `tools`, `resources`, `prompts`, and `logging`. Client capabilities include `roots` and `elicitation` (see [[ai-agents/mcp-elicitation]]). A server that declares `resources` but not `tools` will receive resource fetch requests but no tool calls. A server only sends an elicitation request when the client advertised `elicitation` on that request.

Design servers to declare exactly the capabilities they implement. Advertising capabilities the server cannot fulfil causes the client to send methods that return errors.

## Tools are callable actions; use them for writes and side effects

A tool is a named function with a JSON Schema input definition. The client calls `tools/list` to discover what tools are available and `tools/call` to invoke one. Tools are the correct primitive for anything that performs an action: creating a record, running a query, sending a message. See [[ai-agents/mcp-tool-design]] for schema design rules.

The model reads every tool's `description` field before deciding whether to call it. Tool descriptions are context budget. Keep them accurate and concise.

## Resources are addressable data; use them for read-only context

A resource is a URI-addressed piece of content the client can fetch without triggering side effects. The client calls `resources/list` to enumerate available resources and `resources/read` to fetch one by URI. Resources support subscriptions: the server can push `notifications/resources/updated` when a resource changes.

```text
github://org/repo/issues/401
notion://workspace/page/abc123
```

Resources keep the tool list short and give the model a stable reference scheme. See [[ai-agents/mcp-resources]] for the resource design pattern.

## Prompts are reusable templates the user can invoke by name

A prompt is a named message template with optional arguments. The client calls `prompts/list` to discover them and `prompts/get` to render one with arguments. Prompts are useful for recurring patterns: a code-review template, a release-notes skeleton, a triage prompt. Clients like Claude Desktop surface prompts as slash commands.

Prompts are lower-friction than tools for operations that are primarily compositional rather than computational. If an operation is mostly "fill in a template and present to the user," a prompt is correct. If it calls an API or modifies state, a tool is correct.

## Client and server roles are asymmetric; clients drive, servers respond

The client (Claude Code, Claude Desktop) initiates all requests. The server advertises capabilities and responds. The exception is server-sent notifications (logging, resource updates, progress), which flow server-to-client without a preceding client request. The server never initiates a tool call or resource read.

This asymmetry matters for [[ai-agents/mcp-security]]: the attack surface is on the server side because the server holds credentials and executes code. The client side must validate that it is talking to the intended server, especially over [[ai-agents/mcp-transports|HTTP transports]].

## Related

- [[ai-agents/mcp-servers]]
- [[ai-agents/mcp-tool-design]]
- [[ai-agents/mcp-resources]]
- [[ai-agents/mcp-transports]]
- [[ai-agents/mcp-security]]
- [[ai-agents/mcp-logging]]
- [[ai-agents/claude-code-mcp]]
