Skip to content

Commit 6dc50e2

Browse files
authored
Merge branch 'main' into enum_updates
2 parents 8786667 + 61399b3 commit 6dc50e2

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

72 files changed

+3587
-602
lines changed

.gitattribute

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# Generated
2+
uv.lock linguist-generated=true

.github/CODEOWNERS

Lines changed: 0 additions & 23 deletions
This file was deleted.

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ coverage.xml
5252
*.py,cover
5353
.hypothesis/
5454
.pytest_cache/
55+
.ruff_cache/
5556
cover/
5657

5758
# Translations
@@ -168,3 +169,6 @@ cython_debug/
168169
.vscode/
169170
.windsurfrules
170171
**/CLAUDE.local.md
172+
173+
# claude code
174+
.claude/

.pre-commit-config.yaml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,22 +25,22 @@ repos:
2525
hooks:
2626
- id: ruff-format
2727
name: Ruff Format
28-
entry: uv run ruff
28+
entry: uv run --frozen ruff
2929
args: [format]
3030
language: system
3131
types: [python]
3232
pass_filenames: false
3333
- id: ruff
3434
name: Ruff
35-
entry: uv run ruff
35+
entry: uv run --frozen ruff
3636
args: ["check", "--fix", "--exit-non-zero-on-fix"]
3737
types: [python]
3838
language: system
3939
pass_filenames: false
4040
exclude: ^README\.md$
4141
- id: pyright
4242
name: pyright
43-
entry: uv run pyright
43+
entry: uv run --frozen pyright
4444
language: system
4545
types: [python]
4646
pass_filenames: false
@@ -52,7 +52,7 @@ repos:
5252
pass_filenames: false
5353
- id: readme-snippets
5454
name: Check README snippets are up to date
55-
entry: uv run scripts/update_readme_snippets.py --check
55+
entry: uv run --frozen python scripts/update_readme_snippets.py --check
5656
language: system
5757
files: ^(README\.md|examples/.*\.py|scripts/update_readme_snippets\.py)$
5858
pass_filenames: false

CLAUDE.md

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,6 @@ This document contains critical information about working with this codebase. Fo
4848
the problem it tries to solve, and how it is solved. Don't go into the specifics of the
4949
code unless it adds clarity.
5050

51-
- Always add `jerome3o-anthropic` and `jspahrsummers` as reviewer.
52-
5351
- NEVER ever mention a `co-authored-by` or similar aspects. In particular, never
5452
mention the tool used to create the commit message or PR.
5553

README.md

Lines changed: 155 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@
88
[![MIT licensed][mit-badge]][mit-url]
99
[![Python Version][python-badge]][python-url]
1010
[![Documentation][docs-badge]][docs-url]
11+
[![Protocol][protocol-badge]][protocol-url]
1112
[![Specification][spec-badge]][spec-url]
12-
[![GitHub Discussions][discussions-badge]][discussions-url]
1313

1414
</div>
1515

