|
57 | 57 | - [Advanced Usage](#advanced-usage)
|
58 | 58 | - [Low-Level Server](#low-level-server)
|
59 | 59 | - [Structured Output Support](#structured-output-support)
|
| 60 | + - [Pagination (Advanced)](#pagination-advanced) |
60 | 61 | - [Writing MCP Clients](#writing-mcp-clients)
|
61 | 62 | - [Client Display Utilities](#client-display-utilities)
|
62 | 63 | - [OAuth Authentication for Clients](#oauth-authentication-for-clients)
|
@@ -515,6 +516,41 @@ def debug_error(error: str) -> list[base.Message]:
|
515 | 516 | _Full example: [examples/snippets/servers/basic_prompt.py](https://github.com/modelcontextprotocol/python-sdk/blob/main/examples/snippets/servers/basic_prompt.py)_
|
516 | 517 | <!-- /snippet-source -->
|
517 | 518 |
|
| 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 | + |
518 | 554 | ### Images
|
519 | 555 |
|
520 | 556 | 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
|
746 | 782 | _Full example: [examples/snippets/servers/elicitation.py](https://github.com/modelcontextprotocol/python-sdk/blob/main/examples/snippets/servers/elicitation.py)_
|
747 | 783 | <!-- /snippet-source -->
|
748 | 784 |
|
| 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 | + |
749 | 787 | The `elicit()` method returns an `ElicitationResult` with:
|
750 | 788 |
|
751 | 789 | - `action`: "accept", "decline", or "cancel"
|
@@ -895,6 +933,8 @@ The FastMCP server instance accessible via `ctx.fastmcp` provides access to serv
|
895 | 933 |
|
896 | 934 | - `ctx.fastmcp.name` - The server's name as defined during initialization
|
897 | 935 | - `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 |
898 | 938 | - `ctx.fastmcp.settings` - Complete server configuration object containing:
|
899 | 939 | - `debug` - Debug mode flag
|
900 | 940 | - `log_level` - Current logging level
|
@@ -1737,6 +1777,116 @@ Tools can return data in three ways:
|
1737 | 1777 |
|
1738 | 1778 | When an `outputSchema` is defined, the server automatically validates the structured output against the schema. This ensures type safety and helps catch errors early.
|
1739 | 1779 |
|
| 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 | + |
1740 | 1890 | ### Writing MCP Clients
|
1741 | 1891 |
|
1742 | 1892 | 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):
|
|
0 commit comments