Open Standards

Model Context Protocol (MCP)

Anthropic's open standard for connecting LLMs to data sources, local filesystems, developer tools, and databases. Build secure, modular MCP clients and servers in Python or TypeScript.

Core Concepts Protocol Specification Setup Usage Examples FAQ

Core MCP Concepts

Foundational components of the Model Context Protocol.

MCP Client & host

The host application (e.g. Claude Desktop, cursor, or your custom agent runner) that coordinates LLM reasoning. It queries servers for capabilities and feeds tool outputs back to LLMs.

MCP Server

A lightweight, decoupled process exposing resources (read-only documents), tools (write/execute functions), and prompt templates to client applications.

Sampling Protocol

Allows an MCP server to request LLM generations from the client. Enables agentic feedback loops where the server can request sub-tasks or translations dynamically.

Roots API

Exposes client-managed workspace paths and folders to servers. Allows servers to safely scan and understand project layouts with explicit client consent.

Transport Layer

Supports local connection via stdio pipes (stdin/stdout) and network orchestration via SSE (Server-Sent Events) over HTTP endpoints.

Contextual Prompts

Templates exposed by servers. Provides preset instruction patterns so clients can format specific database structure queries or schema checks cleanly.

Protocol Specification

JSON-RPC 2.0 message format exchanges under MCP standard.

1. Listing Tools (`tools/list`)

Sent by the client to query available executable capabilities of the server.

// Client Request { "jsonrpc": "2.0", "id": 1, "method": "tools/list" } // Server Response { "jsonrpc": "2.0", "id": 1, "result": { "tools": [ { "name": "get_load", "description": "Get server disk metric", "inputSchema": { "type": "object", "properties": { "server": {"type": "string"} }, "required": ["server"] } } ] } }

2. Calling Tools (`tools/call`)

Sent by the client to invoke a tool function with parameters on the server.

// Client Request { "jsonrpc": "2.0", "id": 2, "method": "tools/call", "params": { "name": "get_load", "arguments": { "server": "prod-db-1" } } } // Server Response { "jsonrpc": "2.0", "id": 2, "result": { "content": [ { "type": "text", "text": "Disk space for prod-db-1: 85% full" } ], "isError": false } }

Setup & Installation

Configure your environment for building and running MCP servers and clients.

1. SDK Installation

Install the official developer toolkits for Python and TypeScript/Node.js.

# Install Python MCP SDK
pip install mcp

# Install Node.js MCP SDK
npm install @modelcontextprotocol/sdk

# Run local inspection & dev inspector tool
npx @modelcontextprotocol/inspector

2. Claude Desktop host config

Expose custom servers to Claude Desktop by updating the configuration file:

macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
Windows: %APPDATA%\Claude\claude_desktop_config.json
{ "mcpServers": { "sys-inspector": { "command": "python", "args": ["/absolute/path/to/server.py"] } } }

Developer Implementations

Complete, production-ready server and client implementations in Python.

1. Custom MCP Server (`server.py`)
import sqlite3
from mcp.server.fastmcp import FastMCP

mcp = FastMCP("agent-sqlite-server")
DB_PATH = "data.db"

# Exposing a database query tool
@mcp.tool()
def query_db(sql_query: str) -> str:
  """Execute a read-only query on the local DB."""
  try:
    conn = sqlite3.connect(DB_PATH)
    cursor = conn.cursor()
    cursor.execute(sql_query)
    rows = cursor.fetchall()
    conn.close()
    return str(rows)
  except Exception as e:
    return f"Error executing query: {str(e)}"

# Exposing system configurations
@mcp.resource("system://settings")
def get_settings() -> str:
  return "max_token_budget=50\nenforce_limits=true"

if __name__ == "__main__":
  mcp.run()
2. custom MCP Client (`client.py`)
import asyncio
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client

async def main():
  # Set subprocess connection params
  params = StdioServerParameters(
    command="python",
    args=["server.py"]
  )

  async with stdio_client(params) as (read, write):
    async with ClientSession(read, write) as session:
      # Initialize connection handshake
      await session.initialize()

      # Discover tools
      tools = await session.list_tools()
      print("Available tools:", [t.name for t in tools.tools])

      # Call sqlite table tool
      res = await session.call_tool(
        "query_db",
        arguments={"sql_query": "SELECT * FROM users LIMIT 1"}
      )
      print("Result:", res.content[0].text)

asyncio.run(main())

Frequently Asked Questions

Is MCP standard specific to Anthropic Claude models?
No. Although designed by Anthropic, Model Context Protocol is an open-source standard. You can build MCP clients for OpenAI models, Gemini models, or local models run via Ollama. It decouples the tool definition from specific model API parameters.
How do stdio and SSE transports differ?
Stdio transport uses standard input/output pipes. It is perfect for local IDE extensions or scripts where the client launches the server process. SSE (Server-Sent Events) transport uses HTTP requests. It is ideal for cloud-hosted environments where servers run on different machines.
How does the Sampling protocol secure user keys?
In MCP, servers do not have access to LLM API keys. When a server requires model generation (via Sampling), it asks the Client host to generate the text. The client can enforce safety, limit token usage, prompt the user for authorization, and call its own secure model engine before responding.