MCP Fundamentals
Core architecture of the Model Context Protocol (MCP) — the open protocol from Anthropic that connects AI assistants to external tools and data sources. Covers JSON-RPC transport, capabilities negotiation, server lifecycle, the client-server interaction model, and how tools, resources, and prompts fit together.
You are an AI assistant helping developers understand and build on the Model Context Protocol. MCP is the open standard that lets AI clients (Claude Desktop, Cursor, Claude Code, custom agents) connect to external servers that expose tools, resources, and prompts. Your role is to explain the architecture clearly and guide correct implementations.
## Key Points
- **Host**: The application the user interacts with (Claude Desktop, an IDE, a custom app). The host creates and manages client instances.
- **Client**: A protocol client inside the host that maintains a 1:1 connection with a single MCP server. The client handles capability negotiation and message routing.
- **Server**: A lightweight program that exposes tools, resources, and/or prompts over the MCP protocol. Servers run locally or remotely.
1. **Initialization**: The client sends an `initialize` request with its protocol version and capabilities.
2. **Server Response**: The server responds with its own protocol version, capabilities, and server info.
3. **Initialized Notification**: The client sends an `initialized` notification to confirm the handshake.
4. **Normal Operation**: Both sides can now send requests and notifications according to negotiated capabilities.
5. **Shutdown**: Either side can terminate the connection cleanly.
- `tools` — the server exposes callable tools. `listChanged` means it can notify when tools change.
- `resources` — the server exposes readable resources. `subscribe` means clients can watch for changes.
- `prompts` — the server exposes prompt templates. `listChanged` means it can notify when prompts change.
- `logging` — the server can emit log messages to the client.
## Quick Example
```json
{ "jsonrpc": "2.0", "id": 1, "method": "tools/list", "params": {} }
```
```json
{ "jsonrpc": "2.0", "id": 1, "result": { "tools": [...] } }
```skilldb get mcp-server-skills/MCP FundamentalsFull skill: 226 linesMCP Fundamentals
You are an AI assistant helping developers understand and build on the Model Context Protocol. MCP is the open standard that lets AI clients (Claude Desktop, Cursor, Claude Code, custom agents) connect to external servers that expose tools, resources, and prompts. Your role is to explain the architecture clearly and guide correct implementations.
Philosophy
MCP follows a client-server architecture inspired by the Language Server Protocol. The protocol is transport-agnostic — the same JSON-RPC messages work over stdio, HTTP with Server-Sent Events, or streamable HTTP. Servers should be small, focused, and composable. A single server does one thing well (database access, file operations, API integration) rather than becoming a monolith. Clients discover server capabilities at connection time and adapt accordingly.
Architecture Overview
The Three Roles
- Host: The application the user interacts with (Claude Desktop, an IDE, a custom app). The host creates and manages client instances.
- Client: A protocol client inside the host that maintains a 1:1 connection with a single MCP server. The client handles capability negotiation and message routing.
- Server: A lightweight program that exposes tools, resources, and/or prompts over the MCP protocol. Servers run locally or remotely.
Connection Lifecycle
The connection follows a strict sequence:
- Initialization: The client sends an
initializerequest with its protocol version and capabilities. - Server Response: The server responds with its own protocol version, capabilities, and server info.
- Initialized Notification: The client sends an
initializednotification to confirm the handshake. - Normal Operation: Both sides can now send requests and notifications according to negotiated capabilities.
- Shutdown: Either side can terminate the connection cleanly.
// Client sends initialize request
{
"jsonrpc": "2.0",
"id": 1,
"method": "initialize",
"params": {
"protocolVersion": "2025-03-26",
"capabilities": {
"roots": { "listChanged": true }
},
"clientInfo": {
"name": "my-ai-app",
"version": "1.0.0"
}
}
}
// Server responds
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"protocolVersion": "2025-03-26",
"capabilities": {
"tools": { "listChanged": true },
"resources": { "subscribe": true },
"prompts": { "listChanged": true }
},
"serverInfo": {
"name": "my-mcp-server",
"version": "1.0.0"
}
}
}
Capabilities Negotiation
Capabilities declare what each side supports. A server only needs to declare capabilities it actually implements:
tools— the server exposes callable tools.listChangedmeans it can notify when tools change.resources— the server exposes readable resources.subscribemeans clients can watch for changes.prompts— the server exposes prompt templates.listChangedmeans it can notify when prompts change.logging— the server can emit log messages to the client.
Clients declare their own capabilities:
roots— the client can provide filesystem roots the server should operate within.sampling— the client supports LLM sampling requests from the server.
JSON-RPC 2.0 Transport
All MCP communication uses JSON-RPC 2.0. There are three message types:
Requests expect a response:
{ "jsonrpc": "2.0", "id": 1, "method": "tools/list", "params": {} }
Responses answer a request:
{ "jsonrpc": "2.0", "id": 1, "result": { "tools": [...] } }
Notifications are fire-and-forget (no id field):
{ "jsonrpc": "2.0", "method": "notifications/tools/list_changed" }
Transport Mechanisms
stdio (Local Servers)
The most common transport for local MCP servers. The host spawns the server as a child process. Messages flow over stdin/stdout. Each message is a single line of JSON terminated by a newline.
- Ideal for local tools (file access, git operations, database queries).
- No network configuration needed.
- The host manages the server process lifecycle.
SSE (Server-Sent Events) — Legacy
The older remote transport. The client connects to an SSE endpoint to receive server messages and POSTs requests to a separate endpoint. This transport is being superseded by streamable HTTP but remains supported.
Streamable HTTP (Recommended Remote Transport)
The modern remote transport. A single HTTP endpoint handles both directions:
- Client sends requests via HTTP POST.
- Server can respond with a single JSON response or upgrade to SSE for streaming.
- Supports session management via
Mcp-Session-Idheader. - Supports resumability for long-running operations.
Techniques
Structuring a Minimal Server
Every MCP server must handle these core methods:
initialize— respond with capabilities and server info.ping— respond with an empty result (keepalive).
And optionally:
tools/list— return the list of available tools.tools/call— execute a tool and return results.resources/list— return available resources.resources/read— return resource contents.prompts/list— return available prompts.prompts/get— return a specific prompt with arguments filled in.
Keeping Servers Focused
Each MCP server should have a clear, bounded purpose:
Good: "postgres-server" — queries a specific PostgreSQL database
Good: "github-server" — interacts with GitHub API
Good: "filesystem-server" — reads and writes files in allowed directories
Bad: "everything-server" — database + files + APIs + email in one server
Clients can connect to multiple servers simultaneously. Composition happens at the client level, not inside a single server.
Error Handling at the Protocol Level
MCP uses JSON-RPC error codes:
{
"jsonrpc": "2.0",
"id": 1,
"error": {
"code": -32602,
"message": "Invalid params: missing required field 'query'"
}
}
Standard error codes:
-32700— Parse error (invalid JSON)-32600— Invalid request-32601— Method not found-32602— Invalid params-32603— Internal error
Tool execution errors should NOT use JSON-RPC errors. Instead, return a successful response with isError: true in the tool result. This distinguishes protocol errors from tool-level failures.
Progress and Logging
Servers can report progress on long-running operations:
{
"jsonrpc": "2.0",
"method": "notifications/progress",
"params": {
"progressToken": "abc-123",
"progress": 50,
"total": 100
}
}
Servers can emit log messages at various levels:
{
"jsonrpc": "2.0",
"method": "notifications/message",
"params": {
"level": "info",
"logger": "database",
"data": "Connected to PostgreSQL"
}
}
Anti-Patterns
- Building monolith servers — one server that does everything. Keep servers small and focused.
- Returning tool errors as JSON-RPC errors — use
isError: truein the tool result content instead. - Ignoring capabilities negotiation — always check what the client supports before using features like sampling or roots.
- Blocking the event loop during tool execution — long-running tools should report progress and remain cancellable.
- Hardcoding transport assumptions — write server logic that works regardless of whether the transport is stdio or HTTP.
- Skipping input validation — always validate tool inputs against their schemas before execution.
Best Practices
- Declare the minimum capabilities your server needs. Do not declare
resourcesif you only expose tools. - Use semantic versioning for your server and track protocol version compatibility.
- Implement
pinghandling so clients can verify the server is alive. - Log at appropriate levels — use
debugfor development,infofor normal operation,errorfor failures. - Test with the MCP Inspector during development to verify protocol compliance.
- Document each tool, resource, and prompt with clear descriptions — these are surfaced to AI models for decision-making.
Install this skill directly: skilldb add mcp-server-skills
Related Skills
MCP Auth and Security
Securing MCP servers with authentication, authorization, and defensive practices. Covers OAuth 2.1 integration for remote servers, API key management through environment variables, input validation and sanitization, rate limiting, sandboxing tool execution, path traversal prevention, and the principle of least privilege for tool design.
MCP Deployment
Deploying MCP servers across different environments and transports. Covers local deployment via stdio, remote deployment with SSE and streamable HTTP, Docker containerization, cloud deployment on AWS/GCP/Vercel, npx and uvx distribution for zero-install usage, configuration management, and production hardening.
MCP Patterns
Common architectural patterns for MCP servers — database servers, API wrappers, file system servers, multi-tool orchestration, caching strategies, error recovery, and composition patterns. Practical blueprints for building production-quality MCP servers that handle real-world complexity.
MCP Prompts
Defining prompt templates in MCP servers that AI clients can discover and invoke. Covers prompt definitions with arguments, dynamic prompt generation, multi-turn prompt structures, embedding resources in prompts, prompt discovery, and patterns for building reusable prompt libraries.
MCP Python Server
Building MCP servers in Python using the official mcp SDK and the FastMCP high-level pattern. Covers project setup with uv, defining tools with type hints, async handlers, resources, prompts, stdio and SSE transports, context objects, and deployment strategies including uvx distribution.
MCP Resources
Exposing data and content to AI clients through MCP resources. Covers resource URIs, listing and reading resources, resource templates with URI patterns, MIME types, subscriptions for real-time updates, and patterns for exposing files, database records, and API data as browsable resources.