Skip to content
Blog

MCP Concepts Explained: Tools, Resources, and Prompts

A developer-friendly explainer of the Model Context Protocol — tools, resources, prompts, and how MCP connects AI applications to external systems.

Published on September 9, 2026

AI Assistant

MCP Concepts Explained: Tools, Resources, and Prompts

MCP is the USB-C port for AI applications. It provides a standardized way to connect Claude, ChatGPT, VS Code Copilot, and Cursor to data sources, tools, and workflows. Build once, integrate everywhere.

Architecture: Host, Client, Server

MCP follows a client-server architecture with three participants:

ParticipantRole
MCP HostThe AI application (Claude Desktop, VS Code) that coordinates clients
MCP ClientComponent that maintains a connection to an MCP server
MCP ServerProgram that provides context to clients
MCP Host (AI Application)
├── MCP Client 1 ──→ Server A (Filesystem)
├── MCP Client 2 ──→ Server B (Database)
└── MCP Client 3 ──→ Server C (Sentry)

Two layers:

  • Data Layer — JSON-RPC 2.0 for client-server communication
  • Transport Layer — stdio for local, Streamable HTTP for remote

Three Primitives, Three Control Models

The key insight: MCP defines three primitives with different control models.

Tools (Model-Controlled)

Functions the LLM calls to take actions. The model discovers and invokes tools automatically.

{
  "name": "get_weather",
  "description": "Get current weather for a location",
  "inputSchema": {
    "type": "object",
    "properties": {
      "location": {"type": "string", "description": "City name"}
    },
    "required": ["location"]
  }
}

The flow: Client sends tools/list → LLM selects a tool → Client sends tools/call → Server returns result.

Resources (Application-Controlled)

Data the host application loads into the model’s context. Identified by URI:

{
  "uri": "file:///project/src/main.rs",
  "name": "main.rs",
  "description": "Primary application entry point",
  "mimeType": "text/x-rust"
}

Common URI schemes: https://, file://, git://, custom schemes.

Prompts (User-Controlled)

Reusable templates users invoke by name — slash commands, menu entries.

{
  "name": "code_review",
  "description": "Analyze code quality and suggest improvements",
  "arguments": [
    {"name": "code", "description": "The code to review", "required": true}
  ]
}

Building an MCP Server in Python (15 Lines)

from mcp.server import MCPServer

mcp = MCPServer("Demo")

@mcp.tool()
def add(a: int, b: int) -> int:
    """Add two numbers."""
    return a + b

@mcp.resource("greeting://{name}")
def greeting(name: str) -> str:
    """Greet someone by name."""
    return f"Hello, {name}!"

No JSON Schema needed — type hints are the schema. The SDK handles protocol handling, serialization, and validation automatically.

MCP Client in 10 Lines

import asyncio
from mcp import Client

async def main():
    async with Client("http://localhost:8000/mcp") as client:
        result = await client.call_tool("add", {"a": 1, "b": 2})
        print(result.structured_content)  # {'result': 3}

asyncio.run(main())

TypeScript Server

import { McpServer } from '@modelcontextprotocol/server';
import { serveStdio } from '@modelcontextprotocol/server/stdio';
import * as z from 'zod/v4';

serveStdio(() => {
  const server = new McpServer({ name: 'weather', version: '1.0.0' });
  
  server.registerTool(
    'get-forecast',
    {
      description: 'Get weather forecast for a city',
      inputSchema: z.object({ city: z.string() })
    },
    async ({ city }) => ({
      content: [{ type: 'text', text: `Sunny in ${city} all week.` }]
    })
  );
  
  return server;
});

Client Primitives

MCP also defines primitives that clients expose:

  • Elicitation — Servers can request additional info from users (confirmation, form input)
  • Logging — Servers send log messages to clients

Real-Time Notifications

MCP supports push updates without polling:

  • notifications/tools/list_changed — Available tools changed
  • notifications/resources/list_changed — Available resources changed
  • notifications/resources/updated — A specific resource changed

Clients subscribe via subscriptions/listen with filters.

Security Essentials

  • Servers MUST validate all tool inputs and implement access controls
  • Clients SHOULD prompt for user confirmation on sensitive operations
  • Human-in-the-loop is recommended for trust and safety
  • Rate limit invocations to prevent abuse

The Takeaway

MCP gives you three primitives with clean separation of concerns: Tools let the model act, Resources give the model context, Prompts let users drive. The Python and TypeScript SDKs handle all protocol complexity — write functions with type hints, and the SDK does the rest.

💡 Install the MCP Python SDK with uv add "mcp[cli]" and scaffold a server in seconds.