@@ -57,6 +57,7 @@
5757
- [Advanced Usage](#advanced-usage)
5858
- [Low-Level Server](#low-level-server)
5959
- [Structured Output Support](#structured-output-support)
60+
- [Pagination (Advanced)](#pagination-advanced)
6061
- [Writing MCP Clients](#writing-mcp-clients)
6162
- [Client Display Utilities](#client-display-utilities)
6263
- [OAuth Authentication for Clients](#oauth-authentication-for-clients)
@@ -73,12 +74,12 @@
7374
[mit-url]: https://github.com/modelcontextprotocol/python-sdk/blob/main/LICENSE
7475
[python-badge]: https://img.shields.io/pypi/pyversions/mcp.svg
7576
[python-url]: https://www.python.org/downloads/
76-
[docs-badge]: https://img.shields.io/badge/docs-modelcontextprotocol.io-blue.svg
77-
[docs-url]: https://modelcontextprotocol.io
77+
[docs-badge]: https://img.shields.io/badge/docs-python--sdk-blue.svg
78+
[docs-url]: https://modelcontextprotocol.github.io/python-sdk/
79+
[protocol-badge]: https://img.shields.io/badge/protocol-modelcontextprotocol.io-blue.svg
80+
[protocol-url]: https://modelcontextprotocol.io
7881
[spec-badge]: https://img.shields.io/badge/spec-spec.modelcontextprotocol.io-blue.svg
7982
[spec-url]: https://spec.modelcontextprotocol.io
80-
[discussions-badge]: https://img.shields.io/github/discussions/modelcontextprotocol/python-sdk
81-
[discussions-url]: https://github.com/modelcontextprotocol/python-sdk/discussions
8283

8384
## Overview
8485

@@ -515,6 +516,41 @@ def debug_error(error: str) -> list[base.Message]:
515516
_Full example: [examples/snippets/servers/basic_prompt.py](https://github.com/modelcontextprotocol/python-sdk/blob/main/examples/snippets/servers/basic_prompt.py)_
516517
<!-- /snippet-source -->
517518

519+
### Icons
520+
521+
MCP servers can provide icons for UI display. Icons can be added to the server implementation, tools, resources, and prompts:
522+
523+
```python
524+
from mcp.server.fastmcp import FastMCP, Icon
525+
526+
# Create an icon from a file path or URL
527+
icon = Icon(
528+
src="icon.png",
529+
mimeType="image/png",
530+
sizes="64x64"
531+
)
532+
533+
# Add icons to server
534+
mcp = FastMCP(
535+
"My Server",
536+
website_url="https://example.com",
537+
icons=[icon]
538+
)
539+
540+
# Add icons to tools, resources, and prompts
541+
@mcp.tool(icons=[icon])
542+
def my_tool():
543+
"""Tool with an icon."""
544+
return "result"
545+
546+
@mcp.resource("demo://resource", icons=[icon])
547+
def my_resource():
548+
"""Resource with an icon."""
549+
return "content"
550+
```
551+
552+
_Full example: [examples/fastmcp/icons_demo.py](https://github.com/modelcontextprotocol/python-sdk/blob/main/examples/fastmcp/icons_demo.py)_
553+
518554
### Images
519555

520556
FastMCP provides an `Image` class that automatically handles image data:
@@ -746,6 +782,8 @@ async def book_table(date: str, time: str, party_size: int, ctx: Context[ServerS
746782
_Full example: [examples/snippets/servers/elicitation.py](https://github.com/modelcontextprotocol/python-sdk/blob/main/examples/snippets/servers/elicitation.py)_
747783
<!-- /snippet-source -->
748784

785+
Elicitation schemas support default values for all field types. Default values are automatically included in the JSON schema sent to clients, allowing them to pre-populate forms.
786+
749787
The `elicit()` method returns an `ElicitationResult` with:
750788

751789
- `action`: "accept", "decline", or "cancel"
@@ -895,6 +933,8 @@ The FastMCP server instance accessible via `ctx.fastmcp` provides access to serv
895933

896934
- `ctx.fastmcp.name` - The server's name as defined during initialization
897935
- `ctx.fastmcp.instructions` - Server instructions/description provided to clients
936+
- `ctx.fastmcp.website_url` - Optional website URL for the server
937+
- `ctx.fastmcp.icons` - Optional list of icons for UI display
898938
- `ctx.fastmcp.settings` - Complete server configuration object containing:
899939
- `debug` - Debug mode flag
900940
- `log_level` - Current logging level
@@ -1737,6 +1777,116 @@ Tools can return data in three ways:
17371777

17381778
When an `outputSchema` is defined, the server automatically validates the structured output against the schema. This ensures type safety and helps catch errors early.
17391779

1780+
### Pagination (Advanced)
1781+
1782+
For servers that need to handle large datasets, the low-level server provides paginated versions of list operations. This is an optional optimization - most servers won't need pagination unless they're dealing with hundreds or thousands of items.
1783+
1784+
#### Server-side Implementation
1785+
1786+
<!-- snippet-source examples/snippets/servers/pagination_example.py -->
1787+
```python
1788+
"""
1789+
Example of implementing pagination with MCP server decorators.
1790+
"""
1791+
1792+
from pydantic import AnyUrl
1793+
1794+
import mcp.types as types
1795+
from mcp.server.lowlevel import Server
1796+
1797+
# Initialize the server
1798+
server = Server("paginated-server")
1799+
1800+
# Sample data to paginate
1801+
ITEMS = [f"Item {i}" for i in range(1, 101)] # 100 items
1802+
1803+
1804+
@server.list_resources()
1805+
async def list_resources_paginated(request: types.ListResourcesRequest) -> types.ListResourcesResult:
1806+
"""List resources with pagination support."""
1807+
page_size = 10
1808+
1809+
# Extract cursor from request params
1810+
cursor = request.params.cursor if request.params is not None else None
1811+
1812+
# Parse cursor to get offset
1813+
start = 0 if cursor is None else int(cursor)
1814+
end = start + page_size
1815+
1816+
# Get page of resources
1817+
page_items = [
1818+
types.Resource(uri=AnyUrl(f"resource://items/{item}"), name=item, description=f"Description for {item}")
1819+
for item in ITEMS[start:end]
1820+
]
1821+
1822+
# Determine next cursor
1823+
next_cursor = str(end) if end < len(ITEMS) else None
1824+
1825+
return types.ListResourcesResult(resources=page_items, nextCursor=next_cursor)
1826+
```
1827+
1828+
_Full example: [examples/snippets/servers/pagination_example.py](https://github.com/modelcontextprotocol/python-sdk/blob/main/examples/snippets/servers/pagination_example.py)_
1829+
<!-- /snippet-source -->
1830+
1831+
#### Client-side Consumption
1832+
1833+
<!-- snippet-source examples/snippets/clients/pagination_client.py -->
1834+
```python
1835+
"""
1836+
Example of consuming paginated MCP endpoints from a client.
1837+
"""
1838+
1839+
import asyncio
1840+
1841+
from mcp.client.session import ClientSession
1842+
from mcp.client.stdio import StdioServerParameters, stdio_client
1843+
from mcp.types import Resource
1844+
1845+
1846+
async def list_all_resources() -> None:
1847+
"""Fetch all resources using pagination."""
1848+
async with stdio_client(StdioServerParameters(command="uv", args=["run", "mcp-simple-pagination"])) as (
1849+
read,
1850+
write,
1851+
):
1852+
async with ClientSession(read, write) as session:
1853+
await session.initialize()
1854+
1855+
all_resources: list[Resource] = []
1856+
cursor = None
1857+
1858+
while True:
1859+
# Fetch a page of resources
1860+
result = await session.list_resources(cursor=cursor)
1861+
all_resources.extend(result.resources)
1862+
1863+
print(f"Fetched {len(result.resources)} resources")
1864+
1865+
# Check if there are more pages
1866+
if result.nextCursor:
1867+
cursor = result.nextCursor
1868+
else:
1869+
break
1870+
1871+
print(f"Total resources: {len(all_resources)}")
1872+
1873+
1874+
if __name__ == "__main__":
1875+
asyncio.run(list_all_resources())
1876+
```
1877+
1878+
_Full example: [examples/snippets/clients/pagination_client.py](https://github.com/modelcontextprotocol/python-sdk/blob/main/examples/snippets/clients/pagination_client.py)_
1879+
<!-- /snippet-source -->
1880+
1881+
#### Key Points
1882+
1883+
- **Cursors are opaque strings** - the server defines the format (numeric offsets, timestamps, etc.)
1884+
- **Return `nextCursor=None`** when there are no more pages
1885+
- **Backward compatible** - clients that don't support pagination will still work (they'll just get the first page)
1886+
- **Flexible page sizes** - Each endpoint can define its own page size based on data characteristics
1887+
1888+
See the [simple-pagination example](examples/servers/simple-pagination) for a complete implementation.
1889+
17401890
### Writing MCP Clients
17411891

17421892
The SDK provides a high-level client interface for connecting to MCP servers using various [transports](https://modelcontextprotocol.io/specification/2025-03-26/basic/transports):

docs/authorization.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# Authorization
2+
3+
!!! warning "Under Construction"
4+
5+
This page is currently being written. Check back soon for complete documentation.

docs/concepts.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# Concepts
2+
3+
!!! warning "Under Construction"
4+
5+
This page is currently being written. Check back soon for complete documentation.
6+
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+
-->

docs/index.md

Lines changed: 55 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,57 @@
1-
# MCP Server
1+
# MCP Python SDK
22

3-
This is the MCP Server implementation in Python.
3+
The **Model Context Protocol (MCP)** allows applications to provide context for LLMs in a standardized way, separating the concerns of providing context from the actual LLM interaction.
44

5-
It only contains the [API Reference](api.md) for the time being.
5+
This Python SDK implements the full MCP specification, making it easy to:
6+
7+
- **Build MCP servers** that expose resources, prompts, and tools
8+
- **Create MCP clients** that can connect to any MCP server
9+
- **Use standard transports** like stdio, SSE, and Streamable HTTP
10+
11+
If you want to read more about the specification, please visit the [MCP documentation](https://modelcontextprotocol.io).
12+
13+
## Quick Example
14+
15+
Here's a simple MCP server that exposes a tool, resource, and prompt:
16+
17+
```python title="server.py"
18+
from mcp.server.fastmcp import FastMCP
19+
20+
mcp = FastMCP("Test Server")
21+
22+
23+
@mcp.tool()
24+
def add(a: int, b: int) -> int:
25+
"""Add two numbers"""
26+
return a + b
27+
28+
29+
@mcp.resource("greeting://{name}")
30+
def get_greeting(name: str) -> str:
31+
"""Get a personalized greeting"""
32+
return f"Hello, {name}!"
33+
34+
35+
@mcp.prompt()
36+
def greet_user(name: str, style: str = "friendly") -> str:
37+
"""Generate a greeting prompt"""
38+
return f"Write a {style} greeting for someone named {name}."
39+
```
40+
41+
Test it with the [MCP Inspector](https://github.com/modelcontextprotocol/inspector):
42+
43+
```bash
44+
uv run mcp dev server.py
45+
```
46+
47+
## Getting Started
48+
49+
<!-- TODO(Marcelo): automatically generate the follow references with a header on each of those files. -->
50+
1. **[Install](installation.md)** the MCP SDK
51+
2. **[Learn concepts](concepts.md)** - understand the three primitives and architecture
52+
3. **[Explore authorization](authorization.md)** - add security to your servers
53+
4. **[Use low-level APIs](low-level-server.md)** - for advanced customization
54+
55+
## API Reference
56+
57+
Full API documentation is available in the [API Reference](api.md).

0 commit comments

Comments
 (0)