MCP Core Concepts Basics
9 examples to get you started with MCP Core Concepts - 6 basic and 3 intermediate.
Search across all documentation pages
9 examples to get you started with MCP Core Concepts - 6 basic and 3 intermediate.
pip install mcp.Confirm the SDK is installed and pull in the pieces you need for a minimal server.
# server.py
from mcp.server.fastmcp import FastMCP
mcp = FastMCP("basics-demo")FastMCP is the high-level server class in the official Python SDK, built for quick tool/resource/prompt definitions.FastMCP names the server; clients display this name when listing connections.Register one callable tool using a decorator, the simplest way to expose a function to a client.
@mcp.tool()
def add(a: int, b: int) -> int:
"""Add two numbers together."""
return a + b@mcp.tool() decorator turns an ordinary Python function into a discoverable MCP tool.a: int, b: int) become the tool's input schema automatically.Related: Defining Callable Tools in an MCP Server - full tool schema and handler patterns
Start the server so a local client can spawn it as a subprocess and talk to it over standard input and output.
if __name__ == "__main__":
mcp.run(transport="stdio")transport="stdio" is the simplest transport: the server reads requests from stdin and writes responses to stdout.Related: Choosing Between stdio and HTTP/SSE Transports for MCP - when to reach for a remote transport instead
Use the Python SDK's client helpers to spawn the server process and open a session.
import asyncio
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client
params = StdioServerParameters(command="python", args=["server.py"])
async def main():
async with stdio_client(params) as (read, write):
async with ClientSession(read, write) as session:
await session.initialize()
print("Connected to:", session)
asyncio.run(main())StdioServerParameters tells the client how to launch the server process (command plus arguments).stdio_client opens the subprocess and yields read/write streams for the protocol.session.initialize() performs the MCP handshake before any tool, resource, or prompt calls are made.Ask the connected server what tools it exposes before calling any of them.
async with ClientSession(read, write) as session:
await session.initialize()
tools = await session.list_tools()
for tool in tools.tools:
print(tool.name, "-", tool.description)list_tools() performs discovery: the client learns what is available without hardcoding tool names.Invoke the add tool by name with matching arguments and read back the result.
result = await session.call_tool("add", arguments={"a": 2, "b": 3})
print(result.content)call_tool sends the tool name and a dictionary of arguments matching the tool's schema.content holds the tool's return value, wrapped in MCP's content format.Extend the same server with a second tool to see how multiple tools coexist in one session.
@mcp.tool()
def greet(name: str) -> str:
"""Return a friendly greeting for the given name."""
return f"Hello, {name}!"
# server now exposes both add() and greet()@mcp.tool() functions can live on the same FastMCP instance; each becomes its own discoverable entry.list_tools() again) sees both tools without any server-side registry code.Raise a clear error from inside a tool handler so the client and model get useful feedback instead of a crash.
@mcp.tool()
def divide(a: float, b: float) -> float:
"""Divide a by b."""
if b == 0:
raise ValueError("b must not be zero")
return a / bPoint a real MCP client at your stdio server using its configuration file, instead of the hand-rolled client from example 4.
{
"mcpServers": {
"basics-demo": {
"command": "python",
"args": ["/absolute/path/to/server.py"]
}
}
}StdioServerParameters.server.py avoids working-directory issues when the client spawns the process.Related: MCP Tools vs Resources vs Prompts Comparison - decide what to expose next as your server grows
Stack versions: Written against the Claude model lineup current as of ~June 2026 - Claude Fable 5, Claude Opus 4.8, Claude Sonnet 5 (the default), and Claude Haiku 4.5 - and the current Model Context Protocol specification. Model names, SDK versions, and the MCP spec move quickly - verify current specifics at platform.claude.com/docs and modelcontextprotocol.io before relying on them.
Reviewed by Chris St. John·Last updated Jul 18, 2026