|
1 | 1 | # Concepts |
2 | 2 |
|
3 | | -!!! warning "Under Construction" |
| 3 | +The [Model Context Protocol (MCP)](https://modelcontextprotocol.io) lets you build servers that expose data |
| 4 | +and functionality to LLM applications in a standardized way. Think of it like a web API, but specifically |
| 5 | +designed for LLM interactions. |
4 | 6 |
|
5 | | - This page is currently being written. Check back soon for complete documentation. |
| 7 | +## Architecture |
6 | 8 |
|
7 | | -<!-- |
8 | | - - Server vs Client |
9 | | - - Three primitives (tools, resources, prompts) |
10 | | - - Transports (stdio, SSE, streamable HTTP) |
11 | | - - Context and sessions |
12 | | - - Lifecycle and state |
13 | | - --> |
| 9 | +MCP follows a client-server architecture: |
| 10 | + |
| 11 | +- **Hosts** are LLM applications (like Claude Desktop or an IDE) that initiate connections |
| 12 | +- **Clients** maintain 1:1 connections with servers, inside the host application |
| 13 | +- **Servers** provide context, tools, and prompts to clients |
| 14 | + |
| 15 | +```text |
| 16 | +Host (e.g. Claude Desktop) |
| 17 | +├── Client A ↔ Server A (e.g. file system) |
| 18 | +├── Client B ↔ Server B (e.g. database) |
| 19 | +└── Client C ↔ Server C (e.g. API wrapper) |
| 20 | +``` |
| 21 | + |
| 22 | +## Primitives |
| 23 | + |
| 24 | +MCP servers expose three core primitives: |
| 25 | + |
| 26 | +### Resources |
| 27 | + |
| 28 | +Resources provide data to LLMs — similar to GET endpoints in a REST API. They load information into the |
| 29 | +LLM's context without performing computation or causing side effects. |
| 30 | + |
| 31 | +```python |
| 32 | +@mcp.resource("config://app") |
| 33 | +def get_config() -> str: |
| 34 | + """Expose application configuration.""" |
| 35 | + return json.dumps({"theme": "dark", "version": "2.0"}) |
| 36 | +``` |
| 37 | + |
| 38 | +Resources can be static (fixed URI) or use URI templates for dynamic content: |
| 39 | + |
| 40 | +```python |
| 41 | +@mcp.resource("users://{user_id}/profile") |
| 42 | +def get_profile(user_id: str) -> str: |
| 43 | + """Get a user profile by ID.""" |
| 44 | + return json.dumps(load_profile(user_id)) |
| 45 | +``` |
| 46 | + |
| 47 | +See [Resources](server/resources.md) for full documentation. |
| 48 | + |
| 49 | +### Tools |
| 50 | + |
| 51 | +Tools let LLMs take actions — similar to POST endpoints. They perform computation, call external APIs, |
| 52 | +or produce side effects. |
| 53 | + |
| 54 | +```python |
| 55 | +@mcp.tool() |
| 56 | +def send_email(to: str, subject: str, body: str) -> str: |
| 57 | + """Send an email to the given recipient.""" |
| 58 | + # ... send email logic ... |
| 59 | + return f"Email sent to {to}" |
| 60 | +``` |
| 61 | + |
| 62 | +Tools support structured output, progress reporting, and more. See [Tools](server/tools.md) for full documentation. |
| 63 | + |
| 64 | +### Prompts |
| 65 | + |
| 66 | +Prompts are reusable templates for LLM interactions. They help standardize common workflows: |
| 67 | + |
| 68 | +```python |
| 69 | +@mcp.prompt() |
| 70 | +def review_code(code: str, language: str = "python") -> str: |
| 71 | + """Generate a code review prompt.""" |
| 72 | + return f"Review this {language} code:\n\n```{language}\n{code}\n```" |
| 73 | +``` |
| 74 | + |
| 75 | +See [Prompts](server/prompts.md) for full documentation. |
| 76 | + |
| 77 | +## Transports |
| 78 | + |
| 79 | +MCP supports multiple transport mechanisms for client-server communication: |
| 80 | + |
| 81 | +| Transport | Use case | How it works | |
| 82 | +|---|---|---| |
| 83 | +| **Streamable HTTP** | Remote servers, production deployments | HTTP POST with optional SSE streaming | |
| 84 | +| **stdio** | Local processes, CLI tools | Communication over stdin/stdout | |
| 85 | +| **SSE** | Legacy remote servers | Server-Sent Events over HTTP (deprecated in favor of Streamable HTTP) | |
| 86 | + |
| 87 | +See [Running Your Server](server/running.md) for transport configuration. |
| 88 | + |
| 89 | +## Context |
| 90 | + |
| 91 | +When handling requests, your functions can access a **context object** that provides capabilities |
| 92 | +like logging, progress reporting, and access to the current session: |
| 93 | + |
| 94 | +```python |
| 95 | +from mcp.server.mcpserver import Context |
| 96 | + |
| 97 | +@mcp.tool() |
| 98 | +async def long_task(ctx: Context) -> str: |
| 99 | + """A tool that reports progress.""" |
| 100 | + await ctx.report_progress(0, 100) |
| 101 | + # ... do work ... |
| 102 | + await ctx.report_progress(100, 100) |
| 103 | + return "Done" |
| 104 | +``` |
| 105 | + |
| 106 | +Context enables [logging](server/logging.md), [elicitation](server/elicitation.md), |
| 107 | +[sampling](server/sampling.md), and more. See [Context](server/context.md) for details. |
| 108 | + |
| 109 | +## Server lifecycle |
| 110 | + |
| 111 | +Servers support a **lifespan** pattern for managing startup and shutdown logic — for example |
| 112 | +initializing a database connection pool on startup and closing it on shutdown: |
| 113 | + |
| 114 | +```python |
| 115 | +from contextlib import asynccontextmanager |
| 116 | + |
| 117 | +@asynccontextmanager |
| 118 | +async def app_lifespan(server): |
| 119 | + db = await Database.connect() |
| 120 | + try: |
| 121 | + yield {"db": db} |
| 122 | + finally: |
| 123 | + await db.disconnect() |
| 124 | + |
| 125 | +mcp = MCPServer("My App", lifespan=app_lifespan) |
| 126 | +``` |
| 127 | + |
| 128 | +See [Server](server/index.md) for more on lifecycle management. |
| 129 | + |
| 130 | +## Next steps |
| 131 | + |
| 132 | +- **[Quickstart](quickstart.md)** — build your first server |
| 133 | +- **[Server](server/index.md)** — `MCPServer` configuration and lifecycle |
| 134 | +- **[Tools](server/tools.md)**, **[Resources](server/resources.md)**, **[Prompts](server/prompts.md)** — dive into each primitive |
| 135 | +- **[Client](client/index.md)** — writing MCP clients |
| 136 | +- **[Authorization](authorization.md)** — securing your servers with OAuth 2.1 |
0 commit comments